WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] vtd: fix Dom0 S3 when VT-d is enabled.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] vtd: fix Dom0 S3 when VT-d is enabled.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 29 Aug 2008 08:30:34 -0700
Delivery-date: Fri, 29 Aug 2008 08:32:08 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1220022993 -3600
# Node ID c503269192f265c125a1d8d42375aaead84c5fca
# Parent  481f0dc6beb0b19cb02354dbe9b4ce068a5f6a18
vtd: fix Dom0 S3 when VT-d is enabled.

Now if VT-d is enabled, when Dom0 does S3, Xen doesn't suspend/resume
the IOMMU states.

The patch adds the missing invocations of
iommu_suspend()/iommu_resume() and makes some nesessary fixes:
1) In iommu_set_root_entry(), we should not re-allocate the root-entry
when Xen returns from S3;
2) Define the array iommu_state correctly (u8 -> u32);
3) Only save/restore the necessary IOMMU registers.

The patch was tested on Weybridge.

NOTE: if we have some HVM guests which have assigned devices, and we
want to do Dom S3, we MUST do HVM S3 for each HVM guest first.
Namely, the steps are:
1) Use HVM S3 in guest to suspend the guest (for example, in Linux HVM
guest, this is "echo mem > /sys/power/state");
2) Use Dom0 S3 to suspend Dom0: "echo mem > /sys/power/state";
3) At some point, Dom0 resumes from S3 (for example, by pressing the
power button or using the acpi alarm);
4) Use "xm trigger HVM_DOM_ID s3resume" to resume every HVM guest
which were suspended previously.

Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 xen/arch/x86/acpi/power.c           |    5 ++
 xen/drivers/passthrough/vtd/iommu.c |   70 ++++++++++++++----------------------
 xen/include/xen/iommu.h             |    4 ++
 3 files changed, 37 insertions(+), 42 deletions(-)

diff -r 481f0dc6beb0 -r c503269192f2 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Fri Aug 29 16:11:05 2008 +0100
+++ b/xen/arch/x86/acpi/power.c Fri Aug 29 16:16:33 2008 +0100
@@ -24,6 +24,7 @@
 #include <xen/sched.h>
 #include <xen/domain.h>
 #include <xen/console.h>
+#include <xen/iommu.h>
 #include <public/platform.h>
 #include <asm/tboot.h>
 
@@ -41,6 +42,8 @@ void do_suspend_lowlevel(void);
 
 static int device_power_down(void)
 {
+    iommu_suspend();
+
     console_suspend();
 
     time_suspend();
@@ -65,6 +68,8 @@ static void device_power_up(void)
     time_resume();
 
     console_resume();
+
+    iommu_resume();
 }
 
 static void freeze_domains(void)
