Skip to content

Commit a44e2c2

Browse files
committed
Merge tag 'kvmarm-fixes-5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for 5.18, take #1 - Some PSCI fixes after introducing PSCIv1.1 and SYSTEM_RESET2 - Fix the MMU write-lock not being taken on THP split - Fix mixed-width VM handling - Fix potential UAF when debugfs registration fails - Various selftest updates for all of the above
2 parents 5593473 + 21db838 commit a44e2c2

File tree

14 files changed

+285
-68
lines changed

14 files changed

+285
-68
lines changed

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,22 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
4343

4444
void kvm_vcpu_wfi(struct kvm_vcpu *vcpu);
4545

46+
#if defined(__KVM_VHE_HYPERVISOR__) || defined(__KVM_NVHE_HYPERVISOR__)
4647
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
4748
{
4849
return !(vcpu->arch.hcr_el2 & HCR_RW);
4950
}
51+
#else
52+
static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
53+
{
54+
struct kvm *kvm = vcpu->kvm;
55+
56+
WARN_ON_ONCE(!test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED,
57+
&kvm->arch.flags));
58+
59+
return test_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags);
60+
}
61+
#endif
5062

5163
static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
5264
{
@@ -72,15 +84,14 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
7284
vcpu->arch.hcr_el2 |= HCR_TVM;
7385
}
7486

75-
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
87+
if (vcpu_el1_is_32bit(vcpu))
7688
vcpu->arch.hcr_el2 &= ~HCR_RW;
77-
78-
/*
79-
* TID3: trap feature register accesses that we virtualise.
80-
* For now this is conditional, since no AArch32 feature regs
81-
* are currently virtualised.
82-
*/
83-
if (!vcpu_el1_is_32bit(vcpu))
89+
else
90+
/*
91+
* TID3: trap feature register accesses that we virtualise.
92+
* For now this is conditional, since no AArch32 feature regs
93+
* are currently virtualised.
94+
*/
8495
vcpu->arch.hcr_el2 |= HCR_TID3;
8596

8697
if (cpus_have_const_cap(ARM64_MISMATCHED_CACHE_TYPE) ||

arch/arm64/include/asm/kvm_host.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ struct kvm_arch {
127127
#define KVM_ARCH_FLAG_MTE_ENABLED 1
128128
/* At least one vCPU has ran in the VM */
129129
#define KVM_ARCH_FLAG_HAS_RAN_ONCE 2
130+
/*
131+
* The following two bits are used to indicate the guest's EL1
132+
* register width configuration. A value of KVM_ARCH_FLAG_EL1_32BIT
133+
* bit is valid only when KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED is set.
134+
* Otherwise, the guest's EL1 register width has not yet been
135+
* determined yet.
136+
*/
137+
#define KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED 3
138+
#define KVM_ARCH_FLAG_EL1_32BIT 4
139+
130140
unsigned long flags;
131141

132142
/*

arch/arm64/kvm/mmu.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
10791079
gfn_t gfn;
10801080
kvm_pfn_t pfn;
10811081
bool logging_active = memslot_is_logging(memslot);
1082-
bool logging_perm_fault = false;
1082+
bool use_read_lock = false;
10831083
unsigned long fault_level = kvm_vcpu_trap_get_fault_level(vcpu);
10841084
unsigned long vma_pagesize, fault_granule;
10851085
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
@@ -1114,7 +1114,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
11141114
if (logging_active) {
11151115
force_pte = true;
11161116
vma_shift = PAGE_SHIFT;
1117-
logging_perm_fault = (fault_status == FSC_PERM && write_fault);
1117+
use_read_lock = (fault_status == FSC_PERM && write_fault &&
1118+
fault_granule == PAGE_SIZE);
11181119
} else {
11191120
vma_shift = get_vma_page_shift(vma, hva);
11201121
}
@@ -1218,7 +1219,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
12181219
* logging dirty logging, only acquire read lock for permission
12191220
* relaxation.
12201221
*/
1221-
if (logging_perm_fault)
1222+
if (use_read_lock)
12221223
read_lock(&kvm->mmu_lock);
12231224
else
12241225
write_lock(&kvm->mmu_lock);
@@ -1268,6 +1269,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
12681269
if (fault_status == FSC_PERM && vma_pagesize == fault_granule) {
12691270
ret = kvm_pgtable_stage2_relax_perms(pgt, fault_ipa, prot);
12701271
} else {
1272+
WARN_ONCE(use_read_lock, "Attempted stage-2 map outside of write lock\n");
1273+
12711274
ret = kvm_pgtable_stage2_map(pgt, fault_ipa, vma_pagesize,
12721275
__pfn_to_phys(pfn), prot,
12731276
memcache);
@@ -1280,7 +1283,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
12801283
}
12811284

12821285
out_unlock:
1283-
if (logging_perm_fault)
1286+
if (use_read_lock)
12841287
read_unlock(&kvm->mmu_lock);
12851288
else
12861289
write_unlock(&kvm->mmu_lock);

arch/arm64/kvm/psci.c

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,11 @@ static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
215215

216216
static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
217217
{
218-
switch(fn) {
219-
case PSCI_0_2_FN64_CPU_SUSPEND:
220-
case PSCI_0_2_FN64_CPU_ON:
221-
case PSCI_0_2_FN64_AFFINITY_INFO:
222-
/* Disallow these functions for 32bit guests */
223-
if (vcpu_mode_is_32bit(vcpu))
224-
return PSCI_RET_NOT_SUPPORTED;
225-
break;
226-
}
218+
/*
219+
* Prevent 32 bit guests from calling 64 bit PSCI functions.
220+
*/
221+
if ((fn & PSCI_0_2_64BIT) && vcpu_mode_is_32bit(vcpu))
222+
return PSCI_RET_NOT_SUPPORTED;
227223

228224
return 0;
229225
}
@@ -235,10 +231,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
235231
unsigned long val;
236232
int ret = 1;
237233

238-
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
239-
if (val)
240-
goto out;
241-
242234
switch (psci_fn) {
243235
case PSCI_0_2_FN_PSCI_VERSION:
244236
/*
@@ -306,7 +298,6 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
306298
break;
307299
}
308300

309-
out:
310301
smccc_set_retval(vcpu, val, 0, 0, 0);
311302
return ret;
312303
}
@@ -318,9 +309,6 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
318309
unsigned long val;
319310
int ret = 1;
320311

321-
if (minor > 1)
322-
return -EINVAL;
323-
324312
switch(psci_fn) {
325313
case PSCI_0_2_FN_PSCI_VERSION:
326314
val = minor == 0 ? KVM_ARM_PSCI_1_0 : KVM_ARM_PSCI_1_1;
@@ -426,6 +414,15 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
426414
*/
427415
int kvm_psci_call(struct kvm_vcpu *vcpu)
428416
{
417+
u32 psci_fn = smccc_get_function(vcpu);
418+
unsigned long val;
419+
420+
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
421+
if (val) {
422+
smccc_set_retval(vcpu, val, 0, 0, 0);
423+
return 1;
424+
}
425+
429426
switch (kvm_psci_version(vcpu)) {
430427
case KVM_ARM_PSCI_1_1:
431428
return kvm_psci_1_x_call(vcpu, 1);

arch/arm64/kvm/reset.c

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -181,27 +181,51 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
181181
return 0;
182182
}
183183

184-
static bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu)
184+
/**
185+
* kvm_set_vm_width() - set the register width for the guest
186+
* @vcpu: Pointer to the vcpu being configured
187+
*
188+
* Set both KVM_ARCH_FLAG_EL1_32BIT and KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED
189+
* in the VM flags based on the vcpu's requested register width, the HW
190+
* capabilities and other options (such as MTE).
191+
* When REG_WIDTH_CONFIGURED is already set, the vcpu settings must be
192+
* consistent with the value of the FLAG_EL1_32BIT bit in the flags.
193+
*
194+
* Return: 0 on success, negative error code on failure.
195+
*/
196+
static int kvm_set_vm_width(struct kvm_vcpu *vcpu)
185197
{
186-
struct kvm_vcpu *tmp;
198+
struct kvm *kvm = vcpu->kvm;
187199
bool is32bit;
188-
unsigned long i;
189200

190201
is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
202+
203+
lockdep_assert_held(&kvm->lock);
204+
205+
if (test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags)) {
206+
/*
207+
* The guest's register width is already configured.
208+
* Make sure that the vcpu is consistent with it.
209+
*/
210+
if (is32bit == test_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags))
211+
return 0;
212+
213+
return -EINVAL;
214+
}
215+
191216
if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit)
192-
return false;
217+
return -EINVAL;
193218

194219
/* MTE is incompatible with AArch32 */
195-
if (kvm_has_mte(vcpu->kvm) && is32bit)
196-
return false;
220+
if (kvm_has_mte(kvm) && is32bit)
221+
return -EINVAL;
197222

198-
/* Check that the vcpus are either all 32bit or all 64bit */
199-
kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
200-
if (vcpu_has_feature(tmp, KVM_ARM_VCPU_EL1_32BIT) != is32bit)
201-
return false;
202-
}
223+
if (is32bit)
224+
set_bit(KVM_ARCH_FLAG_EL1_32BIT, &kvm->arch.flags);
203225

