Message ID | 20180209143937.28866-37-andre.przywara@linaro.org |
---|---|
State | New |
Headers | show |
Series | New VGIC(-v2) implementation | expand |
Hi, On 09/02/18 14:39, Andre Przywara wrote: > Triggering an IPI via this register is v2 specific, so the > implementation lives entirely in vgic-mmio-v2.c. > > This is based on Linux commit 55cc01fb9004, written by Andre Przywara. > > Signed-off-by: Andre Przywara <andre.przywara@linaro.org> > --- > xen/arch/arm/vgic/vgic-mmio-v2.c | 47 +++++++++++++++++++++++++++++++++++++++- > 1 file changed, 46 insertions(+), 1 deletion(-) > > diff --git a/xen/arch/arm/vgic/vgic-mmio-v2.c b/xen/arch/arm/vgic/vgic-mmio-v2.c > index c59f2c1ba7..3f67b4659a 100644 > --- a/xen/arch/arm/vgic/vgic-mmio-v2.c > +++ b/xen/arch/arm/vgic/vgic-mmio-v2.c > @@ -66,6 +66,51 @@ static void vgic_mmio_write_v2_misc(struct vcpu *vcpu, > } > } > > +static void vgic_mmio_write_sgir(struct vcpu *source_vcpu, > + paddr_t addr, unsigned int len, > + unsigned long val) > +{ > + struct domain *d = source_vcpu->domain; > + int nr_vcpus = d->max_vcpus; > + int intid = val & 0xf; > + int targets = (val >> 16) & 0xff; > + int mode = (val >> 24) & 0x03; Please use unsigned for value that does not required to be signed. Also, please use define however hardcoded value whenever it is possible./ > + struct vcpu *vcpu; > + unsigned long flags; > + > + switch (mode) > + { > + case 0x0: /* as specified by targets */ > + break; > + case 0x1: > + targets = (1U << nr_vcpus) - 1; /* all, ... */ > + targets &= ~(1U << source_vcpu->vcpu_id); /* but self */ Please keep the both comment indented the same way. > + break; > + case 0x2: /* this very vCPU only */ > + targets = (1U << source_vcpu->vcpu_id); > + break; > + case 0x3: /* reserved */ > + return; > + } > + > + for_each_vcpu(d, vcpu) It would make more sense to iterate on bit set in targets. This would avoid to go through all the vCPUs most of the time. > + { > + struct vgic_irq *irq; > + > + if ( !(targets & (1U << vcpu->vcpu_id)) ) > + continue; > + > + irq = vgic_get_irq(d, vcpu, intid); > + > + spin_lock_irqsave(&irq->irq_lock, flags); > + irq->pending_latch = true; > + irq->source |= 1U << source_vcpu->vcpu_id; > + > + vgic_queue_irq_unlock(d, irq, flags); > + vgic_put_irq(d, irq); > + } > +} > + > static unsigned long vgic_mmio_read_target(struct vcpu *vcpu, > paddr_t addr, unsigned int len) > { > @@ -151,7 +196,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { > vgic_mmio_read_config, vgic_mmio_write_config, NULL, NULL, 2, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_LENGTH(GICD_SGIR, > - vgic_mmio_read_raz, vgic_mmio_write_wi, 4, > + vgic_mmio_read_raz, vgic_mmio_write_sgir, 4, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_LENGTH(GICD_CPENDSGIR, > vgic_mmio_read_raz, vgic_mmio_write_wi, 16, > Cheers,
diff --git a/xen/arch/arm/vgic/vgic-mmio-v2.c b/xen/arch/arm/vgic/vgic-mmio-v2.c index c59f2c1ba7..3f67b4659a 100644 --- a/xen/arch/arm/vgic/vgic-mmio-v2.c +++ b/xen/arch/arm/vgic/vgic-mmio-v2.c @@ -66,6 +66,51 @@ static void vgic_mmio_write_v2_misc(struct vcpu *vcpu, } } +static void vgic_mmio_write_sgir(struct vcpu *source_vcpu, + paddr_t addr, unsigned int len, + unsigned long val) +{ + struct domain *d = source_vcpu->domain; + int nr_vcpus = d->max_vcpus; + int intid = val & 0xf; + int targets = (val >> 16) & 0xff; + int mode = (val >> 24) & 0x03; + struct vcpu *vcpu; + unsigned long flags; + + switch (mode) + { + case 0x0: /* as specified by targets */ + break; + case 0x1: + targets = (1U << nr_vcpus) - 1; /* all, ... */ + targets &= ~(1U << source_vcpu->vcpu_id); /* but self */ + break; + case 0x2: /* this very vCPU only */ + targets = (1U << source_vcpu->vcpu_id); + break; + case 0x3: /* reserved */ + return; + } + + for_each_vcpu(d, vcpu) + { + struct vgic_irq *irq; + + if ( !(targets & (1U << vcpu->vcpu_id)) ) + continue; + + irq = vgic_get_irq(d, vcpu, intid); + + spin_lock_irqsave(&irq->irq_lock, flags); + irq->pending_latch = true; + irq->source |= 1U << source_vcpu->vcpu_id; + + vgic_queue_irq_unlock(d, irq, flags); + vgic_put_irq(d, irq); + } +} + static unsigned long vgic_mmio_read_target(struct vcpu *vcpu, paddr_t addr, unsigned int len) { @@ -151,7 +196,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { vgic_mmio_read_config, vgic_mmio_write_config, NULL, NULL, 2, VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH(GICD_SGIR, - vgic_mmio_read_raz, vgic_mmio_write_wi, 4, + vgic_mmio_read_raz, vgic_mmio_write_sgir, 4, VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH(GICD_CPENDSGIR, vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
Triggering an IPI via this register is v2 specific, so the implementation lives entirely in vgic-mmio-v2.c. This is based on Linux commit 55cc01fb9004, written by Andre Przywara. Signed-off-by: Andre Przywara <andre.przywara@linaro.org> --- xen/arch/arm/vgic/vgic-mmio-v2.c | 47 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-)