[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 19/24] ARM: vITS: handle DISCARD command
On Wed, 28 Sep 2016, Andre Przywara wrote: > The DISCARD command drops the connection between a DeviceID/EventID > and an LPI/collection pair. > We mark the respective structure entries as not allocated and make > sure that any queued IRQs are removed. > > Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> > --- > xen/arch/arm/gic-its.c | 21 +++++++++++++++++++ > xen/arch/arm/vgic-its.c | 48 > +++++++++++++++++++++++++++++++++++++++++++ > xen/include/asm-arm/gic-its.h | 5 +++++ > 3 files changed, 74 insertions(+) > > diff --git a/xen/arch/arm/gic-its.c b/xen/arch/arm/gic-its.c > index d1b1cbb..766a7cb 100644 > --- a/xen/arch/arm/gic-its.c > +++ b/xen/arch/arm/gic-its.c > @@ -634,6 +634,27 @@ int gicv3_lpi_change_vcpu(struct domain *d, uint32_t > host_lpi, int new_vcpu_id) > return 0; > } > > +/* Looks up a given host LPI assigned to that domain and returns the > + * connected virtual LPI number. Also stores the target vcpu ID in > + * the passed vcpu_id pointer. > + * Returns 0 if no host LPI could be found for that domain, or the > + * virtual LPI number (>= 8192) if the lookup succeeded. > + */ > +uint32_t gicv3_lpi_lookup_lpi(struct domain *d, uint32_t host_lpi, int > *vcpu_id) > +{ > + union host_lpi *hlpip, hlpi; > + > + hlpip = gic_find_host_lpi(host_lpi, d); > + if ( !hlpip ) > + return 0; > + > + hlpi.data = hlpip->data; > + if ( vcpu_id ) > + *vcpu_id = hlpi.vcpu_id; > + > + return hlpi.virt_lpi; > +} > + > void gicv3_its_dt_init(const struct dt_device_node *node) > { > const struct dt_device_node *its = NULL; > diff --git a/xen/arch/arm/vgic-its.c b/xen/arch/arm/vgic-its.c > index c0a60ad..028d234 100644 > --- a/xen/arch/arm/vgic-its.c > +++ b/xen/arch/arm/vgic-its.c > @@ -367,6 +367,51 @@ out_unlock: > return 0; > } > > +static int its_handle_discard(struct virt_its *its, uint64_t *cmdptr) > +{ > + uint32_t devid = its_cmd_get_deviceid(cmdptr); > + uint32_t eventid = its_cmd_get_id(cmdptr); > + struct pending_irq *pirq; > + struct vits_itte *itte; > + struct vcpu *vcpu; > + uint32_t vlpi; > + int ret = -1, vcpu_id; > + > + spin_lock(&its->its_lock); > + itte = get_devid_evid(its, devid, eventid); > + if ( !itte ) > + goto out_unlock; > + > + vlpi = gicv3_lpi_lookup_lpi(its->d, itte->hlpi, &vcpu_id); > + if ( !vlpi ) > + goto out_unlock; Using itte->hlpi like that is very dangerous because the guest could be modifying that field while we run gicv3_lpi_lookup_lpi or gicv3_lpi_drop_host_lpi. Actually we need a compiler barrier after reading all guest accessible fields and before using them to access our own data structures. > + vcpu = its->d->vcpu[vcpu_id]; > + > + pirq = lpi_to_pending(vcpu, vlpi, false); > + if ( pirq ) > + { > + clear_bit(GIC_IRQ_GUEST_QUEUED, &pirq->status); > + gic_remove_from_queues(vcpu, vlpi); > + > + /* Mark this pending IRQ struct as availabe again. */ > + if ( !test_bit(GIC_IRQ_GUEST_VISIBLE, &pirq->status) ) > + pirq->irq = 0; We need to do something in case the vlpi is in a GICH_LR register > + } > + > + gicv3_lpi_drop_host_lpi(its->hw_its, devid, eventid, itte->hlpi); Same here regarding itte->hlpi > + itte->hlpi = 0; /* Mark this ITTE as unused. */ > + ret = 0; > + > + put_devid_evid(its, itte); > + > +out_unlock: > + spin_unlock(&its->its_lock); > + > + return ret; > +} > + > #define ITS_CMD_BUFFER_SIZE(baser) ((((baser) & 0xff) + 1) << 12) > > static int vgic_its_handle_cmds(struct domain *d, struct virt_its *its, > @@ -390,6 +435,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct > virt_its *its, > case GITS_CMD_CLEAR: > its_handle_clear(its, cmdptr); > break; > + case GITS_CMD_DISCARD: > + its_handle_discard(its, cmdptr); > + break; > case GITS_CMD_INT: > its_handle_int(its, cmdptr); > break; > diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h > index 7e1142f..3f5698d 100644 > --- a/xen/include/asm-arm/gic-its.h > +++ b/xen/include/asm-arm/gic-its.h > @@ -133,6 +133,11 @@ int gicv3_its_map_device(struct host_its *hw_its, struct > domain *d, > int gicv3_lpi_allocate_host_lpi(struct host_its *its, > uint32_t devid, uint32_t eventid, > struct vcpu *v, int virt_lpi); > +/* Given a physical LPI, looks up and returns the associated virtual LPI > + * and the target VCPU in the given domain. > + */ > +uint32_t gicv3_lpi_lookup_lpi(struct domain *d, uint32_t host_lpi, > + int *vcpu_id); > int gicv3_lpi_change_vcpu(struct domain *d, uint32_t host_lpi, int > new_vcpu_id); > int gicv3_lpi_drop_host_lpi(struct host_its *its, > uint32_t devid, uint32_t eventid, > -- > 2.9.0 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |