[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 20/27] ARM: vITS: handle MAPTI command
Hi, On 24/03/17 14:54, Julien Grall wrote: > Hi Andre, > > On 03/16/2017 11:20 AM, Andre Przywara wrote: >> The MAPTI commands associates a DeviceID/EventID pair with a LPI/CPU >> pair and actually instantiates LPI interrupts. >> We connect the already allocated host LPI to this virtual LPI, so that >> any triggering IRQ on the host can be quickly forwarded to a guest. >> >> Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> >> --- >> xen/arch/arm/gic-v3-its.c | 63 >> ++++++++++++++++++++++++++++++++++++++++ >> xen/arch/arm/gic-v3-lpi.c | 18 ++++++++++++ >> xen/arch/arm/vgic-v3-its.c | 27 +++++++++++++++-- >> xen/include/asm-arm/gic_v3_its.h | 6 ++++ >> 4 files changed, 112 insertions(+), 2 deletions(-) >> >> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c >> index 5a2dbec..e2fcf50 100644 >> --- a/xen/arch/arm/gic-v3-its.c >> +++ b/xen/arch/arm/gic-v3-its.c >> @@ -724,6 +724,69 @@ restart: >> spin_unlock(&d->arch.vgic.its_devices_lock); >> } >> >> +/* >> + * Translates an event for a given guest device ID into the >> associated host >> + * LPI number. This can be used to look up the mapped guest LPI. >> + */ >> +static uint32_t translate_event(struct domain *d, paddr_t doorbell, >> + uint32_t devid, uint32_t eventid) >> +{ >> + struct rb_node *node; >> + struct its_devices *dev; >> + uint32_t host_lpi = 0; >> + int cmp; >> + >> + spin_lock(&d->arch.vgic.its_devices_lock); >> + node = d->arch.vgic.its_devices.rb_node; >> + while (node) >> + { >> + dev = rb_entry(node, struct its_devices, rbnode); >> + cmp = compare_its_guest_devices(dev, doorbell, devid); >> + >> + if ( !cmp ) >> + { >> + if ( eventid >= dev->eventids ) >> + goto out; >> + >> + host_lpi = dev->host_lpis[eventid / LPI_BLOCK] + >> + (eventid % LPI_BLOCK); >> + if ( !is_lpi(host_lpi) ) > > Hmmm, I don't understand this check. host_lpi should always be an LPI. No? Looks like. Dropped in v4. >> + host_lpi = 0; >> + goto out; >> + } >> + >> + if ( cmp > 0 ) >> + node = node->rb_left; >> + else >> + node = node->rb_right; >> + } >> + >> +out: >> + spin_unlock(&d->arch.vgic.its_devices_lock); >> + >> + return host_lpi; >> +} >> + >> +/* >> + * Connects the event ID for an already assigned device to the given >> VCPU/vLPI >> + * pair. The corresponding physical LPI is already mapped on the host >> side >> + * (when assigning the physical device to the guest), so we just >> connect the >> + * target VCPU/vLPI pair to that interrupt to inject it properly if >> it fires. >> + */ >> +int gicv3_assign_guest_event(struct domain *d, paddr_t doorbell_address, >> + uint32_t devid, uint32_t eventid, > > It looks like to me that devid is the virtual deviceID. If so, please > prefix with 'v', otherwise 'p'. Fixed in v4. >> + struct vcpu *v, uint32_t virt_lpi) >> +{ >> + uint32_t host_lpi = translate_event(d, doorbell_address, devid, >> eventid); >> + >> + if ( !host_lpi ) >> + return -ENOENT; >> + >> + gicv3_lpi_update_host_entry(host_lpi, d->domain_id, v->vcpu_id, >> virt_lpi); >> + >> + return 0; >> +} >> + >> /* Scan the DT for any ITS nodes and create a list of host ITSes out >> of it. */ >> void gicv3_its_dt_init(const struct dt_device_node *node) >> { >> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c >> index 994698e..c110ec9 100644 >> --- a/xen/arch/arm/gic-v3-lpi.c >> +++ b/xen/arch/arm/gic-v3-lpi.c >> @@ -153,6 +153,24 @@ void do_LPI(unsigned int lpi) >> vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi); >> } >> >> +int gicv3_lpi_update_host_entry(uint32_t host_lpi, int domain_id, >> + unsigned int vcpu_id, uint32_t virt_lpi) >> +{ >> + union host_lpi *hlpip, hlpi; >> + >> + host_lpi -= LPI_OFFSET; > > I would add an ASSERT(host_lpi > LPI_OFFSET); Fixed in v4. >> + >> + hlpip = &lpi_data.host_lpis[host_lpi / >> HOST_LPIS_PER_PAGE][host_lpi % HOST_LPIS_PER_PAGE]; >> + >> + hlpi.virt_lpi = virt_lpi; >> + hlpi.dom_id = domain_id; >> + hlpi.vcpu_id = vcpu_id; >> + >> + write_u64_atomic(&hlpip->data, hlpi.data); >> + >> + return 0; >> +} >> + >> static int gicv3_lpi_allocate_pendtable(uint64_t *reg) >> { >> uint64_t val; >> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c >> index c26d5d4..600ff69 100644 >> --- a/xen/arch/arm/vgic-v3-its.c >> +++ b/xen/arch/arm/vgic-v3-its.c >> @@ -167,8 +167,8 @@ static bool read_itte(struct virt_its *its, >> uint32_t devid, uint32_t evid, >> } >> >> #define SKIP_LPI_UPDATE 1 >> -bool write_itte(struct virt_its *its, uint32_t devid, uint32_t evid, >> - uint32_t collid, uint32_t vlpi, struct vcpu **vcpu) >> +static bool write_itte(struct virt_its *its, uint32_t devid, uint32_t >> evid, >> + uint32_t collid, uint32_t vlpi, struct vcpu >> **vcpu) > > Please explain in the commit message why you move to static. Fixed in v4. > >> { >> struct vits_itte *itte; >> >> @@ -332,6 +332,25 @@ static int its_handle_mapd(struct virt_its *its, >> uint64_t *cmdptr) >> return 0; >> } >> >> +static int its_handle_mapti(struct virt_its *its, uint64_t *cmdptr) >> +{ >> + uint32_t devid = its_cmd_get_deviceid(cmdptr); >> + uint32_t eventid = its_cmd_get_id(cmdptr); >> + uint32_t intid = its_cmd_get_physical_id(cmdptr); >> + int collid = its_cmd_get_collection(cmdptr); > > This should be unsigned. Fixed in v4. >> + struct vcpu *vcpu; >> + >> + if ( its_cmd_get_command(cmdptr) == GITS_CMD_MAPI ) >> + intid = eventid; >> + >> + if ( !write_itte(its, devid, eventid, collid, intid, &vcpu) ) >> + return -1; >> + >> + gicv3_assign_guest_event(its->d, its->doorbell_address, devid, >> eventid, vcpu, intid); > > If you have a function returning an error, then you should check it and > not ignoring it. Fixed in v3. Cheers, Andre. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |