All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Wang2 <wei.wang2@amd.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH] AMD IOMMU: Fix a xen crash on amd iommu systems
Date: Wed, 16 Dec 2009 16:54:03 +0100	[thread overview]
Message-ID: <200912161654.03752.wei.wang2@amd.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 527 bytes --]

(the correct attachment)

Changeset 20514 implemented deallocation for msi interrupt remapping entries.
Attached patch adds the same support for amd iommu to fix a xen crash on amd 
iommu systems.
Thanks,
Wei
Signed-off-by: Wei Wang <wei.wang2@amd.com>
--
Legal Information:
Advanced Micro Devices GmbH
Karl-Hammerschmidt-Str. 34
85609 Dornach b. München

Geschäftsführer: Andrew Bowd, Thomas M. McCoy, Giuliano Meroni
Sitz: Dornach, Gemeinde Aschheim, Landkreis München
Registergericht München, HRB Nr. 43632

[-- Attachment #2: fix_msi.patch --]
[-- Type: text/x-diff, Size: 6214 bytes --]

diff -r 1e9441f4dcbd xen/drivers/passthrough/amd/iommu_intr.c
--- a/xen/drivers/passthrough/amd/iommu_intr.c	Mon Dec 14 11:58:45 2009 +0000
+++ b/xen/drivers/passthrough/amd/iommu_intr.c	Wed Dec 16 15:49:31 2009 +0100
@@ -23,6 +23,9 @@
 #include <asm/hvm/svm/amd-iommu-proto.h>
 
 #define INTREMAP_TABLE_ORDER    1
+#define INTREMAP_LENGTH 0xB
+#define INTREMAP_ENTRIES (1 << INTREMAP_LENGTH)
+
 int ioapic_bdf[MAX_IO_APICS];
 extern struct ivrs_mappings *ivrs_mappings;
 extern unsigned short ivrs_bdf_entries;
@@ -42,19 +45,30 @@ static int get_intremap_requestor_id(int
     return ivrs_mappings[bdf].dte_requestor_id;
 }
 
-static u8 *get_intremap_entry(int bdf, u8 vector, u8 dm)
-{
-    u8 *table;
+static int get_intremap_offset(u8 vector, u8 dm)
+{
     int offset = 0;
-
-    table = (u8*)ivrs_mappings[bdf].intremap_table;
-    ASSERT( table != NULL );
-
     offset = (dm << INT_REMAP_INDEX_DM_SHIFT) & INT_REMAP_INDEX_DM_MASK;
     offset |= (vector << INT_REMAP_INDEX_VECTOR_SHIFT ) & 
         INT_REMAP_INDEX_VECTOR_MASK;
+    return offset;
+}
+
+static u8 *get_intremap_entry(int bdf, int offset)
+{
+    u8 *table;
+
+    table = (u8*)ivrs_mappings[bdf].intremap_table;
+    ASSERT( (table != NULL) && (offset < INTREMAP_ENTRIES) );
 
     return (u8*) (table + offset);
+}
+
+static void free_intremap_entry(int bdf, int offset)
+{
+    u32* entry;
+    entry = (u32*)get_intremap_entry(bdf, offset);
+    memset(entry, 0, sizeof(u32));
 }
 
 static void update_intremap_entry(u32* entry, u8 vector, u8 int_type,
@@ -111,6 +125,7 @@ static void update_intremap_entry_from_i
     struct IO_APIC_route_entry *rte = ioapic_rte;
     int req_id;
     spinlock_t *lock;
+    int offset;
 
     req_id = get_intremap_requestor_id(bdf);
     lock = get_intremap_lock(req_id);
@@ -123,11 +138,13 @@ static void update_intremap_entry_from_i
         dest = rte->dest.logical.logical_dest;
 
         spin_lock_irqsave(lock, flags);
-        entry = (u32*)get_intremap_entry(req_id, vector, delivery_mode);
+        offset = get_intremap_offset(vector, delivery_mode);
+        entry = (u32*)get_intremap_entry(req_id, offset);
+
         update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
         spin_unlock_irqrestore(lock, flags);
 
-       if ( iommu->enabled )
+        if ( iommu->enabled )
         {
             spin_lock_irqsave(&iommu->lock, flags);
             invalidate_interrupt_table(iommu, req_id);
@@ -147,6 +164,7 @@ int __init amd_iommu_setup_ioapic_remapp
     u16 bdf, req_id;
     struct amd_iommu *iommu;
     spinlock_t *lock;
+    int offset;
 
     /* Read ioapic entries and update interrupt remapping table accordingly */
     for ( apic = 0; apic < nr_ioapics; apic++ )
@@ -178,7 +196,8 @@ int __init amd_iommu_setup_ioapic_remapp
             dest = rte.dest.logical.logical_dest;
 
             spin_lock_irqsave(lock, flags);
-            entry = (u32*)get_intremap_entry(req_id, vector, delivery_mode);
+            offset = get_intremap_offset(vector, delivery_mode);
+            entry = (u32*)get_intremap_entry(req_id, offset);
             update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
             spin_unlock_irqrestore(lock, flags);
 
@@ -242,16 +261,38 @@ void amd_iommu_ioapic_update_ire(
 }
 
 static void update_intremap_entry_from_msi_msg(
-    struct amd_iommu *iommu, struct pci_dev *pdev, struct msi_msg *msg)
+    struct amd_iommu *iommu, struct pci_dev *pdev,
+    struct msi_desc *msi_desc, struct msi_msg *msg)
 {
     unsigned long flags;
     u32* entry;
     u16 bdf, req_id, alias_id;
     u8 delivery_mode, dest, vector, dest_mode;
     spinlock_t *lock;
+    int offset;
 
     bdf = (pdev->bus << 8) | pdev->devfn;
     req_id = get_dma_requestor_id(bdf);
+    alias_id = get_intremap_requestor_id(bdf);
+
+    if ( msg == NULL )
+    {
+        lock = get_intremap_lock(req_id);
+        spin_lock_irqsave(lock, flags);
+        free_intremap_entry(req_id, msi_desc->remap_index);
+        spin_unlock_irqrestore(lock, flags);
+
+        if ( ( req_id != alias_id ) &&
+            ivrs_mappings[alias_id].intremap_table != NULL )
+        {
+            lock = get_intremap_lock(alias_id);
+            spin_lock_irqsave(lock, flags);
+            free_intremap_entry(alias_id, msi_desc->remap_index);
+            spin_unlock_irqrestore(lock, flags);
+        }
+        goto done;
+    }
+
     lock = get_intremap_lock(req_id);
 
     spin_lock_irqsave(lock, flags);
@@ -259,8 +300,10 @@ static void update_intremap_entry_from_m
     delivery_mode = (msg->data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x1;
     vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK;
     dest = (msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff;
-
-    entry = (u32*)get_intremap_entry(req_id, vector, delivery_mode);
+    offset = get_intremap_offset(vector, delivery_mode);
+    msi_desc->remap_index = offset;
+
+    entry = (u32*)get_intremap_entry(req_id, offset);
     update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
     spin_unlock_irqrestore(lock, flags);
 
@@ -270,18 +313,18 @@ static void update_intremap_entry_from_m
      * We have to setup a secondary interrupt remapping entry to satisfy those
      * devices.
      */
-    alias_id = get_intremap_requestor_id(bdf);
+
     lock = get_intremap_lock(alias_id);
-    if ( ( bdf != alias_id ) &&
+    if ( ( req_id != alias_id ) &&
         ivrs_mappings[alias_id].intremap_table != NULL )
     {
         spin_lock_irqsave(lock, flags);
-        entry = (u32*)get_intremap_entry(alias_id, vector, delivery_mode);
+        entry = (u32*)get_intremap_entry(alias_id, offset);
         update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
-        invalidate_interrupt_table(iommu, alias_id);
         spin_unlock_irqrestore(lock, flags);
     }
 
+done:
     if ( iommu->enabled )
     {
         spin_lock_irqsave(&iommu->lock, flags);
@@ -312,7 +355,7 @@ void amd_iommu_msi_msg_update_ire(
         return;
     }
 
-    update_intremap_entry_from_msi_msg(iommu, pdev, msg);
+    update_intremap_entry_from_msi_msg(iommu, pdev, msi_desc, msg);
 }
 
 unsigned int amd_iommu_read_ioapic_from_ire(

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

             reply	other threads:[~2009-12-16 15:54 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-16 15:54 Wei Wang2 [this message]
  -- strict thread matches above, loose matches on Subject: below --
2009-12-16 15:50 [PATCH] AMD IOMMU: Fix a xen crash on amd iommu systems Wei Wang2

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200912161654.03752.wei.wang2@amd.com \
    --to=wei.wang2@amd.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.