Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: gic-v5: Communicate userspace-driveable PPIs via a UAPI

GICv5 systems will likely not support the full set of PPIs. The
presence of any virtual PPI is tied to the presence of the physical
PPI. Therefore, the available PPIs will be limited by the physical
host. Userspace cannot drive any PPIs that are not implemented.

Moreover, it is not desirable to expose all PPIs to the guest in the
first place, even if they are supported in hardware. Some devices,
such as the arch timer, are implemented in KVM, and hence those PPIs
shouldn't be driven by userspace, either.

Provided a new UAPI:
KVM_DEV_ARM_VGIC_GRP_CTRL => KVM_DEV_ARM_VGIC_USERPSPACE_PPIs

This allows userspace to query which PPIs it is able to drive via
KVM_IRQ_LINE.

Additionally, introduce a check in kvm_vm_ioctl_irq_line() to reject
any PPIs not in the userspace mask.

Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20260319154937.3619520-40-sascha.bischoff@arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Sascha Bischoff and committed by
Marc Zyngier
d51c978b eb3c4d2c

+69 -1
+13
Documentation/virt/kvm/devices/arm-vgic-v5.rst
··· 25 25 request the initialization of the VGIC, no additional parameter in 26 26 kvm_device_attr.addr. Must be called after all VCPUs have been created. 27 27 28 + KVM_DEV_ARM_VGIC_USERPSPACE_PPIs 29 + request the mask of userspace-drivable PPIs. Only a subset of the PPIs can 30 + be directly driven from userspace with GICv5, and the returned mask 31 + informs userspace of which it is allowed to drive via KVM_IRQ_LINE. 32 + 33 + Userspace must allocate and point to __u64[2] of data in 34 + kvm_device_attr.addr. When this call returns, the provided memory will be 35 + populated with the userspace PPI mask. The lower __u64 contains the mask 36 + for the lower 64 PPIS, with the remaining 64 being in the second __u64. 37 + 38 + This is a read-only attribute, and cannot be set. Attempts to set it are 39 + rejected. 40 + 28 41 Errors: 29 42 30 43 ======= ========================================================
+1
arch/arm64/include/uapi/asm/kvm.h
··· 428 428 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 429 429 #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 430 430 #define KVM_DEV_ARM_ITS_CTRL_RESET 4 431 + #define KVM_DEV_ARM_VGIC_USERSPACE_PPIS 5 431 432 432 433 /* Device Control API on vcpu fd */ 433 434 #define KVM_ARM_VCPU_PMU_V3_CTRL 0
+10 -1
arch/arm64/kvm/arm.c
··· 1449 1449 int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, 1450 1450 bool line_status) 1451 1451 { 1452 - u32 irq = irq_level->irq; 1453 1452 unsigned int irq_type, vcpu_id, irq_num; 1454 1453 struct kvm_vcpu *vcpu = NULL; 1455 1454 bool level = irq_level->level; 1455 + u32 irq = irq_level->irq; 1456 + unsigned long *mask; 1456 1457 1457 1458 irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK; 1458 1459 vcpu_id = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK; ··· 1485 1484 1486 1485 if (vgic_is_v5(kvm)) { 1487 1486 if (irq_num >= VGIC_V5_NR_PRIVATE_IRQS) 1487 + return -EINVAL; 1488 + 1489 + /* 1490 + * Only allow PPIs that are explicitly exposed to 1491 + * usespace to be driven via KVM_IRQ_LINE 1492 + */ 1493 + mask = kvm->arch.vgic.gicv5_vm.userspace_ppis; 1494 + if (!test_bit(irq_num, mask)) 1488 1495 return -EINVAL; 1489 1496 1490 1497 /* Build a GICv5-style IntID here */
+31
arch/arm64/kvm/vgic/vgic-kvm-device.c
··· 720 720 .has_attr = vgic_v3_has_attr, 721 721 }; 722 722 723 + static int vgic_v5_get_userspace_ppis(struct kvm_device *dev, 724 + struct kvm_device_attr *attr) 725 + { 726 + struct vgic_v5_vm *gicv5_vm = &dev->kvm->arch.vgic.gicv5_vm; 727 + u64 __user *uaddr = (u64 __user *)(long)attr->addr; 728 + int ret; 729 + 730 + guard(mutex)(&dev->kvm->arch.config_lock); 731 + 732 + /* 733 + * We either support 64 or 128 PPIs. In the former case, we need to 734 + * return 0s for the second 64 bits as we have no storage backing those. 735 + */ 736 + ret = put_user(bitmap_read(gicv5_vm->userspace_ppis, 0, 64), uaddr); 737 + if (ret) 738 + return ret; 739 + uaddr++; 740 + 741 + if (VGIC_V5_NR_PRIVATE_IRQS == 128) 742 + ret = put_user(bitmap_read(gicv5_vm->userspace_ppis, 64, 128), uaddr); 743 + else 744 + ret = put_user(0, uaddr); 745 + 746 + return ret; 747 + } 748 + 723 749 static int vgic_v5_set_attr(struct kvm_device *dev, 724 750 struct kvm_device_attr *attr) 725 751 { ··· 758 732 switch (attr->attr) { 759 733 case KVM_DEV_ARM_VGIC_CTRL_INIT: 760 734 return vgic_set_common_attr(dev, attr); 735 + case KVM_DEV_ARM_VGIC_USERSPACE_PPIS: 761 736 default: 762 737 return -ENXIO; 763 738 } ··· 780 753 switch (attr->attr) { 781 754 case KVM_DEV_ARM_VGIC_CTRL_INIT: 782 755 return vgic_get_common_attr(dev, attr); 756 + case KVM_DEV_ARM_VGIC_USERSPACE_PPIS: 757 + return vgic_v5_get_userspace_ppis(dev, attr); 783 758 default: 784 759 return -ENXIO; 785 760 } ··· 801 772 case KVM_DEV_ARM_VGIC_GRP_CTRL: 802 773 switch (attr->attr) { 803 774 case KVM_DEV_ARM_VGIC_CTRL_INIT: 775 + return 0; 776 + case KVM_DEV_ARM_VGIC_USERSPACE_PPIS: 804 777 return 0; 805 778 default: 806 779 return -ENXIO;
+10
arch/arm64/kvm/vgic/vgic-v5.c
··· 143 143 } 144 144 } 145 145 146 + /* We only allow userspace to drive the SW_PPI, if it is implemented. */ 147 + bitmap_zero(kvm->arch.vgic.gicv5_vm.userspace_ppis, 148 + VGIC_V5_NR_PRIVATE_IRQS); 149 + __assign_bit(GICV5_ARCH_PPI_SW_PPI, 150 + kvm->arch.vgic.gicv5_vm.userspace_ppis, 151 + VGIC_V5_NR_PRIVATE_IRQS); 152 + bitmap_and(kvm->arch.vgic.gicv5_vm.userspace_ppis, 153 + kvm->arch.vgic.gicv5_vm.userspace_ppis, 154 + ppi_caps.impl_ppi_mask, VGIC_V5_NR_PRIVATE_IRQS); 155 + 146 156 return 0; 147 157 } 148 158
+3
include/kvm/arm_vgic.h
··· 350 350 */ 351 351 DECLARE_BITMAP(vgic_ppi_mask, VGIC_V5_NR_PRIVATE_IRQS); 352 352 353 + /* A mask of the PPIs that are exposed for userspace to drive. */ 354 + DECLARE_BITMAP(userspace_ppis, VGIC_V5_NR_PRIVATE_IRQS); 355 + 353 356 /* 354 357 * The HMR itself is handled by the hardware, but we still need to have 355 358 * a mask that we can use when merging in pending state (only the state
+1
tools/arch/arm64/include/uapi/asm/kvm.h
··· 428 428 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 429 429 #define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3 430 430 #define KVM_DEV_ARM_ITS_CTRL_RESET 4 431 + #define KVM_DEV_ARM_VGIC_USERSPACE_PPIS 5 431 432 432 433 /* Device Control API on vcpu fd */ 433 434 #define KVM_ARM_VCPU_PMU_V3_CTRL 0