[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 1/4] iommu/amd: support all delivery modes with x2APIC


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Roger Pau Monne <roger.pau@xxxxxxxxxx>
  • Date: Tue, 15 Oct 2019 17:47:33 +0200
  • Authentication-results: esa4.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=roger.pau@xxxxxxxxxx; spf=Pass smtp.mailfrom=roger.pau@xxxxxxxxxx; spf=None smtp.helo=postmaster@xxxxxxxxxxxxxxx
  • Cc: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>, Roger Pau Monne <roger.pau@xxxxxxxxxx>
  • Delivery-date: Tue, 15 Oct 2019 15:48:19 +0000
  • Ironport-sdr: wrQomBz/zHLFiiS7yWU5fdNAcYQhXSOKyFc1JwAer1Y0x/Cudn81VwNghOURdnj2jQGcbstH2Q GesNS7O97yMlxIGRL+nRjs4exnBRQmvB+zJeE796G+yJ6ktHcN3LthSpYqUQYPRVbOH+bostkd Q9zTgPJxsKiDr+AV5Tt9KOjb2Kce91MQOAYoA4YPZvtUjfwHFNLRX0Zwiupnt2lmYfKQcOuqdD tuaoEs6+f51kOLNqeENDoBmRTIZVSbe+k2Vsi82Hrwhvy+Rxg3VXP3rMBCFA3wWzjcszbffzzt wtU=
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Current AMD IOMMU code will attempt to create remapping entries for
all IO-APIC pins, regardless of the delivery mode. AMD IOMMU
implementation doesn't support remapping entries for IO-APIC pins with
delivery mode set to SMI, MNI, INIT or ExtINT, instead those entries
are not translated provided the right bits are set in the device table
entry.

This change checks whether the device table entry has the correct bits
set in order to delivery the requested interrupt or a warning message
is printed. It also translates the 32bit destination field into a
physical or logical IO-APIC entry format. Note that if the 32bit
destination cannot fit into the legacy format a message is printed and
the entry is masked.

Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
My AMD hardware doesn't have any of such entries, hence I've only been
able to compile test this change and assert it doesn't affect the
functionality of other interrupt delivery modes.
---
 xen/drivers/passthrough/amd/iommu_intr.c | 81 ++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/xen/drivers/passthrough/amd/iommu_intr.c 
b/xen/drivers/passthrough/amd/iommu_intr.c
index fb71073c84..02dd3737c7 100644
--- a/xen/drivers/passthrough/amd/iommu_intr.c
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
@@ -439,6 +439,80 @@ int __init amd_iommu_setup_ioapic_remapping(void)
     return 0;
 }
 
+void setup_forced_ioapic_rte(unsigned int apic, unsigned int pin,
+                             struct amd_iommu *iommu,
+                             struct IO_APIC_route_entry *rte)
+{
+    unsigned int idx = ioapic_id_to_index(IO_APIC_ID(apic));
+    struct amd_iommu_dte *table = iommu->dev_table.buffer;
+    unsigned int req_id, dest, offset;
+    union irte_ptr entry;
+
+    ASSERT(x2apic_enabled);
+
+    if ( idx == MAX_IO_APICS )
+    {
+        rte->mask = true;
+        return;
+    }
+
+    req_id = get_intremap_requestor_id(ioapic_sbdf[idx].seg,
+                                       ioapic_sbdf[idx].bdf);
+
+    switch ( rte->delivery_mode )
+    {
+    case dest_SMI:
+        break;
+
+#define DEL_CHECK(type, dte_field)                                      \
+    case dest_ ## type:                                                 \
+        if ( !table[req_id].dte_field )                                 \
+            printk(XENLOG_WARNING                                       \
+                   STR(type) " on IO-APIC %u pin %u will be aborted\n", \
+                   apic, pin);                                          \
+        break;
+
+    DEL_CHECK(NMI, nmi_pass);
+    DEL_CHECK(INIT, init_pass);
+    DEL_CHECK(ExtINT, ext_int_pass);
+#undef DEL_CHECK
+
+    default:
+        ASSERT_UNREACHABLE();
+        return;
+    }
+
+    offset = ioapic_sbdf[idx].pin_2_idx[pin];
+    if ( offset >= INTREMAP_MAX_ENTRIES )
+    {
+        rte->mask = true;
+        return;
+    }
+
+    entry = get_intremap_entry(iommu, req_id, offset);
+    dest = get_full_dest(entry.ptr128);
+
+#define SET_DEST(name, dest_mask) {                                            
\
+    if ( dest & ~(dest_mask) )                                                 
\
+    {                                                                          
\
+        printk(XENLOG_WARNING                                                  
\
+               "IO-APIC %u pin %u " STR(name) " destination (%x) > %x\n",      
\
+               apic, pin, dest, dest_mask);                                    
\
+        rte->mask = true;                                                      
\
+        return;                                                                
\
+    }                                                                          
\
+    rte->dest.name.name ## _dest = dest;                                       
\
+}
+
+    if ( rte->dest_mode )
+        SET_DEST(physical, 0xf)
+    else
+        SET_DEST(logical, 0xff)
+#undef SET_DEST
+
+    return;
+}
+
 void amd_iommu_ioapic_update_ire(
     unsigned int apic, unsigned int reg, unsigned int value)
 {
@@ -482,6 +556,13 @@ void amd_iommu_ioapic_update_ire(
         *((u32 *)&new_rte) = value;
         /* read upper 32 bits from io-apic rte */
         *(((u32 *)&new_rte) + 1) = __io_apic_read(apic, reg + 1);
+
+        if ( new_rte.delivery_mode > 1 && x2apic_enabled )
+        {
+            setup_forced_ioapic_rte(apic, pin, iommu, &new_rte);
+            __ioapic_write_entry(apic, pin, true, new_rte);
+            return;
+        }
     }
     else
     {
-- 
2.23.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.