|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 4/4] x86/iommu: pass full IO-APIC RTE for remapping table update
On 26.07.2023 14:55, Roger Pau Monne wrote:
> --- a/xen/drivers/passthrough/vtd/extern.h
> +++ b/xen/drivers/passthrough/vtd/extern.h
> @@ -92,7 +92,7 @@ int cf_check intel_iommu_get_reserved_device_memory(
> unsigned int cf_check io_apic_read_remap_rte(
> unsigned int apic, unsigned int reg);
> void cf_check io_apic_write_remap_rte(
> - unsigned int apic, unsigned int reg, unsigned int value);
> + unsigned int apic, unsigned int ioapic_pin, uint64_t rte);
Forgot to rename the middle parameter to "pin"?
> @@ -364,48 +363,40 @@ static int ioapic_rte_to_remap_entry(struct vtd_iommu
> *iommu,
>
> new_ire = *iremap_entry;
>
> - if ( rte_upper )
> - {
> - if ( x2apic_enabled )
> - new_ire.remap.dst = value;
> - else
> - new_ire.remap.dst = (value >> 24) << 8;
> - }
> + if ( x2apic_enabled )
> + new_ire.remap.dst = new_rte.dest.dest32;
> else
> - {
> - *(((u32 *)&new_rte) + 0) = value;
> - new_ire.remap.fpd = 0;
> - new_ire.remap.dm = new_rte.dest_mode;
> - new_ire.remap.tm = new_rte.trigger;
> - new_ire.remap.dlm = new_rte.delivery_mode;
> - /* Hardware require RH = 1 for LPR delivery mode */
> - new_ire.remap.rh = (new_ire.remap.dlm == dest_LowestPrio);
> - new_ire.remap.avail = 0;
> - new_ire.remap.res_1 = 0;
> - new_ire.remap.vector = new_rte.vector;
> - new_ire.remap.res_2 = 0;
> -
> - set_ioapic_source_id(IO_APIC_ID(apic), &new_ire);
> - new_ire.remap.res_3 = 0;
> - new_ire.remap.res_4 = 0;
> - new_ire.remap.p = 1; /* finally, set present bit */
> -
> - /* now construct new ioapic rte entry */
> - remap_rte->vector = new_rte.vector;
> - remap_rte->delivery_mode = 0; /* has to be 0 for remap format */
> - remap_rte->index_15 = (index >> 15) & 0x1;
> - remap_rte->index_0_14 = index & 0x7fff;
> -
> - remap_rte->delivery_status = new_rte.delivery_status;
> - remap_rte->polarity = new_rte.polarity;
> - remap_rte->irr = new_rte.irr;
> - remap_rte->trigger = new_rte.trigger;
> - remap_rte->mask = new_rte.mask;
> - remap_rte->reserved = 0;
> - remap_rte->format = 1; /* indicate remap format */
> - }
> -
> - update_irte(iommu, iremap_entry, &new_ire, !init);
> + new_ire.remap.dst = (new_rte.dest.dest32 >> 24) << 8;
I realize this was this way before, but I wonder if we couldn't use
GET_xAPIC_ID() here to reduce the open-coding at least a bit.
> @@ -439,36 +430,45 @@ unsigned int cf_check io_apic_read_remap_rte(
> }
>
> void cf_check io_apic_write_remap_rte(
> - unsigned int apic, unsigned int reg, unsigned int value)
> + unsigned int apic, unsigned int pin, uint64_t rte)
> {
> - unsigned int pin = (reg - 0x10) / 2;
> + struct IO_xAPIC_route_entry new_rte = { .raw = rte };
> struct IO_xAPIC_route_entry old_rte = { };
> - struct IO_APIC_route_remap_entry *remap_rte;
> - unsigned int rte_upper = (reg & 1) ? 1 : 0;
> struct vtd_iommu *iommu = ioapic_to_iommu(IO_APIC_ID(apic));
> - int saved_mask;
> -
> - old_rte = __ioapic_read_entry(apic, pin, true);
> + bool masked = true;
> + int rc;
>
> - remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;
> -
> - /* mask the interrupt while we change the intremap table */
> - saved_mask = remap_rte->mask;
> - remap_rte->mask = 1;
> - __io_apic_write(apic, reg & ~1, *(u32 *)&old_rte);
> - remap_rte->mask = saved_mask;
> -
> - if ( ioapic_rte_to_remap_entry(iommu, apic, pin,
> - &old_rte, rte_upper, value) )
> + if ( !cpu_has_cx16 )
> {
> - __io_apic_write(apic, reg, value);
> + /*
> + * Cannot atomically update the IRTE entry: mask the IO-APIC pin to
> + * avoid interrupts seeing an inconsistent IRTE entry.
> + */
> + old_rte = __ioapic_read_entry(apic, pin, true);
> + if ( !old_rte.mask )
> + {
> + masked = false;
> + old_rte.mask = 1;
> + __ioapic_write_entry(apic, pin, true, old_rte);
> + }
> + }
>
> - /* Recover the original value of 'mask' bit */
> - if ( rte_upper )
> - __io_apic_write(apic, reg & ~1, *(u32 *)&old_rte);
> + rc = ioapic_rte_to_remap_entry(iommu, apic, pin, &old_rte, new_rte);
> + if ( rc )
> + {
> + if ( !masked )
> + {
> + /* Recover the original value of 'mask' bit */
> + old_rte.mask = 0;
> + __ioapic_write_entry(apic, pin, true, old_rte);
> + }
> + dprintk(XENLOG_ERR VTDPREFIX,
> + "failed to update IRTE for IO-APIC#%u pin %u: %d\n",
> + apic, pin, rc);
Afaics you don't alter the error behavior of ioapic_rte_to_remap_entry(),
and in the sole (pre-existing) case of an error a debug log message is
already being issued. Why the addition?
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |