summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '0020-x86-ioapic-RTE-modifications-must-use-ioapic_write_e.patch')
-rw-r--r--0020-x86-ioapic-RTE-modifications-must-use-ioapic_write_e.patch180
1 files changed, 180 insertions, 0 deletions
diff --git a/0020-x86-ioapic-RTE-modifications-must-use-ioapic_write_e.patch b/0020-x86-ioapic-RTE-modifications-must-use-ioapic_write_e.patch
new file mode 100644
index 0000000..43faeeb
--- /dev/null
+++ b/0020-x86-ioapic-RTE-modifications-must-use-ioapic_write_e.patch
@@ -0,0 +1,180 @@
+From 1bd4523d696d26976f64a919df8c7a1b3ea32f6f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com>
+Date: Tue, 5 Sep 2023 08:49:37 +0200
+Subject: [PATCH 20/55] x86/ioapic: RTE modifications must use
+ ioapic_write_entry
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Do not allow to write to RTE registers using io_apic_write and instead
+require changes to RTE to be performed using ioapic_write_entry.
+
+This is in preparation for passing the full contents of the RTE to the
+IOMMU interrupt remapping handlers, so remapping entries for IO-APIC
+RTEs can be updated atomically when possible.
+
+While immediately this commit might expand the number of MMIO accesses
+in order to update an IO-APIC RTE, further changes will benefit from
+getting the full RTE value passed to the IOMMU handlers, as the logic
+is greatly simplified when the IOMMU handlers can get the complete RTE
+value in one go.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+master commit: ef7995ed1bcd7eac37fb3c3fe56eaa54ea9baf6c
+master date: 2023-07-28 09:40:20 +0200
+---
+ xen/arch/x86/include/asm/io_apic.h | 8 ++---
+ xen/arch/x86/io_apic.c | 43 ++++++++++++------------
+ xen/drivers/passthrough/amd/iommu_intr.c | 6 ----
+ 3 files changed, 25 insertions(+), 32 deletions(-)
+
+diff --git a/xen/arch/x86/include/asm/io_apic.h b/xen/arch/x86/include/asm/io_apic.h
+index a558bb063c..6b514b4e3d 100644
+--- a/xen/arch/x86/include/asm/io_apic.h
++++ b/xen/arch/x86/include/asm/io_apic.h
+@@ -161,8 +161,8 @@ static inline void __io_apic_write(unsigned int apic, unsigned int reg, unsigned
+
+ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+ {
+- if ( ioapic_reg_remapped(reg) )
+- return iommu_update_ire_from_apic(apic, reg, value);
++ /* RTE writes must use ioapic_write_entry. */
++ BUG_ON(reg >= 0x10);
+ __io_apic_write(apic, reg, value);
+ }
+
+@@ -172,8 +172,8 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
+ */
+ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+ {
+- if ( ioapic_reg_remapped(reg) )
+- return iommu_update_ire_from_apic(apic, reg, value);
++ /* RTE writes must use ioapic_write_entry. */
++ BUG_ON(reg >= 0x10);
+ *(IO_APIC_BASE(apic) + 4) = value;
+ }
+
+diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
+index aada2ef96c..041233b9b7 100644
+--- a/xen/arch/x86/io_apic.c
++++ b/xen/arch/x86/io_apic.c
+@@ -237,15 +237,15 @@ struct IO_APIC_route_entry __ioapic_read_entry(
+ {
+ union entry_union eu;
+
+- if ( raw )
++ if ( raw || !iommu_intremap )
+ {
+ eu.w1 = __io_apic_read(apic, 0x10 + 2 * pin);
+ eu.w2 = __io_apic_read(apic, 0x11 + 2 * pin);
+ }
+ else
+ {
+- eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+- eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
++ eu.w1 = iommu_read_apic_from_ire(apic, 0x10 + 2 * pin);
++ eu.w2 = iommu_read_apic_from_ire(apic, 0x11 + 2 * pin);
+ }
+
+ return eu.entry;
+@@ -269,15 +269,15 @@ void __ioapic_write_entry(
+ {
+ union entry_union eu = { .entry = e };
+
+- if ( raw )
++ if ( raw || !iommu_intremap )
+ {
+ __io_apic_write(apic, 0x11 + 2 * pin, eu.w2);
+ __io_apic_write(apic, 0x10 + 2 * pin, eu.w1);
+ }
+ else
+ {
+- io_apic_write(apic, 0x11 + 2 * pin, eu.w2);
+- io_apic_write(apic, 0x10 + 2 * pin, eu.w1);
++ iommu_update_ire_from_apic(apic, 0x11 + 2 * pin, eu.w2);
++ iommu_update_ire_from_apic(apic, 0x10 + 2 * pin, eu.w1);
+ }
+ }
+
+@@ -433,16 +433,17 @@ static void modify_IO_APIC_irq(unsigned int irq, unsigned int enable,
+ unsigned int disable)
+ {
+ struct irq_pin_list *entry = irq_2_pin + irq;
+- unsigned int pin, reg;
+
+ for (;;) {
+- pin = entry->pin;
++ unsigned int pin = entry->pin;
++ struct IO_APIC_route_entry rte;
++
+ if (pin == -1)
+ break;
+- reg = io_apic_read(entry->apic, 0x10 + pin*2);
+- reg &= ~disable;
+- reg |= enable;
+- io_apic_modify(entry->apic, 0x10 + pin*2, reg);
++ rte = __ioapic_read_entry(entry->apic, pin, false);
++ rte.raw &= ~(uint64_t)disable;
++ rte.raw |= enable;
++ __ioapic_write_entry(entry->apic, pin, false, rte);
+ if (!entry->next)
+ break;
+ entry = irq_2_pin + entry->next;
+@@ -584,16 +585,16 @@ set_ioapic_affinity_irq(struct irq_desc *desc, const cpumask_t *mask)
+ dest = SET_APIC_LOGICAL_ID(dest);
+ entry = irq_2_pin + irq;
+ for (;;) {
+- unsigned int data;
++ struct IO_APIC_route_entry rte;
++
+ pin = entry->pin;
+ if (pin == -1)
+ break;
+
+- io_apic_write(entry->apic, 0x10 + 1 + pin*2, dest);
+- data = io_apic_read(entry->apic, 0x10 + pin*2);
+- data &= ~IO_APIC_REDIR_VECTOR_MASK;
+- data |= MASK_INSR(desc->arch.vector, IO_APIC_REDIR_VECTOR_MASK);
+- io_apic_modify(entry->apic, 0x10 + pin*2, data);
++ rte = __ioapic_read_entry(entry->apic, pin, false);
++ rte.dest.dest32 = dest;
++ rte.vector = desc->arch.vector;
++ __ioapic_write_entry(entry->apic, pin, false, rte);
+
+ if (!entry->next)
+ break;
+@@ -2127,10 +2128,8 @@ void ioapic_resume(void)
+ reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
+ __io_apic_write(apic, 0, reg_00.raw);
+ }
+- for (i = 0; i < nr_ioapic_entries[apic]; i++, entry++) {
+- __io_apic_write(apic, 0x11+2*i, *(((int *)entry)+1));
+- __io_apic_write(apic, 0x10+2*i, *(((int *)entry)+0));
+- }
++ for (i = 0; i < nr_ioapic_entries[apic]; i++, entry++)
++ __ioapic_write_entry(apic, i, true, *entry);
+ }
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c
+index 9e6be3be35..f32c418a7e 100644
+--- a/xen/drivers/passthrough/amd/iommu_intr.c
++++ b/xen/drivers/passthrough/amd/iommu_intr.c
+@@ -361,12 +361,6 @@ void cf_check amd_iommu_ioapic_update_ire(
+ struct amd_iommu *iommu;
+ unsigned int idx;
+
+- if ( !iommu_intremap )
+- {
+- __io_apic_write(apic, reg, value);
+- return;
+- }
+-
+ idx = ioapic_id_to_index(IO_APIC_ID(apic));
+ if ( idx == MAX_IO_APICS )
+ return;
+--
+2.42.0
+