204-
return true;
226+
set_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags);
227+
228+
return 0;
205229
}
206230

207231
/**
@@ -230,10 +254,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
230254
u32 pstate;
231255

232256
mutex_lock(&vcpu->kvm->lock);
233-
reset_state = vcpu->arch.reset_state;
234-
WRITE_ONCE(vcpu->arch.reset_state.reset, false);
257+
ret = kvm_set_vm_width(vcpu);
258+
if (!ret) {
259+
reset_state = vcpu->arch.reset_state;
260+
WRITE_ONCE(vcpu->arch.reset_state.reset, false);
261+
}
235262
mutex_unlock(&vcpu->kvm->lock);
236263

264+
if (ret)
265+
return ret;
266+
237267
/* Reset PMU outside of the non-preemptible section */
238268
kvm_pmu_vcpu_reset(vcpu);
239269

@@ -260,14 +290,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
260290
}
261291
}
262292

263-
if (!vcpu_allowed_register_width(vcpu)) {
264-
ret = -EINVAL;
265-
goto out;
266-
}
267-
268293
switch (vcpu->arch.target) {
269294
default:
270-
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
295+
if (vcpu_el1_is_32bit(vcpu)) {
271296
pstate = VCPU_RESET_PSTATE_SVC;
272297
} else {
273298
pstate = VCPU_RESET_PSTATE_EL1;

arch/arm64/kvm/vgic/vgic-debug.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static bool end_of_vgic(struct vgic_state_iter *iter)
8282

8383
static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
8484
{
85-
struct kvm *kvm = (struct kvm *)s->private;
85+
struct kvm *kvm = s->private;
8686
struct vgic_state_iter *iter;
8787

8888
mutex_lock(&kvm->lock);
@@ -110,7 +110,7 @@ static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
110110

111111
static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
112112
{
113-
struct kvm *kvm = (struct kvm *)s->private;
113+
struct kvm *kvm = s->private;
114114
struct vgic_state_iter *iter = kvm->arch.vgic.iter;
115115

116116
++*pos;
@@ -122,7 +122,7 @@ static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
122122

123123
static void vgic_debug_stop(struct seq_file *s, void *v)
124124
{
125-
struct kvm *kvm = (struct kvm *)s->private;
125+
struct kvm *kvm = s->private;
126126
struct vgic_state_iter *iter;
127127

128128
/*
@@ -229,8 +229,8 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
229229

230230
static int vgic_debug_show(struct seq_file *s, void *v)
231231
{
232-
struct kvm *kvm = (struct kvm *)s->private;
233-
struct vgic_state_iter *iter = (struct vgic_state_iter *)v;
232+
struct kvm *kvm = s->private;
233+
struct vgic_state_iter *iter = v;
234234
struct vgic_irq *irq;
235235
struct kvm_vcpu *vcpu = NULL;
236236
unsigned long flags;

arch/arm64/kvm/vgic/vgic-its.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2143,7 +2143,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
21432143
static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
21442144
void *ptr, void *opaque)
21452145
{
2146-
struct its_device *dev = (struct its_device *)opaque;
2146+
struct its_device *dev = opaque;
21472147
struct its_collection *collection;
21482148
struct kvm *kvm = its->dev->kvm;
21492149
struct kvm_vcpu *vcpu = NULL;

tools/testing/selftests/kvm/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/aarch64/debug-exceptions
44
/aarch64/get-reg-list
55
/aarch64/psci_cpu_on_test
6+
/aarch64/vcpu_width_config
67
/aarch64/vgic_init
78
/aarch64/vgic_irq
89
/s390x/memop

tools/testing/selftests/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ TEST_GEN_PROGS_aarch64 += aarch64/arch_timer
106106
TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
107107
TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
108108
TEST_GEN_PROGS_aarch64 += aarch64/psci_cpu_on_test
109+
TEST_GEN_PROGS_aarch64 += aarch64/vcpu_width_config
109110
TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
110111
TEST_GEN_PROGS_aarch64 += aarch64/vgic_irq
111112
TEST_GEN_PROGS_aarch64 += demand_paging_test

tools/testing/selftests/kvm/aarch64/arch_timer.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,12 @@ static void test_init_timer_irq(struct kvm_vm *vm)
362362
pr_debug("ptimer_irq: %d; vtimer_irq: %d\n", ptimer_irq, vtimer_irq);
363363
}
364364

365+
static int gic_fd;
366+
365367
static struct kvm_vm *test_vm_create(void)
366368
{
367369
struct kvm_vm *vm;
368370
unsigned int i;
369-
int ret;
370371
int nr_vcpus = test_args.nr_vcpus;
371372

372373
vm = vm_create_default_with_vcpus(nr_vcpus, 0, 0, guest_code, NULL);
@@ -383,8 +384,8 @@ static struct kvm_vm *test_vm_create(void)
383384

384385
ucall_init(vm, NULL);
385386
test_init_timer_irq(vm);
386-
ret = vgic_v3_setup(vm, nr_vcpus, 64, GICD_BASE_GPA, GICR_BASE_GPA);
387-
if (ret < 0) {
387+
gic_fd = vgic_v3_setup(vm, nr_vcpus, 64, GICD_BASE_GPA, GICR_BASE_GPA);
388+
if (gic_fd < 0) {
388389
print_skip("Failed to create vgic-v3");
389390
exit(KSFT_SKIP);
390391
}
@@ -395,6 +396,12 @@ static struct kvm_vm *test_vm_create(void)
395396
return vm;
396397
}
397398

399+
static void test_vm_cleanup(struct kvm_vm *vm)
400+
{
401+
close(gic_fd);
402+
kvm_vm_free(vm);
403+
}
404+
398405
static void test_print_help(char *name)
399406
{
400407
pr_info("Usage: %s [-h] [-n nr_vcpus] [-i iterations] [-p timer_period_ms]\n",
@@ -478,7 +485,7 @@ int main(int argc, char *argv[])
478485

479486
vm = test_vm_create();
480487
test_run(vm);
481-
kvm_vm_free(vm);
488+
test_vm_cleanup(vm);
482489

483490
return 0;
484491
}

0 commit comments

Comments
 (0)