aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2016-01-25 11:45:37 -0500
committerChristoffer Dall <christoffer.dall@linaro.org>2016-05-20 09:39:58 -0400
commit78a714aba030395e72d03f0ff8a4c1481956e808 (patch)
tree16fe9953857caf5510c55986f45dfbdc29479cbc
parent54f59d2b3a0a3d4e6f5038f5831aedb21350209d (diff)
KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register handlers
Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR register can handle, the new IROUTER register covers the whole range of possible target (V)CPUs by using the same MPIDR that the cores report themselves. In addition to translating this MPIDR into a vcpu pointer we store the originally written value as well. The architecture allows to write any values into the register, which must be read back as written. Since we don't support affinity level 3, we don't need to take care about the upper word of this 64-bit register, which simplifies the handling a bit. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v3.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 22e512ca149f..4dcef9ee83ae 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -75,6 +75,45 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
75 } 75 }
76} 76}
77 77
78static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
79 gpa_t addr, unsigned int len)
80{
81 int intid = VGIC_ADDR_TO_INTID(addr, 64);
82 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
83
84 if (!irq)
85 return 0;
86
87 /* The upper word is RAZ for us. */
88 if (addr & 4)
89 return 0;
90
91 return extract_bytes(READ_ONCE(irq->mpidr), addr & 7, len);
92}
93
94static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
95 gpa_t addr, unsigned int len,
96 unsigned long val)
97{
98 int intid = VGIC_ADDR_TO_INTID(addr, 64);
99 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
100
101 if (!irq)
102 return;
103
104 /* The upper word is WI for us since we don't implement Aff3. */
105 if (addr & 4)
106 return;
107
108 spin_lock(&irq->irq_lock);
109
110 /* We only care about and preserve Aff0, Aff1 and Aff2. */
111 irq->mpidr = val & GENMASK(23, 0);
112 irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
113
114 spin_unlock(&irq->irq_lock);
115}
116
78static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu, 117static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
79 gpa_t addr, unsigned int len) 118 gpa_t addr, unsigned int len)
80{ 119{
@@ -170,7 +209,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
170 vgic_mmio_read_raz, vgic_mmio_write_wi, 1, 209 vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
171 VGIC_ACCESS_32bit), 210 VGIC_ACCESS_32bit),
172 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER, 211 REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
173 vgic_mmio_read_raz, vgic_mmio_write_wi, 64, 212 vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
174 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit), 213 VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
175 REGISTER_DESC_WITH_LENGTH(GICD_IDREGS, 214 REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
176 vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48, 215 vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,