diff -r 481f0dc6beb0 -r c503269192f2 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Fri Aug 29 16:11:05 2008 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Fri Aug 29 16:16:33 2008 +0100
@@ -624,15 +624,10 @@ static int iommu_set_root_entry(struct i
     unsigned long flags;
     s_time_t start_time;
 
-    if ( iommu->root_maddr != 0 )
-    {
-        free_pgtable_maddr(iommu->root_maddr);
-        iommu->root_maddr = 0;
-    }
-
     spin_lock_irqsave(&iommu->register_lock, flags);
 
-    iommu->root_maddr = alloc_pgtable_maddr();
+    if ( iommu->root_maddr == 0 )
+        iommu->root_maddr = alloc_pgtable_maddr();
     if ( iommu->root_maddr == 0 )
     {
         spin_unlock_irqrestore(&iommu->register_lock, flags);
@@ -1864,37 +1859,31 @@ static int intel_iommu_group_id(u8 bus, 
         return -1;
 }
 
-u8 iommu_state[MAX_IOMMU_REGS * MAX_IOMMUS];
+static u32 iommu_state[MAX_IOMMUS][MAX_IOMMU_REGS];
 int iommu_suspend(void)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
-    int i = 0;
+    u32    i;
+
+    if ( !vtd_enabled )
+        return 0;
 
     iommu_flush_all();
 
     for_each_drhd_unit ( drhd )
     {
         iommu = drhd->iommu;
-        iommu_state[DMAR_RTADDR_REG * i] =
-            (u64) dmar_readq(iommu->reg, DMAR_RTADDR_REG);
-        iommu_state[DMAR_FECTL_REG * i] =
+        i = iommu->index;
+
+        iommu_state[i][DMAR_FECTL_REG] =
             (u32) dmar_readl(iommu->reg, DMAR_FECTL_REG);
-        iommu_state[DMAR_FEDATA_REG * i] =
+        iommu_state[i][DMAR_FEDATA_REG] =
             (u32) dmar_readl(iommu->reg, DMAR_FEDATA_REG);
-        iommu_state[DMAR_FEADDR_REG * i] =
+        iommu_state[i][DMAR_FEADDR_REG] =
             (u32) dmar_readl(iommu->reg, DMAR_FEADDR_REG);
-        iommu_state[DMAR_FEUADDR_REG * i] =
+        iommu_state[i][DMAR_FEUADDR_REG] =
             (u32) dmar_readl(iommu->reg, DMAR_FEUADDR_REG);
-        iommu_state[DMAR_PLMBASE_REG * i] =
-            (u32) dmar_readl(iommu->reg, DMAR_PLMBASE_REG);
-        iommu_state[DMAR_PLMLIMIT_REG * i] =
-            (u32) dmar_readl(iommu->reg, DMAR_PLMLIMIT_REG);
-        iommu_state[DMAR_PHMBASE_REG * i] =
-            (u64) dmar_readq(iommu->reg, DMAR_PHMBASE_REG);
-        iommu_state[DMAR_PHMLIMIT_REG * i] =
-            (u64) dmar_readq(iommu->reg, DMAR_PHMLIMIT_REG);
-        i++;
     }
 
     return 0;
@@ -1904,37 +1893,34 @@ int iommu_resume(void)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
-    int i = 0;
+    u32 i;
+
+    if ( !vtd_enabled )
+        return 0;
 
     iommu_flush_all();
 
-    init_vtd_hw();
+    if ( init_vtd_hw() != 0  && force_iommu )
+         panic("IOMMU setup failed, crash Xen for security purpose!\n");
+
     for_each_drhd_unit ( drhd )
     {
         iommu = drhd->iommu;
-        dmar_writeq( iommu->reg, DMAR_RTADDR_REG,
-                     (u64) iommu_state[DMAR_RTADDR_REG * i]);
+        i = iommu->index;
+
         dmar_writel(iommu->reg, DMAR_FECTL_REG,
-                    (u32) iommu_state[DMAR_FECTL_REG * i]);
+                    (u32) iommu_state[i][DMAR_FECTL_REG]);
         dmar_writel(iommu->reg, DMAR_FEDATA_REG,
-                    (u32) iommu_state[DMAR_FEDATA_REG * i]);
+                    (u32) iommu_state[i][DMAR_FEDATA_REG]);
         dmar_writel(iommu->reg, DMAR_FEADDR_REG,
-                    (u32) iommu_state[DMAR_FEADDR_REG * i]);
+                    (u32) iommu_state[i][DMAR_FEADDR_REG]);
         dmar_writel(iommu->reg, DMAR_FEUADDR_REG,
-                    (u32) iommu_state[DMAR_FEUADDR_REG * i]);
-        dmar_writel(iommu->reg, DMAR_PLMBASE_REG,
-                    (u32) iommu_state[DMAR_PLMBASE_REG * i]);
-        dmar_writel(iommu->reg, DMAR_PLMLIMIT_REG,
-                    (u32) iommu_state[DMAR_PLMLIMIT_REG * i]);
-        dmar_writeq(iommu->reg, DMAR_PHMBASE_REG,
-                    (u64) iommu_state[DMAR_PHMBASE_REG * i]);
-        dmar_writeq(iommu->reg, DMAR_PHMLIMIT_REG,
-                    (u64) iommu_state[DMAR_PHMLIMIT_REG * i]);
+                    (u32) iommu_state[i][DMAR_FEUADDR_REG]);
 
         if ( iommu_enable_translation(iommu) )
             return -EIO;
-        i++;
-    }
+    }
+
     return 0;
 }
 
diff -r 481f0dc6beb0 -r c503269192f2 xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Fri Aug 29 16:11:05 2008 +0100
+++ b/xen/include/xen/iommu.h   Fri Aug 29 16:16:33 2008 +0100
@@ -109,4 +109,8 @@ struct iommu_ops {
 
 void iommu_update_ire_from_apic(unsigned int apic, unsigned int reg, unsigned 
int value);
 void iommu_update_ire_from_msi(struct msi_desc *msi_desc, struct msi_msg *msg);
+
+int iommu_suspend(void);
+int iommu_resume(void);
+
 #endif /* _IOMMU_H_ */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] vtd: fix Dom0 S3 when VT-d is enabled., Xen patchbot-unstable <=