[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 21/24] ARM: vITS: handle INVALL command
Hi, On 24/10/16 16:32, Vijay Kilari wrote: > On Wed, Sep 28, 2016 at 11:54 PM, Andre Przywara <andre.przywara@xxxxxxx> > wrote: >> The INVALL command instructs an ITS to invalidate the configuration >> data for all LPIs associated with a given redistributor (read: VCPU). >> To avoid iterating (and mapping!) all guest tables, we instead go through >> the host LPI table to find any LPIs targetting this VCPU. We then update >> the configuration bits for the connected virtual LPIs. >> >> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> >> --- >> xen/arch/arm/gic-its.c | 58 >> +++++++++++++++++++++++++++++++++++++++++++ >> xen/arch/arm/vgic-its.c | 30 ++++++++++++++++++++++ >> xen/include/asm-arm/gic-its.h | 2 ++ >> 3 files changed, 90 insertions(+) >> >> diff --git a/xen/arch/arm/gic-its.c b/xen/arch/arm/gic-its.c >> index 6f4329f..5129d6e 100644 >> --- a/xen/arch/arm/gic-its.c >> +++ b/xen/arch/arm/gic-its.c >> @@ -228,6 +228,18 @@ static int its_send_cmd_inv(struct host_its *its, >> return its_send_command(its, cmd); >> } >> >> +static int its_send_cmd_invall(struct host_its *its, int cpu) >> +{ >> + uint64_t cmd[4]; >> + >> + cmd[0] = GITS_CMD_INVALL; >> + cmd[1] = 0x00; >> + cmd[2] = cpu & GENMASK(15, 0); >> + cmd[3] = 0x00; >> + >> + return its_send_command(its, cmd); >> +} >> + >> int gicv3_its_map_device(struct host_its *hw_its, struct domain *d, >> int devid, int bits, bool valid) >> { >> @@ -668,6 +680,52 @@ uint32_t gicv3_lpi_lookup_lpi(struct domain *d, >> uint32_t host_lpi, int *vcpu_id) >> return hlpi.virt_lpi; >> } >> >> +/* Iterate over all host LPIs, and updating the "enabled" state for a given >> + * guest redistributor (VCPU) given the respective state in the provided >> + * proptable. This proptable is indexed by the stored virtual LPI number. >> + * This is to implement a guest INVALL command. >> + */ >> +void gicv3_lpi_update_configurations(struct vcpu *v, uint8_t *proptable) >> +{ >> + int chunk, i; >> + struct host_its *its; >> + >> + for (chunk = 0; chunk < MAX_HOST_LPIS / HOST_LPIS_PER_PAGE; chunk++) >> + { >> + if ( !lpi_data.host_lpis[chunk] ) >> + continue; >> + >> + for (i = 0; i < HOST_LPIS_PER_PAGE; i++) >> + { >> + union host_lpi *hlpip = &lpi_data.host_lpis[chunk][i], hlpi; >> + uint32_t hlpi_nr; >> + >> + hlpi.data = hlpip->data; >> + if ( !hlpi.virt_lpi ) >> + continue; >> + >> + if ( hlpi.dom_id != v->domain->domain_id ) >> + continue; >> + >> + if ( hlpi.vcpu_id != v->vcpu_id ) >> + continue; >> + >> + hlpi_nr = chunk * HOST_LPIS_PER_PAGE + i; >> + >> + if ( proptable[hlpi.virt_lpi] & LPI_PROP_ENABLED ) >> + lpi_data.lpi_property[hlpi_nr - 8192] |= LPI_PROP_ENABLED; >> + else >> + lpi_data.lpi_property[hlpi_nr - 8192] &= ~LPI_PROP_ENABLED; >> + } >> + } > AFAIK, the initial design is to use tasklet to update property > table as it consumes > lot of time to update the table. This is a possible, but premature optimization. Linux (at the moment, at least) only calls INVALL _once_, just after initialising the collections. And at this point no LPI is mapped, so the whole routine does basically nothing - and that quite fast. We can later have any kind of fancy algorithm if there is a need for. Cheers, Andre. >> + >> + /* Tell all ITSes that they should update the property table for CPU 0, >> + * which is where we map all LPIs to. >> + */ >> + list_for_each_entry(its, &host_its_list, entry) >> + its_send_cmd_invall(its, 0); >> +} >> + >> void gicv3_lpi_set_enable(struct host_its *its, >> uint32_t deviceid, uint32_t eventid, >> uint32_t host_lpi, bool enabled) >> diff --git a/xen/arch/arm/vgic-its.c b/xen/arch/arm/vgic-its.c >> index 74da8fc..1e429b7 100644 >> --- a/xen/arch/arm/vgic-its.c >> +++ b/xen/arch/arm/vgic-its.c >> @@ -294,6 +294,33 @@ out_unlock: >> return ret; >> } >> >> +/* INVALL updates the per-LPI configuration status for every LPI mapped to >> + * this redistributor. For the guest side we don't need to update anything, >> + * as we always refer to the actual table for the enabled bit and the >> + * priority. >> + * Enabling or disabling a virtual LPI however needs to be propagated to >> + * the respective host LPI. Instead of iterating over all mapped LPIs in our >> + * emulated GIC (which is expensive due to the required on-demand mapping), >> + * we iterate over all mapped _host_ LPIs and filter for those which are >> + * forwarded to this virtual redistributor. >> + */ >> +static int its_handle_invall(struct virt_its *its, uint64_t *cmdptr) >> +{ >> + uint32_t collid = its_cmd_get_collection(cmdptr); >> + struct vcpu *vcpu; >> + >> + spin_lock(&its->its_lock); >> + vcpu = get_vcpu_from_collection(its, collid); >> + spin_unlock(&its->its_lock); >> + >> + if ( !vcpu ) >> + return -1; >> + >> + gicv3_lpi_update_configurations(vcpu, its->d->arch.vgic.proptable); >> + >> + return 0; >> +} >> + >> static int its_handle_mapc(struct virt_its *its, uint64_t *cmdptr) >> { >> uint32_t collid = its_cmd_get_collection(cmdptr); >> @@ -515,6 +542,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct >> virt_its *its, >> case GITS_CMD_INV: >> its_handle_inv(its, cmdptr); >> break; >> + case GITS_CMD_INVALL: >> + its_handle_invall(its, cmdptr); >> + break; >> case GITS_CMD_MAPC: >> its_handle_mapc(its, cmdptr); >> break; >> diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h >> index 2cdb3e1..ba6b2d5 100644 >> --- a/xen/include/asm-arm/gic-its.h >> +++ b/xen/include/asm-arm/gic-its.h >> @@ -146,6 +146,8 @@ int gicv3_lpi_drop_host_lpi(struct host_its *its, >> uint32_t devid, uint32_t eventid, >> uint32_t host_lpi); >> >> +void gicv3_lpi_update_configurations(struct vcpu *v, uint8_t *proptable); >> + >> static inline int gicv3_lpi_get_priority(struct domain *d, uint32_t lpi) >> { >> return d->arch.vgic.proptable[lpi - 8192] & 0xfc; >> -- >> 2.9.0 >> >> >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@xxxxxxxxxxxxx >> https://lists.xen.org/xen-devel > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |