Skip to content

Commit 9e5e19f

Browse files
committed
Merge tag 'kvmarm-fixes-5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into kvm-master
KVM/arm fixes for Linux 5.7, take #1 - Prevent the userspace API from interacting directly with the HW stage of the virtual GIC - Fix a couple of vGIC memory leaks - Tighten the rules around the use of the 32bit PSCI functions for 64bit guest, as well as the opposite situation (matches the specification)
2 parents dee919d + 446c076 commit 9e5e19f

File tree

7 files changed

+272
-80
lines changed

7 files changed

+272
-80
lines changed

virt/kvm/arm/psci.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,44 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
186186
kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET);
187187
}
188188

189+
static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
190+
{
191+
int i;
192+
193+
/*
194+
* Zero the input registers' upper 32 bits. They will be fully
195+
* zeroed on exit, so we're fine changing them in place.
196+
*/
197+
for (i = 1; i < 4; i++)
198+
vcpu_set_reg(vcpu, i, lower_32_bits(vcpu_get_reg(vcpu, i)));
199+
}
200+
201+
static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
202+
{
203+
switch(fn) {
204+
case PSCI_0_2_FN64_CPU_SUSPEND:
205+
case PSCI_0_2_FN64_CPU_ON:
206+
case PSCI_0_2_FN64_AFFINITY_INFO:
207+
/* Disallow these functions for 32bit guests */
208+
if (vcpu_mode_is_32bit(vcpu))
209+
return PSCI_RET_NOT_SUPPORTED;
210+
break;
211+
}
212+
213+
return 0;
214+
}
215+
189216
static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
190217
{
191218
struct kvm *kvm = vcpu->kvm;
192219
u32 psci_fn = smccc_get_function(vcpu);
193220
unsigned long val;
194221
int ret = 1;
195222

223+
val = kvm_psci_check_allowed_function(vcpu, psci_fn);
224+
if (val)
225+
goto out;
226+
196227
switch (psci_fn) {
197228
case PSCI_0_2_FN_PSCI_VERSION:
198229
/*
@@ -210,12 +241,16 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
210241
val = PSCI_RET_SUCCESS;
211242
break;
212243
case PSCI_0_2_FN_CPU_ON:
244+
kvm_psci_narrow_to_32bit(vcpu);
245+
fallthrough;
213246
case PSCI_0_2_FN64_CPU_ON:
214247
mutex_lock(&kvm->lock);
215248
val = kvm_psci_vcpu_on(vcpu);
216249
mutex_unlock(&kvm->lock);
217250
break;
218251
case PSCI_0_2_FN_AFFINITY_INFO:
252+
kvm_psci_narrow_to_32bit(vcpu);
253+
fallthrough;
219254
case PSCI_0_2_FN64_AFFINITY_INFO:
220255
val = kvm_psci_vcpu_affinity_info(vcpu);
221256
break;
@@ -256,6 +291,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
256291
break;
257292
}
258293

294+
out:
259295
smccc_set_retval(vcpu, val, 0, 0, 0);
260296
return ret;
261297
}
@@ -273,6 +309,10 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
273309
break;
274310
case PSCI_1_0_FN_PSCI_FEATURES:
275311
feature = smccc_get_arg1(vcpu);
312+
val = kvm_psci_check_allowed_function(vcpu, feature);
313+
if (val)
314+
break;
315+
276316
switch(feature) {
277317
case PSCI_0_2_FN_PSCI_VERSION:
278318
case PSCI_0_2_FN_CPU_SUSPEND:

virt/kvm/arm/vgic/vgic-init.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,12 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
348348
{
349349
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
350350

351+
/*
352+
* Retire all pending LPIs on this vcpu anyway as we're
353+
* going to destroy it.
354+
*/
355+
vgic_flush_pending_lpis(vcpu);
356+
351357
INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
352358
}
353359

@@ -359,10 +365,10 @@ static void __kvm_vgic_destroy(struct kvm *kvm)
359365

360366
vgic_debug_destroy(kvm);
361367

362-
kvm_vgic_dist_destroy(kvm);
363-
364368
kvm_for_each_vcpu(i, vcpu, kvm)
365369
kvm_vgic_vcpu_destroy(vcpu);
370+
371+
kvm_vgic_dist_destroy(kvm);
366372
}
367373

368374
void kvm_vgic_destroy(struct kvm *kvm)

virt/kvm/arm/vgic/vgic-its.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,21 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
9696
* We "cache" the configuration table entries in our struct vgic_irq's.
9797
* However we only have those structs for mapped IRQs, so we read in
9898
* the respective config data from memory here upon mapping the LPI.
99+
*
100+
* Should any of these fail, behave as if we couldn't create the LPI
101+
* by dropping the refcount and returning the error.
99102
*/
100103
ret = update_lpi_config(kvm, irq, NULL, false);
101-
if (ret)
104+
if (ret) {
105+
vgic_put_irq(kvm, irq);
102106
return ERR_PTR(ret);
107+
}
103108

104109
ret = vgic_v3_lpi_sync_pending_status(kvm, irq);
105-
if (ret)
110+
if (ret) {
111+
vgic_put_irq(kvm, irq);
106112
return ERR_PTR(ret);
113+
}
107114

108115
return irq;
109116
}

virt/kvm/arm/vgic/vgic-mmio-v2.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -409,24 +409,28 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
409409
NULL, vgic_mmio_uaccess_write_v2_group, 1,
410410
VGIC_ACCESS_32bit),
411411
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
412-
vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
412+
vgic_mmio_read_enable, vgic_mmio_write_senable,
413+
NULL, vgic_uaccess_write_senable, 1,
413414
VGIC_ACCESS_32bit),
414415
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
415-
vgic_mmio_read_enable, vgic_mmio_write_cenable, NULL, NULL, 1,
416+
vgic_mmio_read_enable, vgic_mmio_write_cenable,
417+
NULL, vgic_uaccess_write_cenable, 1,
416418
VGIC_ACCESS_32bit),
417419
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
418-
vgic_mmio_read_pending, vgic_mmio_write_spending, NULL, NULL, 1,
420+
vgic_mmio_read_pending, vgic_mmio_write_spending,
421+
NULL, vgic_uaccess_write_spending, 1,
419422
VGIC_ACCESS_32bit),
420423
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
421-
vgic_mmio_read_pending, vgic_mmio_write_cpending, NULL, NULL, 1,
424+
vgic_mmio_read_pending, vgic_mmio_write_cpending,
425+
NULL, vgic_uaccess_write_cpending, 1,
422426
VGIC_ACCESS_32bit),
423427
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
424428
vgic_mmio_read_active, vgic_mmio_write_sactive,
425-
NULL, vgic_mmio_uaccess_write_sactive, 1,
429+
vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 1,
426430
VGIC_ACCESS_32bit),
427431
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
428432
vgic_mmio_read_active, vgic_mmio_write_cactive,
429-
NULL, vgic_mmio_uaccess_write_cactive, 1,
433+
vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive, 1,
430434
VGIC_ACCESS_32bit),
431435
REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
432436
vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,

virt/kvm/arm/vgic/vgic-mmio-v3.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -538,10 +538,12 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
538538
vgic_mmio_read_group, vgic_mmio_write_group, NULL, NULL, 1,
539539
VGIC_ACCESS_32bit),
540540
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
541-
vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
541+
vgic_mmio_read_enable, vgic_mmio_write_senable,
542+
NULL, vgic_uaccess_write_senable, 1,
542543
VGIC_ACCESS_32bit),
543544
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
544-
vgic_mmio_read_enable, vgic_mmio_write_cenable, NULL, NULL, 1,
545+
vgic_mmio_read_enable, vgic_mmio_write_cenable,
546+
NULL, vgic_uaccess_write_cenable, 1,
545547
VGIC_ACCESS_32bit),
546548
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
547549
vgic_mmio_read_pending, vgic_mmio_write_spending,
@@ -553,11 +555,11 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
553555
VGIC_ACCESS_32bit),
554556
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
555557
vgic_mmio_read_active, vgic_mmio_write_sactive,
556-
NULL, vgic_mmio_uaccess_write_sactive, 1,
558+
vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 1,
557559
VGIC_ACCESS_32bit),
558560
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
559561
vgic_mmio_read_active, vgic_mmio_write_cactive,
560-
NULL, vgic_mmio_uaccess_write_cactive,
562+
vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive,
561563
1, VGIC_ACCESS_32bit),
562564
REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
563565
vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,
@@ -609,11 +611,13 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
609611
REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IGROUPR0,
610612
vgic_mmio_read_group, vgic_mmio_write_group, 4,
611613
VGIC_ACCESS_32bit),
612-
REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ISENABLER0,
613-
vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
614+
REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISENABLER0,
615+
vgic_mmio_read_enable, vgic_mmio_write_senable,
616+
NULL, vgic_uaccess_write_senable, 4,
614617
VGIC_ACCESS_32bit),
615-
REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ICENABLER0,
616-
vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
618+
REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICENABLER0,
619+
vgic_mmio_read_enable, vgic_mmio_write_cenable,
620+
NULL, vgic_uaccess_write_cenable, 4,
617621
VGIC_ACCESS_32bit),
618622
REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0,
619623
vgic_mmio_read_pending, vgic_mmio_write_spending,
@@ -625,12 +629,12 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
625629
VGIC_ACCESS_32bit),
626630
REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISACTIVER0,
627631
vgic_mmio_read_active, vgic_mmio_write_sactive,
628-
NULL, vgic_mmio_uaccess_write_sactive,
629-
4, VGIC_ACCESS_32bit),
632+
vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 4,
633+
VGIC_ACCESS_32bit),
630634
REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICACTIVER0,
631635
vgic_mmio_read_active, vgic_mmio_write_cactive,
632-
NULL, vgic_mmio_uaccess_write_cactive,
633-
4, VGIC_ACCESS_32bit),
636+
vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive, 4,
637+
VGIC_ACCESS_32bit),
634638
REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IPRIORITYR0,
635639
vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
636640
VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),

0 commit comments

Comments
 (0)