|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH RFC 6/6] x86/ioapic: mask entry while updating
When writing an IO-APIC RTE entry make sure incoming interrupts never
see a partially updated entry, by masking the pin while doing the
update when necessary. Add some logic to attempt to limit the number
of writes.
With the masking now handled by __ioapic_write_entry itself when
necessary, we can drop the setting of the disable hook for IO-APIC
edge triggered interrupts.
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
Note this includes a revert of the first patch in the series.
---
xen/arch/x86/io_apic.c | 45 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index f61e56f3d1..1860af7353 100644
--- 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);
+ }
}
else
iommu_update_ire_from_apic(apic, pin, e.raw);
@@ -1780,7 +1815,7 @@ static hw_irq_controller ioapic_edge_type = {
.startup = startup_edge_ioapic_irq,
.shutdown = irq_shutdown_none,
.enable = unmask_IO_APIC_irq,
- .disable = mask_IO_APIC_irq,
+ .disable = irq_disable_none,
.ack = ack_edge_ioapic_irq,
.set_affinity = set_ioapic_affinity_irq,
};
--
2.35.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |