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] merge with xen-unstable.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 04 Oct 2007 17:41:20 -0700
Delivery-date: Thu, 04 Oct 2007 17:44:30 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/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 Alex Williamson <alex.williamson@xxxxxx>
# Date 1191268777 21600
# Node ID f71b7d6ad5d84bc67859bf48b6377ba4f40dcd21
# Parent  d3665dc74a414aea75132dfc585965310b8be05a
# Parent  5c7afb32df999ceca475f6582e3df3d7ff42d2fe
merge with xen-unstable.hg
---
 tools/python/xen/xm/main.py            |   29 +++++
 xen/arch/x86/hvm/hvm.c                 |   73 ++++++++++++++
 xen/arch/x86/hvm/svm/svm.c             |   96 ++----------------
 xen/arch/x86/hvm/vmx/vmx.c             |   61 +-----------
 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c |  167 ++++++++++++++++++++-------------
 xen/arch/x86/mm/paging.c               |   16 +--
 xen/include/asm-x86/hvm/hvm.h          |    3 
 xen/include/asm-x86/hvm/support.h      |    1 
 xen/include/xsm/acm/acm_core.h         |    2 
 xen/include/xsm/acm/acm_hooks.h        |    4 
 xen/xsm/acm/acm_core.c                 |   10 +
 11 files changed, 247 insertions(+), 215 deletions(-)

diff -r d3665dc74a41 -r f71b7d6ad5d8 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Mon Oct 01 09:59:24 2007 -0600
+++ b/tools/python/xen/xm/main.py       Mon Oct 01 13:59:37 2007 -0600
@@ -55,6 +55,9 @@ from xen.util.acmpolicy import ACM_LABEL
 
 import XenAPI
 
+import inspect
+from xen.xend import XendOptions
+xoptions = XendOptions.instance()
 
 # getopt.gnu_getopt is better, but only exists in Python 2.3+.  Use
 # getopt.getopt if gnu_getopt is not available.  This will mean that options
@@ -1595,7 +1598,31 @@ def xm_sched_credit(args):
                 err(str(result))
 
 def xm_info(args):
-    arg_check(args, "info", 0)
+    arg_check(args, "info", 0, 1)
+    
+    try:
+        (options, params) = getopt.gnu_getopt(args, 'c', ['config'])
+    except getopt.GetoptError, opterr:
+        err(opterr)
+        usage('info')
+    
+    show_xend_config = 0
+    for (k, v) in options:
+        if k in ['-c', '--config']:
+            show_xend_config = 1
+
+    if show_xend_config:
+        for name, obj in inspect.getmembers(xoptions):
+            if not inspect.ismethod(obj):
+                if name == "config":
+                    for x in obj[1:]:
+                        if len(x) < 2: 
+                            print "%-38s: (none)" % x[0]
+                        else: 
+                            print "%-38s:" % x[0], x[1]
+                else:
+                    print "%-38s:" % name, obj
+        return
 
     if serverType == SERVER_XEN_API:
 
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/arch/x86/hvm/hvm.c    Mon Oct 01 13:59:37 2007 -0600
@@ -49,6 +49,10 @@
 #include <public/version.h>
 #include <public/memory.h>
 
+/* Xen command-line option to disable hardware-assisted paging */
+static int opt_hap_disabled;
+invbool_param("hap", opt_hap_disabled);
+
 int hvm_enabled __read_mostly;
 
 unsigned int opt_hvm_debug_level __read_mostly;
@@ -74,6 +78,14 @@ void hvm_enable(struct hvm_function_tabl
 
     hvm_funcs   = *fns;
     hvm_enabled = 1;
+
+    if ( hvm_funcs.hap_supported )
+    {
+        if ( opt_hap_disabled )
+            hvm_funcs.hap_supported = 0;
+        printk("HVM: Hardware Assisted Paging %sabled\n",
+               hvm_funcs.hap_supported ? "en" : "dis");
+    }
 }
 
 void hvm_set_guest_time(struct vcpu *v, u64 gtime)
@@ -325,6 +337,34 @@ static int hvm_load_cpu_ctxt(struct doma
     if ( hvm_load_entry(CPU, h, &ctxt) != 0 ) 
         return -EINVAL;
 
+    /* Sanity check some control registers. */
+    if ( (ctxt.cr0 & HVM_CR0_GUEST_RESERVED_BITS) ||
+         !(ctxt.cr0 & X86_CR0_ET) ||
+         ((ctxt.cr0 & (X86_CR0_PE|X86_CR0_PG)) == X86_CR0_PG) )
+    {
+        gdprintk(XENLOG_ERR, "HVM restore: bad CR0 0x%"PRIx64"\n",
+                 ctxt.msr_efer);
+        return -EINVAL;
+    }
+
+    if ( ctxt.cr4 & HVM_CR4_GUEST_RESERVED_BITS )
+    {
+        gdprintk(XENLOG_ERR, "HVM restore: bad CR4 0x%"PRIx64"\n",
+                 ctxt.msr_efer);
+        return -EINVAL;
+    }
+
+    if ( (ctxt.msr_efer & ~(EFER_LME | EFER_NX | EFER_SCE)) ||
+         ((sizeof(long) != 8) && (ctxt.msr_efer & EFER_LME)) ||
+         (!cpu_has_nx && (ctxt.msr_efer & EFER_NX)) ||
+         (!cpu_has_syscall && (ctxt.msr_efer & EFER_SCE)) ||
+         ((ctxt.msr_efer & (EFER_LME|EFER_LMA)) == EFER_LMA) )
+    {
+        gdprintk(XENLOG_ERR, "HVM restore: bad EFER 0x%"PRIx64"\n",
+                 ctxt.msr_efer);
+        return -EINVAL;
+    }
+
     /* Architecture-specific vmcs/vmcb bits */
     if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 )
         return -EINVAL;
@@ -518,6 +558,39 @@ void hvm_triple_fault(void)
     gdprintk(XENLOG_INFO, "Triple fault on VCPU%d - "
              "invoking HVM system reset.\n", v->vcpu_id);
     domain_shutdown(v->domain, SHUTDOWN_reboot);
+}
+
+int hvm_set_efer(uint64_t value)
+{
+    struct vcpu *v = current;
+
+    value &= ~EFER_LMA;
+
+    if ( (value & ~(EFER_LME | EFER_NX | EFER_SCE)) ||
+         ((sizeof(long) != 8) && (value & EFER_LME)) ||
+         (!cpu_has_nx && (value & EFER_NX)) ||
+         (!cpu_has_syscall && (value & EFER_SCE)) )
+    {
+        gdprintk(XENLOG_WARNING, "Trying to set reserved bit in "
+                 "EFER: %"PRIx64"\n", value);
+        hvm_inject_exception(TRAP_gp_fault, 0, 0);
+        return 0;
+    }
+
+    if ( ((value ^ v->arch.hvm_vcpu.guest_efer) & EFER_LME) &&
+         hvm_paging_enabled(v) )
+    {
+        gdprintk(XENLOG_WARNING,
+                 "Trying to change EFER.LME with paging enabled\n");
+        hvm_inject_exception(TRAP_gp_fault, 0, 0);
+        return 0;
+    }
+
+    value |= v->arch.hvm_vcpu.guest_efer & EFER_LMA;
+    v->arch.hvm_vcpu.guest_efer = value;
+    hvm_update_guest_efer(v);
+
+    return 1;
 }
 
 int hvm_set_cr0(unsigned long value)
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Oct 01 13:59:37 2007 -0600
@@ -69,8 +69,7 @@ static void *hsa[NR_CPUS] __read_mostly;
 /* vmcb used for extended host state */
 static void *root_vmcb[NR_CPUS] __read_mostly;
 
-/* hardware assisted paging bits */
-extern int opt_hap_enabled;
+static void svm_update_guest_efer(struct vcpu *v);
 
 static void inline __update_guest_eip(
     struct cpu_user_regs *regs, int inst_len) 
@@ -106,22 +105,10 @@ static void svm_cpu_down(void)
     write_efer(read_efer() & ~EFER_SVME);
 }
 
-static int svm_lme_is_set(struct vcpu *v)
-{
-#ifdef __x86_64__
-    u64 guest_efer = v->arch.hvm_vcpu.guest_efer;
-    return guest_efer & EFER_LME;
-#else
-    return 0;
-#endif
-}
-
 static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
     u32 ecx = regs->ecx;
-    struct vcpu *v = current;
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
     HVM_DBG_LOG(DBG_LEVEL_0, "msr %x msr_content %"PRIx64,
                 ecx, msr_content);
@@ -129,47 +116,8 @@ static enum handler_return long_mode_do_
     switch ( ecx )
     {
     case MSR_EFER:
-        /* Offending reserved bit will cause #GP. */
-#ifdef __x86_64__
-        if ( (msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE)) ||
-#else
-        if ( (msr_content & ~(EFER_NX | EFER_SCE)) ||
-#endif
-             (!cpu_has_nx && (msr_content & EFER_NX)) ||
-             (!cpu_has_syscall && (msr_content & EFER_SCE)) )
-        {
-            gdprintk(XENLOG_WARNING, "Trying to set reserved bit in "
-                     "EFER: %"PRIx64"\n", msr_content);
-            goto gp_fault;
-        }
-
-        if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) )
-        {
-            /* EFER.LME transition from 0 to 1. */
-            if ( hvm_paging_enabled(v) ||
-                 !(v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PAE) )
-            {
-                gdprintk(XENLOG_WARNING, "Trying to set LME bit when "
-                         "in paging mode or PAE bit is not set\n");
-                goto gp_fault;
-            }
-        }
-        else if ( !(msr_content & EFER_LME) && svm_lme_is_set(v) )
-        {
-            /* EFER.LME transistion from 1 to 0. */
-            if ( hvm_paging_enabled(v) )
-            {
-                gdprintk(XENLOG_WARNING, 
-                         "Trying to clear EFER.LME while paging enabled\n");
-                goto gp_fault;
-            }
-        }
-
-        v->arch.hvm_vcpu.guest_efer = msr_content;
-        vmcb->efer = msr_content | EFER_SVME;
-        if ( !hvm_paging_enabled(v) )
-            vmcb->efer &= ~(EFER_LME | EFER_LMA);
-
+        if ( !hvm_set_efer(msr_content) )
+            return HNDL_exception_raised;
         break;
 
     case MSR_K8_MC4_MISC: /* Threshold register */
@@ -185,10 +133,6 @@ static enum handler_return long_mode_do_
     }
 
     return HNDL_done;
-
- gp_fault:
-    svm_inject_exception(v, TRAP_gp_fault, 1, 0);
-    return HNDL_exception_raised;
 }
 
 
@@ -452,11 +396,7 @@ static void svm_load_cpu_state(struct vc
     vmcb->cstar      = data->msr_cstar;
     vmcb->sfmask     = data->msr_syscall_mask;
     v->arch.hvm_vcpu.guest_efer = data->msr_efer;
-    vmcb->efer       = data->msr_efer | EFER_SVME;
-    /* VMCB's EFER.LME isn't set unless we're actually in long mode
-     * (see long_mode_do_msr_write()) */
-    if ( !(vmcb->efer & EFER_LMA) )
-        vmcb->efer &= ~EFER_LME;
+    svm_update_guest_efer(v);
 
     hvm_set_guest_time(v, data->tsc);
 }
@@ -546,14 +486,11 @@ static void svm_update_guest_cr(struct v
 
 static void svm_update_guest_efer(struct vcpu *v)
 {
-#ifdef __x86_64__
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    if ( v->arch.hvm_vcpu.guest_efer & EFER_LMA )
-        vmcb->efer |= EFER_LME | EFER_LMA;
-    else
-        vmcb->efer &= ~(EFER_LME | EFER_LMA);
-#endif
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    vmcb->efer = (v->arch.hvm_vcpu.guest_efer | EFER_SVME) & ~EFER_LME;
+    if ( vmcb->efer & EFER_LMA )
+        vmcb->efer |= EFER_LME;
 }
 
 static void svm_flush_guest_tlbs(void)
@@ -936,18 +873,14 @@ static struct hvm_function_table svm_fun
     .event_pending        = svm_event_pending
 };
 
-static void svm_npt_detect(void)
+static int svm_npt_detect(void)
 {
     u32 eax, ebx, ecx, edx;
 
     /* Check CPUID for nested paging support. */
     cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
 
-    if ( !(edx & 1) && opt_hap_enabled )
-    {
-        printk("SVM: Nested paging is not supported by this CPU.\n");
-        opt_hap_enabled = 0;
-    }
+    return (edx & 1);
 }
 
 int start_svm(struct cpuinfo_x86 *c)
@@ -978,8 +911,6 @@ int start_svm(struct cpuinfo_x86 *c)
 
     write_efer(read_efer() | EFER_SVME);
 
