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

# HG changeset patch
# User Stefano Stabellini <sstabellini@xxxxxxxxxxxxx>
# Date 1281538561 -3600
# Node ID 3b839375d5bcb3a4b484170a890e340493b4738a
# Parent  ca51dba3a7b1d9bd15215d89036eb98dfae8754d
# Parent  47021067a0d5a498cdebca8892384eeb2cd94e48
merge
---
 tools/debugger/gdbsx/Makefile           |    6 
 xen/arch/x86/debug.c                    |    2 
 xen/arch/x86/domain.c                   |    2 
 xen/arch/x86/domctl.c                   |    4 
 xen/arch/x86/hvm/emulate.c              |   10 
 xen/arch/x86/hvm/hvm.c                  |  110 ++--
 xen/arch/x86/hvm/mtrr.c                 |    2 
 xen/arch/x86/hvm/stdvga.c               |    5 
 xen/arch/x86/hvm/svm/svm.c              |   14 
 xen/arch/x86/hvm/vmsi.c                 |   38 +
 xen/arch/x86/hvm/vmx/vmx.c              |   23 -
 xen/arch/x86/mm.c                       |   57 +-
 xen/arch/x86/mm/guest_walk.c            |   15 
 xen/arch/x86/mm/hap/guest_walk.c        |   12 
 xen/arch/x86/mm/hap/hap.c               |   38 -
 xen/arch/x86/mm/hap/p2m-ept.c           |  150 +++---
 xen/arch/x86/mm/mem_event.c             |    4 
 xen/arch/x86/mm/mem_paging.c            |    9 
 xen/arch/x86/mm/mem_sharing.c           |   31 -
 xen/arch/x86/mm/p2m.c                   |  736 ++++++++++++++++----------------
 xen/arch/x86/mm/shadow/common.c         |   38 -
 xen/arch/x86/mm/shadow/multi.c          |   49 +-
 xen/arch/x86/oprofile/nmi_int.c         |    2 
 xen/arch/x86/oprofile/op_counter.h      |   12 
 xen/arch/x86/oprofile/op_model_athlon.c |  356 +++++++++++++++
 xen/arch/x86/oprofile/xenoprof.c        |   17 
 xen/arch/x86/setup.c                    |   58 ++
 xen/arch/x86/x86_32/entry.S             |    2 
 xen/arch/x86/x86_64/compat/entry.S      |    2 
 xen/arch/x86/x86_64/entry.S             |    2 
 xen/common/domain.c                     |   25 +
 xen/common/grant_table.c                |   12 
 xen/common/memory.c                     |   13 
 xen/common/page_alloc.c                 |   72 ++-
 xen/common/sched_credit.c               |   44 +
 xen/common/schedule.c                   |   21 
 xen/common/tmem_xen.c                   |    2 
 xen/common/xenoprof.c                   |   14 
 xen/drivers/passthrough/vtd/intremap.c  |   11 
 xen/include/asm-ia64/xenoprof.h         |    7 
 xen/include/asm-x86/guest_pt.h          |    4 
 xen/include/asm-x86/mem_sharing.h       |    6 
 xen/include/asm-x86/p2m.h               |  134 +++--
 xen/include/asm-x86/xenoprof.h          |    5 
 xen/include/public/xenoprof.h           |   16 
 xen/include/xen/sched-if.h              |    1 
 xen/include/xen/sched.h                 |    9 
 47 files changed, 1449 insertions(+), 753 deletions(-)

diff -r ca51dba3a7b1 -r 3b839375d5bc tools/debugger/gdbsx/Makefile
--- a/tools/debugger/gdbsx/Makefile     Wed Aug 11 15:51:04 2010 +0100
+++ b/tools/debugger/gdbsx/Makefile     Wed Aug 11 15:56:01 2010 +0100
@@ -1,7 +1,5 @@ XEN_ROOT = ../../..
 XEN_ROOT = ../../..
 include ./Rules.mk
-
-sbindir=/usr/sbin
 
 .PHONY: all
 all:
@@ -16,8 +14,8 @@ clean:
 
 .PHONY: install
 install: all
