Skip to content

Commit a7a2c72

Browse files
committed
KVM: arm64: Separate out feature sanitisation and initialisation
kvm_vcpu_set_target() iteratively sanitises and copies feature flags in one go. This is rather odd, especially considering the fact that bitmap accessors can do the heavy lifting. A subsequent change will make vCPU features VM-wide, and fitting that into the present implementation is just a chore. Rework the whole thing to use bitmap accessors to sanitise and copy flags. Link: https://lore.kernel.org/r/20230609190054.1542113-2-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 44c026a commit a7a2c72

2 files changed

Lines changed: 48 additions & 28 deletions

File tree

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
4040

4141
#define KVM_VCPU_MAX_FEATURES 7
42+
#define KVM_VCPU_VALID_FEATURES (BIT(KVM_VCPU_MAX_FEATURES) - 1)
4243

4344
#define KVM_REQ_SLEEP \
4445
KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)

arch/arm64/kvm/arm.c

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,42 +1167,40 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
11671167
return -EINVAL;
11681168
}
11691169

1170-
static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
1171-
const struct kvm_vcpu_init *init)
1170+
static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu,
1171+
const struct kvm_vcpu_init *init)
11721172
{
1173-
unsigned int i, ret;
1174-
u32 phys_target = kvm_target_cpu();
1173+
unsigned long features = init->features[0];
1174+
int i;
11751175

1176-
if (init->target != phys_target)
1177-
return -EINVAL;
1176+
if (features & ~KVM_VCPU_VALID_FEATURES)
1177+
return -ENOENT;
11781178

1179-
/*
1180-
* Secondary and subsequent calls to KVM_ARM_VCPU_INIT must
1181-
* use the same target.
1182-
*/
1183-
if (vcpu->arch.target != -1 && vcpu->arch.target != init->target)
1184-
return -EINVAL;
1179+
for (i = 1; i < ARRAY_SIZE(init->features); i++) {
1180+
if (init->features[i])
1181+
return -ENOENT;
1182+
}
11851183

1186-
/* -ENOENT for unknown features, -EINVAL for invalid combinations. */
1187-
for (i = 0; i < sizeof(init->features) * 8; i++) {
1188-
bool set = (init->features[i / 32] & (1 << (i % 32)));
1184+
return 0;
1185+
}
11891186

1190-
if (set && i >= KVM_VCPU_MAX_FEATURES)
1191-
return -ENOENT;
1187+
static bool kvm_vcpu_init_changed(struct kvm_vcpu *vcpu,
1188+
const struct kvm_vcpu_init *init)
1189+
{
1190+
unsigned long features = init->features[0];
11921191

1193-
/*
1194-
* Secondary and subsequent calls to KVM_ARM_VCPU_INIT must
1195-
* use the same feature set.
1196-
*/
1197-
if (vcpu->arch.target != -1 && i < KVM_VCPU_MAX_FEATURES &&
1198-
test_bit(i, vcpu->arch.features) != set)
1199-
return -EINVAL;
1192+
return !bitmap_equal(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES) ||
1193+
vcpu->arch.target != init->target;
1194+
}
12001195

1201-
if (set)
1202-
set_bit(i, vcpu->arch.features);
1203-
}
1196+
static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
1197+
const struct kvm_vcpu_init *init)
1198+
{
1199+
unsigned long features = init->features[0];
1200+
int ret;
12041201

1205-
vcpu->arch.target = phys_target;
1202+
vcpu->arch.target = init->target;
1203+
bitmap_copy(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
12061204

12071205
/* Now we know what it is, we can reset it. */
12081206
ret = kvm_reset_vcpu(vcpu);
@@ -1214,6 +1212,27 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
12141212
return ret;
12151213
}
12161214

1215+
static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
1216+
const struct kvm_vcpu_init *init)
1217+
{
1218+
int ret;
1219+
1220+
if (init->target != kvm_target_cpu())
1221+
return -EINVAL;
1222+
1223+
ret = kvm_vcpu_init_check_features(vcpu, init);
1224+
if (ret)
1225+
return ret;
1226+
1227+
if (vcpu->arch.target == -1)
1228+
return __kvm_vcpu_set_target(vcpu, init);
1229+
1230+
if (kvm_vcpu_init_changed(vcpu, init))
1231+
return -EINVAL;
1232+
1233+
return kvm_reset_vcpu(vcpu);
1234+
}
1235+
12171236
static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
12181237
struct kvm_vcpu_init *init)
12191238
{

0 commit comments

Comments
 (0)