-    svm_npt_detect();
-
     /* Initialize the HSA for this core. */
     phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
     phys_hsa_lo = (u32) phys_hsa;
@@ -994,11 +925,10 @@ int start_svm(struct cpuinfo_x86 *c)
 
     setup_vmcb_dump();
 
+    svm_function_table.hap_supported = svm_npt_detect();
+
     hvm_enable(&svm_function_table);
 
-    if ( opt_hap_enabled )
-        printk("SVM: Nested paging enabled.\n");
-        
     return 1;
 }
 
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Oct 01 13:59:37 2007 -0600
@@ -199,42 +199,8 @@ static enum handler_return long_mode_do_
     switch ( ecx )
     {
     case MSR_EFER:
-        /* offending reserved bit will cause #GP */
-        if ( (msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE)) ||
-             (!cpu_has_nx && (msr_content & EFER_NX)) ||
-             (!cpu_has_syscall && (msr_content & EFER_SCE)) )
-        {
-            gdprintk(XENLOG_WARNING, "Trying to set reserved bit in "
-                     "EFER: %"PRIx64"\n", msr_content);
-            goto gp_fault;
-        }
-
-        if ( (msr_content & EFER_LME)
-             &&  !(v->arch.hvm_vcpu.guest_efer & EFER_LME) )
-        {
-            if ( unlikely(hvm_paging_enabled(v)) )
-            {
-                gdprintk(XENLOG_WARNING,
-                         "Trying to set EFER.LME with paging enabled\n");
-                goto gp_fault;
-            }
-        }
-        else if ( !(msr_content & EFER_LME)
-                  && (v->arch.hvm_vcpu.guest_efer & EFER_LME) )
-        {
-            if ( unlikely(hvm_paging_enabled(v)) )
-            {
-                gdprintk(XENLOG_WARNING,
-                         "Trying to clear EFER.LME with paging enabled\n");
-                goto gp_fault;
-            }
-        }
-
-        if ( (msr_content ^ v->arch.hvm_vcpu.guest_efer) & (EFER_NX|EFER_SCE) )
-            write_efer((read_efer() & ~(EFER_NX|EFER_SCE)) |
-                       (msr_content & (EFER_NX|EFER_SCE)));
-
-        v->arch.hvm_vcpu.guest_efer = msr_content;
+        if ( !hvm_set_efer(msr_content) )
+            goto exception_raised;
         break;
 
     case MSR_FS_BASE:
@@ -285,6 +251,7 @@ static enum handler_return long_mode_do_
     HVM_DBG_LOG(DBG_LEVEL_0, "Not cano address of msr write %x", ecx);
  gp_fault:
     vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
+ exception_raised:
     return HNDL_exception_raised;
 }
 
@@ -380,7 +347,8 @@ static enum handler_return long_mode_do_
     u64 msr_content = 0;
     struct vcpu *v = current;
 
