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

KVM: arm-vgic: Set base addr through device API

Support setting the distributor and cpu interface base addresses in the
VM physical address space through the KVM_{SET,GET}_DEVICE_ATTR API
in addition to the ARM specific API.

This has the added benefit of being able to share more code in user
space and do things in a uniform manner.

Also deprecate the older API at the same time, but backwards
compatibility will be maintained.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

+96 -15
+6 -1
Documentation/virtual/kvm/api.txt
··· 2391 2391 This ioctl returns the guest registers that are supported for the 2392 2392 KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 2393 2393 2394 - 4.85 KVM_ARM_SET_DEVICE_ADDR 2394 + 2395 + 4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated) 2395 2396 2396 2397 Capability: KVM_CAP_ARM_SET_DEVICE_ADDR 2397 2398 Architectures: arm, arm64 ··· 2429 2428 must be called after calling KVM_CREATE_IRQCHIP, but before calling 2430 2429 KVM_RUN on any of the VCPUs. Calling this ioctl twice for any of the 2431 2430 base addresses will return -EEXIST. 2431 + 2432 + Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API 2433 + should be used instead. 2434 + 2432 2435 2433 2436 4.86 KVM_PPC_RTAS_DEFINE_TOKEN 2434 2437
+11
Documentation/virtual/kvm/devices/arm-vgic.txt
··· 8 8 legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt 9 9 controller, requiring emulated user-space devices to inject interrupts to the 10 10 VGIC instead of directly to CPUs. 11 + 12 + Groups: 13 + KVM_DEV_ARM_VGIC_GRP_ADDR 14 + Attributes: 15 + KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit) 16 + Base address in the guest physical address space of the GIC distributor 17 + register mappings. 18 + 19 + KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit) 20 + Base address in the guest physical address space of the GIC virtual cpu 21 + interface register mappings.
+2
arch/arm/include/uapi/asm/kvm.h
··· 163 163 #define KVM_REG_ARM_VFP_FPINST 0x1009 164 164 #define KVM_REG_ARM_VFP_FPINST2 0x100A 165 165 166 + /* Device Control API: ARM VGIC */ 167 + #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 166 168 167 169 /* KVM_IRQ_LINE irq field index values */ 168 170 #define KVM_ARM_IRQ_TYPE_SHIFT 24
+1 -1
arch/arm/kvm/arm.c
··· 776 776 case KVM_ARM_DEVICE_VGIC_V2: 777 777 if (!vgic_present) 778 778 return -ENXIO; 779 - return kvm_vgic_set_addr(kvm, type, dev_addr->addr); 779 + return kvm_vgic_addr(kvm, type, &dev_addr->addr, true); 780 780 default: 781 781 return -ENODEV; 782 782 }
+1 -1
include/kvm/arm_vgic.h
··· 144 144 struct kvm_exit_mmio; 145 145 146 146 #ifdef CONFIG_KVM_ARM_VGIC 147 - int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr); 147 + int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write); 148 148 int kvm_vgic_hyp_init(void); 149 149 int kvm_vgic_init(struct kvm *kvm); 150 150 int kvm_vgic_create(struct kvm *kvm);
+75 -12
virt/kvm/arm/vgic.c
··· 1495 1495 { 1496 1496 int ret; 1497 1497 1498 + if (addr & ~KVM_PHYS_MASK) 1499 + return -E2BIG; 1500 + 1501 + if (addr & (SZ_4K - 1)) 1502 + return -EINVAL; 1503 + 1498 1504 if (!IS_VGIC_ADDR_UNDEF(*ioaddr)) 1499 1505 return -EEXIST; 1500 1506 if (addr + size < addr) ··· 1513 1507 return ret; 1514 1508 } 1515 1509 1516 - int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr) 1510 + /** 1511 + * kvm_vgic_addr - set or get vgic VM base addresses 1512 + * @kvm: pointer to the vm struct 1513 + * @type: the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX 1514 + * @addr: pointer to address value 1515 + * @write: if true set the address in the VM address space, if false read the 1516 + * address 1517 + * 1518 + * Set or get the vgic base addresses for the distributor and the virtual CPU 1519 + * interface in the VM physical address space. These addresses are properties 1520 + * of the emulated core/SoC and therefore user space initially knows this 1521 + * information. 1522 + */ 1523 + int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) 1517 1524 { 1518 1525 int r = 0; 1519 1526 struct vgic_dist *vgic = &kvm->arch.vgic; 1520 1527 1521 - if (addr & ~KVM_PHYS_MASK) 1522 - return -E2BIG; 1523 - 1524 - if (addr & (SZ_4K - 1)) 1525 - return -EINVAL; 1526 - 1527 1528 mutex_lock(&kvm->lock); 1528 1529 switch (type) { 1529 1530 case KVM_VGIC_V2_ADDR_TYPE_DIST: 1530 - r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base, 1531 - addr, KVM_VGIC_V2_DIST_SIZE); 1531 + if (write) { 1532 + r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base, 1533 + *addr, KVM_VGIC_V2_DIST_SIZE); 1534 + } else { 1535 + *addr = vgic->vgic_dist_base; 1536 + } 1532 1537 break; 1533 1538 case KVM_VGIC_V2_ADDR_TYPE_CPU: 1534 - r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base, 1535 - addr, KVM_VGIC_V2_CPU_SIZE); 1539 + if (write) { 1540 + r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base, 1541 + *addr, KVM_VGIC_V2_CPU_SIZE); 1542 + } else { 1543 + *addr = vgic->vgic_cpu_base; 1544 + } 1536 1545 break; 1537 1546 default: 1538 1547 r = -ENODEV; ··· 1559 1538 1560 1539 static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 1561 1540 { 1541 + int r; 1542 + 1543 + switch (attr->group) { 1544 + case KVM_DEV_ARM_VGIC_GRP_ADDR: { 1545 + u64 __user *uaddr = (u64 __user *)(long)attr->addr; 1546 + u64 addr; 1547 + unsigned long type = (unsigned long)attr->attr; 1548 + 1549 + if (copy_from_user(&addr, uaddr, sizeof(addr))) 1550 + return -EFAULT; 1551 + 1552 + r = kvm_vgic_addr(dev->kvm, type, &addr, true); 1553 + return (r == -ENODEV) ? -ENXIO : r; 1554 + } 1555 + } 1556 + 1562 1557 return -ENXIO; 1563 1558 } 1564 1559 1565 1560 static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 1566 1561 { 1567 - return -ENXIO; 1562 + int r = -ENXIO; 1563 + 1564 + switch (attr->group) { 1565 + case KVM_DEV_ARM_VGIC_GRP_ADDR: { 1566 + u64 __user *uaddr = (u64 __user *)(long)attr->addr; 1567 + u64 addr; 1568 + unsigned long type = (unsigned long)attr->attr; 1569 + 1570 + r = kvm_vgic_addr(dev->kvm, type, &addr, false); 1571 + if (r) 1572 + return (r == -ENODEV) ? -ENXIO : r; 1573 + 1574 + if (copy_to_user(uaddr, &addr, sizeof(addr))) 1575 + return -EFAULT; 1576 + } 1577 + } 1578 + 1579 + return r; 1568 1580 } 1569 1581 1570 1582 static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 1571 1583 { 1584 + switch (attr->group) { 1585 + case KVM_DEV_ARM_VGIC_GRP_ADDR: 1586 + switch (attr->attr) { 1587 + case KVM_VGIC_V2_ADDR_TYPE_DIST: 1588 + case KVM_VGIC_V2_ADDR_TYPE_CPU: 1589 + return 0; 1590 + } 1591 + break; 1592 + } 1572 1593 return -ENXIO; 1573 1594 } 1574 1595