diff options
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 13 | ||||
-rw-r--r-- | Documentation/virtual/kvm/devices/arm-vgic.txt | 22 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/kvm.h | 7 | ||||
-rw-r--r-- | include/kvm/arm_vgic.h | 4 | ||||
-rw-r--r-- | virt/kvm/arm/vgic-v3-emul.c | 3 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 46 |
6 files changed, 73 insertions, 22 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 0007fef4ed81..f4b19d78782b 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -612,11 +612,14 @@ Type: vm ioctl | |||
612 | Parameters: none | 612 | Parameters: none |
613 | Returns: 0 on success, -1 on error | 613 | Returns: 0 on success, -1 on error |
614 | 614 | ||
615 | Creates an interrupt controller model in the kernel. On x86, creates a virtual | 615 | Creates an interrupt controller model in the kernel. |
616 | ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a | 616 | On x86, creates a virtual ioapic, a virtual PIC (two PICs, nested), and sets up |
617 | local APIC. IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23 | 617 | future vcpus to have a local APIC. IRQ routing for GSIs 0-15 is set to both |
618 | only go to the IOAPIC. On ARM/arm64, a GIC is | 618 | PIC and IOAPIC; GSI 16-23 only go to the IOAPIC. |
619 | created. On s390, a dummy irq routing table is created. | 619 | On ARM/arm64, a GICv2 is created. Any other GIC versions require the usage of |
620 | KVM_CREATE_DEVICE, which also supports creating a GICv2. Using | ||
621 | KVM_CREATE_DEVICE is preferred over KVM_CREATE_IRQCHIP for GICv2. | ||
622 | On s390, a dummy irq routing table is created. | ||
620 | 623 | ||
621 | Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled | 624 | Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled |
622 | before KVM_CREATE_IRQCHIP can be used. | 625 | before KVM_CREATE_IRQCHIP can be used. |
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt index 30f5427cf9b0..5d4fd4b944cd 100644 --- a/Documentation/virtual/kvm/devices/arm-vgic.txt +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt | |||
@@ -3,22 +3,38 @@ ARM Virtual Generic Interrupt Controller (VGIC) | |||
3 | 3 | ||
4 | Device types supported: | 4 | Device types supported: |
5 | KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0 | 5 | KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0 |
6 | KVM_DEV_TYPE_ARM_VGIC_V3 ARM Generic Interrupt Controller v3.0 | ||
6 | 7 | ||
7 | Only one VGIC instance may be instantiated through either this API or the | 8 | Only one VGIC instance may be instantiated through either this API or the |
8 | legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt | 9 | legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt |
9 | controller, requiring emulated user-space devices to inject interrupts to the | 10 | controller, requiring emulated user-space devices to inject interrupts to the |
10 | VGIC instead of directly to CPUs. | 11 | VGIC instead of directly to CPUs. |
11 | 12 | ||
13 | Creating a guest GICv3 device requires a host GICv3 as well. | ||
14 | GICv3 implementations with hardware compatibility support allow a guest GICv2 | ||
15 | as well. | ||
16 | |||
12 | Groups: | 17 | Groups: |
13 | KVM_DEV_ARM_VGIC_GRP_ADDR | 18 | KVM_DEV_ARM_VGIC_GRP_ADDR |
14 | Attributes: | 19 | Attributes: |
15 | KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit) | 20 | KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit) |
16 | Base address in the guest physical address space of the GIC distributor | 21 | Base address in the guest physical address space of the GIC distributor |
17 | register mappings. | 22 | register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2. |
18 | 23 | ||
19 | KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit) | 24 | KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit) |
20 | Base address in the guest physical address space of the GIC virtual cpu | 25 | Base address in the guest physical address space of the GIC virtual cpu |
21 | interface register mappings. | 26 | interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2. |
27 | |||
28 | KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit) | ||
29 | Base address in the guest physical address space of the GICv3 distributor | ||
30 | register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3. | ||
31 | |||
32 | KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit) | ||
33 | Base address in the guest physical address space of the GICv3 | ||
34 | redistributor register mappings. There are two 64K pages for each | ||
35 | VCPU and all of the redistributor pages are contiguous. | ||
36 | Only valid for KVM_DEV_TYPE_ARM_VGIC_V3. | ||
37 | |||
22 | 38 | ||
23 | KVM_DEV_ARM_VGIC_GRP_DIST_REGS | 39 | KVM_DEV_ARM_VGIC_GRP_DIST_REGS |
24 | Attributes: | 40 | Attributes: |
@@ -36,6 +52,7 @@ Groups: | |||
36 | the register. | 52 | the register. |
37 | Limitations: | 53 | Limitations: |
38 | - Priorities are not implemented, and registers are RAZ/WI | 54 | - Priorities are not implemented, and registers are RAZ/WI |
55 | - Currently only implemented for KVM_DEV_TYPE_ARM_VGIC_V2. | ||
39 | Errors: | 56 | Errors: |
40 | -ENODEV: Getting or setting this register is not yet supported | 57 | -ENODEV: Getting or setting this register is not yet supported |
41 | -EBUSY: One or more VCPUs are running | 58 | -EBUSY: One or more VCPUs are running |
@@ -68,6 +85,7 @@ Groups: | |||
68 | 85 | ||
69 | Limitations: | 86 | Limitations: |
70 | - Priorities are not implemented, and registers are RAZ/WI | 87 | - Priorities are not implemented, and registers are RAZ/WI |
88 | - Currently only implemented for KVM_DEV_TYPE_ARM_VGIC_V2. | ||
71 | Errors: | 89 | Errors: |
72 | -ENODEV: Getting or setting this register is not yet supported | 90 | -ENODEV: Getting or setting this register is not yet supported |
73 | -EBUSY: One or more VCPUs are running | 91 | -EBUSY: One or more VCPUs are running |
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 480af3461068..3ef77a466018 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h | |||
@@ -78,6 +78,13 @@ struct kvm_regs { | |||
78 | #define KVM_VGIC_V2_DIST_SIZE 0x1000 | 78 | #define KVM_VGIC_V2_DIST_SIZE 0x1000 |
79 | #define KVM_VGIC_V2_CPU_SIZE 0x2000 | 79 | #define KVM_VGIC_V2_CPU_SIZE 0x2000 |
80 | 80 | ||
81 | /* Supported VGICv3 address types */ | ||
82 | #define KVM_VGIC_V3_ADDR_TYPE_DIST 2 | ||
83 | #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3 | ||
84 | |||
85 | #define KVM_VGIC_V3_DIST_SIZE SZ_64K | ||
86 | #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K) | ||
87 | |||
81 | #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ | 88 | #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ |
82 | #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ | 89 | #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */ |
83 | #define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */ | 90 | #define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */ |
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 39039d5f09a8..7c55dd5dd2c9 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h | |||
@@ -36,8 +36,8 @@ | |||
36 | #define VGIC_V2_MAX_CPUS 8 | 36 | #define VGIC_V2_MAX_CPUS 8 |
37 | 37 | ||
38 | /* Sanity checks... */ | 38 | /* Sanity checks... */ |
39 | #if (KVM_MAX_VCPUS > 8) | 39 | #if (KVM_MAX_VCPUS > 255) |
40 | #error Invalid number of CPU interfaces | 40 | #error Too many KVM VCPUs, the VGIC only supports up to 255 VCPUs for now |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | #if (VGIC_NR_IRQS_LEGACY & 31) | 43 | #if (VGIC_NR_IRQS_LEGACY & 31) |
diff --git a/virt/kvm/arm/vgic-v3-emul.c b/virt/kvm/arm/vgic-v3-emul.c index 2d2199d85b74..b3f154631515 100644 --- a/virt/kvm/arm/vgic-v3-emul.c +++ b/virt/kvm/arm/vgic-v3-emul.c | |||
@@ -1007,6 +1007,9 @@ static int vgic_v3_has_attr(struct kvm_device *dev, | |||
1007 | case KVM_VGIC_V2_ADDR_TYPE_DIST: | 1007 | case KVM_VGIC_V2_ADDR_TYPE_DIST: |
1008 | case KVM_VGIC_V2_ADDR_TYPE_CPU: | 1008 | case KVM_VGIC_V2_ADDR_TYPE_CPU: |
1009 | return -ENXIO; | 1009 | return -ENXIO; |
1010 | case KVM_VGIC_V3_ADDR_TYPE_DIST: | ||
1011 | case KVM_VGIC_V3_ADDR_TYPE_REDIST: | ||
1012 | return 0; | ||
1010 | } | 1013 | } |
1011 | break; | 1014 | break; |
1012 | case KVM_DEV_ARM_VGIC_GRP_DIST_REGS: | 1015 | case KVM_DEV_ARM_VGIC_GRP_DIST_REGS: |
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 2efba8231375..184c6dbd5165 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -1667,7 +1667,7 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr, | |||
1667 | /** | 1667 | /** |
1668 | * kvm_vgic_addr - set or get vgic VM base addresses | 1668 | * kvm_vgic_addr - set or get vgic VM base addresses |
1669 | * @kvm: pointer to the vm struct | 1669 | * @kvm: pointer to the vm struct |
1670 | * @type: the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX | 1670 | * @type: the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX |
1671 | * @addr: pointer to address value | 1671 | * @addr: pointer to address value |
1672 | * @write: if true set the address in the VM address space, if false read the | 1672 | * @write: if true set the address in the VM address space, if false read the |
1673 | * address | 1673 | * address |
@@ -1681,29 +1681,49 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) | |||
1681 | { | 1681 | { |
1682 | int r = 0; | 1682 | int r = 0; |
1683 | struct vgic_dist *vgic = &kvm->arch.vgic; | 1683 | struct vgic_dist *vgic = &kvm->arch.vgic; |
1684 | int type_needed; | ||
1685 | phys_addr_t *addr_ptr, block_size; | ||
1684 | 1686 | ||
1685 | mutex_lock(&kvm->lock); | 1687 | mutex_lock(&kvm->lock); |
1686 | switch (type) { | 1688 | switch (type) { |
1687 | case KVM_VGIC_V2_ADDR_TYPE_DIST: | 1689 | case KVM_VGIC_V2_ADDR_TYPE_DIST: |
1688 | if (write) { | 1690 | type_needed = KVM_DEV_TYPE_ARM_VGIC_V2; |
1689 | r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base, | 1691 | addr_ptr = &vgic->vgic_dist_base; |
1690 | *addr, KVM_VGIC_V2_DIST_SIZE); | 1692 | block_size = KVM_VGIC_V2_DIST_SIZE; |
1691 | } else { | ||
1692 | *addr = vgic->vgic_dist_base; | ||
1693 | } | ||
1694 | break; | 1693 | break; |
1695 | case KVM_VGIC_V2_ADDR_TYPE_CPU: | 1694 | case KVM_VGIC_V2_ADDR_TYPE_CPU: |
1696 | if (write) { | 1695 | type_needed = KVM_DEV_TYPE_ARM_VGIC_V2; |
1697 | r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base, | 1696 | addr_ptr = &vgic->vgic_cpu_base; |
1698 | *addr, KVM_VGIC_V2_CPU_SIZE); | 1697 | block_size = KVM_VGIC_V2_CPU_SIZE; |
1699 | } else { | ||
1700 | *addr = vgic->vgic_cpu_base; | ||
1701 | } | ||
1702 | break; | 1698 | break; |
1699 | #ifdef CONFIG_ARM_GIC_V3 | ||
1700 | case KVM_VGIC_V3_ADDR_TYPE_DIST: | ||
1701 | type_needed = KVM_DEV_TYPE_ARM_VGIC_V3; | ||
1702 | addr_ptr = &vgic->vgic_dist_base; | ||
1703 | block_size = KVM_VGIC_V3_DIST_SIZE; | ||
1704 | break; | ||
1705 | case KVM_VGIC_V3_ADDR_TYPE_REDIST: | ||
1706 | type_needed = KVM_DEV_TYPE_ARM_VGIC_V3; | ||
1707 | addr_ptr = &vgic->vgic_redist_base; | ||
1708 | block_size = KVM_VGIC_V3_REDIST_SIZE; | ||
1709 | break; | ||
1710 | #endif | ||
1703 | default: | 1711 | default: |
1704 | r = -ENODEV; | 1712 | r = -ENODEV; |
1713 | goto out; | ||
1714 | } | ||
1715 | |||
1716 | if (vgic->vgic_model != type_needed) { | ||
1717 | r = -ENODEV; | ||
1718 | goto out; | ||
1705 | } | 1719 | } |
1706 | 1720 | ||
1721 | if (write) | ||
1722 | r = vgic_ioaddr_assign(kvm, addr_ptr, *addr, block_size); | ||
1723 | else | ||
1724 | *addr = *addr_ptr; | ||
1725 | |||
1726 | out: | ||
1707 | mutex_unlock(&kvm->lock); | 1727 | mutex_unlock(&kvm->lock); |
1708 | return r; | 1728 | return r; |
1709 | } | 1729 | } |