[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH RFC 6/6] x86/ioapic: mask entry while updating
On 21.04.2022 15:21, Roger Pau Monne wrote: > --- a/xen/arch/x86/io_apic.c > +++ b/xen/arch/x86/io_apic.c > @@ -267,12 +267,47 @@ void __ioapic_write_entry( > unsigned int apic, unsigned int pin, bool raw, > struct IO_APIC_route_entry e) > { > - union entry_union eu = { .entry = e }; > - > if ( raw || !iommu_intremap ) > { > - __io_apic_write(apic, 0x11 + 2 * pin, eu.w2); > - __io_apic_write(apic, 0x10 + 2 * pin, eu.w1); > + union entry_union eu = { .entry = e }; > + union entry_union curr = { > + .entry = __ioapic_read_entry(apic, pin, true), > + }; > + bool masked = true; > + > + if ( curr.entry.mask ) > + { > + /* > + * If pin is currently masked we can update the high part first > + * without worrying about the RTE being in an inconsistent state. > + */ > + if ( curr.w2 != eu.w2 ) > + __io_apic_write(apic, 0x11 + 2 * pin, eu.w2); > + if ( curr.w1 != eu.w1 ) > + __io_apic_write(apic, 0x10 + 2 * pin, eu.w1); > + return; > + } > + > + if ( curr.w1 != eu.w1 && curr.w2 != eu.w2 && !eu.entry.mask ) > + { > + /* > + * If updating both halves mask the entry while updating so > + * interrupts are not injected with an inconsistent RTE. > + */ > + eu.entry.mask = 1; > + masked = false; > + } > + > + if ( curr.w1 != eu.w1 ) > + __io_apic_write(apic, 0x10 + 2 * pin, eu.w1); > + if ( curr.w2 != eu.w2 ) > + __io_apic_write(apic, 0x11 + 2 * pin, eu.w2); > + > + if ( !masked ) > + { > + eu.entry.mask = 0; > + __io_apic_write(apic, 0x10 + 2 * pin, eu.w1); > + } For the write avoidance don't you want to hide differences in the r/o delivery_status field, e.g. by setting curr's to eu's after having read curr? Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |