diff options
author | Andre Przywara <andre.przywara@arm.com> | 2014-06-06 18:54:51 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2015-01-20 12:25:31 -0500 |
commit | a0675c25d6392c2197b796a60c4a2a0138c86355 (patch) | |
tree | 123679ec2053ab33bc40f9c67b9489c9508ca313 /include | |
parent | 9fedf146778e6d1c26319ebaf56131a4f3a6be03 (diff) |
arm/arm64: KVM: add virtual GICv3 distributor emulation
With everything separated and prepared, we implement a model of a
GICv3 distributor and redistributors by using the existing framework
to provide handler functions for each register group.
Currently we limit the emulation to a model enforcing a single
security state, with SRE==1 (forcing system register access) and
ARE==1 (allowing more than 8 VCPUs).
We share some of the functions provided for GICv2 emulation, but take
the different ways of addressing (v)CPUs into account.
Save and restore is currently not implemented.
Similar to the split-off of the GICv2 specific code, the new emulation
code goes into a new file (vgic-v3-emul.c).
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/kvm/arm_vgic.h | 9 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic-v3.h | 32 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/kvm.h | 2 |
4 files changed, 43 insertions, 1 deletions
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index ff04afd0d901..98c30168bce4 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h | |||
@@ -162,7 +162,11 @@ struct vgic_dist { | |||
162 | 162 | ||
163 | /* Distributor and vcpu interface mapping in the guest */ | 163 | /* Distributor and vcpu interface mapping in the guest */ |
164 | phys_addr_t vgic_dist_base; | 164 | phys_addr_t vgic_dist_base; |
165 | phys_addr_t vgic_cpu_base; | 165 | /* GICv2 and GICv3 use different mapped register blocks */ |
166 | union { | ||
167 | phys_addr_t vgic_cpu_base; | ||
168 | phys_addr_t vgic_redist_base; | ||
169 | }; | ||
166 | 170 | ||
167 | /* Distributor enabled */ | 171 | /* Distributor enabled */ |
168 | u32 enabled; | 172 | u32 enabled; |
@@ -224,6 +228,9 @@ struct vgic_dist { | |||
224 | */ | 228 | */ |
225 | struct vgic_bitmap *irq_spi_target; | 229 | struct vgic_bitmap *irq_spi_target; |
226 | 230 | ||
231 | /* Target MPIDR for each IRQ (needed for GICv3 IROUTERn) only */ | ||
232 | u32 *irq_spi_mpidr; | ||
233 | |||
227 | /* Bitmap indicating which CPU has something pending */ | 234 | /* Bitmap indicating which CPU has something pending */ |
228 | unsigned long *irq_pending_on_cpu; | 235 | unsigned long *irq_pending_on_cpu; |
229 | 236 | ||
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 1e8b0cf30792..3fb4d8588a26 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define GICD_SETSPI_SR 0x0050 | 33 | #define GICD_SETSPI_SR 0x0050 |
34 | #define GICD_CLRSPI_SR 0x0058 | 34 | #define GICD_CLRSPI_SR 0x0058 |
35 | #define GICD_SEIR 0x0068 | 35 | #define GICD_SEIR 0x0068 |
36 | #define GICD_IGROUPR 0x0080 | ||
36 | #define GICD_ISENABLER 0x0100 | 37 | #define GICD_ISENABLER 0x0100 |
37 | #define GICD_ICENABLER 0x0180 | 38 | #define GICD_ICENABLER 0x0180 |
38 | #define GICD_ISPENDR 0x0200 | 39 | #define GICD_ISPENDR 0x0200 |
@@ -41,14 +42,37 @@ | |||
41 | #define GICD_ICACTIVER 0x0380 | 42 | #define GICD_ICACTIVER 0x0380 |
42 | #define GICD_IPRIORITYR 0x0400 | 43 | #define GICD_IPRIORITYR 0x0400 |
43 | #define GICD_ICFGR 0x0C00 | 44 | #define GICD_ICFGR 0x0C00 |
45 | #define GICD_IGRPMODR 0x0D00 | ||
46 | #define GICD_NSACR 0x0E00 | ||
44 | #define GICD_IROUTER 0x6000 | 47 | #define GICD_IROUTER 0x6000 |
48 | #define GICD_IDREGS 0xFFD0 | ||
45 | #define GICD_PIDR2 0xFFE8 | 49 | #define GICD_PIDR2 0xFFE8 |
46 | 50 | ||
51 | /* | ||
52 | * Those registers are actually from GICv2, but the spec demands that they | ||
53 | * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3). | ||
54 | */ | ||
55 | #define GICD_ITARGETSR 0x0800 | ||
56 | #define GICD_SGIR 0x0F00 | ||
57 | #define GICD_CPENDSGIR 0x0F10 | ||
58 | #define GICD_SPENDSGIR 0x0F20 | ||
59 | |||
47 | #define GICD_CTLR_RWP (1U << 31) | 60 | #define GICD_CTLR_RWP (1U << 31) |
61 | #define GICD_CTLR_DS (1U << 6) | ||
48 | #define GICD_CTLR_ARE_NS (1U << 4) | 62 | #define GICD_CTLR_ARE_NS (1U << 4) |
49 | #define GICD_CTLR_ENABLE_G1A (1U << 1) | 63 | #define GICD_CTLR_ENABLE_G1A (1U << 1) |
50 | #define GICD_CTLR_ENABLE_G1 (1U << 0) | 64 | #define GICD_CTLR_ENABLE_G1 (1U << 0) |
51 | 65 | ||
66 | /* | ||
67 | * In systems with a single security state (what we emulate in KVM) | ||
68 | * the meaning of the interrupt group enable bits is slightly different | ||
69 | */ | ||
70 | #define GICD_CTLR_ENABLE_SS_G1 (1U << 1) | ||
71 | #define GICD_CTLR_ENABLE_SS_G0 (1U << 0) | ||
72 | |||
73 | #define GICD_TYPER_LPIS (1U << 17) | ||
74 | #define GICD_TYPER_MBIS (1U << 16) | ||
75 | |||
52 | #define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1) | 76 | #define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1) |
53 | #define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32) | 77 | #define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32) |
54 | #define GICD_TYPER_LPIS (1U << 17) | 78 | #define GICD_TYPER_LPIS (1U << 17) |
@@ -60,6 +84,8 @@ | |||
60 | #define GIC_PIDR2_ARCH_GICv3 0x30 | 84 | #define GIC_PIDR2_ARCH_GICv3 0x30 |
61 | #define GIC_PIDR2_ARCH_GICv4 0x40 | 85 | #define GIC_PIDR2_ARCH_GICv4 0x40 |
62 | 86 | ||
87 | #define GIC_V3_DIST_SIZE 0x10000 | ||
88 | |||
63 | /* | 89 | /* |
64 | * Re-Distributor registers, offsets from RD_base | 90 | * Re-Distributor registers, offsets from RD_base |
65 | */ | 91 | */ |
@@ -78,6 +104,7 @@ | |||
78 | #define GICR_SYNCR 0x00C0 | 104 | #define GICR_SYNCR 0x00C0 |
79 | #define GICR_MOVLPIR 0x0100 | 105 | #define GICR_MOVLPIR 0x0100 |
80 | #define GICR_MOVALLR 0x0110 | 106 | #define GICR_MOVALLR 0x0110 |
107 | #define GICR_IDREGS GICD_IDREGS | ||
81 | #define GICR_PIDR2 GICD_PIDR2 | 108 | #define GICR_PIDR2 GICD_PIDR2 |
82 | 109 | ||
83 | #define GICR_CTLR_ENABLE_LPIS (1UL << 0) | 110 | #define GICR_CTLR_ENABLE_LPIS (1UL << 0) |
@@ -104,6 +131,7 @@ | |||
104 | /* | 131 | /* |
105 | * Re-Distributor registers, offsets from SGI_base | 132 | * Re-Distributor registers, offsets from SGI_base |
106 | */ | 133 | */ |
134 | #define GICR_IGROUPR0 GICD_IGROUPR | ||
107 | #define GICR_ISENABLER0 GICD_ISENABLER | 135 | #define GICR_ISENABLER0 GICD_ISENABLER |
108 | #define GICR_ICENABLER0 GICD_ICENABLER | 136 | #define GICR_ICENABLER0 GICD_ICENABLER |
109 | #define GICR_ISPENDR0 GICD_ISPENDR | 137 | #define GICR_ISPENDR0 GICD_ISPENDR |
@@ -112,11 +140,15 @@ | |||
112 | #define GICR_ICACTIVER0 GICD_ICACTIVER | 140 | #define GICR_ICACTIVER0 GICD_ICACTIVER |
113 | #define GICR_IPRIORITYR0 GICD_IPRIORITYR | 141 | #define GICR_IPRIORITYR0 GICD_IPRIORITYR |
114 | #define GICR_ICFGR0 GICD_ICFGR | 142 | #define GICR_ICFGR0 GICD_ICFGR |
143 | #define GICR_IGRPMODR0 GICD_IGRPMODR | ||
144 | #define GICR_NSACR GICD_NSACR | ||
115 | 145 | ||
116 | #define GICR_TYPER_PLPIS (1U << 0) | 146 | #define GICR_TYPER_PLPIS (1U << 0) |
117 | #define GICR_TYPER_VLPIS (1U << 1) | 147 | #define GICR_TYPER_VLPIS (1U << 1) |
118 | #define GICR_TYPER_LAST (1U << 4) | 148 | #define GICR_TYPER_LAST (1U << 4) |
119 | 149 | ||
150 | #define GIC_V3_REDIST_SIZE 0x20000 | ||
151 | |||
120 | #define LPI_PROP_GROUP1 (1 << 1) | 152 | #define LPI_PROP_GROUP1 (1 << 1) |
121 | #define LPI_PROP_ENABLED (1 << 0) | 153 | #define LPI_PROP_ENABLED (1 << 0) |
122 | 154 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 25d7ce31a5d4..0ef2daa199d8 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -1052,6 +1052,7 @@ void kvm_unregister_device_ops(u32 type); | |||
1052 | extern struct kvm_device_ops kvm_mpic_ops; | 1052 | extern struct kvm_device_ops kvm_mpic_ops; |
1053 | extern struct kvm_device_ops kvm_xics_ops; | 1053 | extern struct kvm_device_ops kvm_xics_ops; |
1054 | extern struct kvm_device_ops kvm_arm_vgic_v2_ops; | 1054 | extern struct kvm_device_ops kvm_arm_vgic_v2_ops; |
1055 | extern struct kvm_device_ops kvm_arm_vgic_v3_ops; | ||
1055 | 1056 | ||
1056 | #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT | 1057 | #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT |
1057 | 1058 | ||
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a37fd1224f36..b4e6f1e70f03 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h | |||
@@ -952,6 +952,8 @@ enum kvm_device_type { | |||
952 | #define KVM_DEV_TYPE_ARM_VGIC_V2 KVM_DEV_TYPE_ARM_VGIC_V2 | 952 | #define KVM_DEV_TYPE_ARM_VGIC_V2 KVM_DEV_TYPE_ARM_VGIC_V2 |
953 | KVM_DEV_TYPE_FLIC, | 953 | KVM_DEV_TYPE_FLIC, |
954 | #define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC | 954 | #define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC |
955 | KVM_DEV_TYPE_ARM_VGIC_V3, | ||
956 | #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3 | ||
955 | KVM_DEV_TYPE_MAX, | 957 | KVM_DEV_TYPE_MAX, |
956 | }; | 958 | }; |
957 | 959 | ||