-    switch ( regs->ecx ) {
+    switch ( regs->ecx )
+    {
     case MSR_EFER:
         msr_content = v->arch.hvm_vcpu.guest_efer;
         break;
@@ -398,25 +366,12 @@ static enum handler_return long_mode_do_
 static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content = regs->eax | ((u64)regs->edx << 32);
-    struct vcpu *v = current;
 
     switch ( regs->ecx )
     {
     case MSR_EFER:
-        /* offending reserved bit will cause #GP */
-        if ( (msr_content & ~EFER_NX) ||
-             (!cpu_has_nx && (msr_content & EFER_NX)) )
-        {
-            gdprintk(XENLOG_WARNING, "Trying to set reserved bit in "
-                     "EFER: %"PRIx64"\n", msr_content);
-            vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
+        if ( !hvm_set_efer(msr_content) )
             return HNDL_exception_raised;
-        }
-
-        if ( (msr_content ^ v->arch.hvm_vcpu.guest_efer) & EFER_NX )
-            write_efer((read_efer() & ~EFER_NX) | (msr_content & EFER_NX));
-
-        v->arch.hvm_vcpu.guest_efer = msr_content;
         break;
 
     default:
@@ -1096,6 +1051,10 @@ static void vmx_update_guest_efer(struct
 
     vmx_vmcs_exit(v);
 #endif
+
+    if ( v == current )
+        write_efer((read_efer() & ~(EFER_NX|EFER_SCE)) |
+                   (v->arch.hvm_vcpu.guest_efer & (EFER_NX|EFER_SCE)));
 }
 
 static void vmx_flush_guest_tlbs(void)
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
--- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Mon Oct 01 13:59:37 2007 -0600
@@ -134,7 +134,7 @@ static int device_context_mapped(struct 
 #define level_mask(l) (((u64)(-1)) << level_to_offset_bits(l))
 #define level_size(l) (1 << level_to_offset_bits(l))
 #define align_to_level(addr, l) ((addr + level_size(l) - 1) & level_mask(l))
-static struct dma_pte *addr_to_dma_pte(struct domain *domain, u64 addr)
+static struct page_info *addr_to_dma_page(struct domain *domain, u64 addr)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
     struct acpi_drhd_unit *drhd;
@@ -144,6 +144,8 @@ static struct dma_pte *addr_to_dma_pte(s
     int level = agaw_to_level(hd->agaw);
     int offset;
     unsigned long flags;
+    struct page_info *pg = NULL;
+    u64 *vaddr = NULL;
 
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
     iommu = drhd->iommu;
@@ -153,79 +155,105 @@ static struct dma_pte *addr_to_dma_pte(s
     if ( !hd->pgd )
     {
         pgd = (struct dma_pte *)alloc_xenheap_page();
-        if ( !pgd && !hd->pgd )
+        if ( !pgd )
         {
             spin_unlock_irqrestore(&hd->mapping_lock, flags);
             return NULL;
         }
-        memset((u8*)pgd, 0, PAGE_SIZE);
-        if ( !hd->pgd )
-            hd->pgd = pgd;
-        else /* somebody is fast */
-            free_xenheap_page((void *) pgd);
-    }
+        memset(pgd, 0, PAGE_SIZE);
+        hd->pgd = pgd;
+    }
+
     parent = hd->pgd;
-    while ( level > 0 )
-    {
-        u8 *tmp;
+    while ( level > 1 )
+    {
         offset = address_level_offset(addr, level);
         pte = &parent[offset];
-        if ( level == 1 )
-            break;
+
         if ( dma_pte_addr(*pte) == 0 )
         {
-            tmp = alloc_xenheap_page();
-            memset(tmp, 0, PAGE_SIZE);
-            iommu_flush_cache_page(iommu, tmp);
-
-            if ( !tmp && dma_pte_addr(*pte) == 0 )
+            pg = alloc_domheap_page(NULL);
+            vaddr = map_domain_page(mfn_x(page_to_mfn(pg)));
+            if ( !vaddr )
             {
                 spin_unlock_irqrestore(&hd->mapping_lock, flags);
                 return NULL;
             }
-            if ( dma_pte_addr(*pte) == 0 )
+            memset(vaddr, 0, PAGE_SIZE);
+            iommu_flush_cache_page(iommu, vaddr);
+
+            dma_set_pte_addr(*pte, page_to_maddr(pg));
+
+            /*
+             * high level table always sets r/w, last level
+             * page table control read/write
+             */
+            dma_set_pte_readable(*pte);
+            dma_set_pte_writable(*pte);
+            iommu_flush_cache_entry(iommu, pte);
+        }
+        else
+        {
+            pg = maddr_to_page(pte->val);
+            vaddr = map_domain_page(mfn_x(page_to_mfn(pg)));
+            if ( !vaddr )
             {
-                dma_set_pte_addr(*pte,
-                                 virt_to_maddr(tmp));
-                /*
-                 * high level table always sets r/w, last level
-                 * page table control read/write
-                 */
-                dma_set_pte_readable(*pte);
-                dma_set_pte_writable(*pte);
-                iommu_flush_cache_entry(iommu, pte);
-            } else /* somebody is fast */
-                free_xenheap_page(tmp);
-        }
-        parent = maddr_to_virt(dma_pte_addr(*pte));
+                spin_unlock_irqrestore(&hd->mapping_lock, flags);
+                return NULL;
+            }
+        }
+
+        if ( parent != hd->pgd )
+            unmap_domain_page(parent);
+
+        if ( level == 2 && vaddr )
+        {
+            unmap_domain_page(vaddr);
+            break;
+        }
+
+        parent = (struct dma_pte *)vaddr;
+        vaddr = NULL;
         level--;
     }
+
     spin_unlock_irqrestore(&hd->mapping_lock, flags);
-    return pte;
-}
-
-/* return address's pte at specific level */
-static struct dma_pte *dma_addr_level_pte(struct domain *domain, u64 addr,
-                                          int level)
+    return pg;
+}
+
+/* return address's page at specific level */
+static struct page_info *dma_addr_level_page(struct domain *domain,
+                                             u64 addr, int level)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
     struct dma_pte *parent, *pte = NULL;
     int total = agaw_to_level(hd->agaw);
     int offset;
+    struct page_info *pg = NULL;
 
     parent = hd->pgd;
     while ( level <= total )
     {
         offset = address_level_offset(addr, total);
         pte = &parent[offset];
+        if ( dma_pte_addr(*pte) == 0 )
+        {
+            if ( parent != hd->pgd )
+                unmap_domain_page(parent);
+            break;
+        }
+
+        pg = maddr_to_page(pte->val);
+        if ( parent != hd->pgd )
+            unmap_domain_page(parent);
+
         if ( level == total )
-            return pte;
-
-        if ( dma_pte_addr(*pte) == 0 )
-            break;
-        parent = maddr_to_virt(dma_pte_addr(*pte));
+            return pg;
+
+        parent = map_domain_page(mfn_x(page_to_mfn(pg)));
         total--;
     }
+
     return NULL;
 }
 
@@ -506,12 +534,16 @@ static void dma_pte_clear_one(struct dom
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
     struct dma_pte *pte = NULL;
+    struct page_info *pg = NULL;
 
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
 
     /* get last level pte */
-    pte = dma_addr_level_pte(domain, addr, 1);
-
+    pg = dma_addr_level_page(domain, addr, 1);
+    if ( !pg )
+        return;
+    pte = (struct dma_pte *)map_domain_page(mfn_x(page_to_mfn(pg)));
+    pte += address_level_offset(addr, 1);
     if ( pte )
     {
         dma_clear_pte(*pte);
@@ -559,6 +591,7 @@ void dma_pte_free_pagetable(struct domai
     int total = agaw_to_level(hd->agaw);
     int level;
     u32 tmp;
+    struct page_info *pg = NULL;
 
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
     iommu = drhd->iommu;
@@ -576,13 +609,16 @@ void dma_pte_free_pagetable(struct domai
 
         while ( tmp < end )
         {
-            pte = dma_addr_level_pte(domain, tmp, level);
-            if ( pte )
-            {
-                free_xenheap_page((void *) maddr_to_virt(dma_pte_addr(*pte)));
-                dma_clear_pte(*pte);
-                iommu_flush_cache_entry(iommu, pte);
-            }
+            pg = dma_addr_level_page(domain, tmp, level);
+            if ( !pg )
+                return;
+            pte = (struct dma_pte *)map_domain_page(mfn_x(page_to_mfn(pg)));
+            pte += address_level_offset(tmp, level);
+            dma_clear_pte(*pte);
+            iommu_flush_cache_entry(iommu, pte);
+            unmap_domain_page(pte);
+            free_domheap_page(pg);
+
             tmp += level_size(level);
         }
         level++;
@@ -1445,6 +1481,7 @@ int iommu_map_page(struct domain *d, pad
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
     struct dma_pte *pte = NULL;
+    struct page_info *pg = NULL;
 
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
     iommu = drhd->iommu;
@@ -1453,12 +1490,15 @@ int iommu_map_page(struct domain *d, pad
     if ( ecap_pass_thru(iommu->ecap) && (d->domain_id == 0) )
         return 0;
 
-    pte = addr_to_dma_pte(d, gfn << PAGE_SHIFT_4K);
-    if ( !pte )
+    pg = addr_to_dma_page(d, gfn << PAGE_SHIFT_4K);
+    if ( !pg )
         return -ENOMEM;
+    pte = (struct dma_pte *)map_domain_page(mfn_x(page_to_mfn(pg)));
+    pte += mfn & LEVEL_MASK;
     dma_set_pte_addr(*pte, mfn << PAGE_SHIFT_4K);
     dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE);
     iommu_flush_cache_entry(iommu, pte);
+    unmap_domain_page(pte);
 
     for_each_drhd_unit ( drhd )
     {
@@ -1477,7 +1517,6 @@ int iommu_unmap_page(struct domain *d, d
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
-    struct dma_pte *pte = NULL;
 
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
     iommu = drhd->iommu;
@@ -1486,10 +1525,8 @@ int iommu_unmap_page(struct domain *d, d
     if ( ecap_pass_thru(iommu->ecap) && (d->domain_id == 0) )
         return 0;
 
-    /* get last level pte */
-    pte = dma_addr_level_pte(d, gfn << PAGE_SHIFT_4K, 1);
     dma_pte_clear_one(d, gfn << PAGE_SHIFT_4K);
-    
+
     return 0;
 }
 
@@ -1501,6 +1538,7 @@ int iommu_page_mapping(struct domain *do
     unsigned long start_pfn, end_pfn;
     struct dma_pte *pte = NULL;
     int index;
+    struct page_info *pg = NULL;
 
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
     iommu = drhd->iommu;
@@ -1513,12 +1551,15 @@ int iommu_page_mapping(struct domain *do
     index = 0;
     while ( start_pfn < end_pfn )
     {
-        pte = addr_to_dma_pte(domain, iova + PAGE_SIZE_4K * index);
-        if ( !pte )
+        pg = addr_to_dma_page(domain, iova + PAGE_SIZE_4K * index);
+        if ( !pg )
             return -ENOMEM;
+        pte = (struct dma_pte *)map_domain_page(mfn_x(page_to_mfn(pg)));
+        pte += start_pfn & LEVEL_MASK;
         dma_set_pte_addr(*pte, start_pfn << PAGE_SHIFT_4K);
         dma_set_pte_prot(*pte, prot);
         iommu_flush_cache_entry(iommu, pte);
+        unmap_domain_page(pte);
         start_pfn++;
         index++;
     }
@@ -1537,12 +1578,8 @@ int iommu_page_mapping(struct domain *do
 
 int iommu_page_unmapping(struct domain *domain, dma_addr_t addr, size_t size)
 {
-    struct dma_pte *pte = NULL;
-
-    /* get last level pte */
-    pte = dma_addr_level_pte(domain, addr, 1);
     dma_pte_clear_range(domain, addr, addr + size);
-    
+
     return 0;
 }
 
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c  Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/arch/x86/mm/paging.c  Mon Oct 01 13:59:37 2007 -0600
@@ -28,9 +28,7 @@
 #include <asm/guest_access.h>
 #include <xsm/xsm.h>
 
-/* Xen command-line option to enable hardware-assisted paging */
-int opt_hap_enabled;
-boolean_param("hap", opt_hap_enabled);
+#define hap_enabled(d) (hvm_funcs.hap_supported && is_hvm_domain(d))
 
 /* Printouts */
 #define PAGING_PRINTK(_f, _a...)                                     \
@@ -363,14 +361,14 @@ void paging_domain_init(struct domain *d
     shadow_domain_init(d);
 
     /* ... but we will use hardware assistance if it's available. */
-    if ( opt_hap_enabled && is_hvm_domain(d) )
+    if ( hap_enabled(d) )
         hap_domain_init(d);
 }
 
 /* vcpu paging struct initialization goes here */
 void paging_vcpu_init(struct vcpu *v)
 {
-    if ( opt_hap_enabled && is_hvm_vcpu(v) )
+    if ( hap_enabled(v->domain) )
         hap_vcpu_init(v);
     else
         shadow_vcpu_init(v);
@@ -434,7 +432,7 @@ int paging_domctl(struct domain *d, xen_
     }
 
     /* Here, dispatch domctl to the appropriate paging code */
-    if ( opt_hap_enabled && is_hvm_domain(d) )
+    if ( hap_enabled(d) )
         return hap_domctl(d, sc, u_domctl);
     else
         return shadow_domctl(d, sc, u_domctl);
@@ -443,7 +441,7 @@ int paging_domctl(struct domain *d, xen_
 /* Call when destroying a domain */
 void paging_teardown(struct domain *d)
 {
-    if ( opt_hap_enabled && is_hvm_domain(d) )
+    if ( hap_enabled(d) )
         hap_teardown(d);
     else
         shadow_teardown(d);
@@ -455,7 +453,7 @@ void paging_teardown(struct domain *d)
 /* Call once all of the references to the domain have gone away */
 void paging_final_teardown(struct domain *d)
 {
-    if ( opt_hap_enabled && is_hvm_domain(d) )
+    if ( hap_enabled(d) )
         hap_final_teardown(d);
     else
         shadow_final_teardown(d);
@@ -465,7 +463,7 @@ void paging_final_teardown(struct domain
  * creation. */
 int paging_enable(struct domain *d, u32 mode)
 {
-    if ( opt_hap_enabled && is_hvm_domain(d) )
+    if ( hap_enabled(d) )
         return hap_enable(d, mode | PG_HAP_enable);
     else
         return shadow_enable(d, mode | PG_SH_enable);
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/include/asm-x86/hvm/hvm.h     Mon Oct 01 13:59:37 2007 -0600
@@ -71,6 +71,9 @@ enum hvm_intack {
  */
 struct hvm_function_table {
     char *name;
+
+    /* Support Hardware-Assisted Paging? */
+    int hap_supported;
 
     /*
      * Initialise/destroy HVM domain/vcpu resources
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/include/asm-x86/hvm/support.h
--- a/xen/include/asm-x86/hvm/support.h Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/include/asm-x86/hvm/support.h Mon Oct 01 13:59:37 2007 -0600
@@ -234,6 +234,7 @@ void hvm_hlt(unsigned long rflags);
 void hvm_hlt(unsigned long rflags);
 void hvm_triple_fault(void);
 
+int hvm_set_efer(uint64_t value);
 int hvm_set_cr0(unsigned long value);
 int hvm_set_cr3(unsigned long value);
 int hvm_set_cr4(unsigned long value);
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/include/xsm/acm/acm_core.h
--- a/xen/include/xsm/acm/acm_core.h    Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/include/xsm/acm/acm_core.h    Mon Oct 01 13:59:37 2007 -0600
@@ -154,7 +154,7 @@ static inline int acm_array_append_tuple
 
 /* protos */
 int acm_init_domain_ssid(struct domain *, ssidref_t ssidref);
-void acm_free_domain_ssid(struct acm_ssid_domain *ssid);
+void acm_free_domain_ssid(struct domain *);
 int acm_init_binary_policy(u32 policy_code);
 int acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size);
 int do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy,
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/include/xsm/acm/acm_hooks.h
--- a/xen/include/xsm/acm/acm_hooks.h   Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/include/xsm/acm/acm_hooks.h   Mon Oct 01 13:59:37 2007 -0600
@@ -258,7 +258,7 @@ static inline void acm_domain_destroy(st
             acm_secondary_ops->domain_destroy(ssid, d);
         /* free security ssid for the destroyed domain (also if null policy */
         acm_domain_ssid_off_list(ssid);
-        acm_free_domain_ssid((struct acm_ssid_domain *)(ssid));
+        acm_free_domain_ssid(d);
     }
 }
 
@@ -294,7 +294,7 @@ static inline int acm_domain_create(stru
     {
         acm_domain_ssid_onto_list(d->ssid);
     } else {
-        acm_free_domain_ssid(d->ssid);
+        acm_free_domain_ssid(d);
     }
 
 error_out:
diff -r d3665dc74a41 -r f71b7d6ad5d8 xen/xsm/acm/acm_core.c
--- a/xen/xsm/acm/acm_core.c    Mon Oct 01 09:59:24 2007 -0600
+++ b/xen/xsm/acm/acm_core.c    Mon Oct 01 13:59:37 2007 -0600
@@ -361,7 +361,7 @@ int acm_init_domain_ssid(struct domain *
     {
         printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
                __func__, subj->domain_id);
-        acm_free_domain_ssid(ssid);
+        acm_free_domain_ssid(subj);
         return ACM_INIT_SSID_ERROR;
     }
 
@@ -372,8 +372,10 @@ int acm_init_domain_ssid(struct domain *
 
 
 void
-acm_free_domain_ssid(struct acm_ssid_domain *ssid)
-{
+acm_free_domain_ssid(struct domain *d)
+{
+    struct acm_ssid_domain *ssid = d->ssid;
+    
     /* domain is already gone, just ssid is left */
     if (ssid == NULL)
         return;
@@ -387,6 +389,8 @@ acm_free_domain_ssid(struct acm_ssid_dom
     ssid->secondary_ssid = NULL;
 
     xfree(ssid);
+    d->ssid = NULL;
+    
     printkd("%s: Freed individual domain ssid (domain=%02x).\n",
             __func__, id);
 }

_______________________________________________
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] merge with xen-unstable.hg, Xen patchbot-unstable <=