-       [ -d $(DESTDIR)$(sbindir) ] || $(INSTALL_DIR) $(DESTDIR)$(sbindir)
-       $(INSTALL_PROG) gdbsx $(DESTDIR)$(sbindir)/gdbsx
+       [ -d $(DESTDIR)$(SBINDIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
+       $(INSTALL_PROG) gdbsx $(DESTDIR)$(SBINDIR)/gdbsx
 
 gdbsx: gx/gx_all.a xg/xg_all.a 
        $(CC) -o $@ $^
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/debug.c
--- a/xen/arch/x86/debug.c      Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/debug.c      Wed Aug 11 15:56:01 2010 +0100
@@ -61,7 +61,7 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct dom
         return INVALID_MFN;
     }
 
-    mfn = mfn_x(gfn_to_mfn(dp, gfn, &gfntype)); 
+    mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(dp), gfn, &gfntype)); 
     if ( p2m_is_readonly(gfntype) && toaddr )
     {
         DBGP2("kdb:p2m_is_readonly: gfntype:%x\n", gfntype);
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/domain.c     Wed Aug 11 15:56:01 2010 +0100
@@ -151,7 +151,7 @@ void dump_pageframe_info(struct domain *
 
     if ( is_hvm_domain(d) )
     {
-        p2m_pod_dump_data(d);
+        p2m_pod_dump_data(p2m_get_hostp2m(d));
     }
 
     spin_lock(&d->page_alloc_lock);
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/domctl.c     Wed Aug 11 15:56:01 2010 +0100
@@ -982,7 +982,7 @@ long arch_do_domctl(
 
             ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
             for ( i = 0; i < nr_mfns; i++ )
-                set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i));
+                set_mmio_p2m_entry(p2m_get_hostp2m(d), gfn+i, _mfn(mfn+i));
         }
         else
         {
@@ -991,7 +991,7 @@ long arch_do_domctl(
                  gfn, mfn, nr_mfns);
 
             for ( i = 0; i < nr_mfns; i++ )
-                clear_mmio_p2m_entry(d, gfn+i);
+                clear_mmio_p2m_entry(p2m_get_hostp2m(d), gfn+i);
             ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
         }
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c        Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/emulate.c        Wed Aug 11 15:56:01 2010 +0100
@@ -55,6 +55,7 @@ int hvmemul_do_io(
     paddr_t value = ram_gpa;
     int value_is_ptr = (p_data == NULL);
     struct vcpu *curr = current;
+    struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
     ioreq_t *p = get_ioreq(curr);
     unsigned long ram_gfn = paddr_to_pfn(ram_gpa);
     p2m_type_t p2mt;
@@ -62,10 +63,10 @@ int hvmemul_do_io(
     int rc;
 
     /* Check for paged out page */
-    ram_mfn = gfn_to_mfn_unshare(current->domain, ram_gfn, &p2mt, 0);
+    ram_mfn = gfn_to_mfn_unshare(p2m, ram_gfn, &p2mt, 0);
     if ( p2m_is_paging(p2mt) )
     {
-        p2m_mem_paging_populate(curr->domain, ram_gfn);
+        p2m_mem_paging_populate(p2m, ram_gfn);
         return X86EMUL_RETRY;
     }
     if ( p2m_is_shared(p2mt) )
@@ -638,6 +639,7 @@ static int hvmemul_rep_movs(
     unsigned long saddr, daddr, bytes;
     paddr_t sgpa, dgpa;
     uint32_t pfec = PFEC_page_present;
+    struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
     p2m_type_t p2mt;
     int rc, df = !!(ctxt->regs->eflags & X86_EFLAGS_DF);
     char *buf;
@@ -668,12 +670,12 @@ static int hvmemul_rep_movs(
     if ( rc != X86EMUL_OKAY )
         return rc;
 
-    (void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
+    (void)gfn_to_mfn(p2m, sgpa >> PAGE_SHIFT, &p2mt);
     if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
         return hvmemul_do_mmio(
             sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL);
 
-    (void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt);
+    (void)gfn_to_mfn(p2m, dgpa >> PAGE_SHIFT, &p2mt);
     if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
         return hvmemul_do_mmio(
             dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL);
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Wed Aug 11 15:56:01 2010 +0100
@@ -335,16 +335,17 @@ static int hvm_set_ioreq_page(
     struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn)
 {
     struct page_info *page;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     p2m_type_t p2mt;
     unsigned long mfn;
     void *va;
 
-    mfn = mfn_x(gfn_to_mfn_unshare(d, gmfn, &p2mt, 0));
+    mfn = mfn_x(gfn_to_mfn_unshare(p2m, gmfn, &p2mt, 0));
     if ( !p2m_is_ram(p2mt) )
         return -EINVAL;
     if ( p2m_is_paging(p2mt) )
     {
-        p2m_mem_paging_populate(d, gmfn);
+        p2m_mem_paging_populate(p2m, gmfn);
         return -ENOENT;
     }
     if ( p2m_is_shared(p2mt) )
@@ -968,8 +969,10 @@ bool_t hvm_hap_nested_page_fault(unsigne
 {
     p2m_type_t p2mt;
     mfn_t mfn;
-
-    mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
+    struct vcpu *v = current;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
+
+    mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
 
     /*
      * If this GFN is emulated MMIO or marked as read-only, pass the fault
@@ -985,12 +988,12 @@ bool_t hvm_hap_nested_page_fault(unsigne
 #ifdef __x86_64__
     /* Check if the page has been paged out */
     if ( p2m_is_paged(p2mt) || (p2mt == p2m_ram_paging_out) )
-        p2m_mem_paging_populate(current->domain, gfn);
+        p2m_mem_paging_populate(p2m, gfn);
 
     /* Mem sharing: unshare the page and try again */
     if ( p2mt == p2m_ram_shared )
     {
-        mem_sharing_unshare_page(current->domain, gfn, 0);
+        mem_sharing_unshare_page(p2m, gfn, 0);
         return 1;
     }
 #endif
@@ -1003,8 +1006,8 @@ bool_t hvm_hap_nested_page_fault(unsigne
          * a large page, we do not change other pages type within that large
          * page.
          */
-        paging_mark_dirty(current->domain, mfn_x(mfn));
-        p2m_change_type(current->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
+        paging_mark_dirty(v->domain, mfn_x(mfn));
+        p2m_change_type(p2m, gfn, p2m_ram_logdirty, p2m_ram_rw);
         return 1;
     }
 
@@ -1088,6 +1091,7 @@ int hvm_set_cr0(unsigned long value)
 {
     struct vcpu *v = current;
     p2m_type_t p2mt;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
     unsigned long gfn, mfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
 
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
@@ -1126,7 +1130,7 @@ int hvm_set_cr0(unsigned long value)
         {
             /* The guest CR3 must be pointing to the guest physical. */
             gfn = v->arch.hvm_vcpu.guest_cr[3]>>PAGE_SHIFT;
-            mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
+            mfn = mfn_x(gfn_to_mfn(p2m, gfn, &p2mt));
             if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
                  !get_page(mfn_to_page(mfn), v->domain))
             {
@@ -1213,7 +1217,8 @@ int hvm_set_cr3(unsigned long value)
     {
         /* Shadow-mode CR3 change. Check PDBR and update refcounts. */
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
-        mfn = mfn_x(gfn_to_mfn_current(value >> PAGE_SHIFT, &p2mt));
+        mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
+            value >> PAGE_SHIFT, &p2mt));
         if ( !p2m_is_ram(p2mt) || !mfn_valid(mfn) ||
              !get_page(mfn_to_page(mfn), v->domain) )
               goto bad_cr3;
@@ -1356,6 +1361,8 @@ static void *hvm_map_entry(unsigned long
     unsigned long gfn, mfn;
     p2m_type_t p2mt;
     uint32_t pfec;
+    struct vcpu *v = current;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
 
     if ( ((va & ~PAGE_MASK) + 8) > PAGE_SIZE )
     {
@@ -1372,10 +1379,10 @@ static void *hvm_map_entry(unsigned long
     gfn = paging_gva_to_gfn(current, va, &pfec);
     if ( pfec == PFEC_page_paged || pfec == PFEC_page_shared )
         return NULL;
-    mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
+    mfn = mfn_x(gfn_to_mfn_unshare(p2m, gfn, &p2mt, 0));
     if ( p2m_is_paging(p2mt) )
     {
-        p2m_mem_paging_populate(current->domain, gfn);
+        p2m_mem_paging_populate(p2m, gfn);
         return NULL;
     }
     if ( p2m_is_shared(p2mt) )
@@ -1742,6 +1749,7 @@ static enum hvm_copy_result __hvm_copy(
     void *buf, paddr_t addr, int size, unsigned int flags, uint32_t pfec)
 {
     struct vcpu *curr = current;
+    struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain);
     unsigned long gfn, mfn;
     p2m_type_t p2mt;
     char *p;
@@ -1770,11 +1778,11 @@ static enum hvm_copy_result __hvm_copy(
             gfn = addr >> PAGE_SHIFT;
         }
 
-        mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
+        mfn = mfn_x(gfn_to_mfn_unshare(p2m, gfn, &p2mt, 0));
 
         if ( p2m_is_paging(p2mt) )
         {
-            p2m_mem_paging_populate(curr->domain, gfn);
+            p2m_mem_paging_populate(p2m, gfn);
             return HVMCOPY_gfn_paged_out;
         }
         if ( p2m_is_shared(p2mt) )
@@ -2021,7 +2029,7 @@ int hvm_msr_read_intercept(unsigned int 
     uint64_t *var_range_base, *fixed_range_base;
     int index, mtrr;
     uint32_t cpuid[4];
-    int ret;
+    int ret = X86EMUL_OKAY;
 
     var_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.var_ranges;
     fixed_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.fixed_ranges;
@@ -2094,24 +2102,25 @@ int hvm_msr_read_intercept(unsigned int 
          break;
 
     default:
-        ret = vmce_rdmsr(msr, msr_content);
-        if ( ret < 0 )
+        if ( (ret = vmce_rdmsr(msr, msr_content)) < 0 )
             goto gp_fault;
-        else if ( ret )
-            break;
-        /* ret == 0, This is not an MCE MSR, see other MSRs */
-        else if (!ret) {
-            return hvm_funcs.msr_read_intercept(msr, msr_content);
-        }
-    }
-
-    HVMTRACE_3D(MSR_READ, (uint32_t)*msr_content, (uint32_t)(*msr_content >> 
32), msr);
-
-    return X86EMUL_OKAY;
-
-gp_fault:
+        /* If ret == 0 then this is not an MCE MSR, see other MSRs. */
+        ret = ((ret == 0)
+               ? hvm_funcs.msr_read_intercept(msr, msr_content)
+               : X86EMUL_OKAY);
+        break;
+    }
+
+ out:
+    HVMTRACE_3D(MSR_READ, msr,
+                (uint32_t)*msr_content, (uint32_t)(*msr_content >> 32));
+    return ret;
+
+ gp_fault:
     hvm_inject_exception(TRAP_gp_fault, 0, 0);
-    return X86EMUL_EXCEPTION;
+    ret = X86EMUL_EXCEPTION;
+    *msr_content = -1ull;
+    goto out;
 }
 
 int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
@@ -2119,9 +2128,10 @@ int hvm_msr_write_intercept(unsigned int
     struct vcpu *v = current;
     int index, mtrr;
     uint32_t cpuid[4];
-    int ret;
-
-    HVMTRACE_3D(MSR_WRITE, (uint32_t)msr_content, (uint32_t)(msr_content >> 
32), msr);
+    int ret = X86EMUL_OKAY;
+
+    HVMTRACE_3D(MSR_WRITE, msr,
+               (uint32_t)msr_content, (uint32_t)(msr_content >> 32));
 
     hvm_cpuid(1, &cpuid[0], &cpuid[1], &cpuid[2], &cpuid[3]);
     mtrr = !!(cpuid[3] & bitmaskof(X86_FEATURE_MTRR));
@@ -2194,16 +2204,16 @@ int hvm_msr_write_intercept(unsigned int
         break;
 
     default:
-        ret = vmce_wrmsr(msr, msr_content);
-        if ( ret < 0 )
+        if ( (ret = vmce_wrmsr(msr, msr_content)) < 0 )
             goto gp_fault;
-        else if ( ret )
-            break;
-        else if (!ret)
-            return hvm_funcs.msr_write_intercept(msr, msr_content);
-    }
-
-    return X86EMUL_OKAY;
+        /* If ret == 0 then this is not an MCE MSR, see other MSRs. */
+        ret = ((ret == 0)
+               ? hvm_funcs.msr_write_intercept(msr, msr_content)
+               : X86EMUL_OKAY);
+        break;
+    }
+
+    return ret;
 
 gp_fault:
     hvm_inject_exception(TRAP_gp_fault, 0, 0);
@@ -3029,6 +3039,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
     {
         struct xen_hvm_modified_memory a;
         struct domain *d;
+        struct p2m_domain *p2m;
         unsigned long pfn;
 
         if ( copy_from_guest(&a, arg, 1) )
@@ -3056,13 +3067,14 @@ long do_hvm_op(unsigned long op, XEN_GUE
         if ( !paging_mode_log_dirty(d) )
             goto param_fail3;
 
+        p2m = p2m_get_hostp2m(d);
         for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
         {
             p2m_type_t t;
-            mfn_t mfn = gfn_to_mfn(d, pfn, &t);
+            mfn_t mfn = gfn_to_mfn(p2m, pfn, &t);
             if ( p2m_is_paging(t) )
             {
-                p2m_mem_paging_populate(d, pfn);
+                p2m_mem_paging_populate(p2m, pfn);
 
                 rc = -EINVAL;
                 goto param_fail3;
@@ -3089,6 +3101,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
     {
         struct xen_hvm_set_mem_type a;
         struct domain *d;
+        struct p2m_domain *p2m;
         unsigned long pfn;
         
         /* Interface types to internal p2m types */
@@ -3118,15 +3131,16 @@ long do_hvm_op(unsigned long op, XEN_GUE
         if ( a.hvmmem_type >= ARRAY_SIZE(memtype) )
             goto param_fail4;
 
+        p2m = p2m_get_hostp2m(d);
         for ( pfn = a.first_pfn; pfn < a.first_pfn + a.nr; pfn++ )
         {
             p2m_type_t t;
             p2m_type_t nt;
             mfn_t mfn;
-            mfn = gfn_to_mfn_unshare(d, pfn, &t, 0);
+            mfn = gfn_to_mfn_unshare(p2m, pfn, &t, 0);
             if ( p2m_is_paging(t) )
             {
-                p2m_mem_paging_populate(d, pfn);
+                p2m_mem_paging_populate(p2m, pfn);
 
                 rc = -EINVAL;
                 goto param_fail4;
@@ -3145,7 +3159,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
             }
             else
             {
-                nt = p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
+                nt = p2m_change_type(p2m, pfn, t, memtype[a.hvmmem_type]);
                 if ( nt != t )
                 {
                     gdprintk(XENLOG_WARNING,
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/mtrr.c
--- a/xen/arch/x86/hvm/mtrr.c   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/mtrr.c   Wed Aug 11 15:56:01 2010 +0100
@@ -399,7 +399,7 @@ uint32_t get_pat_flags(struct vcpu *v,
     {
         struct domain *d = v->domain;
         p2m_type_t p2mt;
-        gfn_to_mfn(d, paddr_to_pfn(gpaddr), &p2mt);
+        gfn_to_mfn(p2m_get_hostp2m(d), paddr_to_pfn(gpaddr), &p2mt);
         if (p2m_is_ram(p2mt))
             gdprintk(XENLOG_WARNING,
                     "Conflict occurs for a given guest l1e flags:%x "
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/stdvga.c
--- a/xen/arch/x86/hvm/stdvga.c Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/stdvga.c Wed Aug 11 15:56:01 2010 +0100
@@ -469,6 +469,7 @@ static int mmio_move(struct hvm_hw_stdvg
     int i;
     int sign = p->df ? -1 : 1;
     p2m_type_t p2mt;
+    struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
 
     if ( p->data_is_ptr )
     {
@@ -481,7 +482,7 @@ static int mmio_move(struct hvm_hw_stdvg
                 if ( hvm_copy_to_guest_phys(data, &tmp, p->size) !=
                      HVMCOPY_okay )
                 {
-                    (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
+                    (void)gfn_to_mfn(p2m, data >> PAGE_SHIFT, &p2mt);
                     /*
                      * The only case we handle is vga_mem <-> vga_mem.
                      * Anything else disables caching and leaves it to qemu-dm.
@@ -503,7 +504,7 @@ static int mmio_move(struct hvm_hw_stdvg
                 if ( hvm_copy_from_guest_phys(&tmp, data, p->size) !=
                      HVMCOPY_okay )
                 {
-                    (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt);
+                    (void)gfn_to_mfn(p2m, data >> PAGE_SHIFT, &p2mt);
                     if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) ||
                          ((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) )
                         return 0;
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Wed Aug 11 15:56:01 2010 +0100
@@ -232,7 +232,7 @@ static int svm_vmcb_restore(struct vcpu 
     {
         if ( c->cr0 & X86_CR0_PG )
         {
-            mfn = mfn_x(gfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT, &p2mt));
+            mfn = mfn_x(gfn_to_mfn(p2m, c->cr3 >> PAGE_SHIFT, &p2mt));
             if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
             {
                 gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%"PRIx64"\n",
@@ -946,6 +946,9 @@ static void svm_do_nested_pgfault(paddr_
     unsigned long gfn = gpa >> PAGE_SHIFT;
     mfn_t mfn;
     p2m_type_t p2mt;
+    struct p2m_domain *p2m;
+
+    p2m = p2m_get_hostp2m(current->domain);
 
     if ( tb_init_done )
     {
@@ -958,7 +961,7 @@ static void svm_do_nested_pgfault(paddr_
 
         _d.gpa = gpa;
         _d.qualification = 0;
-        _d.mfn = mfn_x(gfn_to_mfn_query(current->domain, gfn, &_d.p2mt));
+        _d.mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &_d.p2mt));
         
         __trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&_d);
     }
@@ -967,7 +970,7 @@ static void svm_do_nested_pgfault(paddr_
         return;
 
     /* Everything else is an error. */
-    mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
+    mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
     gdprintk(XENLOG_ERR, "SVM violation gpa %#"PRIpaddr", mfn %#lx, type %i\n",
              gpa, mfn_x(mfn), p2mt);
     domain_crash(current->domain);
@@ -1117,8 +1120,6 @@ static int svm_msr_read_intercept(unsign
         goto gpf;
     }
 
-    HVMTRACE_3D (MSR_READ, msr,
-                (uint32_t)*msr_content, (uint32_t)(*msr_content>>32));
     HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, msr_value=%"PRIx64,
                 msr, *msr_content);
     return X86EMUL_OKAY;
@@ -1132,9 +1133,6 @@ static int svm_msr_write_intercept(unsig
 {
     struct vcpu *v = current;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    HVMTRACE_3D(MSR_WRITE, msr,
-               (uint32_t)msr_content, (uint32_t)(msr_content >> 32)); 
 
     switch ( msr )
     {
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/vmsi.c
--- a/xen/arch/x86/hvm/vmsi.c   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/vmsi.c   Wed Aug 11 15:56:01 2010 +0100
@@ -159,7 +159,10 @@ struct msixtbl_entry
     unsigned long gtable;       /* gpa of msix table */
     unsigned long table_len;
     unsigned long table_flags[MAX_MSIX_TABLE_ENTRIES / BITS_PER_LONG + 1];
-
+#define MAX_MSIX_ACC_ENTRIES 3
+    struct { 
+        uint32_t msi_ad[3];    /* Shadow of address low, high and data */
+    } gentries[MAX_MSIX_ACC_ENTRIES];
     struct rcu_head rcu;
 };
 
@@ -205,18 +208,15 @@ static int msixtbl_read(
     struct vcpu *v, unsigned long address,
     unsigned long len, unsigned long *pval)
 {
-    unsigned long offset;
+    unsigned long offset, val;
     struct msixtbl_entry *entry;
     void *virt;
+    int nr_entry, index;
     int r = X86EMUL_UNHANDLEABLE;
 
     rcu_read_lock(&msixtbl_rcu_lock);
 
     if ( len != 4 )
-        goto out;
-
-    offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
-    if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
         goto out;
 
     entry = msixtbl_find_entry(v, address);
@@ -224,9 +224,24 @@ static int msixtbl_read(
     if ( !virt )
         goto out;
 
-    *pval = readl(virt);
+    nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
+    offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
+    if ( nr_entry >= MAX_MSIX_ACC_ENTRIES && 
+         offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
+        goto out;
+
+    val = readl(virt);
+    if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET )
+    {
+        index = offset / sizeof(uint32_t);
+        *pval = entry->gentries[nr_entry].msi_ad[index];
+    }
+    else 
+    {
+        *pval = val;
+    }
+    
     r = X86EMUL_OKAY;
-
 out:
     rcu_read_unlock(&msixtbl_rcu_lock);
     return r;
@@ -238,7 +253,7 @@ static int msixtbl_write(struct vcpu *v,
     unsigned long offset;
     struct msixtbl_entry *entry;
     void *virt;
-    int nr_entry;
+    int nr_entry, index;
     int r = X86EMUL_UNHANDLEABLE;
 
     rcu_read_lock(&msixtbl_rcu_lock);
@@ -252,6 +267,11 @@ static int msixtbl_write(struct vcpu *v,
     offset = address & (PCI_MSIX_ENTRY_SIZE - 1);
     if ( offset != PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)
     {
+        if ( nr_entry < MAX_MSIX_ACC_ENTRIES ) 
+        {
+            index = offset / sizeof(uint32_t);
+            entry->gentries[nr_entry].msi_ad[index] = val;
+        }
         set_bit(nr_entry, &entry->table_flags);
         goto out;
     }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Wed Aug 11 15:56:01 2010 +0100
@@ -486,7 +486,8 @@ static int vmx_restore_cr0_cr3(
     {
         if ( cr0 & X86_CR0_PG )
         {
-            mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
+            mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
+                cr3 >> PAGE_SHIFT, &p2mt));
             if ( !p2m_is_ram(p2mt) || !get_page(mfn_to_page(mfn), v->domain) )
             {
                 gdprintk(XENLOG_ERR, "Invalid CR3 value=0x%lx\n", cr3);
@@ -1002,7 +1003,8 @@ static void vmx_load_pdptrs(struct vcpu 
     if ( cr3 & 0x1fUL )
         goto crash;
 
-    mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
+    mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain),
+        cr3 >> PAGE_SHIFT, &p2mt));
     if ( !p2m_is_ram(p2mt) )
         goto crash;
 
@@ -1221,7 +1223,7 @@ void ept_sync_domain(struct domain *d)
         return;
 
     ASSERT(local_irq_is_enabled());
-    ASSERT(p2m_locked_by_me(d->arch.p2m));
+    ASSERT(p2m_locked_by_me(p2m_get_hostp2m(d)));
 
     /*
      * Flush active cpus synchronously. Flush others the next time this domain
@@ -1340,7 +1342,7 @@ static void vmx_set_uc_mode(struct vcpu 
 {
     if ( paging_mode_hap(v->domain) )
         ept_change_entry_emt_with_range(
-            v->domain, 0, v->domain->arch.p2m->max_mapped_pfn);
+            v->domain, 0, p2m_get_hostp2m(v->domain)->max_mapped_pfn);
     hvm_asid_flush_vcpu(v);
 }
 
@@ -1872,8 +1874,6 @@ static int vmx_msr_read_intercept(unsign
     }
 
 done:
-    HVMTRACE_3D(MSR_READ, msr,
-                (uint32_t)*msr_content, (uint32_t)(*msr_content >> 32));
     HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%x, msr_value=0x%"PRIx64,
                 msr, *msr_content);
     return X86EMUL_OKAY;
@@ -1895,7 +1895,8 @@ static int vmx_alloc_vlapic_mapping(stru
         return -ENOMEM;
     share_xen_page_with_guest(virt_to_page(apic_va), d, XENSHARE_writable);
     set_mmio_p2m_entry(
-        d, paddr_to_pfn(APIC_DEFAULT_PHYS_BASE), _mfn(virt_to_mfn(apic_va)));
+        p2m_get_hostp2m(d), paddr_to_pfn(APIC_DEFAULT_PHYS_BASE),
+        _mfn(virt_to_mfn(apic_va)));
     d->arch.hvm_domain.vmx.apic_access_mfn = virt_to_mfn(apic_va);
 
     return 0;
@@ -1949,9 +1950,6 @@ static int vmx_msr_write_intercept(unsig
 
     HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%x, msr_value=0x%"PRIx64,
                 msr, msr_content);
-
-    HVMTRACE_3D(MSR_WRITE, msr,
-               (uint32_t)msr_content, (uint32_t)(msr_content >> 32));
 
     switch ( msr )
     {
@@ -2103,6 +2101,7 @@ static void ept_handle_violation(unsigne
     unsigned long gla, gfn = gpa >> PAGE_SHIFT;
     mfn_t mfn;
     p2m_type_t p2mt;
+    struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
 
     if ( tb_init_done )
     {
@@ -2115,7 +2114,7 @@ static void ept_handle_violation(unsigne
 
         _d.gpa = gpa;
         _d.qualification = qualification;
-        _d.mfn = mfn_x(gfn_to_mfn_query(current->domain, gfn, &_d.p2mt));
+        _d.mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &_d.p2mt));
         
         __trace_var(TRC_HVM_NPF, 0, sizeof(_d), (unsigned char *)&_d);
     }
@@ -2125,7 +2124,7 @@ static void ept_handle_violation(unsigne
         return;
 
     /* Everything else is an error. */
-    mfn = gfn_to_mfn_type_current(gfn, &p2mt, p2m_guest);
+    mfn = gfn_to_mfn_guest(p2m, gfn, &p2mt);
     gdprintk(XENLOG_ERR, "EPT violation %#lx (%c%c%c/%c%c%c), "
              "gpa %#"PRIpaddr", mfn %#lx, type %i.\n", 
              qualification, 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm.c Wed Aug 11 15:56:01 2010 +0100
@@ -398,7 +398,7 @@ unsigned long domain_get_maximum_gpfn(st
 unsigned long domain_get_maximum_gpfn(struct domain *d)
 {
     if ( is_hvm_domain(d) )
-        return d->arch.p2m->max_mapped_pfn;
+        return p2m_get_hostp2m(d)->max_mapped_pfn;
     /* NB. PV guests specify nr_pfns rather than max_pfn so we adjust here. */
     return arch_get_max_pfn(d) - 1;
 }
@@ -1741,7 +1741,8 @@ static int mod_l1_entry(l1_pgentry_t *pl
     if ( l1e_get_flags(nl1e) & _PAGE_PRESENT )
     {
         /* Translate foreign guest addresses. */
-        mfn = mfn_x(gfn_to_mfn(pg_dom, l1e_get_pfn(nl1e), &p2mt));
+        mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pg_dom),
+            l1e_get_pfn(nl1e), &p2mt));
         if ( !p2m_is_ram(p2mt) || unlikely(mfn == INVALID_MFN) )
             return 0;
         ASSERT((mfn & ~(PADDR_MASK >> PAGE_SHIFT)) == 0);
@@ -3318,8 +3319,8 @@ int do_mmu_update(
     struct page_info *page;
     int rc = 0, okay = 1, i = 0;
     unsigned int cmd, done = 0, pt_dom;
-    struct domain *d = current->domain, *pt_owner = d, *pg_owner;
     struct vcpu *v = current;
+    struct domain *d = v->domain, *pt_owner = d, *pg_owner;
     struct domain_mmap_cache mapcache;
 
     if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
@@ -3403,13 +3404,13 @@ int do_mmu_update(
 
             req.ptr -= cmd;
             gmfn = req.ptr >> PAGE_SHIFT;
-            mfn = mfn_x(gfn_to_mfn(pt_owner, gmfn, &p2mt));
+            mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pt_owner), gmfn, &p2mt));
             if ( !p2m_is_valid(p2mt) )
               mfn = INVALID_MFN;
 
             if ( p2m_is_paged(p2mt) )
             {
-                p2m_mem_paging_populate(pg_owner, gmfn);
+                p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner), gmfn);
 
                 rc = -ENOENT;
                 break;
@@ -3434,12 +3435,13 @@ int do_mmu_update(
                 {
                     l1_pgentry_t l1e = l1e_from_intpte(req.val);
                     p2m_type_t l1e_p2mt;
-                    gfn_to_mfn(pg_owner, l1e_get_pfn(l1e), &l1e_p2mt);
+                    gfn_to_mfn(p2m_get_hostp2m(pg_owner),
+                        l1e_get_pfn(l1e), &l1e_p2mt);
 
                     if ( p2m_is_paged(l1e_p2mt) )
                     {
-                        p2m_mem_paging_populate(pg_owner, l1e_get_pfn(l1e));
-
+                        p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+                            l1e_get_pfn(l1e));
                         rc = -ENOENT;
                         break;
                     }
@@ -3457,7 +3459,7 @@ int do_mmu_update(
                         /* Unshare the page for RW foreign mappings */
                         if ( l1e_get_flags(l1e) & _PAGE_RW )
                         {
-                            rc = mem_sharing_unshare_page(pg_owner, 
+                            rc = 
mem_sharing_unshare_page(p2m_get_hostp2m(pg_owner), 
                                                           l1e_get_pfn(l1e), 
                                                           0);
                             if ( rc )
@@ -3475,12 +3477,12 @@ int do_mmu_update(
                 {
                     l2_pgentry_t l2e = l2e_from_intpte(req.val);
                     p2m_type_t l2e_p2mt;
-                    gfn_to_mfn(pg_owner, l2e_get_pfn(l2e), &l2e_p2mt);
+                    gfn_to_mfn(p2m_get_hostp2m(pg_owner), l2e_get_pfn(l2e), 
&l2e_p2mt);
 
                     if ( p2m_is_paged(l2e_p2mt) )
                     {
-                        p2m_mem_paging_populate(pg_owner, l2e_get_pfn(l2e));
-
+                        p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+                            l2e_get_pfn(l2e));
                         rc = -ENOENT;
                         break;
                     }
@@ -3505,12 +3507,12 @@ int do_mmu_update(
                 {
                     l3_pgentry_t l3e = l3e_from_intpte(req.val);
                     p2m_type_t l3e_p2mt;
-                    gfn_to_mfn(pg_owner, l3e_get_pfn(l3e), &l3e_p2mt);
+                    gfn_to_mfn(p2m_get_hostp2m(pg_owner), l3e_get_pfn(l3e), 
&l3e_p2mt);
 
                     if ( p2m_is_paged(l3e_p2mt) )
                     {
-                        p2m_mem_paging_populate(pg_owner, l3e_get_pfn(l3e));
-
+                        p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+                            l3e_get_pfn(l3e));
                         rc = -ENOENT;
                         break;
                     }
@@ -3536,12 +3538,13 @@ int do_mmu_update(
                 {
                     l4_pgentry_t l4e = l4e_from_intpte(req.val);
                     p2m_type_t l4e_p2mt;
-                    gfn_to_mfn(pg_owner, l4e_get_pfn(l4e), &l4e_p2mt);
+                    gfn_to_mfn(p2m_get_hostp2m(pg_owner),
+                        l4e_get_pfn(l4e), &l4e_p2mt);
 
                     if ( p2m_is_paged(l4e_p2mt) )
                     {
-                        p2m_mem_paging_populate(pg_owner, l4e_get_pfn(l4e));
-
+                        p2m_mem_paging_populate(p2m_get_hostp2m(pg_owner),
+                            l4e_get_pfn(l4e));
                         rc = -ENOENT;
                         break;
                     }
@@ -3923,8 +3926,8 @@ static int create_grant_p2m_mapping(uint
         p2mt = p2m_grant_map_ro;
     else
         p2mt = p2m_grant_map_rw;
-    rc = guest_physmap_add_entry(current->domain, addr >> PAGE_SHIFT,
-                                 frame, 0, p2mt);
+    rc = guest_physmap_add_entry(p2m_get_hostp2m(current->domain),
+                                 addr >> PAGE_SHIFT, frame, 0, p2mt);
     if ( rc )
         return GNTST_general_error;
     else
@@ -3962,11 +3965,12 @@ static int replace_grant_p2m_mapping(
     unsigned long gfn = (unsigned long)(addr >> PAGE_SHIFT);
     p2m_type_t type;
     mfn_t old_mfn;
+    struct domain *d = current->domain;
 
     if ( new_addr != 0 || (flags & GNTMAP_contains_pte) )
         return GNTST_general_error;
 
-    old_mfn = gfn_to_mfn_current(gfn, &type);
+    old_mfn = gfn_to_mfn(p2m_get_hostp2m(d), gfn, &type);
     if ( !p2m_is_grant(type) || mfn_x(old_mfn) != frame )
     {
         gdprintk(XENLOG_WARNING,
@@ -3974,7 +3978,7 @@ static int replace_grant_p2m_mapping(
                  type, mfn_x(old_mfn), frame);
         return GNTST_general_error;
     }
-    guest_physmap_remove_page(current->domain, gfn, frame, 0);
+    guest_physmap_remove_page(d, gfn, frame, 0);
 
     return GNTST_okay;
 }
@@ -4581,7 +4585,8 @@ long arch_memory_op(int op, XEN_GUEST_HA
         {
             p2m_type_t p2mt;
 
-            xatp.idx = mfn_x(gfn_to_mfn_unshare(d, xatp.idx, &p2mt, 0));
+            xatp.idx = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(d),
+                                                xatp.idx, &p2mt, 0));
             /* If the page is still shared, exit early */
             if ( p2m_is_shared(p2mt) )
             {
@@ -4771,6 +4776,7 @@ long arch_memory_op(int op, XEN_GUEST_HA
     {
         xen_pod_target_t target;
         struct domain *d;
+        struct p2m_domain *p2m;
 
         /* Support DOMID_SELF? */
         if ( !IS_PRIV(current->domain) )
@@ -4794,9 +4800,10 @@ long arch_memory_op(int op, XEN_GUEST_HA
             rc = p2m_pod_set_mem_target(d, target.target_pages);
         }
 
+        p2m = p2m_get_hostp2m(d);
         target.tot_pages       = d->tot_pages;
-        target.pod_cache_pages = d->arch.p2m->pod.count;
-        target.pod_entries     = d->arch.p2m->pod.entry_count;
+        target.pod_cache_pages = p2m->pod.count;
+        target.pod_entries     = p2m->pod.entry_count;
 
         if ( copy_to_guest(arg, &target, 1) )
         {
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/guest_walk.c
--- a/xen/arch/x86/mm/guest_walk.c      Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/guest_walk.c      Wed Aug 11 15:56:01 2010 +0100
@@ -86,17 +86,17 @@ static uint32_t set_ad_bits(void *guest_
     return 0;
 }
 
-static inline void *map_domain_gfn(struct domain *d,
+static inline void *map_domain_gfn(struct p2m_domain *p2m,
                                    gfn_t gfn, 
                                    mfn_t *mfn,
                                    p2m_type_t *p2mt,
                                    uint32_t *rc) 
 {
     /* Translate the gfn, unsharing if shared */
-    *mfn = gfn_to_mfn_unshare(d, gfn_x(gfn), p2mt, 0);
+    *mfn = gfn_to_mfn_unshare(p2m, gfn_x(gfn), p2mt, 0);
     if ( p2m_is_paging(*p2mt) )
     {
-        p2m_mem_paging_populate(d, gfn_x(gfn));
+        p2m_mem_paging_populate(p2m, gfn_x(gfn));
 
         *rc = _PAGE_PAGED;
         return NULL;
@@ -119,7 +119,8 @@ static inline void *map_domain_gfn(struc
 
 /* Walk the guest pagetables, after the manner of a hardware walker. */
 uint32_t
-guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, 
+guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
+                  unsigned long va, walk_t *gw, 
                   uint32_t pfec, mfn_t top_mfn, void *top_map)
 {
     struct domain *d = v->domain;
@@ -154,7 +155,7 @@ guest_walk_tables(struct vcpu *v, unsign
     if ( rc & _PAGE_PRESENT ) goto out;
 
     /* Map the l3 table */
-    l3p = map_domain_gfn(d, 
+    l3p = map_domain_gfn(p2m, 
                          guest_l4e_get_gfn(gw->l4e), 
                          &gw->l3mfn,
                          &p2mt, 
@@ -181,7 +182,7 @@ guest_walk_tables(struct vcpu *v, unsign
 #endif /* PAE or 64... */
 
     /* Map the l2 table */
-    l2p = map_domain_gfn(d, 
+    l2p = map_domain_gfn(p2m, 
                          guest_l3e_get_gfn(gw->l3e), 
                          &gw->l2mfn,
                          &p2mt, 
@@ -237,7 +238,7 @@ guest_walk_tables(struct vcpu *v, unsign
     else 
     {
         /* Not a superpage: carry on and find the l1e. */
-        l1p = map_domain_gfn(d, 
+        l1p = map_domain_gfn(p2m, 
                              guest_l2e_get_gfn(gw->l2e), 
                              &gw->l1mfn,
                              &p2mt,
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/hap/guest_walk.c
--- a/xen/arch/x86/mm/hap/guest_walk.c  Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/hap/guest_walk.c  Wed Aug 11 15:56:01 2010 +0100
@@ -43,13 +43,14 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
     void *top_map;
     p2m_type_t p2mt;
     walk_t gw;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
 
     /* Get the top-level table's MFN */
     cr3 = v->arch.hvm_vcpu.guest_cr[3];
-    top_mfn = gfn_to_mfn_unshare(v->domain, cr3 >> PAGE_SHIFT, &p2mt, 0);
+    top_mfn = gfn_to_mfn_unshare(p2m, cr3 >> PAGE_SHIFT, &p2mt, 0);
     if ( p2m_is_paging(p2mt) )
     {
-        p2m_mem_paging_populate(v->domain, cr3 >> PAGE_SHIFT);
+        p2m_mem_paging_populate(p2m, cr3 >> PAGE_SHIFT);
 
         pfec[0] = PFEC_page_paged;
         return INVALID_GFN;
@@ -71,17 +72,17 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
 #if GUEST_PAGING_LEVELS == 3
     top_map += (cr3 & ~(PAGE_MASK | 31));
 #endif
-    missing = guest_walk_tables(v, gva, &gw, pfec[0], top_mfn, top_map);
+    missing = guest_walk_tables(v, p2m, gva, &gw, pfec[0], top_mfn, top_map);
     unmap_domain_page(top_map);
 
     /* Interpret the answer */
     if ( missing == 0 )
     {
         gfn_t gfn = guest_l1e_get_gfn(gw.l1e);
-        gfn_to_mfn_unshare(v->domain, gfn_x(gfn), &p2mt, 0);
+        gfn_to_mfn_unshare(p2m, gfn_x(gfn), &p2mt, 0);
         if ( p2m_is_paging(p2mt) )
         {
-            p2m_mem_paging_populate(v->domain, gfn_x(gfn));
+            p2m_mem_paging_populate(p2m, gfn_x(gfn));
 
             pfec[0] = PFEC_page_paged;
             return INVALID_GFN;
@@ -130,4 +131,3 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
  * indent-tabs-mode: nil
  * End:
  */
-
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/hap/hap.c
--- a/xen/arch/x86/mm/hap/hap.c Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/hap/hap.c Wed Aug 11 15:56:01 2010 +0100
@@ -70,7 +70,7 @@ static int hap_enable_vram_tracking(stru
 
     /* set l1e entries of P2M table to be read-only. */
     for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
-        p2m_change_type(d, i, p2m_ram_rw, p2m_ram_logdirty);
+        p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_rw, p2m_ram_logdirty);
 
     flush_tlb_mask(&d->domain_dirty_cpumask);
     return 0;
@@ -90,7 +90,7 @@ static int hap_disable_vram_tracking(str
 
     /* set l1e entries of P2M table with normal mode */
     for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
-        p2m_change_type(d, i, p2m_ram_logdirty, p2m_ram_rw);
+        p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_logdirty, p2m_ram_rw);
 
     flush_tlb_mask(&d->domain_dirty_cpumask);
     return 0;
@@ -106,7 +106,7 @@ static void hap_clean_vram_tracking(stru
 
     /* set l1e entries of P2M table to be read-only. */
     for (i = dirty_vram->begin_pfn; i < dirty_vram->end_pfn; i++)
-        p2m_change_type(d, i, p2m_ram_rw, p2m_ram_logdirty);
+        p2m_change_type(p2m_get_hostp2m(d), i, p2m_ram_rw, p2m_ram_logdirty);
 
     flush_tlb_mask(&d->domain_dirty_cpumask);
 }
@@ -200,7 +200,8 @@ static int hap_enable_log_dirty(struct d
     hap_unlock(d);
 
     /* set l1e entries of P2M table to be read-only. */
-    p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
+    p2m_change_entry_type_global(p2m_get_hostp2m(d),
+        p2m_ram_rw, p2m_ram_logdirty);
     flush_tlb_mask(&d->domain_dirty_cpumask);
     return 0;
 }
@@ -212,14 +213,16 @@ static int hap_disable_log_dirty(struct 
     hap_unlock(d);
 
     /* set l1e entries of P2M table with normal mode */
-    p2m_change_entry_type_global(d, p2m_ram_logdirty, p2m_ram_rw);
+    p2m_change_entry_type_global(p2m_get_hostp2m(d),
+        p2m_ram_logdirty, p2m_ram_rw);
     return 0;
 }
 
 static void hap_clean_dirty_bitmap(struct domain *d)
 {
     /* set l1e entries of P2M table to be read-only. */
-    p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
+    p2m_change_entry_type_global(p2m_get_hostp2m(d),
+        p2m_ram_rw, p2m_ram_logdirty);
     flush_tlb_mask(&d->domain_dirty_cpumask);
 }
 
@@ -273,8 +276,9 @@ static void hap_free(struct domain *d, m
     page_list_add_tail(pg, &d->arch.paging.hap.freelist);
 }
 
-static struct page_info *hap_alloc_p2m_page(struct domain *d)
-{
+static struct page_info *hap_alloc_p2m_page(struct p2m_domain *p2m)
+{
+    struct domain *d = p2m->domain;
     struct page_info *pg;
 
     hap_lock(d);
@@ -312,8 +316,9 @@ static struct page_info *hap_alloc_p2m_p
     return pg;
 }
 
-static void hap_free_p2m_page(struct domain *d, struct page_info *pg)
-{
+static void hap_free_p2m_page(struct p2m_domain *p2m, struct page_info *pg)
+{
+    struct domain *d = p2m->domain;
     hap_lock(d);
     ASSERT(page_get_owner(pg) == d);
     /* Should have just the one ref we gave it in alloc_p2m_page() */
@@ -594,7 +599,8 @@ int hap_enable(struct domain *d, u32 mod
     /* allocate P2m table */
     if ( mode & PG_translate )
     {
-        rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page);
+        rv = p2m_alloc_table(p2m_get_hostp2m(d),
+            hap_alloc_p2m_page, hap_free_p2m_page);
         if ( rv != 0 )
             goto out;
     }
@@ -611,7 +617,7 @@ void hap_final_teardown(struct domain *d
     if ( d->arch.paging.hap.total_pages != 0 )
         hap_teardown(d);
 
-    p2m_teardown(d);
+    p2m_teardown(p2m_get_hostp2m(d));
     ASSERT(d->arch.paging.hap.p2m_pages == 0);
 }
 
@@ -711,9 +717,11 @@ static int hap_page_fault(struct vcpu *v
 static int hap_page_fault(struct vcpu *v, unsigned long va,
                           struct cpu_user_regs *regs)
 {
+    struct domain *d = v->domain;
+
     HAP_ERROR("Intercepted a guest #PF (%u:%u) with HAP enabled.\n",
-              v->domain->domain_id, v->vcpu_id);
-    domain_crash(v->domain);
+              d->domain_id, v->vcpu_id);
+    domain_crash(d);
     return 0;
 }
 
@@ -882,5 +890,3 @@ static const struct paging_mode hap_pagi
  * indent-tabs-mode: nil
  * End:
  */
-
-
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/hap/p2m-ept.c     Wed Aug 11 15:56:01 2010 +0100
@@ -36,23 +36,23 @@
 #define is_epte_superpage(ept_entry)    ((ept_entry)->sp)
 
 /* Non-ept "lock-and-check" wrapper */
-static int ept_pod_check_and_populate(struct domain *d, unsigned long gfn,
+static int ept_pod_check_and_populate(struct p2m_domain *p2m, unsigned long 
gfn,
                                       ept_entry_t *entry, int order,
                                       p2m_query_t q)
 {
     int r;
-    p2m_lock(d->arch.p2m);
+    p2m_lock(p2m);
 
     /* Check to make sure this is still PoD */
     if ( entry->avail1 != p2m_populate_on_demand )
     {
-        p2m_unlock(d->arch.p2m);
+        p2m_unlock(p2m);
         return 0;
     }
 
-    r = p2m_pod_demand_populate(d, gfn, order, q);
-
-    p2m_unlock(d->arch.p2m);
+    r = p2m_pod_demand_populate(p2m, gfn, order, q);
+
+    p2m_unlock(p2m);
 
     return r;
 }
@@ -98,11 +98,11 @@ static void ept_p2m_type_to_flags(ept_en
 #define GUEST_TABLE_POD_PAGE    3
 
 /* Fill in middle levels of ept table */
-static int ept_set_middle_entry(struct domain *d, ept_entry_t *ept_entry)
+static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
 {
     struct page_info *pg;
 
-    pg = p2m_alloc_ptp(d, 0);
+    pg = p2m_alloc_ptp(p2m, 0);
     if ( pg == NULL )
         return 0;
 
@@ -119,7 +119,7 @@ static int ept_set_middle_entry(struct d
 }
 
 /* free ept sub tree behind an entry */
-void ept_free_entry(struct domain *d, ept_entry_t *ept_entry, int level)
+void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
 {
     /* End if the entry is a leaf entry. */
     if ( level == 0 || !is_epte_present(ept_entry) ||
@@ -130,14 +130,14 @@ void ept_free_entry(struct domain *d, ep
     {
         ept_entry_t *epte = map_domain_page(ept_entry->mfn);
         for ( int i = 0; i < EPT_PAGETABLE_ENTRIES; i++ )
-            ept_free_entry(d, epte + i, level - 1);
+            ept_free_entry(p2m, epte + i, level - 1);
         unmap_domain_page(epte);
     }
 
-    d->arch.p2m->free_page(d, mfn_to_page(ept_entry->mfn));
-}
-
-static int ept_split_super_page(struct domain *d, ept_entry_t *ept_entry,
+    p2m->free_page(p2m, mfn_to_page(ept_entry->mfn));
+}
+
+static int ept_split_super_page(struct p2m_domain *p2m, ept_entry_t *ept_entry,
                                 int level, int target)
 {
     ept_entry_t new_ept, *table;
@@ -150,7 +150,7 @@ static int ept_split_super_page(struct d
 
     ASSERT(is_epte_superpage(ept_entry));
 
-    if ( !ept_set_middle_entry(d, &new_ept) )
+    if ( !ept_set_middle_entry(p2m, &new_ept) )
         return 0;
 
     table = map_domain_page(new_ept.mfn);
@@ -174,7 +174,7 @@ static int ept_split_super_page(struct d
 
         ASSERT(is_epte_superpage(epte));
 
-        if ( !(rv = ept_split_super_page(d, epte, level - 1, target)) )
+        if ( !(rv = ept_split_super_page(p2m, epte, level - 1, target)) )
             break;
     }
 
@@ -200,7 +200,7 @@ static int ept_split_super_page(struct d
  *  GUEST_TABLE_POD:
  *   The next entry is marked populate-on-demand.
  */
-static int ept_next_level(struct domain *d, bool_t read_only,
+static int ept_next_level(struct p2m_domain *p2m, bool_t read_only,
                           ept_entry_t **table, unsigned long *gfn_remainder,
                           int next_level)
 {
@@ -225,7 +225,7 @@ static int ept_next_level(struct domain 
         if ( read_only )
             return GUEST_TABLE_MAP_FAILED;
 
-        if ( !ept_set_middle_entry(d, ept_entry) )
+        if ( !ept_set_middle_entry(p2m, ept_entry) )
             return GUEST_TABLE_MAP_FAILED;
     }
 
@@ -245,7 +245,7 @@ static int ept_next_level(struct domain 
  * by observing whether any gfn->mfn translations are modified.
  */
 static int
-ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
+ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, 
               unsigned int order, p2m_type_t p2mt)
 {
     ept_entry_t *table, *ept_entry;
@@ -259,6 +259,7 @@ ept_set_entry(struct domain *d, unsigned
     uint8_t ipat = 0;
     int need_modify_vtd_table = 1;
     int needs_sync = 1;
+    struct domain *d = p2m->domain;
 
     /*
      * the caller must make sure:
@@ -267,7 +268,7 @@ ept_set_entry(struct domain *d, unsigned
      * 3. passing a valid order.
      */
     if ( ((gfn | mfn_x(mfn)) & ((1UL << order) - 1)) ||
-         (gfn >> ((ept_get_wl(d) + 1) * EPT_TABLE_ORDER)) ||
+         ((u64)gfn >> ((ept_get_wl(d) + 1) * EPT_TABLE_ORDER)) ||
          (order % EPT_TABLE_ORDER) )
         return 0;
 
@@ -281,7 +282,7 @@ ept_set_entry(struct domain *d, unsigned
 
     for ( i = ept_get_wl(d); i > target; i-- )
     {
-        ret = ept_next_level(d, 0, &table, &gfn_remainder, i);
+        ret = ept_next_level(p2m, 0, &table, &gfn_remainder, i);
         if ( !ret )
             goto out;
         else if ( ret != GUEST_TABLE_NORMAL_PAGE )
@@ -311,7 +312,7 @@ ept_set_entry(struct domain *d, unsigned
         if ( mfn_valid(mfn_x(mfn)) || direct_mmio || p2m_is_paged(p2mt) ||
              (p2mt == p2m_ram_paging_in_start) )
         {
-            ept_entry->emt = epte_get_entry_emt(d, gfn, mfn, &ipat,
+            ept_entry->emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat,
                                                 direct_mmio);
             ept_entry->ipat = ipat;
             ept_entry->sp = order ? 1 : 0;
@@ -337,9 +338,9 @@ ept_set_entry(struct domain *d, unsigned
 
         split_ept_entry = *ept_entry;
 
-        if ( !ept_split_super_page(d, &split_ept_entry, i, target) )
-        {
-            ept_free_entry(d, &split_ept_entry, i);
+        if ( !ept_split_super_page(p2m, &split_ept_entry, i, target) )
+        {
+            ept_free_entry(p2m, &split_ept_entry, i);
             goto out;
         }
 
@@ -349,7 +350,7 @@ ept_set_entry(struct domain *d, unsigned
 
         /* then move to the level we want to make real changes */
         for ( ; i > target; i-- )
-            ept_next_level(d, 0, &table, &gfn_remainder, i);
+            ept_next_level(p2m, 0, &table, &gfn_remainder, i);
 
         ASSERT(i == target);
 
@@ -374,8 +375,8 @@ ept_set_entry(struct domain *d, unsigned
 
     /* Track the highest gfn for which we have ever had a valid mapping */
     if ( mfn_valid(mfn_x(mfn)) &&
-         (gfn + (1UL << order) - 1 > d->arch.p2m->max_mapped_pfn) )
-        d->arch.p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
+         (gfn + (1UL << order) - 1 > p2m->max_mapped_pfn) )
+        p2m->max_mapped_pfn = gfn + (1UL << order) - 1;
 
     /* Success */
     rv = 1;
@@ -384,10 +385,10 @@ out:
     unmap_domain_page(table);
 
     if ( needs_sync )
-        ept_sync_domain(d);
+        ept_sync_domain(p2m->domain);
 
     /* Now the p2m table is not shared with vt-d page table */
-    if ( rv && iommu_enabled && need_iommu(d) && need_modify_vtd_table )
+    if ( rv && iommu_enabled && need_iommu(p2m->domain) && 
need_modify_vtd_table )
     {
         if ( p2mt == p2m_ram_rw )
         {
@@ -395,22 +396,22 @@ out:
             {
                 for ( i = 0; i < (1 << order); i++ )
                     iommu_map_page(
-                        d, gfn - offset + i, mfn_x(mfn) - offset + i,
+                        p2m->domain, gfn - offset + i, mfn_x(mfn) - offset + i,
                         IOMMUF_readable | IOMMUF_writable);
             }
             else if ( !order )
                 iommu_map_page(
-                    d, gfn, mfn_x(mfn), IOMMUF_readable | IOMMUF_writable);
+                    p2m->domain, gfn, mfn_x(mfn), IOMMUF_readable | 
IOMMUF_writable);
         }
         else
         {
             if ( order == EPT_TABLE_ORDER )
             {
                 for ( i = 0; i < (1 << order); i++ )
-                    iommu_unmap_page(d, gfn - offset + i);
+                    iommu_unmap_page(p2m->domain, gfn - offset + i);
             }
             else if ( !order )
-                iommu_unmap_page(d, gfn);
+                iommu_unmap_page(p2m->domain, gfn);
         }
     }
 
@@ -418,9 +419,11 @@ out:
 }
 
 /* Read ept p2m entries */
-static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
+static mfn_t ept_get_entry(struct p2m_domain *p2m,
+                           unsigned long gfn, p2m_type_t *t,
                            p2m_query_t q)
 {
+    struct domain *d = p2m->domain;
     ept_entry_t *table = map_domain_page(ept_get_asr(d));
     unsigned long gfn_remainder = gfn;
     ept_entry_t *ept_entry;
@@ -432,7 +435,7 @@ static mfn_t ept_get_entry(struct domain
     *t = p2m_mmio_dm;
 
     /* This pfn is higher than the highest the p2m map currently holds */
-    if ( gfn > d->arch.p2m->max_mapped_pfn )
+    if ( gfn > p2m->max_mapped_pfn )
         goto out;
 
     /* Should check if gfn obeys GAW here. */
@@ -440,7 +443,7 @@ static mfn_t ept_get_entry(struct domain
     for ( i = ept_get_wl(d); i > 0; i-- )
     {
     retry:
-        ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
+        ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
         if ( !ret )
             goto out;
         else if ( ret == GUEST_TABLE_POD_PAGE )
@@ -457,7 +460,7 @@ static mfn_t ept_get_entry(struct domain
             index = gfn_remainder >> ( i * EPT_TABLE_ORDER);
             ept_entry = table + index;
 
-            if ( !ept_pod_check_and_populate(d, gfn,
+            if ( !ept_pod_check_and_populate(p2m, gfn,
                                              ept_entry, 9, q) )
                 goto retry;
             else
@@ -480,7 +483,7 @@ static mfn_t ept_get_entry(struct domain
 
         ASSERT(i == 0);
         
-        if ( ept_pod_check_and_populate(d, gfn,
+        if ( ept_pod_check_and_populate(p2m, gfn,
                                         ept_entry, 0, q) )
             goto out;
     }
@@ -511,9 +514,10 @@ out:
 /* WARNING: Only caller doesn't care about PoD pages.  So this function will
  * always return 0 for PoD pages, not populate them.  If that becomes 
necessary,
  * pass a p2m_query_t type along to distinguish. */
-static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn, 
int *level)
-{
-    ept_entry_t *table = map_domain_page(ept_get_asr(d));
+static ept_entry_t ept_get_entry_content(struct p2m_domain *p2m,
+    unsigned long gfn, int *level)
+{
+    ept_entry_t *table = map_domain_page(ept_get_asr(p2m->domain));
     unsigned long gfn_remainder = gfn;
     ept_entry_t *ept_entry;
     ept_entry_t content = { .epte = 0 };
@@ -522,12 +526,12 @@ static ept_entry_t ept_get_entry_content
     int ret=0;
 
     /* This pfn is higher than the highest the p2m map currently holds */
-    if ( gfn > d->arch.p2m->max_mapped_pfn )
+    if ( gfn > p2m->max_mapped_pfn )
         goto out;
 
-    for ( i = ept_get_wl(d); i > 0; i-- )
-    {
-        ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
+    for ( i = ept_get_wl(p2m->domain); i > 0; i-- )
+    {
+        ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
         if ( !ret || ret == GUEST_TABLE_POD_PAGE )
             goto out;
         else if ( ret == GUEST_TABLE_SUPER_PAGE )
@@ -546,6 +550,7 @@ static ept_entry_t ept_get_entry_content
 
 void ept_walk_table(struct domain *d, unsigned long gfn)
 {
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     ept_entry_t *table = map_domain_page(ept_get_asr(d));
     unsigned long gfn_remainder = gfn;
 
@@ -555,10 +560,10 @@ void ept_walk_table(struct domain *d, un
            d->domain_id, gfn);
 
     /* This pfn is higher than the highest the p2m map currently holds */
-    if ( gfn > d->arch.p2m->max_mapped_pfn )
+    if ( gfn > p2m->max_mapped_pfn )
     {
         gdprintk(XENLOG_ERR, " gfn exceeds max_mapped_pfn %lx\n",
-               d->arch.p2m->max_mapped_pfn);
+               p2m->max_mapped_pfn);
         goto out;
     }
 
@@ -593,17 +598,18 @@ out:
     return;
 }
 
-static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t,
+static mfn_t ept_get_entry_current(struct p2m_domain *p2m,
+                                   unsigned long gfn, p2m_type_t *t,
                                    p2m_query_t q)
 {
-    return ept_get_entry(current->domain, gfn, t, q);
+    return ept_get_entry(p2m, gfn, t, q);
 }
 
 /*
  * To test if the new emt type is the same with old,
  * return 1 to not to reset ept entry.
  */
-static int need_modify_ept_entry(struct domain *d, unsigned long gfn,
+static int need_modify_ept_entry(struct p2m_domain *p2m, unsigned long gfn,
                                  mfn_t mfn, uint8_t o_ipat, uint8_t o_emt,
                                  p2m_type_t p2mt)
 {
@@ -611,7 +617,7 @@ static int need_modify_ept_entry(struct 
     uint8_t emt;
     bool_t direct_mmio = (p2mt == p2m_mmio_direct);
 
-    emt = epte_get_entry_emt(d, gfn, mfn, &ipat, direct_mmio);
+    emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat, direct_mmio);
 
     if ( (emt == o_emt) && (ipat == o_ipat) )
         return 0;
@@ -619,21 +625,23 @@ static int need_modify_ept_entry(struct 
     return 1;
 }
 
-void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
+void ept_change_entry_emt_with_range(struct domain *d,
+                                     unsigned long start_gfn,
                                      unsigned long end_gfn)
 {
     unsigned long gfn;
     ept_entry_t e;
     mfn_t mfn;
     int order = 0;
-
-    p2m_lock(d->arch.p2m);
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+    p2m_lock(p2m);
     for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
     {
         int level = 0;
         uint64_t trunk = 0;
 
-        e = ept_get_entry_content(d, gfn, &level);
+        e = ept_get_entry_content(p2m, gfn, &level);
         if ( !p2m_has_emt(e.avail1) )
             continue;
 
@@ -652,9 +660,9 @@ void ept_change_entry_emt_with_range(str
                      * Set emt for super page.
                      */
                     order = level * EPT_TABLE_ORDER;
-                    if ( need_modify_ept_entry(d, gfn, mfn, 
+                    if ( need_modify_ept_entry(p2m, gfn, mfn, 
                           e.ipat, e.emt, e.avail1) )
-                        ept_set_entry(d, gfn, mfn, order, e.avail1);
+                        ept_set_entry(p2m, gfn, mfn, order, e.avail1);
                     gfn += trunk;
                     break;
                 }
@@ -663,11 +671,11 @@ void ept_change_entry_emt_with_range(str
         }
         else /* gfn assigned with 4k */
         {
-            if ( need_modify_ept_entry(d, gfn, mfn, e.ipat, e.emt, e.avail1) )
-                ept_set_entry(d, gfn, mfn, order, e.avail1);
-        }
-    }
-    p2m_unlock(d->arch.p2m);
+            if ( need_modify_ept_entry(p2m, gfn, mfn, e.ipat, e.emt, e.avail1) 
)
+                ept_set_entry(p2m, gfn, mfn, order, e.avail1);
+        }
+    }
+    p2m_unlock(p2m);
 }
 
 /*
@@ -701,9 +709,10 @@ static void ept_change_entry_type_page(m
     unmap_domain_page(epte);
 }
 
-static void ept_change_entry_type_global(struct domain *d,
+static void ept_change_entry_type_global(struct p2m_domain *p2m,
                                          p2m_type_t ot, p2m_type_t nt)
 {
+    struct domain *d = p2m->domain;
     if ( ept_get_asr(d) == 0 )
         return;
 
@@ -714,10 +723,11 @@ static void ept_change_entry_type_global
 
 void ept_p2m_init(struct domain *d)
 {
-    d->arch.p2m->set_entry = ept_set_entry;
-    d->arch.p2m->get_entry = ept_get_entry;
-    d->arch.p2m->get_entry_current = ept_get_entry_current;
-    d->arch.p2m->change_entry_type_global = ept_change_entry_type_global;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+    p2m->set_entry = ept_set_entry;
+    p2m->get_entry = ept_get_entry;
+    p2m->get_entry_current = ept_get_entry_current;
+    p2m->change_entry_type_global = ept_change_entry_type_global;
 }
 
 static void ept_dump_p2m_table(unsigned char key)
@@ -742,7 +752,7 @@ static void ept_dump_p2m_table(unsigned 
         p2m = p2m_get_hostp2m(d);
         printk("\ndomain%d EPT p2m table: \n", d->domain_id);
 
-        for ( gfn = 0; gfn <= d->arch.p2m->max_mapped_pfn; gfn += (1 << order) 
)
+        for ( gfn = 0; gfn <= p2m->max_mapped_pfn; gfn += (1 << order) )
         {
             gfn_remainder = gfn;
             mfn = _mfn(INVALID_MFN);
@@ -750,7 +760,7 @@ static void ept_dump_p2m_table(unsigned 
 
             for ( i = ept_get_wl(d); i > 0; i-- )
             {
-                ret = ept_next_level(d, 1, &table, &gfn_remainder, i);
+                ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
                 if ( ret != GUEST_TABLE_NORMAL_PAGE )
                     break;
             }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/mem_event.c
--- a/xen/arch/x86/mm/mem_event.c       Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/mem_event.c       Wed Aug 11 15:56:01 2010 +0100
@@ -235,7 +235,7 @@ int mem_event_domctl(struct domain *d, x
             /* Get MFN of ring page */
             guest_get_eff_l1e(v, ring_addr, &l1e);
             gfn = l1e_get_pfn(l1e);
-            ring_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
+            ring_mfn = gfn_to_mfn(p2m_get_hostp2m(dom_mem_event), gfn, &p2mt);
 
             rc = -EINVAL;
             if ( unlikely(!mfn_valid(mfn_x(ring_mfn))) )
@@ -244,7 +244,7 @@ int mem_event_domctl(struct domain *d, x
             /* Get MFN of shared page */
             guest_get_eff_l1e(v, shared_addr, &l1e);
             gfn = l1e_get_pfn(l1e);
-            shared_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
+            shared_mfn = gfn_to_mfn(p2m_get_hostp2m(dom_mem_event), gfn, 
&p2mt);
 
             rc = -EINVAL;
             if ( unlikely(!mfn_valid(mfn_x(shared_mfn))) )
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/mem_paging.c
--- a/xen/arch/x86/mm/mem_paging.c      Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/mem_paging.c      Wed Aug 11 15:56:01 2010 +0100
@@ -29,33 +29,34 @@ int mem_paging_domctl(struct domain *d, 
                       XEN_GUEST_HANDLE(void) u_domctl)
 {
     int rc;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     switch( mec->op )
     {
     case XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE:
     {
         unsigned long gfn = mec->gfn;
-        rc = p2m_mem_paging_nominate(d, gfn);
+        rc = p2m_mem_paging_nominate(p2m, gfn);
     }
     break;
 
     case XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT:
     {
         unsigned long gfn = mec->gfn;
-        rc = p2m_mem_paging_evict(d, gfn);
+        rc = p2m_mem_paging_evict(p2m, gfn);
     }
     break;
 
     case XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP:
     {
         unsigned long gfn = mec->gfn;
-        rc = p2m_mem_paging_prep(d, gfn);
+        rc = p2m_mem_paging_prep(p2m, gfn);
     }
     break;
 
     case XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME:
     {
-        p2m_mem_paging_resume(d);
+        p2m_mem_paging_resume(p2m);
         rc = 0;
     }
     break;
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/mem_sharing.c
--- a/xen/arch/x86/mm/mem_sharing.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/mem_sharing.c     Wed Aug 11 15:56:01 2010 +0100
@@ -251,6 +251,7 @@ static void mem_sharing_audit(void)
             list_for_each(le, &e->gfns)
             {
                 struct domain *d;
+                struct p2m_domain *p2m;
                 p2m_type_t t;
                 mfn_t mfn;
 
@@ -262,7 +263,8 @@ static void mem_sharing_audit(void)
                             g->domain, g->gfn, mfn_x(e->mfn));
                     continue;
                 }
-                mfn = gfn_to_mfn(d, g->gfn, &t); 
+                p2m = p2m_get_hostp2m(d);
+                mfn = gfn_to_mfn(p2m, g->gfn, &t); 
                 if(mfn_x(mfn) != mfn_x(e->mfn))
                     MEM_SHARING_DEBUG("Incorrect P2M for d=%d, PFN=%lx."
                                       "Expecting MFN=%ld, got %ld\n",
@@ -377,7 +379,7 @@ int mem_sharing_debug_gfn(struct domain 
     mfn_t mfn;
     struct page_info *page;
 
-    mfn = gfn_to_mfn(d, gfn, &p2mt);
+    mfn = gfn_to_mfn(p2m_get_hostp2m(d), gfn, &p2mt);
     page = mfn_to_page(mfn);
 
     printk("Debug for domain=%d, gfn=%lx, ", 
@@ -487,7 +489,7 @@ int mem_sharing_debug_gref(struct domain
     return mem_sharing_debug_gfn(d, gfn); 
 }
 
-int mem_sharing_nominate_page(struct domain *d, 
+int mem_sharing_nominate_page(struct p2m_domain *p2m, 
                               unsigned long gfn,
                               int expected_refcnt,
                               shr_handle_t *phandle)
@@ -499,10 +501,11 @@ int mem_sharing_nominate_page(struct dom
     shr_handle_t handle;
     shr_hash_entry_t *hash_entry;
     struct gfn_info *gfn_info;
+    struct domain *d = p2m->domain;
 
     *phandle = 0UL;
 
-    mfn = gfn_to_mfn(d, gfn, &p2mt);
+    mfn = gfn_to_mfn(p2m, gfn, &p2mt);
 
     /* Check if mfn is valid */
     ret = -EINVAL;
@@ -536,7 +539,7 @@ int mem_sharing_nominate_page(struct dom
     }
 
     /* Change the p2m type */
-    if(p2m_change_type(d, gfn, p2mt, p2m_ram_shared) != p2mt) 
+    if(p2m_change_type(p2m, gfn, p2mt, p2m_ram_shared) != p2mt) 
     {
         /* This is unlikely, as the type must have changed since we've checked
          * it a few lines above.
@@ -599,7 +602,7 @@ int mem_sharing_share_pages(shr_handle_t
         list_del(&gfn->list);
         d = get_domain_by_id(gfn->domain);
         BUG_ON(!d);
-        BUG_ON(set_shared_p2m_entry(d, gfn->gfn, se->mfn) == 0);
+        BUG_ON(set_shared_p2m_entry(p2m_get_hostp2m(d), gfn->gfn, se->mfn) == 
0);
         put_domain(d);
         list_add(&gfn->list, &se->gfns);
         put_page_and_type(cpage);
@@ -618,7 +621,7 @@ err_out:
     return ret;
 }
 
-int mem_sharing_unshare_page(struct domain *d, 
+int mem_sharing_unshare_page(struct p2m_domain *p2m,
                              unsigned long gfn, 
                              uint16_t flags)
 {
@@ -631,8 +634,9 @@ int mem_sharing_unshare_page(struct doma
     struct gfn_info *gfn_info = NULL;
     shr_handle_t handle;
     struct list_head *le;
-
-    mfn = gfn_to_mfn(d, gfn, &p2mt);
+    struct domain *d = p2m->domain;
+
+    mfn = gfn_to_mfn(p2m, gfn, &p2mt);
 
     page = mfn_to_page(mfn);
     handle = page->shr_handle;
@@ -696,7 +700,7 @@ gfn_found:
     unmap_domain_page(s);
     unmap_domain_page(t);
 
-    ASSERT(set_shared_p2m_entry(d, gfn, page_to_mfn(page)) != 0);
+    ASSERT(set_shared_p2m_entry(p2m, gfn, page_to_mfn(page)) != 0);
     put_page_and_type(old_page);
 
 private_page_found:    
@@ -708,7 +712,7 @@ private_page_found:
         atomic_dec(&nr_saved_mfns);
     shr_unlock();
 
-    if(p2m_change_type(d, gfn, p2m_ram_shared, p2m_ram_rw) != 
+    if(p2m_change_type(p2m, gfn, p2m_ram_shared, p2m_ram_rw) != 
                                                 p2m_ram_shared) 
     {
         printk("Could not change p2m type.\n");
@@ -740,7 +744,7 @@ int mem_sharing_domctl(struct domain *d,
             shr_handle_t handle;
             if(!mem_sharing_enabled(d))
                 return -EINVAL;
-            rc = mem_sharing_nominate_page(d, gfn, 0, &handle);
+            rc = mem_sharing_nominate_page(p2m_get_hostp2m(d), gfn, 0, 
&handle);
             mec->u.nominate.handle = handle;
             mem_sharing_audit();
         }
@@ -756,7 +760,8 @@ int mem_sharing_domctl(struct domain *d,
                 return -EINVAL;
             if(mem_sharing_gref_to_gfn(d, gref, &gfn) < 0)
                 return -EINVAL;
-            rc = mem_sharing_nominate_page(d, gfn, 3, &handle);
+            rc = mem_sharing_nominate_page(p2m_get_hostp2m(d),
+                gfn, 3, &handle);
             mec->u.nominate.handle = handle;
             mem_sharing_audit();
         }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/p2m.c     Wed Aug 11 15:56:01 2010 +0100
@@ -108,9 +108,9 @@ static unsigned long p2m_type_to_flags(p
 }
 
 #if P2M_AUDIT
-static void audit_p2m(struct domain *d);
+static void audit_p2m(struct p2m_domain *p2m);
 #else
-# define audit_p2m(_d) do { (void)(_d); } while(0)
+# define audit_p2m(_p2m) do { (void)(_p2m); } while(0)
 #endif /* P2M_AUDIT */
 
 // Find the next level's P2M entry, checking for out-of-range gfn's...
@@ -135,15 +135,17 @@ p2m_find_entry(void *table, unsigned lon
 }
 
 struct page_info *
-p2m_alloc_ptp(struct domain *d, unsigned long type)
+p2m_alloc_ptp(struct p2m_domain *p2m, unsigned long type)
 {
     struct page_info *pg;
 
-    pg = d->arch.p2m->alloc_page(d);
+    ASSERT(p2m);
+    ASSERT(p2m->alloc_page);
+    pg = p2m->alloc_page(p2m);
     if (pg == NULL)
         return NULL;
 
-    page_list_add_tail(pg, &d->arch.p2m->pages);
+    page_list_add_tail(pg, &p2m->pages);
     pg->u.inuse.type_info = type | 1 | PGT_validated;
     pg->count_info |= 1;
 
@@ -154,7 +156,7 @@ p2m_alloc_ptp(struct domain *d, unsigned
 // Returns 0 on error.
 //
 static int
-p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table,
+p2m_next_level(struct p2m_domain *p2m, mfn_t *table_mfn, void **table,
                unsigned long *gfn_remainder, unsigned long gfn, u32 shift,
                u32 max, unsigned long type)
 {
@@ -163,7 +165,7 @@ p2m_next_level(struct domain *d, mfn_t *
     l1_pgentry_t new_entry;
     void *next;
     int i;
-    ASSERT(d->arch.p2m->alloc_page);
+    ASSERT(p2m->alloc_page);
 
     if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn,
                                       shift, max)) )
@@ -174,7 +176,7 @@ p2m_next_level(struct domain *d, mfn_t *
     {
         struct page_info *pg;
 
-        pg = p2m_alloc_ptp(d, type);
+        pg = p2m_alloc_ptp(p2m, type);
         if ( pg == NULL )
             return 0;
 
@@ -183,7 +185,7 @@ p2m_next_level(struct domain *d, mfn_t *
 
         switch ( type ) {
         case PGT_l3_page_table:
-            paging_write_p2m_entry(d, gfn,
+            paging_write_p2m_entry(p2m->domain, gfn,
                                    p2m_entry, *table_mfn, new_entry, 4);
             break;
         case PGT_l2_page_table:
@@ -191,11 +193,11 @@ p2m_next_level(struct domain *d, mfn_t *
             /* for PAE mode, PDPE only has PCD/PWT/P bits available */
             new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), _PAGE_PRESENT);
 #endif
-            paging_write_p2m_entry(d, gfn,
+            paging_write_p2m_entry(p2m->domain, gfn,
                                    p2m_entry, *table_mfn, new_entry, 3);
             break;
         case PGT_l1_page_table:
-            paging_write_p2m_entry(d, gfn,
+            paging_write_p2m_entry(p2m->domain, gfn,
                                    p2m_entry, *table_mfn, new_entry, 2);
             break;
         default:
@@ -212,7 +214,7 @@ p2m_next_level(struct domain *d, mfn_t *
         unsigned long flags, pfn;
         struct page_info *pg;
 
-        pg = p2m_alloc_ptp(d, PGT_l2_page_table);
+        pg = p2m_alloc_ptp(p2m, PGT_l2_page_table);
         if ( pg == NULL )
             return 0;
 
@@ -223,13 +225,13 @@ p2m_next_level(struct domain *d, mfn_t *
         for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
         {
             new_entry = l1e_from_pfn(pfn + (i * L1_PAGETABLE_ENTRIES), flags);
-            paging_write_p2m_entry(d, gfn, l1_entry+i, *table_mfn, new_entry,
-                                   2);
+            paging_write_p2m_entry(p2m->domain, gfn,
+                                   l1_entry+i, *table_mfn, new_entry, 2);
         }
         unmap_domain_page(l1_entry);
         new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                  __PAGE_HYPERVISOR|_PAGE_USER); //disable PSE
-        paging_write_p2m_entry(d, gfn,
+        paging_write_p2m_entry(p2m->domain, gfn,
                                p2m_entry, *table_mfn, new_entry, 3);
     }
 
@@ -240,7 +242,7 @@ p2m_next_level(struct domain *d, mfn_t *
         unsigned long flags, pfn;
         struct page_info *pg;
 
-        pg = p2m_alloc_ptp(d, PGT_l1_page_table);
+        pg = p2m_alloc_ptp(p2m, PGT_l1_page_table);
         if ( pg == NULL )
             return 0;
 
@@ -257,14 +259,14 @@ p2m_next_level(struct domain *d, mfn_t *
         for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
         {
             new_entry = l1e_from_pfn(pfn + i, flags);
-            paging_write_p2m_entry(d, gfn,
+            paging_write_p2m_entry(p2m->domain, gfn,
                                    l1_entry+i, *table_mfn, new_entry, 1);
         }
         unmap_domain_page(l1_entry);
         
         new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)),
                                  __PAGE_HYPERVISOR|_PAGE_USER);
-        paging_write_p2m_entry(d, gfn,
+        paging_write_p2m_entry(p2m->domain, gfn,
                                p2m_entry, *table_mfn, new_entry, 2);
     }
 
@@ -280,17 +282,17 @@ p2m_next_level(struct domain *d, mfn_t *
  * Populate-on-demand functionality
  */
 static
-int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, 
+int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, 
                   unsigned int page_order, p2m_type_t p2mt);
 
 static int
-p2m_pod_cache_add(struct domain *d,
+p2m_pod_cache_add(struct p2m_domain *p2m,
                   struct page_info *page,
                   unsigned long order)
 {
     int i;
     struct page_info *p;
-    struct p2m_domain *p2md = d->arch.p2m;
+    struct domain *d = p2m->domain;
 
 #ifndef NDEBUG
     mfn_t mfn;
@@ -320,7 +322,7 @@ p2m_pod_cache_add(struct domain *d,
     }
 #endif
 
-    ASSERT(p2m_locked_by_me(p2md));
+    ASSERT(p2m_locked_by_me(p2m));
 
     /*
      * Pages from domain_alloc and returned by the balloon driver aren't
@@ -347,12 +349,12 @@ p2m_pod_cache_add(struct domain *d,
     switch(order)
     {
     case 9:
-        page_list_add_tail(page, &p2md->pod.super); /* lock: page_alloc */
-        p2md->pod.count += 1 << order;
+        page_list_add_tail(page, &p2m->pod.super); /* lock: page_alloc */
+        p2m->pod.count += 1 << order;
         break;
     case 0:
-        page_list_add_tail(page, &p2md->pod.single); /* lock: page_alloc */
-        p2md->pod.count += 1 ;
+        page_list_add_tail(page, &p2m->pod.single); /* lock: page_alloc */
+        p2m->pod.count += 1;
         break;
     default:
         BUG();
@@ -371,57 +373,56 @@ p2m_pod_cache_add(struct domain *d,
  * down 2-meg pages into singleton pages automatically.  Returns null if
  * a superpage is requested and no superpages are available.  Must be called
  * with the d->page_lock held. */
-static struct page_info * p2m_pod_cache_get(struct domain *d,
+static struct page_info * p2m_pod_cache_get(struct p2m_domain *p2m,
                                             unsigned long order)
 {
-    struct p2m_domain *p2md = d->arch.p2m;
     struct page_info *p = NULL;
     int i;
 
-    if ( order == 9 && page_list_empty(&p2md->pod.super) )
+    if ( order == 9 && page_list_empty(&p2m->pod.super) )
     {
         return NULL;
     }
-    else if ( order == 0 && page_list_empty(&p2md->pod.single) )
+    else if ( order == 0 && page_list_empty(&p2m->pod.single) )
     {
         unsigned long mfn;
         struct page_info *q;
 
-        BUG_ON( page_list_empty(&p2md->pod.super) );
+        BUG_ON( page_list_empty(&p2m->pod.super) );
 
         /* Break up a superpage to make single pages. NB count doesn't
          * need to be adjusted. */
-        p = page_list_remove_head(&p2md->pod.super);
+        p = page_list_remove_head(&p2m->pod.super);
         mfn = mfn_x(page_to_mfn(p));
 
         for ( i=0; i<SUPERPAGE_PAGES; i++ )
         {
             q = mfn_to_page(_mfn(mfn+i));
-            page_list_add_tail(q, &p2md->pod.single);
+            page_list_add_tail(q, &p2m->pod.single);
         }
     }
 
     switch ( order )
     {
     case 9:
-        BUG_ON( page_list_empty(&p2md->pod.super) );
-        p = page_list_remove_head(&p2md->pod.super);
-        p2md->pod.count -= 1 << order; /* Lock: page_alloc */
+        BUG_ON( page_list_empty(&p2m->pod.super) );
+        p = page_list_remove_head(&p2m->pod.super);
+        p2m->pod.count -= 1 << order; /* Lock: page_alloc */
         break;
     case 0:
-        BUG_ON( page_list_empty(&p2md->pod.single) );
-        p = page_list_remove_head(&p2md->pod.single);
-        p2md->pod.count -= 1;
+        BUG_ON( page_list_empty(&p2m->pod.single) );
+        p = page_list_remove_head(&p2m->pod.single);
+        p2m->pod.count -= 1;
         break;
     default:
         BUG();
     }
 
     /* Put the pages back on the domain page_list */
-    for ( i = 0 ; i < (1 << order) ; i++ )
-    {
-        BUG_ON(page_get_owner(p + i) != d);
-        page_list_add_tail(p + i, &d->page_list);
+    for ( i = 0 ; i < (1 << order); i++ )
+    {
+        BUG_ON(page_get_owner(p + i) != p2m->domain);
+        page_list_add_tail(p + i, &p2m->domain->page_list);
     }
 
     return p;
@@ -429,18 +430,18 @@ static struct page_info * p2m_pod_cache_
 
 /* Set the size of the cache, allocating or freeing as necessary. */
 static int
-p2m_pod_set_cache_target(struct domain *d, unsigned long pod_target)
-{
-    struct p2m_domain *p2md = d->arch.p2m;
+p2m_pod_set_cache_target(struct p2m_domain *p2m, unsigned long pod_target)
+{
+    struct domain *d = p2m->domain;
     int ret = 0;
 
     /* Increasing the target */
-    while ( pod_target > p2md->pod.count )
+    while ( pod_target > p2m->pod.count )
     {
         struct page_info * page;
         int order;
 
-        if ( (pod_target - p2md->pod.count) >= SUPERPAGE_PAGES )
+        if ( (pod_target - p2m->pod.count) >= SUPERPAGE_PAGES )
             order = 9;
         else
             order = 0;
@@ -456,18 +457,18 @@ p2m_pod_set_cache_target(struct domain *
             }   
             
             printk("%s: Unable to allocate domheap page for pod cache.  target 
%lu cachesize %d\n",
-                   __func__, pod_target, p2md->pod.count);
+                   __func__, pod_target, p2m->pod.count);
             ret = -ENOMEM;
             goto out;
         }
 
-        p2m_pod_cache_add(d, page, order);
+        p2m_pod_cache_add(p2m, page, order);
     }
 
     /* Decreasing the target */
     /* We hold the p2m lock here, so we don't need to worry about
      * cache disappearing under our feet. */
-    while ( pod_target < p2md->pod.count )
+    while ( pod_target < p2m->pod.count )
     {
         struct page_info * page;
         int order, i;
@@ -476,13 +477,13 @@ p2m_pod_set_cache_target(struct domain *
          * entries may disappear before we grab the lock. */
         spin_lock(&d->page_alloc_lock);
 
-        if ( (p2md->pod.count - pod_target) > SUPERPAGE_PAGES
-             && !page_list_empty(&p2md->pod.super) )
+        if ( (p2m->pod.count - pod_target) > SUPERPAGE_PAGES
+             && !page_list_empty(&p2m->pod.super) )
             order = 9;
         else
             order = 0;
 
-        page = p2m_pod_cache_get(d, order);
+        page = p2m_pod_cache_get(p2m, order);
 
         ASSERT(page != NULL);
 
@@ -553,14 +554,14 @@ p2m_pod_set_mem_target(struct domain *d,
 p2m_pod_set_mem_target(struct domain *d, unsigned long target)
 {
     unsigned pod_target;
-    struct p2m_domain *p2md = d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int ret = 0;
     unsigned long populated;
 
-    p2m_lock(p2md);
+    p2m_lock(p2m);
 
     /* P == B: Nothing to do. */
-    if ( p2md->pod.entry_count == 0 )
+    if ( p2m->pod.entry_count == 0 )
         goto out;
 
     /* Don't do anything if the domain is being torn down */
@@ -572,21 +573,21 @@ p2m_pod_set_mem_target(struct domain *d,
     if ( target < d->tot_pages )
         goto out;
 
-    populated  = d->tot_pages - p2md->pod.count;
+    populated  = d->tot_pages - p2m->pod.count;
 
     pod_target = target - populated;
 
     /* B < T': Set the cache size equal to # of outstanding entries,
      * let the balloon driver fill in the rest. */
-    if ( pod_target > p2md->pod.entry_count )
-        pod_target = p2md->pod.entry_count;
-
-    ASSERT( pod_target >= p2md->pod.count );
-
-    ret = p2m_pod_set_cache_target(d, pod_target);
+    if ( pod_target > p2m->pod.entry_count )
+        pod_target = p2m->pod.entry_count;
+
+    ASSERT( pod_target >= p2m->pod.count );
+
+    ret = p2m_pod_set_cache_target(p2m, pod_target);
 
 out:
-    p2m_unlock(p2md);
+    p2m_unlock(p2m);
 
     return ret;
 }
@@ -594,16 +595,16 @@ void
 void
 p2m_pod_empty_cache(struct domain *d)
 {
-    struct p2m_domain *p2md = d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *page;
 
     /* After this barrier no new PoD activities can happen. */
     BUG_ON(!d->is_dying);
-    spin_barrier(&p2md->lock);
+    spin_barrier(&p2m->lock);
 
     spin_lock(&d->page_alloc_lock);
 
-    while ( (page = page_list_remove_head(&p2md->pod.super)) )
+    while ( (page = page_list_remove_head(&p2m->pod.super)) )
     {
         int i;
             
@@ -613,18 +614,18 @@ p2m_pod_empty_cache(struct domain *d)
             page_list_add_tail(page + i, &d->page_list);
         }
 
-        p2md->pod.count -= SUPERPAGE_PAGES;
-    }
-
-    while ( (page = page_list_remove_head(&p2md->pod.single)) )
+        p2m->pod.count -= SUPERPAGE_PAGES;
+    }
+
+    while ( (page = page_list_remove_head(&p2m->pod.single)) )
     {
         BUG_ON(page_get_owner(page) != d);
         page_list_add_tail(page, &d->page_list);
 
-        p2md->pod.count -= 1;
-    }
-
-    BUG_ON(p2md->pod.count != 0);
+        p2m->pod.count -= 1;
+    }
+
+    BUG_ON(p2m->pod.count != 0);
 
     spin_unlock(&d->page_alloc_lock);
 }
@@ -642,9 +643,9 @@ p2m_pod_decrease_reservation(struct doma
                              xen_pfn_t gpfn,
                              unsigned int order)
 {
-    struct p2m_domain *p2md = d->arch.p2m;
     int ret=0;
     int i;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     int steal_for_cache = 0;
     int pod = 0, nonpod = 0, ram = 0;
@@ -652,14 +653,14 @@ p2m_pod_decrease_reservation(struct doma
 
     /* If we don't have any outstanding PoD entries, let things take their
      * course */
-    if ( p2md->pod.entry_count == 0 )
+    if ( p2m->pod.entry_count == 0 )
         goto out;
 
     /* Figure out if we need to steal some freed memory for our cache */
-    steal_for_cache =  ( p2md->pod.entry_count > p2md->pod.count );
-
-    p2m_lock(p2md);
-    audit_p2m(d);
+    steal_for_cache =  ( p2m->pod.entry_count > p2m->pod.count );
+
+    p2m_lock(p2m);
+    audit_p2m(p2m);
 
     if ( unlikely(d->is_dying) )
         goto out_unlock;
@@ -670,7 +671,7 @@ p2m_pod_decrease_reservation(struct doma
     {
         p2m_type_t t;
 
-        gfn_to_mfn_query(d, gpfn + i, &t);
+        gfn_to_mfn_query(p2m, gpfn + i, &t);
 
         if ( t == p2m_populate_on_demand )
             pod++;
@@ -690,9 +691,9 @@ p2m_pod_decrease_reservation(struct doma
     {
         /* All PoD: Mark the whole region invalid and tell caller
          * we're done. */
-        set_p2m_entry(d, gpfn, _mfn(INVALID_MFN), order, p2m_invalid);
-        p2md->pod.entry_count-=(1<<order); /* Lock: p2m */
-        BUG_ON(p2md->pod.entry_count < 0);
+        set_p2m_entry(p2m, gpfn, _mfn(INVALID_MFN), order, p2m_invalid);
+        p2m->pod.entry_count-=(1<<order); /* Lock: p2m */
+        BUG_ON(p2m->pod.entry_count < 0);
         ret = 1;
         goto out_entry_check;
     }
@@ -710,12 +711,12 @@ p2m_pod_decrease_reservation(struct doma
         mfn_t mfn;
         p2m_type_t t;
 
-        mfn = gfn_to_mfn_query(d, gpfn + i, &t);
+        mfn = gfn_to_mfn_query(p2m, gpfn + i, &t);
         if ( t == p2m_populate_on_demand )
         {
-            set_p2m_entry(d, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
-            p2md->pod.entry_count--; /* Lock: p2m */
-            BUG_ON(p2md->pod.entry_count < 0);
+            set_p2m_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
+            p2m->pod.entry_count--; /* Lock: p2m */
+            BUG_ON(p2m->pod.entry_count < 0);
             pod--;
         }
         else if ( steal_for_cache && p2m_is_ram(t) )
@@ -726,12 +727,12 @@ p2m_pod_decrease_reservation(struct doma
 
             page = mfn_to_page(mfn);
 
-            set_p2m_entry(d, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
+            set_p2m_entry(p2m, gpfn + i, _mfn(INVALID_MFN), 0, p2m_invalid);
             set_gpfn_from_mfn(mfn_x(mfn), INVALID_M2P_ENTRY);
 
-            p2m_pod_cache_add(d, page, 0);
-
-            steal_for_cache =  ( p2md->pod.entry_count > p2md->pod.count );
+            p2m_pod_cache_add(p2m, page, 0);
+
+            steal_for_cache =  ( p2m->pod.entry_count > p2m->pod.count );
 
             nonpod--;
             ram--;
@@ -745,33 +746,31 @@ p2m_pod_decrease_reservation(struct doma
 
 out_entry_check:
     /* If we've reduced our "liabilities" beyond our "assets", free some */
-    if ( p2md->pod.entry_count < p2md->pod.count )
-    {
-        p2m_pod_set_cache_target(d, p2md->pod.entry_count);
+    if ( p2m->pod.entry_count < p2m->pod.count )
+    {
+        p2m_pod_set_cache_target(p2m, p2m->pod.entry_count);
     }
 
 out_unlock:
-    audit_p2m(d);
-    p2m_unlock(p2md);
+    audit_p2m(p2m);
+    p2m_unlock(p2m);
 
 out:
     return ret;
 }
 
 void
-p2m_pod_dump_data(struct domain *d)
-{
-    struct p2m_domain *p2md = d->arch.p2m;
-    
+p2m_pod_dump_data(struct p2m_domain *p2m)
+{
     printk("    PoD entries=%d cachesize=%d\n",
-           p2md->pod.entry_count, p2md->pod.count);
+           p2m->pod.entry_count, p2m->pod.count);
 }
 
 
 /* Search for all-zero superpages to be reclaimed as superpages for the
  * PoD cache. Must be called w/ p2m lock held, page_alloc lock not held. */
 static int
-p2m_pod_zero_check_superpage(struct domain *d, unsigned long gfn)
+p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
 {
     mfn_t mfn, mfn0 = _mfn(INVALID_MFN);
     p2m_type_t type, type0 = 0;
@@ -779,6 +778,7 @@ p2m_pod_zero_check_superpage(struct doma
     int ret=0, reset = 0;
     int i, j;
     int max_ref = 1;
+    struct domain *d = p2m->domain;
 
     if ( !superpage_aligned(gfn) )
         goto out;
@@ -792,7 +792,7 @@ p2m_pod_zero_check_superpage(struct doma
     for ( i=0; i<SUPERPAGE_PAGES; i++ )
     {
         
-        mfn = gfn_to_mfn_query(d, gfn + i, &type);
+        mfn = gfn_to_mfn_query(p2m, gfn + i, &type);
 
         if ( i == 0 )
         {
@@ -840,7 +840,7 @@ p2m_pod_zero_check_superpage(struct doma
     }
 
     /* Try to remove the page, restoring old mapping if it fails. */
-    set_p2m_entry(d, gfn,
+    set_p2m_entry(p2m, gfn,
                   _mfn(POPULATE_ON_DEMAND_MFN), 9,
                   p2m_populate_on_demand);
 
@@ -892,23 +892,24 @@ p2m_pod_zero_check_superpage(struct doma
 
     /* Finally!  We've passed all the checks, and can add the mfn superpage
      * back on the PoD cache, and account for the new p2m PoD entries */
-    p2m_pod_cache_add(d, mfn_to_page(mfn0), 9);
-    d->arch.p2m->pod.entry_count += SUPERPAGE_PAGES;
+    p2m_pod_cache_add(p2m, mfn_to_page(mfn0), 9);
+    p2m->pod.entry_count += SUPERPAGE_PAGES;
 
 out_reset:
     if ( reset )
-        set_p2m_entry(d, gfn, mfn0, 9, type0);
+        set_p2m_entry(p2m, gfn, mfn0, 9, type0);
     
 out:
     return ret;
 }
 
 static void
-p2m_pod_zero_check(struct domain *d, unsigned long *gfns, int count)
+p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
 {
     mfn_t mfns[count];
     p2m_type_t types[count];
     unsigned long * map[count];
+    struct domain *d = p2m->domain;
 
     int i, j;
     int max_ref = 1;
@@ -920,7 +921,7 @@ p2m_pod_zero_check(struct domain *d, uns
     /* First, get the gfn list, translate to mfns, and map the pages. */
     for ( i=0; i<count; i++ )
     {
-        mfns[i] = gfn_to_mfn_query(d, gfns[i], types + i);
+        mfns[i] = gfn_to_mfn_query(p2m, gfns[i], types + i);
         /* If this is ram, and not a pagetable or from the xen heap, and 
probably not mapped
            elsewhere, map it; otherwise, skip. */
         if ( p2m_is_ram(types[i])
@@ -952,7 +953,7 @@ p2m_pod_zero_check(struct domain *d, uns
         }
 
         /* Try to remove the page, restoring old mapping if it fails. */
-        set_p2m_entry(d, gfns[i],
+        set_p2m_entry(p2m, gfns[i],
                       _mfn(POPULATE_ON_DEMAND_MFN), 0,
                       p2m_populate_on_demand);
 
@@ -963,7 +964,7 @@ p2m_pod_zero_check(struct domain *d, uns
             unmap_domain_page(map[i]);
             map[i] = NULL;
 
-            set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
+            set_p2m_entry(p2m, gfns[i], mfns[i], 0, types[i]);
 
             continue;
         }
@@ -985,7 +986,7 @@ p2m_pod_zero_check(struct domain *d, uns
          * check timing.  */
         if ( j < PAGE_SIZE/sizeof(*map[i]) )
         {
-            set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
+            set_p2m_entry(p2m, gfns[i], mfns[i], 0, types[i]);
         }
         else
         {
@@ -1005,8 +1006,8 @@ p2m_pod_zero_check(struct domain *d, uns
             }
 
             /* Add to cache, and account for the new p2m PoD entry */
-            p2m_pod_cache_add(d, mfn_to_page(mfns[i]), 0);
-            d->arch.p2m->pod.entry_count++;
+            p2m_pod_cache_add(p2m, mfn_to_page(mfns[i]), 0);
+            p2m->pod.entry_count++;
         }
     }
     
@@ -1014,56 +1015,53 @@ p2m_pod_zero_check(struct domain *d, uns
 
 #define POD_SWEEP_LIMIT 1024
 static void
-p2m_pod_emergency_sweep_super(struct domain *d)
-{
-    struct p2m_domain *p2md = d->arch.p2m;
+p2m_pod_emergency_sweep_super(struct p2m_domain *p2m)
+{
     unsigned long i, start, limit;
 
-    if ( p2md->pod.reclaim_super == 0 )
-    {
-        p2md->pod.reclaim_super = (p2md->pod.max_guest>>9)<<9;
-        p2md->pod.reclaim_super -= SUPERPAGE_PAGES;
+    if ( p2m->pod.reclaim_super == 0 )
+    {
+        p2m->pod.reclaim_super = (p2m->pod.max_guest>>9)<<9;
+        p2m->pod.reclaim_super -= SUPERPAGE_PAGES;
     }
     
-    start = p2md->pod.reclaim_super;
+    start = p2m->pod.reclaim_super;
     limit = (start > POD_SWEEP_LIMIT) ? (start - POD_SWEEP_LIMIT) : 0;
 
-    for ( i=p2md->pod.reclaim_super ; i > 0 ; i-=SUPERPAGE_PAGES )
-    {
-        p2m_pod_zero_check_superpage(d, i);
+    for ( i=p2m->pod.reclaim_super ; i > 0 ; i -= SUPERPAGE_PAGES )
+    {
+        p2m_pod_zero_check_superpage(p2m, i);
         /* Stop if we're past our limit and we have found *something*.
          *
          * NB that this is a zero-sum game; we're increasing our cache size
          * by increasing our 'debt'.  Since we hold the p2m lock,
          * (entry_count - count) must remain the same. */
-        if ( !page_list_empty(&p2md->pod.super) &&  i < limit )
+        if ( !page_list_empty(&p2m->pod.super) &&  i < limit )
             break;
     }
 
-    p2md->pod.reclaim_super = i ? i - SUPERPAGE_PAGES : 0;
-
+    p2m->pod.reclaim_super = i ? i - SUPERPAGE_PAGES : 0;
 }
 
 #define POD_SWEEP_STRIDE  16
 static void
-p2m_pod_emergency_sweep(struct domain *d)
-{
-    struct p2m_domain *p2md = d->arch.p2m;
+p2m_pod_emergency_sweep(struct p2m_domain *p2m)
+{
     unsigned long gfns[POD_SWEEP_STRIDE];
     unsigned long i, j=0, start, limit;
     p2m_type_t t;
 
 
-    if ( p2md->pod.reclaim_single == 0 )
-        p2md->pod.reclaim_single = p2md->pod.max_guest;
-
-    start = p2md->pod.reclaim_single;
+    if ( p2m->pod.reclaim_single == 0 )
+        p2m->pod.reclaim_single = p2m->pod.max_guest;
+
+    start = p2m->pod.reclaim_single;
     limit = (start > POD_SWEEP_LIMIT) ? (start - POD_SWEEP_LIMIT) : 0;
 
     /* FIXME: Figure out how to avoid superpages */
-    for ( i=p2md->pod.reclaim_single ; i > 0 ; i-- )
-    {
-        gfn_to_mfn_query(d, i, &t );
+    for ( i=p2m->pod.reclaim_single; i > 0 ; i-- )
+    {
+        gfn_to_mfn_query(p2m, i, &t );
         if ( p2m_is_ram(t) )
         {
             gfns[j] = i;
@@ -1071,7 +1069,7 @@ p2m_pod_emergency_sweep(struct domain *d
             BUG_ON(j > POD_SWEEP_STRIDE);
             if ( j == POD_SWEEP_STRIDE )
             {
-                p2m_pod_zero_check(d, gfns, j);
+                p2m_pod_zero_check(p2m, gfns, j);
                 j = 0;
             }
         }
@@ -1080,29 +1078,29 @@ p2m_pod_emergency_sweep(struct domain *d
          * NB that this is a zero-sum game; we're increasing our cache size
          * by re-increasing our 'debt'.  Since we hold the p2m lock,
          * (entry_count - count) must remain the same. */
-        if ( p2md->pod.count > 0 && i < limit )
+        if ( p2m->pod.count > 0 && i < limit )
             break;
     }
 
     if ( j )
-        p2m_pod_zero_check(d, gfns, j);
-
-    p2md->pod.reclaim_single = i ? i - 1 : i;
+        p2m_pod_zero_check(p2m, gfns, j);
+
+    p2m->pod.reclaim_single = i ? i - 1 : i;
 
 }
 
 int
-p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
+p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
                         unsigned int order,
                         p2m_query_t q)
 {
+    struct domain *d = p2m->domain;
     struct page_info *p = NULL; /* Compiler warnings */
     unsigned long gfn_aligned;
     mfn_t mfn;
-    struct p2m_domain *p2md = d->arch.p2m;
     int i;
 
-    ASSERT(p2m_locked_by_me(d->arch.p2m));
+    ASSERT(p2m_locked_by_me(p2m));
 
     /* This check is done with the p2m lock held.  This will make sure that
      * even if d->is_dying changes under our feet, p2m_pod_empty_cache() 
@@ -1120,34 +1118,34 @@ p2m_pod_demand_populate(struct domain *d
          * set_p2m_entry() should automatically shatter the 1GB page into 
          * 512 2MB pages. The rest of 511 calls are unnecessary.
          */
-        set_p2m_entry(d, gfn_aligned, _mfn(POPULATE_ON_DEMAND_MFN), 9,
+        set_p2m_entry(p2m, gfn_aligned, _mfn(POPULATE_ON_DEMAND_MFN), 9,
                       p2m_populate_on_demand);
-        audit_p2m(d);
-        p2m_unlock(p2md);
+        audit_p2m(p2m);
+        p2m_unlock(p2m);
         return 0;
     }
 
     /* If we're low, start a sweep */
-    if ( order == 9 && page_list_empty(&p2md->pod.super) )
-        p2m_pod_emergency_sweep_super(d);
-
-    if ( page_list_empty(&p2md->pod.single) &&
+    if ( order == 9 && page_list_empty(&p2m->pod.super) )
+        p2m_pod_emergency_sweep_super(p2m);
+
+    if ( page_list_empty(&p2m->pod.single) &&
          ( ( order == 0 )
-           || (order == 9 && page_list_empty(&p2md->pod.super) ) ) )
-        p2m_pod_emergency_sweep(d);
+           || (order == 9 && page_list_empty(&p2m->pod.super) ) ) )
+        p2m_pod_emergency_sweep(p2m);
 
     /* Keep track of the highest gfn demand-populated by a guest fault */
-    if ( q == p2m_guest && gfn > p2md->pod.max_guest )
-        p2md->pod.max_guest = gfn;
+    if ( q == p2m_guest && gfn > p2m->pod.max_guest )
+        p2m->pod.max_guest = gfn;
 
     spin_lock(&d->page_alloc_lock);
 
-    if ( p2md->pod.count == 0 )
+    if ( p2m->pod.count == 0 )
         goto out_of_memory;
 
     /* Get a page f/ the cache.  A NULL return value indicates that the
      * 2-meg range should be marked singleton PoD, and retried */
-    if ( (p = p2m_pod_cache_get(d, order)) == NULL )
+    if ( (p = p2m_pod_cache_get(p2m, order)) == NULL )
         goto remap_and_retry;
 
     mfn = page_to_mfn(p);
@@ -1158,13 +1156,13 @@ p2m_pod_demand_populate(struct domain *d
 
     gfn_aligned = (gfn >> order) << order;
 
-    set_p2m_entry(d, gfn_aligned, mfn, order, p2m_ram_rw);
-
-    for( i = 0 ; i < (1UL << order) ; i++ )
+    set_p2m_entry(p2m, gfn_aligned, mfn, order, p2m_ram_rw);
+
+    for( i = 0; i < (1UL << order); i++ )
         set_gpfn_from_mfn(mfn_x(mfn) + i, gfn_aligned + i);
     
-    p2md->pod.entry_count -= (1 << order); /* Lock: p2m */
-    BUG_ON(p2md->pod.entry_count < 0);
+    p2m->pod.entry_count -= (1 << order); /* Lock: p2m */
+    BUG_ON(p2m->pod.entry_count < 0);
 
     if ( tb_init_done )
     {
@@ -1186,7 +1184,7 @@ out_of_memory:
     spin_unlock(&d->page_alloc_lock);
 
     printk("%s: Out of populate-on-demand memory! tot_pages %" PRIu32 " 
pod_entries %" PRIi32 "\n",
-           __func__, d->tot_pages, p2md->pod.entry_count);
+           __func__, d->tot_pages, p2m->pod.entry_count);
     domain_crash(d);
 out_fail:
     return -1;
@@ -1197,7 +1195,7 @@ remap_and_retry:
     /* Remap this 2-meg region in singleton chunks */
     gfn_aligned = (gfn>>order)<<order;
     for(i=0; i<(1<<order); i++)
-        set_p2m_entry(d, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
+        set_p2m_entry(p2m, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
                       p2m_populate_on_demand);
     if ( tb_init_done )
     {
@@ -1216,44 +1214,44 @@ remap_and_retry:
 }
 
 /* Non-ept "lock-and-check" wrapper */
-static int p2m_pod_check_and_populate(struct domain *d, unsigned long gfn,
+static int p2m_pod_check_and_populate(struct p2m_domain *p2m, unsigned long 
gfn,
                                       l1_pgentry_t *p2m_entry, int order,
                                       p2m_query_t q)
 {
     /* Only take the lock if we don't already have it.  Otherwise it
      * wouldn't be safe to do p2m lookups with the p2m lock held */
-    int do_locking = !p2m_locked_by_me(d->arch.p2m);
+    int do_locking = !p2m_locked_by_me(p2m);
     int r;
 
     if ( do_locking )
-        p2m_lock(d->arch.p2m);
-
-    audit_p2m(d);
+        p2m_lock(p2m);
+
+    audit_p2m(p2m);
 
     /* Check to make sure this is still PoD */
     if ( p2m_flags_to_type(l1e_get_flags(*p2m_entry)) != 
p2m_populate_on_demand )
     {
         if ( do_locking )
-            p2m_unlock(d->arch.p2m);
+            p2m_unlock(p2m);
         return 0;
     }
 
-    r = p2m_pod_demand_populate(d, gfn, order, q);
-
-    audit_p2m(d);
+    r = p2m_pod_demand_populate(p2m, gfn, order, q);
+
+    audit_p2m(p2m);
     if ( do_locking )
-        p2m_unlock(d->arch.p2m);
+        p2m_unlock(p2m);
 
     return r;
 }
 
 // Returns 0 on error (out of memory)
 static int
-p2m_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, 
+p2m_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, 
               unsigned int page_order, p2m_type_t p2mt)
 {
     // XXX -- this might be able to be faster iff current->domain == d
-    mfn_t table_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
+    mfn_t table_mfn = pagetable_get_mfn(p2m_get_pagetable(p2m));
     void *table =map_domain_page(mfn_x(table_mfn));
     unsigned long i, gfn_remainder = gfn;
     l1_pgentry_t *p2m_entry;
@@ -1273,14 +1271,14 @@ p2m_set_entry(struct domain *d, unsigned
         t.gfn = gfn;
         t.mfn = mfn_x(mfn);
         t.p2mt = p2mt;
-        t.d = d->domain_id;
+        t.d = p2m->domain->domain_id;
         t.order = page_order;
 
         __trace_var(TRC_MEM_SET_P2M_ENTRY, 0, sizeof(t), (unsigned char *)&t);
     }
 
 #if CONFIG_PAGING_LEVELS >= 4
-    if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
+    if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
                          L4_PAGETABLE_SHIFT - PAGE_SHIFT,
                          L4_PAGETABLE_ENTRIES, PGT_l3_page_table) )
         goto out;
@@ -1298,14 +1296,15 @@ p2m_set_entry(struct domain *d, unsigned
              !(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
         {
             P2M_ERROR("configure P2M table L3 entry with large page\n");
-            domain_crash(d);
+            domain_crash(p2m->domain);
             goto out;
         }
         l3e_content = mfn_valid(mfn) 
             ? l3e_from_pfn(mfn_x(mfn), p2m_type_to_flags(p2mt) | _PAGE_PSE)
             : l3e_empty();
         entry_content.l1 = l3e_content.l3;
-        paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 3);
+        paging_write_p2m_entry(p2m->domain, gfn, p2m_entry,
+                               table_mfn, entry_content, 3);
 
     }
     /*
@@ -1315,17 +1314,17 @@ p2m_set_entry(struct domain *d, unsigned
      * in Xen's address space for translated PV guests.
      * When using AMD's NPT on PAE Xen, we are restricted to 4GB.
      */
-    else if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
+    else if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
                               L3_PAGETABLE_SHIFT - PAGE_SHIFT,
                               ((CONFIG_PAGING_LEVELS == 3)
-                               ? (paging_mode_hap(d) ? 4 : 8)
+                               ? (paging_mode_hap(p2m->domain) ? 4 : 8)
                                : L3_PAGETABLE_ENTRIES),
                               PGT_l2_page_table) )
         goto out;
 
     if ( page_order == 0 )
     {
-        if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn,
+        if ( !p2m_next_level(p2m, &table_mfn, &table, &gfn_remainder, gfn,
                              L2_PAGETABLE_SHIFT - PAGE_SHIFT,
                              L2_PAGETABLE_ENTRIES, PGT_l1_page_table) )
             goto out;
@@ -1340,7 +1339,8 @@ p2m_set_entry(struct domain *d, unsigned
             entry_content = l1e_empty();
         
         /* level 1 entry */
-        paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 1);
+        paging_write_p2m_entry(p2m->domain, gfn, p2m_entry,
+                               table_mfn, entry_content, 1);
     }
     else if ( page_order == 9 )
     {
@@ -1354,7 +1354,7 @@ p2m_set_entry(struct domain *d, unsigned
              !(l1e_get_flags(*p2m_entry) & _PAGE_PSE) )
         {
             P2M_ERROR("configure P2M table 4KB L2 entry with large page\n");
-            domain_crash(d);
+            domain_crash(p2m->domain);
             goto out;
         }
         
@@ -1365,23 +1365,24 @@ p2m_set_entry(struct domain *d, unsigned
             l2e_content = l2e_empty();
         
         entry_content.l1 = l2e_content.l2;
-        paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 2);
+        paging_write_p2m_entry(p2m->domain, gfn, p2m_entry,
+                               table_mfn, entry_content, 2);
     }
 
     /* Track the highest gfn for which we have ever had a valid mapping */
     if ( mfn_valid(mfn) 
-         && (gfn + (1UL << page_order) - 1 > d->arch.p2m->max_mapped_pfn) )
-        d->arch.p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1;
-
-    if ( iommu_enabled && need_iommu(d) )
+         && (gfn + (1UL << page_order) - 1 > p2m->max_mapped_pfn) )
+        p2m->max_mapped_pfn = gfn + (1UL << page_order) - 1;
+
+    if ( iommu_enabled && need_iommu(p2m->domain) )
     {
         if ( p2mt == p2m_ram_rw )
             for ( i = 0; i < (1UL << page_order); i++ )
-                iommu_map_page(d, gfn+i, mfn_x(mfn)+i,
+                iommu_map_page(p2m->domain, gfn+i, mfn_x(mfn)+i,
                                IOMMUF_readable|IOMMUF_writable);
         else
             for ( int i = 0; i < (1UL << page_order); i++ )
-                iommu_unmap_page(d, gfn+i);
+                iommu_unmap_page(p2m->domain, gfn+i);
     }
 
     /* Success */
@@ -1393,7 +1394,7 @@ out:
 }
 
 static mfn_t
-p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t,
+p2m_gfn_to_mfn(struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t,
                p2m_query_t q)
 {
     mfn_t mfn;
@@ -1401,7 +1402,7 @@ p2m_gfn_to_mfn(struct domain *d, unsigne
     l2_pgentry_t *l2e;
     l1_pgentry_t *l1e;
 
-    ASSERT(paging_mode_translate(d));
+    ASSERT(paging_mode_translate(p2m->domain));
 
     /* XXX This is for compatibility with the old model, where anything not 
      * XXX marked as RAM was considered to be emulated MMIO space.
@@ -1409,9 +1410,9 @@ p2m_gfn_to_mfn(struct domain *d, unsigne
      * XXX we will return p2m_invalid for unmapped gfns */
     *t = p2m_mmio_dm;
 
-    mfn = pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
-
-    if ( gfn > d->arch.p2m->max_mapped_pfn )
+    mfn = pagetable_get_mfn(p2m_get_pagetable(p2m));
+
+    if ( gfn > p2m->max_mapped_pfn )
         /* This pfn is higher than the highest the p2m map currently holds */
         return _mfn(INVALID_MFN);
 
@@ -1447,7 +1448,7 @@ pod_retry_l3:
             {
                 if ( q != p2m_query )
                 {
-                    if ( !p2m_pod_demand_populate(d, gfn, 18, q) )
+                    if ( !p2m_pod_demand_populate(p2m, gfn, 18, q) )
                         goto pod_retry_l3;
                 }
                 else
@@ -1482,8 +1483,8 @@ pod_retry_l2:
         if ( p2m_flags_to_type(l2e_get_flags(*l2e)) == p2m_populate_on_demand )
         {
             if ( q != p2m_query ) {
-                if ( !p2m_pod_check_and_populate(d, gfn,
-                                                       (l1_pgentry_t *)l2e, 9, 
q) )
+                if ( !p2m_pod_check_and_populate(p2m, gfn,
+                                                 (l1_pgentry_t *)l2e, 9, q) )
                     goto pod_retry_l2;
             } else
                 *t = p2m_populate_on_demand;
@@ -1514,8 +1515,8 @@ pod_retry_l1:
         if ( p2m_flags_to_type(l1e_get_flags(*l1e)) == p2m_populate_on_demand )
         {
             if ( q != p2m_query ) {
-                if ( !p2m_pod_check_and_populate(d, gfn,
-                                                       (l1_pgentry_t *)l1e, 0, 
q) )
+                if ( !p2m_pod_check_and_populate(p2m, gfn,
+                                                 (l1_pgentry_t *)l1e, 0, q) )
                     goto pod_retry_l1;
             } else
                 *t = p2m_populate_on_demand;
@@ -1533,7 +1534,8 @@ pod_retry_l1:
 }
 
 /* Read the current domain's p2m table (through the linear mapping). */
-static mfn_t p2m_gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t,
+static mfn_t p2m_gfn_to_mfn_current(struct p2m_domain *p2m,
+                                    unsigned long gfn, p2m_type_t *t,
                                     p2m_query_t q)
 {
     mfn_t mfn = _mfn(INVALID_MFN);
@@ -1544,7 +1546,7 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
      * XXX Once we start explicitly registering MMIO regions in the p2m 
      * XXX we will return p2m_invalid for unmapped gfns */
 
-    if ( gfn <= current->domain->arch.p2m->max_mapped_pfn )
+    if ( gfn <= p2m->max_mapped_pfn )
     {
         l1_pgentry_t l1e = l1e_empty(), *p2m_entry;
         l2_pgentry_t l2e = l2e_empty();
@@ -1574,7 +1576,7 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
                 /* The read has succeeded, so we know that mapping exists */
                 if ( q != p2m_query )
                 {
-                    if ( !p2m_pod_demand_populate(current->domain, gfn, 18, q) 
)
+                    if ( !p2m_pod_demand_populate(p2m, gfn, 18, q) )
                         goto pod_retry_l3;
                     p2mt = p2m_invalid;
                     printk("%s: Allocate 1GB failed!\n", __func__);
@@ -1624,8 +1626,8 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
                  * exits at this point.  */
                 if ( q != p2m_query )
                 {
-                    if ( !p2m_pod_check_and_populate(current->domain, gfn,
-                                                            p2m_entry, 9, q) )
+                    if ( !p2m_pod_check_and_populate(p2m, gfn,
+                                                     p2m_entry, 9, q) )
                         goto pod_retry_l2;
 
                     /* Allocate failed. */
@@ -1680,8 +1682,8 @@ static mfn_t p2m_gfn_to_mfn_current(unsi
                  * exits at this point.  */
                 if ( q != p2m_query )
                 {
-                    if ( !p2m_pod_check_and_populate(current->domain, gfn,
-                                                            (l1_pgentry_t 
*)p2m_entry, 0, q) )
+                    if ( !p2m_pod_check_and_populate(p2m, gfn,
+                                                     (l1_pgentry_t 
*)p2m_entry, 0, q) )
                         goto pod_retry_l1;
 
                     /* Allocate failed. */
@@ -1708,22 +1710,15 @@ out:
 }
 
 /* Init the datastructures for later use by the p2m code */
-int p2m_init(struct domain *d)
-{
-    struct p2m_domain *p2m;
-
-    p2m = xmalloc(struct p2m_domain);
-    if ( p2m == NULL )
-        return -ENOMEM;
-
-    d->arch.p2m = p2m;
-
+static void p2m_initialise(struct domain *d, struct p2m_domain *p2m)
+{
     memset(p2m, 0, sizeof(*p2m));
     p2m_lock_init(p2m);
     INIT_PAGE_LIST_HEAD(&p2m->pages);
     INIT_PAGE_LIST_HEAD(&p2m->pod.super);
     INIT_PAGE_LIST_HEAD(&p2m->pod.single);
 
+    p2m->domain = d;
     p2m->set_entry = p2m_set_entry;
     p2m->get_entry = p2m_gfn_to_mfn;
     p2m->get_entry_current = p2m_gfn_to_mfn_current;
@@ -1732,23 +1727,34 @@ int p2m_init(struct domain *d)
     if ( hap_enabled(d) && (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) )
         ept_p2m_init(d);
 
+    return;
+}
+
+int p2m_init(struct domain *d)
+{
+    struct p2m_domain *p2m;
+
+    p2m_get_hostp2m(d) = p2m = xmalloc(struct p2m_domain);
+    if ( p2m == NULL )
+        return -ENOMEM;
+    p2m_initialise(d, p2m);
+
     return 0;
 }
 
-void p2m_change_entry_type_global(struct domain *d,
+void p2m_change_entry_type_global(struct p2m_domain *p2m,
                                   p2m_type_t ot, p2m_type_t nt)
 {
-    struct p2m_domain *p2m = d->arch.p2m;
-
     p2m_lock(p2m);
-    p2m->change_entry_type_global(d, ot, nt);
+    p2m->change_entry_type_global(p2m, ot, nt);
     p2m_unlock(p2m);
 }
 
 static
-int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, 
+int set_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn, 
                     unsigned int page_order, p2m_type_t p2mt)
 {
+    struct domain *d = p2m->domain;
     unsigned long todo = 1ul << page_order;
     unsigned int order;
     int rc = 1;
@@ -1763,7 +1769,7 @@ int set_p2m_entry(struct domain *d, unsi
         else
             order = 0;
 
-        if ( !d->arch.p2m->set_entry(d, gfn, mfn, order, p2mt) )
+        if ( !p2m->set_entry(p2m, gfn, mfn, order, p2mt) )
             rc = 0;
         gfn += 1ul << order;
         if ( mfn_x(mfn) != INVALID_MFN )
@@ -1784,16 +1790,14 @@ int set_p2m_entry(struct domain *d, unsi
 //
 // Returns 0 for success or -errno.
 //
-int p2m_alloc_table(struct domain *d,
-                    struct page_info * (*alloc_page)(struct domain *d),
-                    void (*free_page)(struct domain *d, struct page_info *pg))
-
+int p2m_alloc_table(struct p2m_domain *p2m,
+               struct page_info * (*alloc_page)(struct p2m_domain *p2m),
+               void (*free_page)(struct p2m_domain *p2m, struct page_info *pg))
 {
     mfn_t mfn = _mfn(INVALID_MFN);
     struct page_info *page, *p2m_top;
     unsigned int page_count = 0;
     unsigned long gfn = -1UL;
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     p2m_lock(p2m);
 
@@ -1809,7 +1813,7 @@ int p2m_alloc_table(struct domain *d,
     p2m->alloc_page = alloc_page;
     p2m->free_page = free_page;
 
-    p2m_top = p2m_alloc_ptp(d,
+    p2m_top = p2m_alloc_ptp(p2m,
 #if CONFIG_PAGING_LEVELS == 4
         PGT_l4_page_table
 #else
@@ -1828,13 +1832,13 @@ int p2m_alloc_table(struct domain *d,
     P2M_PRINTK("populating p2m table\n");
 
     /* Initialise physmap tables for slot zero. Other code assumes this. */
-    if ( !set_p2m_entry(d, 0, _mfn(INVALID_MFN), 0,
+    if ( !set_p2m_entry(p2m, 0, _mfn(INVALID_MFN), 0,
                         p2m_invalid) )
         goto error;
 
     /* Copy all existing mappings from the page list and m2p */
-    spin_lock(&d->page_alloc_lock);
-    page_list_for_each(page, &d->page_list)
+    spin_lock(&p2m->domain->page_alloc_lock);
+    page_list_for_each(page, &p2m->domain->page_list)
     {
         mfn = page_to_mfn(page);
         gfn = get_gpfn_from_mfn(mfn_x(mfn));
@@ -1848,17 +1852,17 @@ int p2m_alloc_table(struct domain *d,
             (gfn != 0x55555555L)
 #endif
              && gfn != INVALID_M2P_ENTRY
-            && !set_p2m_entry(d, gfn, mfn, 0, p2m_ram_rw) )
+            && !set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_rw) )
             goto error_unlock;
     }
-    spin_unlock(&d->page_alloc_lock);
+    spin_unlock(&p2m->domain->page_alloc_lock);
 
     P2M_PRINTK("p2m table initialised (%u pages)\n", page_count);
     p2m_unlock(p2m);
     return 0;
 
 error_unlock:
-    spin_unlock(&d->page_alloc_lock);
+    spin_unlock(&p2m->domain->page_alloc_lock);
  error:
     P2M_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%"
                PRI_mfn "\n", gfn, mfn_x(mfn));
@@ -1866,12 +1870,11 @@ error_unlock:
     return -ENOMEM;
 }
 
-void p2m_teardown(struct domain *d)
+void p2m_teardown(struct p2m_domain *p2m)
 /* Return all the p2m pages to Xen.
  * We know we don't have any extra mappings to these pages */
 {
     struct page_info *pg;
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 #ifdef __x86_64__
     unsigned long gfn;
     p2m_type_t t;
@@ -1883,27 +1886,28 @@ void p2m_teardown(struct domain *d)
 #ifdef __x86_64__
     for ( gfn=0; gfn < p2m->max_mapped_pfn; gfn++ )
     {
-        mfn = p2m->get_entry(d, gfn, &t, p2m_query);
+        mfn = p2m->get_entry(p2m, gfn, &t, p2m_query);
         if ( mfn_valid(mfn) && (t == p2m_ram_shared) )
-            BUG_ON(mem_sharing_unshare_page(d, gfn, MEM_SHARING_DESTROY_GFN));
+            BUG_ON(mem_sharing_unshare_page(p2m, gfn, 
MEM_SHARING_DESTROY_GFN));
     }
 #endif
 
     p2m->phys_table = pagetable_null();
 
     while ( (pg = page_list_remove_head(&p2m->pages)) )
-        p2m->free_page(d, pg);
+        p2m->free_page(p2m, pg);
     p2m_unlock(p2m);
 }
 
 void p2m_final_teardown(struct domain *d)
 {
+    /* Iterate over all p2m tables per domain */
     xfree(d->arch.p2m);
     d->arch.p2m = NULL;
 }
 
 #if P2M_AUDIT
-static void audit_p2m(struct domain *d)
+static void audit_p2m(struct p2m_domain *p2m)
 {
     struct page_info *page;
     struct domain *od;
@@ -1913,6 +1917,7 @@ static void audit_p2m(struct domain *d)
     unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0;
     int test_linear;
     p2m_type_t type;
+    struct domain *d = p2m->domain;
 
     if ( !paging_mode_translate(d) )
         return;
@@ -1967,7 +1972,7 @@ static void audit_p2m(struct domain *d)
             continue;
         }
 
-        p2mfn = gfn_to_mfn_type_foreign(d, gfn, &type, p2m_query);
+        p2mfn = gfn_to_mfn_type_p2m(p2m, gfn, &type, p2m_query);
         if ( mfn_x(p2mfn) != mfn )
         {
             mpbad++;
@@ -1983,9 +1988,9 @@ static void audit_p2m(struct domain *d)
             set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
         }
 
-        if ( test_linear && (gfn <= d->arch.p2m->max_mapped_pfn) )
-        {
-            lp2mfn = mfn_x(gfn_to_mfn_query(d, gfn, &type));
+        if ( test_linear && (gfn <= p2m->max_mapped_pfn) )
+        {
+            lp2mfn = mfn_x(gfn_to_mfn_query(p2m, gfn, &type));
             if ( lp2mfn != mfn_x(p2mfn) )
             {
                 P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
@@ -2000,7 +2005,7 @@ static void audit_p2m(struct domain *d)
     spin_unlock(&d->page_alloc_lock);
 
     /* Audit part two: walk the domain's p2m table, checking the entries. */
-    if ( pagetable_get_pfn(p2m_get_pagetable(p2m_get_hostp2m(d)) != 0 )
+    if ( pagetable_get_pfn(p2m_get_pagetable(p2m)) != 0 )
     {
         l2_pgentry_t *l2e;
         l1_pgentry_t *l1e;
@@ -2009,12 +2014,12 @@ static void audit_p2m(struct domain *d)
 #if CONFIG_PAGING_LEVELS == 4
         l4_pgentry_t *l4e;
         l3_pgentry_t *l3e;
-        int i3, i4;
-        l4e = 
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)))));
+        int i4, i3;
+        l4e = 
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
 #else /* CONFIG_PAGING_LEVELS == 3 */
         l3_pgentry_t *l3e;
         int i3;
-        l3e = 
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m_get_hostp2m(d)))));
+        l3e = 
map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
 #endif
 
         gfn = 0;
@@ -2144,11 +2149,11 @@ static void audit_p2m(struct domain *d)
 
     }
 
-    if ( entry_count != d->arch.p2m->pod.entry_count )
+    if ( entry_count != p2m->pod.entry_count )
     {
         printk("%s: refcounted entry count %d, audit count %d!\n",
                __func__,
-               d->arch.p2m->pod.entry_count,
+               p2m->pod.entry_count,
                entry_count);
         BUG();
     }
@@ -2166,18 +2171,18 @@ static void audit_p2m(struct domain *d)
 
 
 static void
-p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn,
+p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn,
                 unsigned int page_order)
 {
     unsigned long i;
     mfn_t mfn_return;
     p2m_type_t t;
 
-    if ( !paging_mode_translate(d) )
-    {
-        if ( need_iommu(d) )
+    if ( !paging_mode_translate(p2m->domain) )
+    {
+        if ( need_iommu(p2m->domain) )
             for ( i = 0; i < (1 << page_order); i++ )
-                iommu_unmap_page(d, mfn + i);
+                iommu_unmap_page(p2m->domain, mfn + i);
         return;
     }
 
@@ -2185,23 +2190,23 @@ p2m_remove_page(struct domain *d, unsign
 
     for ( i = 0; i < (1UL << page_order); i++ )
     {
-        mfn_return = d->arch.p2m->get_entry(d, gfn + i, &t, p2m_query);
+        mfn_return = p2m->get_entry(p2m, gfn + i, &t, p2m_query);
         if ( !p2m_is_grant(t) )
             set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY);
         ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) );
     }
-    set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid);
+    set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, p2m_invalid);
 }
 
 void
-guest_physmap_remove_page(struct domain *d, unsigned long gfn,
+guest_physmap_remove_entry(struct p2m_domain *p2m, unsigned long gfn,
                           unsigned long mfn, unsigned int page_order)
 {
-    p2m_lock(d->arch.p2m);
-    audit_p2m(d);
-    p2m_remove_page(d, gfn, mfn, page_order);
-    audit_p2m(d);
-    p2m_unlock(d->arch.p2m);
+    p2m_lock(p2m);
+    audit_p2m(p2m);
+    p2m_remove_page(p2m, gfn, mfn, page_order);
+    audit_p2m(p2m);
+    p2m_unlock(p2m);
 }
 
 #if CONFIG_PAGING_LEVELS == 3
@@ -2232,7 +2237,7 @@ guest_physmap_mark_populate_on_demand(st
 guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
                                       unsigned int order)
 {
-    struct p2m_domain *p2md = d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     unsigned long i;
     p2m_type_t ot;
     mfn_t omfn;
@@ -2245,15 +2250,15 @@ guest_physmap_mark_populate_on_demand(st
     if ( rc != 0 )
         return rc;
 
-    p2m_lock(p2md);
-    audit_p2m(d);
+    p2m_lock(p2m);
+    audit_p2m(p2m);
 
     P2M_DEBUG("mark pod gfn=%#lx\n", gfn);
 
     /* Make sure all gpfns are unused */
     for ( i = 0; i < (1UL << order); i++ )
     {
-        omfn = gfn_to_mfn_query(d, gfn + i, &ot);
+        omfn = gfn_to_mfn_query(p2m, gfn + i, &ot);
         if ( p2m_is_ram(ot) )
         {
             printk("%s: gfn_to_mfn returned type %d!\n",
@@ -2269,29 +2274,29 @@ guest_physmap_mark_populate_on_demand(st
     }
 
     /* Now, actually do the two-way mapping */
-    if ( !set_p2m_entry(d, gfn, _mfn(POPULATE_ON_DEMAND_MFN), order,
+    if ( !set_p2m_entry(p2m, gfn, _mfn(POPULATE_ON_DEMAND_MFN), order,
                         p2m_populate_on_demand) )
         rc = -EINVAL;
     else
     {
-        p2md->pod.entry_count += 1 << order; /* Lock: p2m */
-        p2md->pod.entry_count -= pod_count;
-        BUG_ON(p2md->pod.entry_count < 0);
-    }
-
-    audit_p2m(d);
-    p2m_unlock(p2md);
+        p2m->pod.entry_count += 1 << order; /* Lock: p2m */
+        p2m->pod.entry_count -= pod_count;
+        BUG_ON(p2m->pod.entry_count < 0);
+    }
+
+    audit_p2m(p2m);
+    p2m_unlock(p2m);
 
 out:
     return rc;
-
 }
 
 int
-guest_physmap_add_entry(struct domain *d, unsigned long gfn,
+guest_physmap_add_entry(struct p2m_domain *p2m, unsigned long gfn,
                         unsigned long mfn, unsigned int page_order, 
                         p2m_type_t t)
 {
+    struct domain *d = p2m->domain;
     unsigned long i, ogfn;
     p2m_type_t ot;
     mfn_t omfn;
@@ -2321,20 +2326,20 @@ guest_physmap_add_entry(struct domain *d
     if ( rc != 0 )
         return rc;
 
-    p2m_lock(d->arch.p2m);
-    audit_p2m(d);
+    p2m_lock(p2m);
+    audit_p2m(p2m);
 
     P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn);
 
     /* First, remove m->p mappings for existing p->m mappings */
     for ( i = 0; i < (1UL << page_order); i++ )
     {
-        omfn = gfn_to_mfn_query(d, gfn + i, &ot);
+        omfn = gfn_to_mfn_query(p2m, gfn + i, &ot);
         if ( p2m_is_grant(ot) )
         {
             /* Really shouldn't be unmapping grant maps this way */
             domain_crash(d);
-            p2m_unlock(d->arch.p2m);
+            p2m_unlock(p2m);
             return -EINVAL;
         }
         else if ( p2m_is_ram(ot) )
@@ -2368,7 +2373,7 @@ guest_physmap_add_entry(struct domain *d
              * address */
             P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n",
                       mfn + i, ogfn, gfn + i);
-            omfn = gfn_to_mfn_query(d, ogfn, &ot);
+            omfn = gfn_to_mfn_query(p2m, ogfn, &ot);
             /* If we get here, we know the local domain owns the page,
                so it can't have been grant mapped in. */
             BUG_ON( p2m_is_grant(ot) );
@@ -2378,7 +2383,7 @@ guest_physmap_add_entry(struct domain *d
                 P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n",
                           ogfn , mfn_x(omfn));
                 if ( mfn_x(omfn) == (mfn + i) )
-                    p2m_remove_page(d, ogfn, mfn + i, 0);
+                    p2m_remove_page(p2m, ogfn, mfn + i, 0);
             }
         }
     }
@@ -2386,7 +2391,7 @@ guest_physmap_add_entry(struct domain *d
     /* Now, actually do the two-way mapping */
     if ( mfn_valid(_mfn(mfn)) ) 
     {
-        if ( !set_p2m_entry(d, gfn, _mfn(mfn), page_order, t) )
+        if ( !set_p2m_entry(p2m, gfn, _mfn(mfn), page_order, t) )
             rc = -EINVAL;
         if ( !p2m_is_grant(t) )
         {
@@ -2398,18 +2403,18 @@ guest_physmap_add_entry(struct domain *d
     {
         gdprintk(XENLOG_WARNING, "Adding bad mfn to p2m map (%#lx -> %#lx)\n",
                  gfn, mfn);
-        if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), page_order, 
+        if ( !set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), page_order, 
                             p2m_invalid) )
             rc = -EINVAL;
         else
         {
-            d->arch.p2m->pod.entry_count -= pod_count; /* Lock: p2m */
-            BUG_ON(d->arch.p2m->pod.entry_count < 0);
-        }
-    }
-
-    audit_p2m(d);
-    p2m_unlock(d->arch.p2m);
+            p2m->pod.entry_count -= pod_count; /* Lock: p2m */
+            BUG_ON(p2m->pod.entry_count < 0);
+        }
+    }
+
+    audit_p2m(p2m);
+    p2m_unlock(p2m);
 
     return rc;
 }
@@ -2417,7 +2422,7 @@ guest_physmap_add_entry(struct domain *d
 /* Walk the whole p2m table, changing any entries of the old type
  * to the new type.  This is used in hardware-assisted paging to 
  * quickly enable or diable log-dirty tracking */
-void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt)
+void p2m_change_type_global(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t 
nt)
 {
     unsigned long mfn, gfn, flags;
     l1_pgentry_t l1e_content;
@@ -2430,17 +2435,16 @@ void p2m_change_type_global(struct domai
     l4_pgentry_t *l4e;
     unsigned long i4;
 #endif /* CONFIG_PAGING_LEVELS == 4 */
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
 
-    if ( !paging_mode_translate(d) )
+    if ( !paging_mode_translate(p2m->domain) )
         return;
 
     if ( pagetable_get_pfn(p2m_get_pagetable(p2m)) == 0 )
         return;
 
-    ASSERT(p2m_locked_by_me(d->arch.p2m));
+    ASSERT(p2m_locked_by_me(p2m));
 
 #if CONFIG_PAGING_LEVELS == 4
     l4e = map_domain_page(mfn_x(pagetable_get_mfn(p2m_get_pagetable(p2m))));
@@ -2476,7 +2480,8 @@ void p2m_change_type_global(struct domai
                 gfn = get_gpfn_from_mfn(mfn);
                 flags = p2m_type_to_flags(nt);
                 l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE);
-                paging_write_p2m_entry(d, gfn, (l1_pgentry_t *)&l3e[i3],
+                paging_write_p2m_entry(p2m->domain, gfn,
+                                       (l1_pgentry_t *)&l3e[i3],
                                        l3mfn, l1e_content, 3);
                 continue;
             }
@@ -2506,7 +2511,8 @@ void p2m_change_type_global(struct domai
                            * L2_PAGETABLE_ENTRIES) * L1_PAGETABLE_ENTRIES; 
                     flags = p2m_type_to_flags(nt);
                     l1e_content = l1e_from_pfn(mfn, flags | _PAGE_PSE);
-                    paging_write_p2m_entry(d, gfn, (l1_pgentry_t *)&l2e[i2],
+                    paging_write_p2m_entry(p2m->domain, gfn,
+                                           (l1_pgentry_t *)&l2e[i2],
                                            l2mfn, l1e_content, 2);
                     continue;
                 }
@@ -2529,7 +2535,7 @@ void p2m_change_type_global(struct domai
                     /* create a new 1le entry with the new type */
                     flags = p2m_type_to_flags(nt);
                     l1e_content = l1e_from_pfn(mfn, flags);
-                    paging_write_p2m_entry(d, gfn, &l1e[i1],
+                    paging_write_p2m_entry(p2m->domain, gfn, &l1e[i1],
                                            l1mfn, l1e_content, 1);
                 }
                 unmap_domain_page(l1e);
@@ -2551,7 +2557,7 @@ void p2m_change_type_global(struct domai
 
 /* Modify the p2m type of a single gfn from ot to nt, returning the 
  * entry's previous type */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn, 
+p2m_type_t p2m_change_type(struct p2m_domain *p2m, unsigned long gfn, 
                            p2m_type_t ot, p2m_type_t nt)
 {
     p2m_type_t pt;
@@ -2559,31 +2565,31 @@ p2m_type_t p2m_change_type(struct domain
 
     BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
 
-    p2m_lock(d->arch.p2m);
-
-    mfn = gfn_to_mfn_query(d, gfn, &pt);
+    p2m_lock(p2m);
+
+    mfn = gfn_to_mfn_query(p2m, gfn, &pt);
     if ( pt == ot )
-        set_p2m_entry(d, gfn, mfn, 0, nt);
-
-    p2m_unlock(d->arch.p2m);
+        set_p2m_entry(p2m, gfn, mfn, 0, nt);
+
+    p2m_unlock(p2m);
 
     return pt;
 }
 
 int
-set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+set_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn)
 {
     int rc = 0;
     p2m_type_t ot;
     mfn_t omfn;
 
-    if ( !paging_mode_translate(d) )
+    if ( !paging_mode_translate(p2m->domain) )
         return 0;
 
-    omfn = gfn_to_mfn_query(d, gfn, &ot);
+    omfn = gfn_to_mfn_query(p2m, gfn, &ot);
     if ( p2m_is_grant(ot) )
     {
-        domain_crash(d);
+        domain_crash(p2m->domain);
         return 0;
     }
     else if ( p2m_is_ram(ot) )
@@ -2593,51 +2599,51 @@ set_mmio_p2m_entry(struct domain *d, uns
     }
 
     P2M_DEBUG("set mmio %lx %lx\n", gfn, mfn_x(mfn));
-    p2m_lock(d->arch.p2m);
-    rc = set_p2m_entry(d, gfn, mfn, 0, p2m_mmio_direct);
-    p2m_unlock(d->arch.p2m);
+    p2m_lock(p2m);
+    rc = set_p2m_entry(p2m, gfn, mfn, 0, p2m_mmio_direct);
+    p2m_unlock(p2m);
     if ( 0 == rc )
         gdprintk(XENLOG_ERR,
             "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
-            gmfn_to_mfn(d, gfn));
+            mfn_x(gfn_to_mfn(p2m, gfn, &ot)));
     return rc;
 }
 
 int
-clear_mmio_p2m_entry(struct domain *d, unsigned long gfn)
+clear_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn)
 {
     int rc = 0;
-    unsigned long mfn;
-
-    if ( !paging_mode_translate(d) )
+    mfn_t mfn;
+    p2m_type_t t;
+
+    if ( !paging_mode_translate(p2m->domain) )
         return 0;
 
-    mfn = gmfn_to_mfn(d, gfn);
-    if ( INVALID_MFN == mfn )
+    mfn = gfn_to_mfn(p2m, gfn, &t);
+    if ( !mfn_valid(mfn) )
     {
         gdprintk(XENLOG_ERR,
             "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn);
         return 0;
     }
-    p2m_lock(d->arch.p2m);
-    rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0, 0);
-    p2m_unlock(d->arch.p2m);
+    p2m_lock(p2m);
+    rc = set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), 0, 0);
+    p2m_unlock(p2m);
 
     return rc;
 }
 
-#ifdef __x86_64__
 int
-set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+set_shared_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn)
 {
     int rc = 0;
     p2m_type_t ot;
     mfn_t omfn;
 
-    if ( !paging_mode_translate(d) )
+    if ( !paging_mode_translate(p2m->domain) )
         return 0;
 
-    omfn = gfn_to_mfn_query(d, gfn, &ot);
+    omfn = gfn_to_mfn_query(p2m, gfn, &ot);
     /* At the moment we only allow p2m change if gfn has already been made
      * sharable first */
     ASSERT(p2m_is_shared(ot));
@@ -2646,22 +2652,23 @@ set_shared_p2m_entry(struct domain *d, u
     set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
 
     P2M_DEBUG("set shared %lx %lx\n", gfn, mfn_x(mfn));
-    rc = set_p2m_entry(d, gfn, mfn, 0, p2m_ram_shared);
+    rc = set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_shared);
     if ( 0 == rc )
         gdprintk(XENLOG_ERR,
             "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
-            gmfn_to_mfn(d, gfn));
+            gmfn_to_mfn(p2m->domain, gfn));
     return rc;
 }
 
-int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn)
+#ifdef __x86_64__
+int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn)
 {
     struct page_info *page;
     p2m_type_t p2mt;
     mfn_t mfn;
     int ret;
 
-    mfn = gfn_to_mfn(d, gfn, &p2mt);
+    mfn = gfn_to_mfn(p2m, gfn, &p2mt);
 
     /* Check if mfn is valid */
     ret = -EINVAL;
@@ -2687,9 +2694,9 @@ int p2m_mem_paging_nominate(struct domai
         goto out;
 
     /* Fix p2m entry */
-    p2m_lock(d->arch.p2m);
-    set_p2m_entry(d, gfn, mfn, 0, p2m_ram_paging_out);
-    p2m_unlock(d->arch.p2m);
+    p2m_lock(p2m);
+    set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_paging_out);
+    p2m_unlock(p2m);
 
     ret = 0;
 
@@ -2697,14 +2704,15 @@ int p2m_mem_paging_nominate(struct domai
     return ret;
 }
 
-int p2m_mem_paging_evict(struct domain *d, unsigned long gfn)
+int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn)
 {
     struct page_info *page;
     p2m_type_t p2mt;
     mfn_t mfn;
+    struct domain *d = p2m->domain;
 
     /* Get mfn */
-    mfn = gfn_to_mfn(d, gfn, &p2mt);
+    mfn = gfn_to_mfn(p2m, gfn, &p2mt);
     if ( unlikely(!mfn_valid(mfn)) )
         return -EINVAL;
 
@@ -2722,9 +2730,9 @@ int p2m_mem_paging_evict(struct domain *
         put_page(page);
 
     /* Remove mapping from p2m table */
-    p2m_lock(d->arch.p2m);
-    set_p2m_entry(d, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paged);
-    p2m_unlock(d->arch.p2m);
+    p2m_lock(p2m);
+    set_p2m_entry(p2m, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paged);
+    p2m_unlock(p2m);
 
     /* Put the page back so it gets freed */
     put_page(page);
@@ -2732,11 +2740,12 @@ int p2m_mem_paging_evict(struct domain *
     return 0;
 }
 
-void p2m_mem_paging_populate(struct domain *d, unsigned long gfn)
+void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
 {
     struct vcpu *v = current;
     mem_event_request_t req;
     p2m_type_t p2mt;
+    struct domain *d = p2m->domain;
 
     memset(&req, 0, sizeof(req));
 
@@ -2747,12 +2756,12 @@ void p2m_mem_paging_populate(struct doma
     /* Fix p2m mapping */
     /* XXX: It seems inefficient to have this here, as it's only needed
      *      in one case (ept guest accessing paging out page) */
-    gfn_to_mfn(d, gfn, &p2mt);
+    gfn_to_mfn(p2m, gfn, &p2mt);
     if ( p2mt != p2m_ram_paging_out )
     {
-        p2m_lock(d->arch.p2m);
-        set_p2m_entry(d, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paging_in_start);
-        p2m_unlock(d->arch.p2m);
+        p2m_lock(p2m);
+        set_p2m_entry(p2m, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paging_in_start);
+        p2m_unlock(p2m);
     }
 
     /* Pause domain */
@@ -2770,25 +2779,26 @@ void p2m_mem_paging_populate(struct doma
     mem_event_put_request(d, &req);
 }
 
-int p2m_mem_paging_prep(struct domain *d, unsigned long gfn)
+int p2m_mem_paging_prep(struct p2m_domain *p2m, unsigned long gfn)
 {
     struct page_info *page;
 
     /* Get a free page */
-    page = alloc_domheap_page(d, 0);
+    page = alloc_domheap_page(p2m->domain, 0);
     if ( unlikely(page == NULL) )
         return -EINVAL;
 
     /* Fix p2m mapping */
-    p2m_lock(d->arch.p2m);
-    set_p2m_entry(d, gfn, page_to_mfn(page), 0, p2m_ram_paging_in);
-    p2m_unlock(d->arch.p2m);
+    p2m_lock(p2m);
+    set_p2m_entry(p2m, gfn, page_to_mfn(page), 0, p2m_ram_paging_in);
+    p2m_unlock(p2m);
 
     return 0;
 }
 
-void p2m_mem_paging_resume(struct domain *d)
-{
+void p2m_mem_paging_resume(struct p2m_domain *p2m)
+{
+    struct domain *d = p2m->domain;
     mem_event_response_t rsp;
     p2m_type_t p2mt;
     mfn_t mfn;
@@ -2797,10 +2807,10 @@ void p2m_mem_paging_resume(struct domain
     mem_event_get_response(d, &rsp);
 
     /* Fix p2m entry */
-    mfn = gfn_to_mfn(d, rsp.gfn, &p2mt);
-    p2m_lock(d->arch.p2m);
-    set_p2m_entry(d, rsp.gfn, mfn, 0, p2m_ram_rw);
-    p2m_unlock(d->arch.p2m);
+    mfn = gfn_to_mfn(p2m, rsp.gfn, &p2mt);
+    p2m_lock(p2m);
+    set_p2m_entry(p2m, rsp.gfn, mfn, 0, p2m_ram_rw);
+    p2m_unlock(p2m);
 
     /* Unpause domain */
     if ( rsp.flags & MEM_EVENT_FLAG_VCPU_PAUSED )
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Wed Aug 11 15:56:01 2010 +0100
@@ -1714,8 +1714,9 @@ sh_alloc_p2m_pages(struct domain *d)
 
 // Returns 0 if no memory is available...
 static struct page_info *
-shadow_alloc_p2m_page(struct domain *d)
-{
+shadow_alloc_p2m_page(struct p2m_domain *p2m)
+{
+    struct domain *d = p2m->domain;
     struct page_info *pg;
     mfn_t mfn;
     void *p;
@@ -1741,8 +1742,9 @@ shadow_alloc_p2m_page(struct domain *d)
 }
 
 static void
-shadow_free_p2m_page(struct domain *d, struct page_info *pg)
-{
+shadow_free_p2m_page(struct p2m_domain *p2m, struct page_info *pg)
+{
+    struct domain *d = p2m->domain;
     ASSERT(page_get_owner(pg) == d);
     /* Should have just the one ref we gave it in alloc_p2m_page() */
     if ( (pg->count_info & PGC_count_mask) != 1 )
@@ -3100,6 +3102,7 @@ int shadow_enable(struct domain *d, u32 
     struct page_info *pg = NULL;
     uint32_t *e;
     int i, rv = 0;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     mode |= PG_SH_enable;
 
@@ -3135,7 +3138,8 @@ int shadow_enable(struct domain *d, u32 
      * to avoid possible deadlock. */
     if ( mode & PG_translate )
     {
-        rv = p2m_alloc_table(d, shadow_alloc_p2m_page, shadow_free_p2m_page);
+        rv = p2m_alloc_table(p2m,
+            shadow_alloc_p2m_page, shadow_free_p2m_page);
         if (rv != 0)
             goto out_unlocked;
     }
@@ -3146,7 +3150,7 @@ int shadow_enable(struct domain *d, u32 
     {
         /* Get a single page from the shadow pool.  Take it via the 
          * P2M interface to make freeing it simpler afterwards. */
-        pg = shadow_alloc_p2m_page(d);
+        pg = shadow_alloc_p2m_page(p2m);
         if ( pg == NULL )
         {
             rv = -ENOMEM;
@@ -3195,10 +3199,10 @@ int shadow_enable(struct domain *d, u32 
  out_locked:
     shadow_unlock(d);
  out_unlocked:
-    if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m_get_hostp2m(d))) )
-        p2m_teardown(d);
+    if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m)) )
+        p2m_teardown(p2m);
     if ( rv != 0 && pg != NULL )
-        shadow_free_p2m_page(d, pg);
+        shadow_free_p2m_page(p2m, pg);
     domain_unpause(d);
     return rv;
 }
@@ -3210,6 +3214,7 @@ void shadow_teardown(struct domain *d)
     struct vcpu *v;
     mfn_t mfn;
     struct page_info *pg;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     ASSERT(d->is_dying);
     ASSERT(d != current->domain);
@@ -3264,7 +3269,7 @@ void shadow_teardown(struct domain *d)
 #endif /* (SHADOW_OPTIMIZATIONS & (SHOPT_VIRTUAL_TLB|SHOPT_OUT_OF_SYNC)) */
 
     while ( (pg = page_list_remove_head(&d->arch.paging.shadow.p2m_freelist)) )
-        shadow_free_p2m_page(d, pg);
+        shadow_free_p2m_page(p2m, pg);
 
     if ( d->arch.paging.shadow.total_pages != 0 )
     {
@@ -3298,7 +3303,7 @@ void shadow_teardown(struct domain *d)
             if ( !hvm_paging_enabled(v) )
                 v->arch.guest_table = pagetable_null();
         }
-        shadow_free_p2m_page(d, 
+        shadow_free_p2m_page(p2m, 
             pagetable_get_page(d->arch.paging.shadow.unpaged_pagetable));
         d->arch.paging.shadow.unpaged_pagetable = pagetable_null();
     }
@@ -3335,7 +3340,7 @@ void shadow_final_teardown(struct domain
         shadow_teardown(d);
 
     /* It is now safe to pull down the p2m map. */
-    p2m_teardown(d);
+    p2m_teardown(p2m_get_hostp2m(d));
 
     SHADOW_PRINTK("dom %u final teardown done."
                    "  Shadow pages total = %u, free = %u, p2m=%u\n",
@@ -3657,10 +3662,11 @@ int shadow_track_dirty_vram(struct domai
     unsigned long i;
     p2m_type_t t;
     struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     if (end_pfn < begin_pfn
-            || begin_pfn > d->arch.p2m->max_mapped_pfn
-            || end_pfn >= d->arch.p2m->max_mapped_pfn)
+            || begin_pfn > p2m->max_mapped_pfn
+            || end_pfn >= p2m->max_mapped_pfn)
         return -EINVAL;
 
     shadow_lock(d);
@@ -3729,7 +3735,7 @@ int shadow_track_dirty_vram(struct domai
 
         /* Iterate over VRAM to track dirty bits. */
         for ( i = 0; i < nr; i++ ) {
-            mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t);
+            mfn_t mfn = gfn_to_mfn(p2m, begin_pfn + i, &t);
             struct page_info *page;
             int dirty = 0;
             paddr_t sl1ma = dirty_vram->sl1ma[i];
@@ -3814,7 +3820,7 @@ int shadow_track_dirty_vram(struct domai
                 /* was clean for more than two seconds, try to disable guest
                  * write access */
                 for ( i = begin_pfn; i < end_pfn; i++ ) {
-                    mfn_t mfn = gfn_to_mfn(d, i, &t);
+                    mfn_t mfn = gfn_to_mfn(p2m, i, &t);
                     if (mfn_x(mfn) != INVALID_MFN)
                         flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn, 
1, 0);
                 }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Wed Aug 11 15:56:01 2010 +0100
@@ -167,7 +167,7 @@ sh_walk_guest_tables(struct vcpu *v, uns
 sh_walk_guest_tables(struct vcpu *v, unsigned long va, walk_t *gw, 
                      uint32_t pfec)
 {
-    return guest_walk_tables(v, va, gw, pfec, 
+    return guest_walk_tables(v, p2m_get_hostp2m(v->domain), va, gw, pfec, 
 #if GUEST_PAGING_LEVELS == 3 /* PAE */
                              _mfn(INVALID_MFN),
                              v->arch.paging.shadow.gl3e
@@ -2240,6 +2240,7 @@ static int validate_gl4e(struct vcpu *v,
     shadow_l4e_t *sl4p = se;
     mfn_t sl3mfn = _mfn(INVALID_MFN);
     struct domain *d = v->domain;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     p2m_type_t p2mt;
     int result = 0;
 
@@ -2248,7 +2249,7 @@ static int validate_gl4e(struct vcpu *v,
     if ( guest_l4e_get_flags(new_gl4e) & _PAGE_PRESENT )
     {
         gfn_t gl3gfn = guest_l4e_get_gfn(new_gl4e);
-        mfn_t gl3mfn = gfn_to_mfn_query(d, gl3gfn, &p2mt);
+        mfn_t gl3mfn = gfn_to_mfn_query(p2m, gl3gfn, &p2mt);
         if ( p2m_is_ram(p2mt) )
             sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
         else if ( p2mt != p2m_populate_on_demand )
@@ -2299,13 +2300,14 @@ static int validate_gl3e(struct vcpu *v,
     mfn_t sl2mfn = _mfn(INVALID_MFN);
     p2m_type_t p2mt;
     int result = 0;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
 
     perfc_incr(shadow_validate_gl3e_calls);
 
     if ( guest_l3e_get_flags(new_gl3e) & _PAGE_PRESENT )
     {
         gfn_t gl2gfn = guest_l3e_get_gfn(new_gl3e);
-        mfn_t gl2mfn = gfn_to_mfn_query(v->domain, gl2gfn, &p2mt);
+        mfn_t gl2mfn = gfn_to_mfn_query(p2m, gl2gfn, &p2mt);
         if ( p2m_is_ram(p2mt) )
             sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
         else if ( p2mt != p2m_populate_on_demand )
@@ -2329,6 +2331,7 @@ static int validate_gl2e(struct vcpu *v,
     guest_l2e_t new_gl2e = *(guest_l2e_t *)new_ge;
     shadow_l2e_t *sl2p = se;
     mfn_t sl1mfn = _mfn(INVALID_MFN);
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
     p2m_type_t p2mt;
     int result = 0;
 
@@ -2354,7 +2357,7 @@ static int validate_gl2e(struct vcpu *v,
         }
         else
         {
-            mfn_t gl1mfn = gfn_to_mfn_query(v->domain, gl1gfn, &p2mt);
+            mfn_t gl1mfn = gfn_to_mfn_query(p2m, gl1gfn, &p2mt);
             if ( p2m_is_ram(p2mt) )
                 sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow); 
             else if ( p2mt != p2m_populate_on_demand )
@@ -2415,6 +2418,7 @@ static int validate_gl1e(struct vcpu *v,
     shadow_l1e_t *sl1p = se;
     gfn_t gfn;
     mfn_t gmfn;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
     p2m_type_t p2mt;
     int result = 0;
 #if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
@@ -2424,7 +2428,7 @@ static int validate_gl1e(struct vcpu *v,
     perfc_incr(shadow_validate_gl1e_calls);
 
     gfn = guest_l1e_get_gfn(new_gl1e);
-    gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+    gmfn = gfn_to_mfn_query(p2m, gfn, &p2mt);
 
     l1e_propagate_from_guest(v, new_gl1e, gmfn, &new_sl1e, ft_prefetch, p2mt);
     result |= shadow_set_l1e(v, sl1p, new_sl1e, p2mt, sl1mfn);
@@ -2484,7 +2488,7 @@ void sh_resync_l1(struct vcpu *v, mfn_t 
             shadow_l1e_t nsl1e;
 
             gfn = guest_l1e_get_gfn(gl1e);
-            gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+            gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
             l1e_propagate_from_guest(v, gl1e, gmfn, &nsl1e, ft_prefetch, p2mt);
             rc |= shadow_set_l1e(v, sl1p, nsl1e, p2mt, sl1mfn);
 
@@ -2810,7 +2814,7 @@ static void sh_prefetch(struct vcpu *v, 
 
         /* Look at the gfn that the l1e is pointing at */
         gfn = guest_l1e_get_gfn(gl1e);
-        gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+        gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt);
 
         /* Propagate the entry.  */
         l1e_propagate_from_guest(v, gl1e, gmfn, &sl1e, ft_prefetch, p2mt);
@@ -3166,7 +3170,7 @@ static int sh_page_fault(struct vcpu *v,
 
     /* What mfn is the guest trying to access? */
     gfn = guest_l1e_get_gfn(gw.l1e);
-    gmfn = gfn_to_mfn_guest(d, gfn, &p2mt);
+    gmfn = gfn_to_mfn_guest(p2m_get_hostp2m(d), gfn, &p2mt);
 
     if ( shadow_mode_refcounts(d) && 
          ((!p2m_is_valid(p2mt) && !p2m_is_grant(p2mt)) ||
@@ -4272,7 +4276,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
             if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
             {
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
-                gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
+                gl2mfn = gfn_to_mfn_query(p2m_get_hostp2m(d), gl2gfn, &p2mt);
                 if ( p2m_is_ram(p2mt) )
                     flush |= sh_remove_write_access(v, gl2mfn, 2, 0);
             }
@@ -4285,7 +4289,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
             if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
             {
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
-                gl2mfn = gfn_to_mfn_query(d, gl2gfn, &p2mt);
+                gl2mfn = gfn_to_mfn_query(p2m_get_hostp2m(d), gl2gfn, &p2mt);
                 if ( p2m_is_ram(p2mt) )
                     sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3) 
                                            ? SH_type_l2h_shadow 
@@ -4682,7 +4686,7 @@ static void sh_pagetable_dying(struct vc
     if ( gcr3 == gpa )
         fast_path = 1;
 
-    gmfn = gfn_to_mfn_query(v->domain, _gfn(gpa >> PAGE_SHIFT), &p2mt);
+    gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gpa >> 
PAGE_SHIFT), &p2mt);
     if ( !mfn_valid(gmfn) || !p2m_is_ram(p2mt) )
     {
         printk(XENLOG_DEBUG "sh_pagetable_dying: gpa not valid %"PRIpaddr"\n",
@@ -4702,7 +4706,7 @@ static void sh_pagetable_dying(struct vc
         {
             /* retrieving the l2s */
             gl2a = guest_l3e_get_paddr(gl3e[i]);
-            gmfn = gfn_to_mfn_query(v->domain, _gfn(gl2a >> PAGE_SHIFT), 
&p2mt);
+            gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gl2a >> 
PAGE_SHIFT), &p2mt);
             smfn = shadow_hash_lookup(v, mfn_x(gmfn), SH_type_l2_pae_shadow);
         }
 
@@ -4737,7 +4741,7 @@ static void sh_pagetable_dying(struct vc
 
     shadow_lock(v->domain);
 
-    gmfn = gfn_to_mfn_query(v->domain, _gfn(gpa >> PAGE_SHIFT), &p2mt);
+    gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), _gfn(gpa >> 
PAGE_SHIFT), &p2mt);
 #if GUEST_PAGING_LEVELS == 2
     smfn = shadow_hash_lookup(v, mfn_x(gmfn), SH_type_l2_32_shadow);
 #else
@@ -4777,6 +4781,7 @@ static mfn_t emulate_gva_to_mfn(struct v
     mfn_t mfn;
     p2m_type_t p2mt;
     uint32_t pfec = PFEC_page_present | PFEC_write_access;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
 
     /* Translate the VA to a GFN */
     gfn = sh_gva_to_gfn(v, vaddr, &pfec);
@@ -4792,9 +4797,9 @@ static mfn_t emulate_gva_to_mfn(struct v
     /* Translate the GFN to an MFN */
     /* PoD: query only if shadow lock is held (to avoid deadlock) */
     if ( shadow_locked_by_me(v->domain) )
-        mfn = gfn_to_mfn_query(v->domain, _gfn(gfn), &p2mt);
+        mfn = gfn_to_mfn_query(p2m, _gfn(gfn), &p2mt);
     else
-        mfn = gfn_to_mfn(v->domain, _gfn(gfn), &p2mt);
+        mfn = gfn_to_mfn(p2m, _gfn(gfn), &p2mt);
         
     if ( p2m_is_readonly(p2mt) )
         return _mfn(READONLY_GFN);
@@ -5199,7 +5204,7 @@ int sh_audit_l1_table(struct vcpu *v, mf
             {
                 gfn = guest_l1e_get_gfn(*gl1e);
                 mfn = shadow_l1e_get_mfn(*sl1e);
-                gmfn = gfn_to_mfn_query(v->domain, gfn, &p2mt);
+                gmfn = gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, 
&p2mt);
                 if ( !p2m_is_grant(p2mt) && mfn_x(gmfn) != mfn_x(mfn) )
                     AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn
                                " --> %" PRI_mfn " != mfn %" PRI_mfn,
@@ -5243,6 +5248,7 @@ int sh_audit_l2_table(struct vcpu *v, mf
     shadow_l2e_t *sl2e;
     mfn_t mfn, gmfn, gl2mfn;
     gfn_t gfn;
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
     p2m_type_t p2mt;
     char *s;
     int done = 0;
@@ -5269,7 +5275,7 @@ int sh_audit_l2_table(struct vcpu *v, mf
             mfn = shadow_l2e_get_mfn(*sl2e);
             gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)  
                 ? get_fl1_shadow_status(v, gfn)
-                : get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, 
&p2mt), 
+                : get_shadow_status(v, gfn_to_mfn_query(p2m, gfn, &p2mt), 
                                     SH_type_l1_shadow);
             if ( mfn_x(gmfn) != mfn_x(mfn) )
                 AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
@@ -5277,8 +5283,8 @@ int sh_audit_l2_table(struct vcpu *v, mf
                            " --> %" PRI_mfn " != mfn %" PRI_mfn,
                            gfn_x(gfn), 
                            (guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0
-                           : mfn_x(gfn_to_mfn_query(v->domain, gfn, &p2mt)),
-                           mfn_x(gmfn), mfn_x(mfn));
+                           : mfn_x(gfn_to_mfn_query(p2m,
+                                   gfn, &p2mt)), mfn_x(gmfn), mfn_x(mfn));
         }
     });
     sh_unmap_domain_page(gp);
@@ -5316,7 +5322,7 @@ int sh_audit_l3_table(struct vcpu *v, mf
         {
             gfn = guest_l3e_get_gfn(*gl3e);
             mfn = shadow_l3e_get_mfn(*sl3e);
-            gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, 
&p2mt), 
+            gmfn = get_shadow_status(v, 
gfn_to_mfn_query(p2m_get_hostp2m(v->domain), gfn, &p2mt), 
                                      ((GUEST_PAGING_LEVELS == 3 ||
                                        is_pv_32on64_vcpu(v))
                                       && !shadow_mode_external(v->domain)
@@ -5363,7 +5369,8 @@ int sh_audit_l4_table(struct vcpu *v, mf
         {
             gfn = guest_l4e_get_gfn(*gl4e);
             mfn = shadow_l4e_get_mfn(*sl4e);
-            gmfn = get_shadow_status(v, gfn_to_mfn_query(v->domain, gfn, 
&p2mt), 
+            gmfn = get_shadow_status(v, 
gfn_to_mfn_query(p2m_get_hostp2m(v->domain),
+                                     gfn, &p2mt), 
                                      SH_type_l3_shadow);
             if ( mfn_x(gmfn) != mfn_x(mfn) )
                 AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/oprofile/nmi_int.c
--- a/xen/arch/x86/oprofile/nmi_int.c   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/oprofile/nmi_int.c   Wed Aug 11 15:56:01 2010 +0100
@@ -28,6 +28,7 @@
 #include "op_x86_model.h"
  
 struct op_counter_config counter_config[OP_MAX_COUNTER];
+struct op_ibs_config ibs_config;
 
 static struct op_x86_model_spec const *__read_mostly model;
 static struct op_msrs cpu_msrs[NR_CPUS];
@@ -430,6 +431,7 @@ static int __init nmi_init(void)
                        case 0x10:
                                model = &op_athlon_spec;
                                cpu_type = "x86-64/family10";
+                               ibs_caps = ibs_init();
                                break;
                        case 0x11:
                                model = &op_athlon_spec;
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/oprofile/op_counter.h
--- a/xen/arch/x86/oprofile/op_counter.h        Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/oprofile/op_counter.h        Wed Aug 11 15:56:01 2010 +0100
@@ -26,4 +26,16 @@ struct op_counter_config {
 
 extern struct op_counter_config counter_config[];
 
+/* AMD IBS configuration */
+struct op_ibs_config {
+    unsigned long op_enabled;
+    unsigned long fetch_enabled;
+    unsigned long max_cnt_fetch;
+    unsigned long max_cnt_op;
+    unsigned long rand_en;
+    unsigned long dispatched_ops;
+};
+
+extern struct op_ibs_config ibs_config;
+
 #endif /* OP_COUNTER_H */
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/oprofile/op_model_athlon.c
--- a/xen/arch/x86/oprofile/op_model_athlon.c   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/oprofile/op_model_athlon.c   Wed Aug 11 15:56:01 2010 +0100
@@ -19,6 +19,7 @@
 #include <asm/regs.h>
 #include <asm/current.h>
 #include <asm/hvm/support.h>
+#include <xen/pci_regs.h>
  
 #include "op_x86_model.h"
 #include "op_counter.h"
@@ -47,6 +48,116 @@ static unsigned long reset_value[NUM_COU
 
 extern char svm_stgi_label[];
 
+u32 ibs_caps = 0;
+static u64 ibs_op_ctl;
+
+/* IBS cpuid feature detection */
+#define IBS_CPUID_FEATURES              0x8000001b
+
+/* IBS MSRs */
+#define MSR_AMD64_IBSFETCHCTL           0xc0011030
+#define MSR_AMD64_IBSFETCHLINAD         0xc0011031
+#define MSR_AMD64_IBSFETCHPHYSAD        0xc0011032
+#define MSR_AMD64_IBSOPCTL              0xc0011033
+#define MSR_AMD64_IBSOPRIP              0xc0011034
+#define MSR_AMD64_IBSOPDATA             0xc0011035
+#define MSR_AMD64_IBSOPDATA2            0xc0011036
+#define MSR_AMD64_IBSOPDATA3            0xc0011037
+#define MSR_AMD64_IBSDCLINAD            0xc0011038
+#define MSR_AMD64_IBSDCPHYSAD           0xc0011039
+#define MSR_AMD64_IBSCTL                0xc001103a
+
+/*
+ * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
+ * bit 0 is used to indicate the existence of IBS.
+ */
+#define IBS_CAPS_AVAIL                  (1LL<<0)
+#define IBS_CAPS_RDWROPCNT              (1LL<<3)
+#define IBS_CAPS_OPCNT                  (1LL<<4)
+
+/* IBS randomization macros */
+#define IBS_RANDOM_BITS                 12
+#define IBS_RANDOM_MASK                 ((1ULL << IBS_RANDOM_BITS) - 1)
+#define IBS_RANDOM_MAXCNT_OFFSET        (1ULL << (IBS_RANDOM_BITS - 5))
+
+/* IbsFetchCtl bits/masks */
+#define IBS_FETCH_RAND_EN               (1ULL<<57)
+#define IBS_FETCH_VAL                   (1ULL<<49)
+#define IBS_FETCH_ENABLE                (1ULL<<48)
+#define IBS_FETCH_CNT                   0xFFFF0000ULL
+#define IBS_FETCH_MAX_CNT               0x0000FFFFULL
+
+/* IbsOpCtl bits */
+#define IBS_OP_CNT_CTL                  (1ULL<<19)
+#define IBS_OP_VAL                      (1ULL<<18)
+#define IBS_OP_ENABLE                   (1ULL<<17)
+#define IBS_OP_MAX_CNT                  0x0000FFFFULL
+
+/* IBS sample identifier */
+#define IBS_FETCH_CODE                  13
+#define IBS_OP_CODE                     14
+
+#define clamp(val, min, max) ({                        \
+       typeof(val) __val = (val);              \
+       typeof(min) __min = (min);              \
+       typeof(max) __max = (max);              \
+       (void) (&__val == &__min);              \
+       (void) (&__val == &__max);              \
+       __val = __val < __min ? __min: __val;   \
+       __val > __max ? __max: __val; })
+
+/*
+ * 16-bit Linear Feedback Shift Register (LFSR)
+ */
+static unsigned int lfsr_random(void)
+{
+    static unsigned int lfsr_value = 0xF00D;
+    unsigned int bit;
+
+    /* Compute next bit to shift in */
+    bit = ((lfsr_value >> 0) ^
+           (lfsr_value >> 2) ^
+           (lfsr_value >> 3) ^
+           (lfsr_value >> 5)) & 0x0001;
+
+    /* Advance to next register value */
+    lfsr_value = (lfsr_value >> 1) | (bit << 15);
+
+    return lfsr_value;
+}
+
+/*
+ * IBS software randomization
+ *
+ * The IBS periodic op counter is randomized in software. The lower 12
+ * bits of the 20 bit counter are randomized. IbsOpCurCnt is
+ * initialized with a 12 bit random value.
+ */
+static inline u64 op_amd_randomize_ibs_op(u64 val)
+{
+    unsigned int random = lfsr_random();
+
+    if (!(ibs_caps & IBS_CAPS_RDWROPCNT))
+        /*
+         * Work around if the hw can not write to IbsOpCurCnt
+         *
+         * Randomize the lower 8 bits of the 16 bit
+         * IbsOpMaxCnt [15:0] value in the range of -128 to
+         * +127 by adding/subtracting an offset to the
+         * maximum count (IbsOpMaxCnt).
+         *
+         * To avoid over or underflows and protect upper bits
+         * starting at bit 16, the initial value for
+         * IbsOpMaxCnt must fit in the range from 0x0081 to
+         * 0xff80.
+         */
+        val += (s8)(random >> 4);
+    else
+        val |= (u64)(random & IBS_RANDOM_MASK) << 32;
+
+    return val;
+}
+
 static void athlon_fill_in_addresses(struct op_msrs * const msrs)
 {
        msrs->counters[0].addr = MSR_K7_PERFCTR0;
@@ -101,6 +212,78 @@ static void athlon_setup_ctrs(struct op_
        }
 }
 
+static inline void
+ibs_log_event(u64 data, struct cpu_user_regs * const regs, int mode)
+{
+       struct vcpu *v = current;
+       u32 temp = 0;
+
+       temp = data & 0xFFFFFFFF;
+       xenoprof_log_event(v, regs, temp, mode, 0);
+       
+       temp = (data >> 32) & 0xFFFFFFFF;
+       xenoprof_log_event(v, regs, temp, mode, 0);
+       
+}
+
+static inline int handle_ibs(int mode, struct cpu_user_regs * const regs)
+{
+       u64 val, ctl;
+       struct vcpu *v = current;
+
+       if (!ibs_caps)
+               return 1;
+
+       if (ibs_config.fetch_enabled) {
+               rdmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
+               if (ctl & IBS_FETCH_VAL) {
+                       rdmsrl(MSR_AMD64_IBSFETCHLINAD, val);
+                       xenoprof_log_event(v, regs, IBS_FETCH_CODE, mode, 0);
+                       xenoprof_log_event(v, regs, val, mode, 0);
+
+                       ibs_log_event(val, regs, mode);
+                       ibs_log_event(ctl, regs, mode);
+
+                       rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, val);
+                       ibs_log_event(val, regs, mode);
+               
+                       /* reenable the IRQ */
+                       ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT);
+                       ctl |= IBS_FETCH_ENABLE;
+                       wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
+               }
+       }
+
+       if (ibs_config.op_enabled) {
+               rdmsrl(MSR_AMD64_IBSOPCTL, ctl);
+               if (ctl & IBS_OP_VAL) {
+
+                       rdmsrl(MSR_AMD64_IBSOPRIP, val);
+                       xenoprof_log_event(v, regs, IBS_OP_CODE, mode, 0);
+                       xenoprof_log_event(v, regs, val, mode, 0);
+                       
+                       ibs_log_event(val, regs, mode);
+
+                       rdmsrl(MSR_AMD64_IBSOPDATA, val);
+                       ibs_log_event(val, regs, mode);
+                       rdmsrl(MSR_AMD64_IBSOPDATA2, val);
+                       ibs_log_event(val, regs, mode);
+                       rdmsrl(MSR_AMD64_IBSOPDATA3, val);
+                       ibs_log_event(val, regs, mode);
+                       rdmsrl(MSR_AMD64_IBSDCLINAD, val);
+                       ibs_log_event(val, regs, mode);
+                       rdmsrl(MSR_AMD64_IBSDCPHYSAD, val);
+                       ibs_log_event(val, regs, mode);
+
+                       /* reenable the IRQ */
+                       ctl = op_amd_randomize_ibs_op(ibs_op_ctl);
+                       wrmsrl(MSR_AMD64_IBSOPCTL, ctl);
+               }
+       }
+
+    return 1;
+}
+
 static int athlon_check_ctrs(unsigned int const cpu,
                             struct op_msrs const * const msrs,
                             struct cpu_user_regs * const regs)
@@ -134,10 +317,51 @@ static int athlon_check_ctrs(unsigned in
                }
        }
 
+       ovf = handle_ibs(mode, regs);
        /* See op_model_ppro.c */
        return ovf;
 }
 
+static inline void start_ibs(void)
+{
+       u64 val = 0;
+
+       if (!ibs_caps)
+               return;
+
+       if (ibs_config.fetch_enabled) {
+               val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT;
+               val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
+               val |= IBS_FETCH_ENABLE;
+               wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
+       }
+
+       if (ibs_config.op_enabled) {
+               ibs_op_ctl = ibs_config.max_cnt_op >> 4;
+               if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) {
+                       /*
+                        * IbsOpCurCnt not supported.  See
+                        * op_amd_randomize_ibs_op() for details.
+                        */
+                       ibs_op_ctl = clamp((unsigned long long)ibs_op_ctl, 
+                                                       0x0081ULL, 0xFF80ULL);
+               } else {
+                       /*
+                        * The start value is randomized with a
+                        * positive offset, we need to compensate it
+                        * with the half of the randomized range. Also
+                        * avoid underflows.
+                        */
+               ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET,
+                                       IBS_OP_MAX_CNT);
+               }
+               if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
+                       ibs_op_ctl |= IBS_OP_CNT_CTL;
+               ibs_op_ctl |= IBS_OP_ENABLE;
+               val = op_amd_randomize_ibs_op(ibs_op_ctl);
+               wrmsrl(MSR_AMD64_IBSOPCTL, val);
+       }
+}
  
 static void athlon_start(struct op_msrs const * const msrs)
 {
@@ -150,8 +374,22 @@ static void athlon_start(struct op_msrs 
                        CTRL_WRITE(msr_content, msrs, i);
                }
        }
-}
-
+       start_ibs();
+}
+
+static void stop_ibs(void)
+{
+       if (!ibs_caps)
+               return;
+
+       if (ibs_config.fetch_enabled)
+               /* clear max count and enable */
+               wrmsrl(MSR_AMD64_IBSFETCHCTL, 0);
+
+       if (ibs_config.op_enabled)
+               /* clear max count and enable */
+               wrmsrl(MSR_AMD64_IBSOPCTL, 0);
+}
 
 static void athlon_stop(struct op_msrs const * const msrs)
 {
@@ -165,8 +403,118 @@ static void athlon_stop(struct op_msrs c
                CTRL_SET_INACTIVE(msr_content);
                CTRL_WRITE(msr_content, msrs, i);
        }
-}
-
+
+       stop_ibs();
+}
+
+#define IBSCTL_LVTOFFSETVAL             (1 << 8)
+#define APIC_EILVT_MSG_NMI              0x4
+#define APIC_EILVT_LVTOFF_IBS           1
+#define APIC_EILVTn(n)                  (0x500 + 0x10 * n)
+static inline void init_ibs_nmi_per_cpu(void *arg)
+{
+       unsigned long reg;
+
+       reg = (APIC_EILVT_LVTOFF_IBS << 4) + APIC_EILVTn(0);
+       apic_write(reg, APIC_EILVT_MSG_NMI << 8);
+}
+
+#define PCI_VENDOR_ID_AMD               0x1022
+#define PCI_DEVICE_ID_AMD_10H_NB_MISC   0x1203
+#define IBSCTL                          0x1cc
+static int init_ibs_nmi(void)
+{
+       int bus, dev, func;
+       u32 id, value;
+       u16 vendor_id, dev_id;
+       int nodes;
+
+       /* per CPU setup */
+       on_each_cpu(init_ibs_nmi_per_cpu, NULL, 1);
+
+       nodes = 0;
+       for (bus = 0; bus < 256; bus++) {
+               for (dev = 0; dev < 32; dev++) {
+                       for (func = 0; func < 8; func++) {
+                               id = pci_conf_read32(bus, dev, func, 
PCI_VENDOR_ID);
+
+                               if ((id == 0xffffffff) || (id == 0x00000000) ||
+                                       (id == 0x0000ffff) || (id == 
0xffff0000))
+                                       continue;
+
+                               vendor_id = id & 0xffff;
+                               dev_id = (id >> 16) & 0xffff;
+
+                               if ((vendor_id == PCI_VENDOR_ID_AMD) &&
+                                       (dev_id == 
PCI_DEVICE_ID_AMD_10H_NB_MISC)) {
+
+                                       pci_conf_write32(bus, dev, func, IBSCTL,
+                                               IBSCTL_LVTOFFSETVAL | 
APIC_EILVT_LVTOFF_IBS);
+
+                                       value = pci_conf_read32(bus, dev, func, 
IBSCTL);
+
+                                       if (value != (IBSCTL_LVTOFFSETVAL |
+                                               APIC_EILVT_LVTOFF_IBS)) {
+                                               printk("Xenoprofile: Failed to 
setup IBS LVT offset, "
+                                                       "IBSCTL = 0x%08x", 
value);
+                                               return 1;
+                                       }
+                                       nodes++;
+                               }
+                       }
+               }
+       }
+
+       if (!nodes) {
+               printk("Xenoprofile: No CPU node configured for IBS");
+               return 1;
+       }
+
+       return 0;
+}
+
+static u32 get_ibs_caps(void)
+{
+#ifdef CONFIG_X86_32
+       return 0;
+#else
+       unsigned int max_level;
+
+       if (!boot_cpu_has(X86_FEATURE_IBS))
+               return 0;
+
+    /* check IBS cpuid feature flags */
+       max_level = cpuid_eax(0x80000000);
+       if (max_level < IBS_CPUID_FEATURES)
+               return IBS_CAPS_AVAIL;
+
+       ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
+       if (!(ibs_caps & IBS_CAPS_AVAIL))
+               /* cpuid flags not valid */
+               return IBS_CAPS_AVAIL;
+
+       return ibs_caps;
+#endif
+}
+
+u32 ibs_init(void)
+{
+       u32 ibs_caps = 0;
+
+       ibs_caps = get_ibs_caps();
+
+       if ( !ibs_caps )
+               return 0;
+
+       if (init_ibs_nmi()) {
+               ibs_caps = 0;
+               return 0;
+       }
+
+       printk("Xenoprofile: AMD IBS detected (0x%08x)\n",
+               (unsigned)ibs_caps);
+       return ibs_caps;
+}
 
 struct op_x86_model_spec const op_athlon_spec = {
        .num_counters = NUM_COUNTERS,
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/oprofile/xenoprof.c
--- a/xen/arch/x86/oprofile/xenoprof.c  Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/oprofile/xenoprof.c  Wed Aug 11 15:56:01 2010 +0100
@@ -34,6 +34,23 @@ int xenoprof_arch_counter(XEN_GUEST_HAND
     counter_config[counter.ind].kernel    = counter.kernel;
     counter_config[counter.ind].user      = counter.user;
     counter_config[counter.ind].unit_mask = counter.unit_mask;
+
+    return 0;
+}
+
+int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg)
+{
+    struct xenoprof_ibs_counter ibs_counter;
+
+    if ( copy_from_guest(&ibs_counter, arg, 1) )
+        return -EFAULT;
+
+    ibs_config.op_enabled = ibs_counter.op_enabled;
+    ibs_config.fetch_enabled = ibs_counter.fetch_enabled;
+    ibs_config.max_cnt_fetch = ibs_counter.max_cnt_fetch;
+    ibs_config.max_cnt_op = ibs_counter.max_cnt_op;
+    ibs_config.rand_en = ibs_counter.rand_en;
+    ibs_config.dispatched_ops = ibs_counter.dispatched_ops;
 
     return 0;
 }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/setup.c      Wed Aug 11 15:56:01 2010 +0100
@@ -203,6 +203,58 @@ void __devinit srat_detect_node(int cpu)
 
     if ( opt_cpu_info && acpi_numa > 0 )
         printk("CPU %d APIC %d -> Node %d\n", cpu, apicid, node);
+}
+
+/*
+ * Sort CPUs by <node,package,core,thread> tuple. Fortunately this hierarchy is
+ * reflected in the structure of modern APIC identifiers, so we sort based on
+ * those. This is slightly complicated by the fact that the BSP must remain
+ * CPU 0. Hence we do a variation on longest-prefix matching to do the best we
+ * can while keeping CPU 0 static.
+ */
+static void __init normalise_cpu_order(void)
+{
+    unsigned int i, j, min_cpu;
+    uint32_t apicid, diff, min_diff;
+
+    for_each_present_cpu ( i )
+    {
+        apicid = x86_cpu_to_apicid[i];
+        min_diff = min_cpu = ~0u;
+
+        /*
+         * Find remaining CPU with longest-prefix match on APIC ID.
+         * Among identical longest-prefix matches, pick the smallest APIC ID.
+         */
+        for ( j = next_cpu(i, cpu_present_map);
+              j < NR_CPUS;
+              j = next_cpu(j, cpu_present_map) )
+        {
+            diff = x86_cpu_to_apicid[j] ^ apicid;
+            while ( diff & (diff-1) )
+                diff &= diff-1;
+            if ( (diff < min_diff) ||
+                 ((diff == min_diff) &&
+                  (x86_cpu_to_apicid[j] < x86_cpu_to_apicid[min_cpu])) )
+            {
+                min_diff = diff;
+                min_cpu = j;
+            }
+        }
+
+        /* If no match then there must be no CPUs remaining to consider. */
+        if ( min_cpu >= NR_CPUS )
+        {
+            BUG_ON(next_cpu(i, cpu_present_map) < NR_CPUS);
+            break;
+        }
+
+        /* Switch the best-matching CPU with the next CPU in logical order. */
+        j = next_cpu(i, cpu_present_map);
+        apicid = x86_cpu_to_apicid[min_cpu];
+        x86_cpu_to_apicid[min_cpu] = x86_cpu_to_apicid[j];
+        x86_cpu_to_apicid[j] = apicid;
+    }
 }
 
 /*
@@ -952,8 +1004,6 @@ void __init __start_xen(unsigned long mb
 
     acpi_boot_init();
 
-    init_cpu_to_node();
-
     if ( smp_found_config )
         get_smp_config();
 
@@ -963,6 +1013,10 @@ void __init __start_xen(unsigned long mb
 #endif
 
     init_apic_mappings();
+
+    normalise_cpu_order();
+
+    init_cpu_to_node();
 
     if ( x2apic_is_available() )
         enable_x2apic();
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/x86_32/entry.S       Wed Aug 11 15:56:01 2010 +0100
@@ -264,7 +264,7 @@ process_mce:
         ALIGN
 /* %ebx: struct vcpu */
 process_nmi:
-        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%ebx)
+        testb $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%ebx)
         jnz  test_guest_events
         sti
         movb $0,VCPU_nmi_pending(%ebx)
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S        Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/x86_64/compat/entry.S        Wed Aug 11 15:56:01 2010 +0100
@@ -137,7 +137,7 @@ compat_process_mce:
        ALIGN
 /* %rbx: struct vcpu */
 compat_process_nmi:
-        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
+        testb $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
         jnz  compat_test_guest_events
         sti
         movb  $0,VCPU_nmi_pending(%rbx)
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/arch/x86/x86_64/entry.S       Wed Aug 11 15:56:01 2010 +0100
@@ -239,7 +239,7 @@ process_mce:
         ALIGN
 /* %rbx: struct vcpu */
 process_nmi:
-        cmpw $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
+        testb $1 << VCPU_TRAP_NMI,VCPU_async_exception_mask(%rbx)
         jnz  test_guest_events
         sti
         movb $0,VCPU_nmi_pending(%rbx)
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/domain.c
--- a/xen/common/domain.c       Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/domain.c       Wed Aug 11 15:56:01 2010 +0100
@@ -191,6 +191,8 @@ struct vcpu *alloc_vcpu(
     /* Must be called after making new vcpu visible to for_each_vcpu(). */
     vcpu_check_shutdown(v);
 
+    domain_update_node_affinity(d);
+
     return v;
 }
 
@@ -234,6 +236,8 @@ struct domain *domain_create(
     spin_lock_init(&d->hypercall_deadlock_mutex);
     INIT_PAGE_LIST_HEAD(&d->page_list);
     INIT_PAGE_LIST_HEAD(&d->xenpage_list);
+
+    spin_lock_init(&d->node_affinity_lock);
 
     spin_lock_init(&d->shutdown_lock);
     d->shutdown_code = -1;
@@ -338,6 +342,27 @@ struct domain *domain_create(
     xfree(d->pirq_to_evtchn);
     free_domain_struct(d);
     return NULL;
+}
+
+
+void domain_update_node_affinity(struct domain *d)
+{
+    cpumask_t cpumask = CPU_MASK_NONE;
+    nodemask_t nodemask = NODE_MASK_NONE;
+    struct vcpu *v;
+    unsigned int node;
+
+    spin_lock(&d->node_affinity_lock);
+
+    for_each_vcpu ( d, v )
+        cpus_or(cpumask, cpumask, v->cpu_affinity);
+
+    for_each_online_node ( node )
+        if ( cpus_intersects(node_to_cpumask(node), cpumask) )
+            node_set(node, nodemask);
+
+    d->node_affinity = nodemask;
+    spin_unlock(&d->node_affinity_lock);
 }
 
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/grant_table.c
--- a/xen/common/grant_table.c  Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/grant_table.c  Wed Aug 11 15:56:01 2010 +0100
@@ -109,7 +109,7 @@ static unsigned inline int max_nr_maptra
 #define gfn_to_mfn_private(_d, _gfn) ({                     \
     p2m_type_t __p2mt;                                      \
     unsigned long __x;                                      \
-    __x = mfn_x(gfn_to_mfn_unshare(_d, _gfn, &__p2mt, 1));  \
+    __x = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(_d), _gfn, &__p2mt, 1));  \
     if ( !p2m_is_valid(__p2mt) )                            \
         __x = INVALID_MFN;                                  \
     __x; })
@@ -1933,12 +1933,13 @@ __gnttab_copy(
     {
 #ifdef CONFIG_X86
         p2m_type_t p2mt;
-        s_frame = mfn_x(gfn_to_mfn(sd, op->source.u.gmfn, &p2mt));
+        struct p2m_domain *p2m = p2m_get_hostp2m(sd);
+        s_frame = mfn_x(gfn_to_mfn(p2m, op->source.u.gmfn, &p2mt));
         if ( !p2m_is_valid(p2mt) )
           s_frame = INVALID_MFN;
         if ( p2m_is_paging(p2mt) )
         {
-            p2m_mem_paging_populate(sd, op->source.u.gmfn);
+            p2m_mem_paging_populate(p2m, op->source.u.gmfn);
             rc = -ENOENT;
             goto error_out;
         }
@@ -1979,12 +1980,13 @@ __gnttab_copy(
     {
 #ifdef CONFIG_X86
         p2m_type_t p2mt;
-        d_frame = mfn_x(gfn_to_mfn_unshare(dd, op->dest.u.gmfn, &p2mt, 1));
+        struct p2m_domain *p2m = p2m_get_hostp2m(dd);
+        d_frame = mfn_x(gfn_to_mfn_unshare(p2m, op->dest.u.gmfn, &p2mt, 1));
         if ( !p2m_is_valid(p2mt) )
           d_frame = INVALID_MFN;
         if ( p2m_is_paging(p2mt) )
         {
-            p2m_mem_paging_populate(dd, op->dest.u.gmfn);
+            p2m_mem_paging_populate(p2m, op->dest.u.gmfn);
             rc = -ENOENT;
             goto error_out;
         }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/memory.c
--- a/xen/common/memory.c       Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/memory.c       Wed Aug 11 15:56:01 2010 +0100
@@ -161,7 +161,7 @@ int guest_remove_page(struct domain *d, 
     unsigned long mfn;
 
 #ifdef CONFIG_X86
-    mfn = mfn_x(gfn_to_mfn(d, gmfn, &p2mt)); 
+    mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(d), gmfn, &p2mt)); 
 #else
     mfn = gmfn_to_mfn(d, gmfn);
 #endif
@@ -259,7 +259,7 @@ static long memory_exchange(XEN_GUEST_HA
     unsigned long in_chunk_order, out_chunk_order;
     xen_pfn_t     gpfn, gmfn, mfn;
     unsigned long i, j, k;
-    unsigned int  node, memflags = 0;
+    unsigned int  memflags = 0;
     long          rc = 0;
     struct domain *d;
     struct page_info *page;
@@ -324,10 +324,7 @@ static long memory_exchange(XEN_GUEST_HA
         d,
         XENMEMF_get_address_bits(exch.out.mem_flags) ? :
         (BITS_PER_LONG+PAGE_SHIFT)));
-    node = XENMEMF_get_node(exch.out.mem_flags);
-    if ( node == NUMA_NO_NODE )
-        node = domain_to_node(d);
-    memflags |= MEMF_node(node);
+    memflags |= MEMF_node(XENMEMF_get_node(exch.out.mem_flags));
 
     for ( i = (exch.nr_exchanged >> in_chunk_order);
           i < (exch.in.nr_extents >> in_chunk_order);
@@ -359,7 +356,7 @@ static long memory_exchange(XEN_GUEST_HA
                 p2m_type_t p2mt;
 
                 /* Shared pages cannot be exchanged */
-                mfn = mfn_x(gfn_to_mfn_unshare(d, gmfn + k, &p2mt, 0));
+                mfn = mfn_x(gfn_to_mfn_unshare(p2m_get_hostp2m(d), gmfn + k, 
&p2mt, 0));
                 if ( p2m_is_shared(p2mt) )
                 {
                     rc = -ENOMEM;
@@ -545,7 +542,7 @@ long do_memory_op(unsigned long cmd, XEN
         }
 
         args.memflags |= MEMF_node(XENMEMF_get_node(reservation.mem_flags));
-        if (reservation.mem_flags & XENMEMF_exact_node_request)
+        if ( reservation.mem_flags & XENMEMF_exact_node_request )
             args.memflags |= MEMF_exact_node;
 
         if ( op == XENMEM_populate_physmap
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/page_alloc.c   Wed Aug 11 15:56:01 2010 +0100
@@ -295,20 +295,29 @@ static unsigned long init_node_heap(int 
 /* Allocate 2^@order contiguous pages. */
 static struct page_info *alloc_heap_pages(
     unsigned int zone_lo, unsigned int zone_hi,
-    unsigned int node, unsigned int order, unsigned int memflags)
-{
-    unsigned int i, j, zone = 0;
-    unsigned int num_nodes = num_online_nodes();
+    unsigned int order, unsigned int memflags,
+    struct domain *d)
+{
+    unsigned int first_node, i, j, zone = 0, nodemask_retry = 0;
+    unsigned int node = (uint8_t)((memflags >> _MEMF_node) - 1);
     unsigned long request = 1UL << order;
-    bool_t exact_node_request = !!(memflags & MEMF_exact_node);
     cpumask_t extra_cpus_mask, mask;
     struct page_info *pg;
+    nodemask_t nodemask = (d != NULL ) ? d->node_affinity : node_online_map;
 
     if ( node == NUMA_NO_NODE )
     {
-        node = cpu_to_node(smp_processor_id());
-        exact_node_request = 0;
-    }
+        memflags &= ~MEMF_exact_node;
+        if ( d != NULL )
+        {
+            node = next_node(d->last_alloc_node, nodemask);
+            if ( node >= MAX_NUMNODES )
+                node = first_node(nodemask);
+        }
+        if ( node >= MAX_NUMNODES )
+            node = cpu_to_node(smp_processor_id());
+    }
+    first_node = node;
 
     ASSERT(node >= 0);
     ASSERT(zone_lo <= zone_hi);
@@ -335,7 +344,7 @@ static struct page_info *alloc_heap_page
      * zone before failing, only calc new node value if we fail to find memory 
      * in target node, this avoids needless computation on fast-path.
      */
-    for ( i = 0; i < num_nodes; i++ )
+    for ( ; ; )
     {
         zone = zone_hi;
         do {
@@ -349,18 +358,35 @@ static struct page_info *alloc_heap_page
                     goto found;
         } while ( zone-- > zone_lo ); /* careful: unsigned zone may wrap */
 
-        if ( exact_node_request )
+        if ( memflags & MEMF_exact_node )
             goto not_found;
 
-        /* Pick next node, wrapping around if needed. */
-        node = next_node(node, node_online_map);
-        if (node == MAX_NUMNODES)
-            node = first_node(node_online_map);
+        /* Pick next node. */
+        if ( !node_isset(node, nodemask) )
+        {
+            /* Very first node may be caller-specified and outside nodemask. */
+            ASSERT(!nodemask_retry);
+            first_node = node = first_node(nodemask);
+            if ( node < MAX_NUMNODES )
+                continue;
+        }
+        else if ( (node = next_node(node, nodemask)) >= MAX_NUMNODES )
+            node = first_node(nodemask);
+        if ( node == first_node )
+        {
+            /* When we have tried all in nodemask, we fall back to others. */
+            if ( nodemask_retry++ )
+                goto not_found;
+            nodes_andnot(nodemask, node_online_map, nodemask);
+            first_node = node = first_node(nodemask);
+            if ( node >= MAX_NUMNODES )
+                goto not_found;
+        }
     }
 
  try_tmem:
     /* Try to free memory from tmem */
-    if ( (pg = tmem_relinquish_pages(order,memflags)) != NULL )
+    if ( (pg = tmem_relinquish_pages(order, memflags)) != NULL )
     {
         /* reassigning an already allocated anonymous heap page */
         spin_unlock(&heap_lock);
@@ -385,6 +411,9 @@ static struct page_info *alloc_heap_page
     avail[node][zone] -= request;
     total_avail_pages -= request;
     ASSERT(total_avail_pages >= 0);
+
+    if ( d != NULL )
+        d->last_alloc_node = node;
 
     spin_unlock(&heap_lock);
 
@@ -1010,7 +1039,7 @@ void *alloc_xenheap_pages(unsigned int o
     ASSERT(!in_irq());
 
     pg = alloc_heap_pages(MEMZONE_XEN, MEMZONE_XEN,
-        cpu_to_node(smp_processor_id()), order, memflags);
+                          order, memflags, NULL);
     if ( unlikely(pg == NULL) )
         return NULL;
 
@@ -1153,24 +1182,21 @@ struct page_info *alloc_domheap_pages(
 {
     struct page_info *pg = NULL;
     unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1;
-    unsigned int node = (uint8_t)((memflags >> _MEMF_node) - 1), dma_zone;
+    unsigned int dma_zone;
 
     ASSERT(!in_irq());
-
-    if ( (node == NUMA_NO_NODE) && (d != NULL) )
-        node = domain_to_node(d);
 
     bits = domain_clamp_alloc_bitsize(d, bits ? : (BITS_PER_LONG+PAGE_SHIFT));
     if ( (zone_hi = min_t(unsigned int, bits_to_zone(bits), zone_hi)) == 0 )
         return NULL;
 
     if ( dma_bitsize && ((dma_zone = bits_to_zone(dma_bitsize)) < zone_hi) )
-        pg = alloc_heap_pages(dma_zone + 1, zone_hi, node, order, memflags);
+        pg = alloc_heap_pages(dma_zone + 1, zone_hi, order, memflags, d);
 
     if ( (pg == NULL) &&
          ((memflags & MEMF_no_dma) ||
-          ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi,
-                                  node, order, memflags)) == NULL)) )
+          ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi, order,
+                                  memflags, d)) == NULL)) )
          return NULL;
 
     if ( (d != NULL) && assign_pages(d, pg, order, memflags) )
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/sched_credit.c Wed Aug 11 15:56:01 2010 +0100
@@ -64,7 +64,8 @@
 /*
  * Flags
  */
-#define CSCHED_FLAG_VCPU_PARKED 0x0001  /* VCPU over capped credits */
+#define CSCHED_FLAG_VCPU_PARKED    0x0001  /* VCPU over capped credits */
+#define CSCHED_FLAG_VCPU_YIELD     0x0002  /* VCPU yielding */
 
 
 /*
@@ -106,6 +107,12 @@
 
 #endif /* CSCHED_STATS */
 
+
+/*
+ * Boot parameters
+ */
+int sched_credit_default_yield = 0;
+boolean_param("sched_credit_default_yield", sched_credit_default_yield);
 
 /*
  * Physical CPU
@@ -202,6 +209,18 @@ __runq_insert(unsigned int cpu, struct c
             break;
     }
 
+    /* If the vcpu yielded, try to put it behind one lower-priority
+     * runnable vcpu if we can.  The next runq_sort will bring it forward
+     * within 30ms if the queue too long. */
+    if ( svc->flags & CSCHED_FLAG_VCPU_YIELD
+         && __runq_elem(iter)->pri > CSCHED_PRI_IDLE )
+    {
+        iter=iter->next;
+
+        /* Some sanity checks */
+        BUG_ON(iter == runq);
+    }
+
     list_add_tail(&svc->runq_elem, iter);
 }
 
@@ -748,6 +767,18 @@ csched_vcpu_wake(const struct scheduler 
     __runq_tickle(cpu, svc);
 }
 
+static void
+csched_vcpu_yield(const struct scheduler *ops, struct vcpu *vc)
+{
+    struct csched_vcpu * const sv = CSCHED_VCPU(vc);
+
+    if ( !sched_credit_default_yield )
+    {
+        /* Let the scheduler know that this vcpu is trying to yield */
+        sv->flags |= CSCHED_FLAG_VCPU_YIELD;
+    }
+}
+
 static int
 csched_dom_cntl(
     const struct scheduler *ops,
@@ -1069,7 +1100,9 @@ csched_acct(void* dummy)
                 if ( credit > CSCHED_CREDITS_PER_TSLICE )
                 {
                     __csched_vcpu_acct_stop_locked(prv, svc);
-                    credit = 0;
+                    /* Divide credits in half, so that when it starts
+                     * accounting again, it starts a little bit "ahead" */
+                    credit /= 2;
                     atomic_set(&svc->credit, credit);
                 }
             }
@@ -1280,6 +1313,12 @@ csched_schedule(
         snext = CSCHED_VCPU(idle_vcpu[cpu]);
         snext->pri = CSCHED_PRI_TS_BOOST;
     }
+
+    /*
+     * Clear YIELD flag before scheduling out
+     */
+    if ( scurr->flags & CSCHED_FLAG_VCPU_YIELD )
+        scurr->flags &= ~(CSCHED_FLAG_VCPU_YIELD);
 
     /*
      * SMP Load balance:
@@ -1509,6 +1548,7 @@ const struct scheduler sched_credit_def 
 
     .sleep          = csched_vcpu_sleep,
     .wake           = csched_vcpu_wake,
+    .yield          = csched_vcpu_yield,
 
     .adjust         = csched_dom_cntl,
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/schedule.c
--- a/xen/common/schedule.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/schedule.c     Wed Aug 11 15:56:01 2010 +0100
@@ -276,6 +276,7 @@ int sched_move_domain(struct domain *d, 
 
         new_p = cycle_cpu(new_p, c->cpu_valid);
     }
+    domain_update_node_affinity(d);
 
     d->cpupool = c;
     SCHED_OP(DOM2OP(d), free_domdata, d->sched_priv);
@@ -457,6 +458,7 @@ int cpu_disable_scheduler(unsigned int c
     struct vcpu *v;
     struct cpupool *c;
     int    ret = 0;
+    bool_t affinity_broken;
 
     c = per_cpu(cpupool, cpu);
     if ( c == NULL )
@@ -466,6 +468,8 @@ int cpu_disable_scheduler(unsigned int c
     {
         if ( d->cpupool != c )
             continue;
+
+        affinity_broken = 0;
 
         for_each_vcpu ( d, v )
         {
@@ -477,6 +481,7 @@ int cpu_disable_scheduler(unsigned int c
                 printk("Breaking vcpu affinity for domain %d vcpu %d\n",
                         v->domain->domain_id, v->vcpu_id);
                 cpus_setall(v->cpu_affinity);
+                affinity_broken = 1;
             }
 
             if ( v->processor == cpu )
@@ -499,7 +504,11 @@ int cpu_disable_scheduler(unsigned int c
             if ( v->processor == cpu )
                 ret = -EAGAIN;
         }
-    }
+
+        if ( affinity_broken )
+            domain_update_node_affinity(d);
+    }
+
     return ret;
 }
 
@@ -524,6 +533,8 @@ int vcpu_set_affinity(struct vcpu *v, cp
         set_bit(_VPF_migrating, &v->pause_flags);
 
     vcpu_schedule_unlock_irq(v);
+
+    domain_update_node_affinity(v->domain);
 
     if ( test_bit(_VPF_migrating, &v->pause_flags) )
     {
@@ -631,6 +642,12 @@ static long do_poll(struct sched_poll *s
 /* Voluntarily yield the processor for this allocation. */
 static long do_yield(void)
 {
+    struct vcpu * v=current;
+
+    vcpu_schedule_lock_irq(v);
+    SCHED_OP(VCPU2OP(v), yield, v);
+    vcpu_schedule_unlock_irq(v);
+
     TRACE_2D(TRC_SCHED_YIELD, current->domain->domain_id, current->vcpu_id);
     raise_softirq(SCHEDULE_SOFTIRQ);
     return 0;
@@ -1296,7 +1313,7 @@ void schedule_cpu_switch(unsigned int cp
 
     spin_unlock_irqrestore(per_cpu(schedule_data, cpu).schedule_lock, flags);
 
-    SCHED_OP(old_ops, free_vdata, vpriv);
+    SCHED_OP(old_ops, free_vdata, vpriv_old);
     SCHED_OP(old_ops, free_pdata, ppriv_old, cpu);
 }
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/tmem_xen.c
--- a/xen/common/tmem_xen.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/tmem_xen.c     Wed Aug 11 15:56:01 2010 +0100
@@ -100,7 +100,7 @@ static inline void *cli_mfn_to_va(tmem_c
     unsigned long cli_mfn;
     p2m_type_t t;
 
-    cli_mfn = mfn_x(gfn_to_mfn(current->domain, cmfn, &t));
+    cli_mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(current->domain), cmfn, &t));
     if (t != p2m_ram_rw || cli_mfn == INVALID_MFN)
         return NULL;
     if (pcli_mfn != NULL)
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/common/xenoprof.c
--- a/xen/common/xenoprof.c     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/common/xenoprof.c     Wed Aug 11 15:56:01 2010 +0100
@@ -881,6 +881,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
             ret = -EFAULT;
         break;
 
+    case XENOPROF_ibs_counter:
+        if ( (xenoprof_state != XENOPROF_COUNTERS_RESERVED) ||
+             (adomains == 0) )
+        {
+            ret = -EPERM;
+            break;
+        }
+        ret = xenoprof_arch_ibs_counter(arg);
+        break;
+
+    case XENOPROF_get_ibs_caps:
+        ret = ibs_caps;
+        break;
+
     default:
         ret = -ENOSYS;
     }
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c    Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c    Wed Aug 11 15:56:01 2010 +0100
@@ -440,14 +440,21 @@ void io_apic_write_remap_rte(
     {
         *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
         *(IO_APIC_BASE(apic)+4) = value;
+
+        /* Recover the original value of 'mask' bit */
+        if ( rte_upper )
+        {
+            *IO_APIC_BASE(apic) = reg;
+            *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0);
+        }
         return;
     }
 
     /* write new entry to ioapic */
+    *IO_APIC_BASE(apic) = reg + 1;
+    *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1);
     *IO_APIC_BASE(apic) = reg;
     *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0);
-    *IO_APIC_BASE(apic) = reg + 1;
-    *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1);
 }
 
 #if defined(__i386__) || defined(__x86_64__)
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/asm-ia64/xenoprof.h
--- a/xen/include/asm-ia64/xenoprof.h   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/asm-ia64/xenoprof.h   Wed Aug 11 15:56:01 2010 +0100
@@ -33,6 +33,13 @@ void xenoprof_arch_stop(void);
 void xenoprof_arch_stop(void);
 void xenoprof_arch_disable_virq(void);
 void xenoprof_arch_release_counters(void);
+
+static inline int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg)
+{
+    return -ENOSYS;  /* not supported */
+}
+/* AMD IBS not supported */
+#define ibs_caps       0
 
 struct vcpu;
 struct cpu_user_regs;
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/asm-x86/guest_pt.h
--- a/xen/include/asm-x86/guest_pt.h    Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/asm-x86/guest_pt.h    Wed Aug 11 15:56:01 2010 +0100
@@ -272,8 +272,8 @@ guest_walk_to_gpa(walk_t *gw)
 #define guest_walk_tables GPT_RENAME(guest_walk_tables, GUEST_PAGING_LEVELS)
 
 extern uint32_t 
-guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, 
-                  uint32_t pfec, mfn_t top_mfn, void *top_map);
+guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va,
+                  walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map);
 
 /* Pretty-print the contents of a guest-walk */
 static inline void print_gw(walk_t *gw)
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/asm-x86/mem_sharing.h
--- a/xen/include/asm-x86/mem_sharing.h Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/asm-x86/mem_sharing.h Wed Aug 11 15:56:01 2010 +0100
@@ -30,17 +30,17 @@ typedef uint64_t shr_handle_t;
 typedef uint64_t shr_handle_t; 
 
 unsigned int mem_sharing_get_nr_saved_mfns(void);
-int mem_sharing_nominate_page(struct domain *d, 
+int mem_sharing_nominate_page(struct p2m_domain *p2m, 
                               unsigned long gfn,
                               int expected_refcnt,
                               shr_handle_t *phandle);
 #define MEM_SHARING_MUST_SUCCEED      (1<<0)
 #define MEM_SHARING_DESTROY_GFN       (1<<1)
-int mem_sharing_unshare_page(struct domain *d, 
+int mem_sharing_unshare_page(struct p2m_domain *p2m, 
                              unsigned long gfn, 
                              uint16_t flags);
 int mem_sharing_sharing_resume(struct domain *d);
-int mem_sharing_cache_resize(struct domain *d, int new_size);
+int mem_sharing_cache_resize(struct p2m_domain *p2m, int new_size);
 int mem_sharing_domctl(struct domain *d, 
                        xen_domctl_mem_sharing_op_t *mec);
 void mem_sharing_init(void);
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/asm-x86/p2m.h Wed Aug 11 15:56:01 2010 +0100
@@ -172,23 +172,28 @@ struct p2m_domain {
     /* Shadow translated domain: p2m mapping */
     pagetable_t        phys_table;
 
+    struct domain     *domain;   /* back pointer to domain */
+
     /* Pages used to construct the p2m */
     struct page_list_head pages;
 
     /* Functions to call to get or free pages for the p2m */
-    struct page_info * (*alloc_page  )(struct domain *d);
-    void               (*free_page   )(struct domain *d,
+    struct page_info * (*alloc_page  )(struct p2m_domain *p2m);
+    void               (*free_page   )(struct p2m_domain *p2m,
                                        struct page_info *pg);
-    int                (*set_entry   )(struct domain *d, unsigned long gfn,
+    int                (*set_entry   )(struct p2m_domain *p2m,
+                                       unsigned long gfn,
                                        mfn_t mfn, unsigned int page_order,
                                        p2m_type_t p2mt);
-    mfn_t              (*get_entry   )(struct domain *d, unsigned long gfn,
+    mfn_t              (*get_entry   )(struct p2m_domain *p2m,
+                                       unsigned long gfn,
                                        p2m_type_t *p2mt,
                                        p2m_query_t q);
-    mfn_t              (*get_entry_current)(unsigned long gfn,
+    mfn_t              (*get_entry_current)(struct p2m_domain *p2m,
+                                            unsigned long gfn,
                                             p2m_type_t *p2mt,
                                             p2m_query_t q);
-    void               (*change_entry_type_global)(struct domain *d,
+    void               (*change_entry_type_global)(struct p2m_domain *p2m,
                                                    p2m_type_t ot,
                                                    p2m_type_t nt);
 
@@ -279,65 +284,64 @@ static inline p2m_type_t p2m_flags_to_ty
 }
 
 /* Read the current domain's p2m table.  Do not populate PoD pages. */
-static inline mfn_t gfn_to_mfn_type_current(unsigned long gfn, p2m_type_t *t,
+static inline mfn_t gfn_to_mfn_type_current(struct p2m_domain *p2m,
+                                            unsigned long gfn, p2m_type_t *t,
                                             p2m_query_t q)
 {
-    return current->domain->arch.p2m->get_entry_current(gfn, t, q);
-}
-
-/* Read another domain's P2M table, mapping pages as we go.
+    return p2m->get_entry_current(p2m, gfn, t, q);
+}
+
+/* Read P2M table, mapping pages as we go.
  * Do not populate PoD pages. */
-static inline
-mfn_t gfn_to_mfn_type_foreign(struct domain *d, unsigned long gfn, p2m_type_t 
*t,
-                              p2m_query_t q)
-{
-    return d->arch.p2m->get_entry(d, gfn, t, q);
-}
+static inline mfn_t
+gfn_to_mfn_type_p2m(struct p2m_domain *p2m, unsigned long gfn,
+                              p2m_type_t *t, p2m_query_t q)
+{
+    return p2m->get_entry(p2m, gfn, t, q);
+}
+
 
 /* General conversion function from gfn to mfn */
-static inline mfn_t _gfn_to_mfn_type(struct domain *d,
+static inline mfn_t _gfn_to_mfn_type(struct p2m_domain *p2m,
                                      unsigned long gfn, p2m_type_t *t,
                                      p2m_query_t q)
 {
-    if ( !paging_mode_translate(d) )
+    if ( !p2m || !paging_mode_translate(p2m->domain) )
     {
         /* Not necessarily true, but for non-translated guests, we claim
          * it's the most generic kind of memory */
         *t = p2m_ram_rw;
         return _mfn(gfn);
     }
-    if ( likely(current->domain == d) )
-        return gfn_to_mfn_type_current(gfn, t, q);
+    if ( likely(current->domain == p2m->domain) )
+        return gfn_to_mfn_type_current(p2m, gfn, t, q);
     else
-        return gfn_to_mfn_type_foreign(d, gfn, t, q);
-}
-
-#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_alloc)
-#define gfn_to_mfn_query(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_query)
-#define gfn_to_mfn_guest(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_guest)
-
-#define gfn_to_mfn_current(g, t) gfn_to_mfn_type_current((g), (t), p2m_alloc)
-#define gfn_to_mfn_foreign(d, g, t) gfn_to_mfn_type_foreign((d), (g), (t), 
p2m_alloc)
-
-static inline mfn_t gfn_to_mfn_unshare(struct domain *d,
+        return gfn_to_mfn_type_p2m(p2m, gfn, t, q);
+}
+
+#define gfn_to_mfn(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), p2m_alloc)
+#define gfn_to_mfn_query(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), 
p2m_query)
+#define gfn_to_mfn_guest(p2m, g, t) _gfn_to_mfn_type((p2m), (g), (t), 
p2m_guest)
+
+static inline mfn_t gfn_to_mfn_unshare(struct p2m_domain *p2m,
                                        unsigned long gfn,
                                        p2m_type_t *p2mt,
                                        int must_succeed)
 {
     mfn_t mfn;
 
-    mfn = gfn_to_mfn(d, gfn, p2mt);
+    mfn = gfn_to_mfn(p2m, gfn, p2mt);
 #ifdef __x86_64__
     if ( p2m_is_shared(*p2mt) )
     {
-        if ( mem_sharing_unshare_page(d, gfn,
+        if ( mem_sharing_unshare_page(p2m, gfn,
                                       must_succeed 
                                       ? MEM_SHARING_MUST_SUCCEED : 0) )
         {
             BUG_ON(must_succeed);
             return mfn;
         }
-        mfn = gfn_to_mfn(d, gfn, p2mt);
+        mfn = gfn_to_mfn(p2m, gfn, p2mt);
     }
 #endif
 
@@ -350,7 +354,7 @@ static inline unsigned long gmfn_to_mfn(
 {
     mfn_t mfn;
     p2m_type_t t;
-    mfn = gfn_to_mfn(d, gpfn, &t);
+    mfn = gfn_to_mfn(d->arch.p2m, gpfn, &t);
     if ( p2m_is_valid(t) )
         return mfn_x(mfn);
     return INVALID_MFN;
@@ -374,16 +378,16 @@ int p2m_init(struct domain *d);
  * build the p2m, and to release it again at the end of day. 
  *
  * Returns 0 for success or -errno. */
-int p2m_alloc_table(struct domain *d,
-                    struct page_info * (*alloc_page)(struct domain *d),
-                    void (*free_page)(struct domain *d, struct page_info *pg));
+int p2m_alloc_table(struct p2m_domain *p2m,
+               struct page_info * (*alloc_page)(struct p2m_domain *p2m),
+               void (*free_page)(struct p2m_domain *p2m, struct page_info 
*pg));
 
 /* Return all the p2m resources to Xen. */
-void p2m_teardown(struct domain *d);
+void p2m_teardown(struct p2m_domain *p2m);
 void p2m_final_teardown(struct domain *d);
 
 /* Dump PoD information about the domain */
-void p2m_pod_dump_data(struct domain *d);
+void p2m_pod_dump_data(struct p2m_domain *p2m);
 
 /* Move all pages from the populate-on-demand cache to the domain page_list
  * (usually in preparation for domain destruction) */
@@ -402,14 +406,18 @@ p2m_pod_decrease_reservation(struct doma
 
 /* Called by p2m code when demand-populating a PoD page */
 int
-p2m_pod_demand_populate(struct domain *d, unsigned long gfn,
+p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
                         unsigned int order,
                         p2m_query_t q);
 
 /* Add a page to a domain's p2m table */
-int guest_physmap_add_entry(struct domain *d, unsigned long gfn,
+int guest_physmap_add_entry(struct p2m_domain *p2m, unsigned long gfn,
                             unsigned long mfn, unsigned int page_order, 
                             p2m_type_t t);
+
+/* Remove a page from a domain's p2m table */
+void guest_physmap_remove_entry(struct p2m_domain *p2m, unsigned long gfn,
+                            unsigned long mfn, unsigned int page_order);
 
 /* Set a p2m range as populate-on-demand */
 int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
@@ -419,49 +427,55 @@ int guest_physmap_mark_populate_on_deman
  *
  * Return 0 for success
  */
-static inline int guest_physmap_add_page(struct domain *d, unsigned long gfn,
+static inline int guest_physmap_add_page(struct domain *d,
+                                         unsigned long gfn,
                                          unsigned long mfn,
                                          unsigned int page_order)
 {
-    return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw);
+    return guest_physmap_add_entry(d->arch.p2m, gfn, mfn, page_order, 
p2m_ram_rw);
 }
 
 /* Remove a page from a domain's p2m table */
-void guest_physmap_remove_page(struct domain *d, unsigned long gfn,
-                               unsigned long mfn, unsigned int page_order);
+static inline void guest_physmap_remove_page(struct domain *d,
+                               unsigned long gfn,
+                               unsigned long mfn, unsigned int page_order)
+{
+    guest_physmap_remove_entry(d->arch.p2m, gfn, mfn, page_order);
+}
 
 /* Change types across all p2m entries in a domain */
-void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt);
-void p2m_change_entry_type_global(struct domain *d, p2m_type_t ot, p2m_type_t 
nt);
+void p2m_change_type_global(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t 
nt);
+void p2m_change_entry_type_global(struct p2m_domain *p2m, p2m_type_t ot, 
p2m_type_t nt);
 
 /* Compare-exchange the type of a single p2m entry */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
+p2m_type_t p2m_change_type(struct p2m_domain *p2m, unsigned long gfn,
                            p2m_type_t ot, p2m_type_t nt);
 
 /* Set mmio addresses in the p2m table (for pass-through) */
-int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
-int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn);
+int set_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
+int clear_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn);
 
 
 #ifdef __x86_64__
 /* Modify p2m table for shared gfn */
-int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+int set_shared_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
+
 /* Check if a nominated gfn is valid to be paged out */
-int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn);
+int p2m_mem_paging_nominate(struct p2m_domain *p2m, unsigned long gfn);
 /* Evict a frame */
-int p2m_mem_paging_evict(struct domain *d, unsigned long gfn);
+int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn);
 /* Start populating a paged out frame */
-void p2m_mem_paging_populate(struct domain *d, unsigned long gfn);
+void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn);
 /* Prepare the p2m for paging a frame in */
-int p2m_mem_paging_prep(struct domain *d, unsigned long gfn);
+int p2m_mem_paging_prep(struct p2m_domain *p2m, unsigned long gfn);
 /* Resume normal operation (in case a domain was paused) */
-void p2m_mem_paging_resume(struct domain *d);
+void p2m_mem_paging_resume(struct p2m_domain *p2m);
 #else
-static inline void p2m_mem_paging_populate(struct domain *d, unsigned long gfn)
+static inline void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned 
long gfn)
 { }
 #endif
 
-struct page_info *p2m_alloc_ptp(struct domain *d, unsigned long type);
+struct page_info *p2m_alloc_ptp(struct p2m_domain *p2m, unsigned long type);
 
 #endif /* _XEN_P2M_H */
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/asm-x86/xenoprof.h
--- a/xen/include/asm-x86/xenoprof.h    Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/asm-x86/xenoprof.h    Wed Aug 11 15:56:01 2010 +0100
@@ -42,9 +42,14 @@ int xenoprof_arch_init(int *num_events, 
 
 int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg);
 int compat_oprof_arch_counter(XEN_GUEST_HANDLE(void) arg);
+int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg);
 
 struct vcpu;
 struct cpu_user_regs;
+
+/* AMD IBS support */
+u32 ibs_init(void);
+extern u32 ibs_caps;
 
 int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/public/xenoprof.h
--- a/xen/include/public/xenoprof.h     Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/public/xenoprof.h     Wed Aug 11 15:56:01 2010 +0100
@@ -50,7 +50,11 @@
 #define XENOPROF_shutdown           13
 #define XENOPROF_get_buffer         14
 #define XENOPROF_set_backtrace      15
-#define XENOPROF_last_op            15
+
+/* AMD IBS support */
+#define XENOPROF_get_ibs_caps       16
+#define XENOPROF_ibs_counter        17
+#define XENOPROF_last_op            17
 
 #define MAX_OPROF_EVENTS    32
 #define MAX_OPROF_DOMAINS   25
@@ -124,6 +128,16 @@ typedef struct xenoprof_passive {
 } xenoprof_passive_t;
 DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
 
+struct xenoprof_ibs_counter {
+    uint64_t op_enabled;
+    uint64_t fetch_enabled;
+    uint64_t max_cnt_fetch;
+    uint64_t max_cnt_op;
+    uint64_t rand_en;
+    uint64_t dispatched_ops;
+};
+typedef struct xenoprof_ibs_counter xenoprof_ibs_counter_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_ibs_counter_t);
 
 #endif /* __XEN_PUBLIC_XENOPROF_H__ */
 
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h        Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/xen/sched-if.h        Wed Aug 11 15:56:01 2010 +0100
@@ -107,6 +107,7 @@ struct scheduler {
 
     void         (*sleep)          (const struct scheduler *, struct vcpu *);
     void         (*wake)           (const struct scheduler *, struct vcpu *);
+    void         (*yield)          (const struct scheduler *, struct vcpu *);
     void         (*context_saved)  (const struct scheduler *, struct vcpu *);
 
     struct task_slice (*do_schedule) (const struct scheduler *, s_time_t,
diff -r ca51dba3a7b1 -r 3b839375d5bc xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Aug 11 15:51:04 2010 +0100
+++ b/xen/include/xen/sched.h   Wed Aug 11 15:56:01 2010 +0100
@@ -23,6 +23,8 @@
 #include <xen/mm.h>
 #include <xen/tasklet.h>
 #include <public/mem_event.h>
+#include <xen/cpumask.h>
+#include <xen/nodemask.h>
 
 #ifdef CONFIG_COMPAT
 #include <compat/vcpu.h>
@@ -326,6 +328,11 @@ struct domain
 
     /* Memory paging support */
     struct mem_event_domain mem_event;
+
+    /* Currently computed from union of all vcpu cpu-affinity masks. */
+    nodemask_t node_affinity;
+    unsigned int last_alloc_node;
+    spinlock_t node_affinity_lock;
 };
 
 struct domain_setup_info
@@ -393,6 +400,8 @@ static inline void get_knownalive_domain
     ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
 }
 
+void domain_update_node_affinity(struct domain *d);
+
 struct domain *domain_create(
     domid_t domid, unsigned int domcr_flags, ssidref_t ssidref);
  /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */

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

<Prev in Thread] Current Thread [Next in Thread>