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] Make xc_translate_foreign_address aware o

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Make xc_translate_foreign_address aware of compat-mode guests and
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 08 Jan 2009 06:57:29 -0800
Delivery-date: Thu, 08 Jan 2009 07:00:55 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1231153705 0
# Node ID 34f52eafd4e32b297a24f58cef60770e00c5bb15
# Parent  5ce75a8eec7fa4274f210bd1dfad91493199972a
Make xc_translate_foreign_address aware of compat-mode guests and
(32-bit) HVM guests.  64-bit HVM guests are still not supported for
now, pending a sensible way of getting at the guest's EFER.LMA.

Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
 tools/libxc/xc_pagetab.c |  235 +++++++++++++++--------------------------------
 tools/libxc/xenctrl.h    |    4 
 2 files changed, 77 insertions(+), 162 deletions(-)

diff -r 5ce75a8eec7f -r 34f52eafd4e3 tools/libxc/xc_pagetab.c
--- a/tools/libxc/xc_pagetab.c  Mon Jan 05 10:47:51 2009 +0000
+++ b/tools/libxc/xc_pagetab.c  Mon Jan 05 11:08:25 2009 +0000
@@ -4,181 +4,96 @@
  * Function to translate virtual to physical addresses.
  */
 #include "xc_private.h"
+#include <strings.h>
 
-#if defined(__i386__)
-
-#define L1_PAGETABLE_SHIFT_PAE 12
-#define L2_PAGETABLE_SHIFT_PAE 21
-#define L3_PAGETABLE_SHIFT_PAE 30
-
-#define L1_PAGETABLE_SHIFT             12
-#define L2_PAGETABLE_SHIFT             22
-
-#define L0_PAGETABLE_MASK_PAE  0x00000ffffffff000ULL
-#define L1_PAGETABLE_MASK_PAE  0x1ffULL
-#define L2_PAGETABLE_MASK_PAE  0x1ffULL
-#define L3_PAGETABLE_MASK_PAE  0x3ULL
-
-#define L0_PAGETABLE_MASK              0xfffff000ULL
-#define L1_PAGETABLE_MASK              0x3ffULL
-#define L2_PAGETABLE_MASK              0x3ffULL
-
-#elif defined(__x86_64__)
-
-#define L1_PAGETABLE_SHIFT_PAE 12
-#define L2_PAGETABLE_SHIFT_PAE 21
-#define L3_PAGETABLE_SHIFT_PAE 30
-#define L4_PAGETABLE_SHIFT_PAE 39
-
-#define L1_PAGETABLE_SHIFT             L1_PAGETABLE_SHIFT_PAE
-#define L2_PAGETABLE_SHIFT             L2_PAGETABLE_SHIFT_PAE
-
-#define L0_PAGETABLE_MASK_PAE  0x000ffffffffff000ULL
-#define L1_PAGETABLE_MASK_PAE  0x1ffULL
-#define L2_PAGETABLE_MASK_PAE  0x1ffULL
-#define L3_PAGETABLE_MASK_PAE  0x1ffULL
-#define L4_PAGETABLE_MASK_PAE  0x1ffULL
-
-#define L0_PAGETABLE_MASK              L0_PAGETABLE_MASK_PAE
-#define L1_PAGETABLE_MASK              L1_PAGETABLE_MASK_PAE
-#define L2_PAGETABLE_MASK              L2_PAGETABLE_MASK_PAE
-
-#endif
+#define CR0_PG  0x80000000
+#define CR4_PAE 0x20
+#define PTE_PSE 0x80
 
 unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
-                                           int vcpu, unsigned long long virt )
+                                           int vcpu, unsigned long long virt)
 {
+    xc_dominfo_t dominfo;
     vcpu_guest_context_any_t ctx;
-    unsigned long long cr3;
-    void *pd, *pt, *pdppage = NULL, *pdp, *pml = NULL;
-    unsigned long long pde, pte, pdpe, pmle;
-    unsigned long mfn = 0;
-#if defined (__i386__)
-    static int pt_levels = 0;
+    uint64_t paddr, mask, pte = 0;
+    int size, level, pt_levels = 2;
+    void *map;
 
-    if (pt_levels == 0) {
+    if (xc_domain_getinfo(xc_handle, dom, 1, &dominfo) != 1 
+        || dominfo.domid != dom
+        || xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0)
+        return 0;
+
+    /* What kind of paging are we dealing with? */
+    if (dominfo.hvm) {
+        unsigned long cr0, cr3, cr4;
         xen_capabilities_info_t xen_caps = "";
-
         if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
-            goto out;
-        if (strstr(xen_caps, "xen-3.0-x86_64"))
+            return 0;
+        /* HVM context records are always host-sized */
+        if (strstr(xen_caps, "xen-3.0-x86_64")) {
+            cr0 = ctx.x64.ctrlreg[0];
+            cr3 = ctx.x64.ctrlreg[3];
+            cr4 = ctx.x64.ctrlreg[4];
+        } else {
+            cr0 = ctx.x32.ctrlreg[0];
+            cr3 = ctx.x32.ctrlreg[3];
+            cr4 = ctx.x32.ctrlreg[4];
+        }
+        if (!(cr0 & CR0_PG))
+            return virt;
+        if (0 /* XXX how to get EFER.LMA? */) 
             pt_levels = 4;
-        else if (strstr(xen_caps, "xen-3.0-x86_32p"))
+        else
+            pt_levels = (cr4 & CR4_PAE) ? 3 : 2;
+        paddr = cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull);
+    } else {
+        DECLARE_DOMCTL;
+        domctl.domain = dom;
+        domctl.cmd = XEN_DOMCTL_get_address_size;
+        if ( do_domctl(xc_handle, &domctl) != 0 )
+            return 0;
+        if (domctl.u.address_size.size == 64) {
+            pt_levels = 4;
+            paddr = ctx.x64.ctrlreg[3] & ~0xfffull;
+        } else {
             pt_levels = 3;
-        else if (strstr(xen_caps, "xen-3.0-x86_32"))
-            pt_levels = 2;
-        else
-            goto out;
-    }
-#elif defined (__x86_64__)
-#define pt_levels 4
-#endif
-
-    if (xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0) {
-        DPRINTF("failed to retreive vcpu context\n");
-        goto out;
-    }
-    cr3 = ((unsigned long long)xen_cr3_to_pfn(ctx.c.ctrlreg[3])) << PAGE_SHIFT;
-
-    /* Page Map Level 4 */
-
-#if defined(__i386__)
-    pmle = cr3;
-#elif defined(__x86_64__)
-    pml = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, cr3 >> 
PAGE_SHIFT);
-    if (pml == NULL) {
-        DPRINTF("failed to map PML4\n");
-        goto out;
-    }
-    pmle = *(unsigned long long *)(pml + 8 * ((virt >> L4_PAGETABLE_SHIFT_PAE) 
& L4_PAGETABLE_MASK_PAE));
-    if((pmle & 1) == 0) {
-        DPRINTF("page entry not present in PML4\n");
-        goto out_unmap_pml;
-    }
-#endif
-
-    /* Page Directory Pointer Table */
-
-    if (pt_levels >= 3) {
-        pdppage = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, 
pmle >> PAGE_SHIFT);
-        if (pdppage == NULL) {
-            DPRINTF("failed to map PDP\n");
-            goto out_unmap_pml;
+            paddr = (((uint64_t) xen_cr3_to_pfn(ctx.x32.ctrlreg[3])) 
+                     << PAGE_SHIFT);
         }
-        if (pt_levels >= 4)
-            pdp = pdppage;
-        else
-            /* PDP is only 32 bit aligned with 3 level pts */
-            pdp = pdppage + (pmle & ~(XC_PAGE_MASK | 0x1f));
-
-        pdpe = *(unsigned long long *)(pdp + 8 * ((virt >> 
L3_PAGETABLE_SHIFT_PAE) & L3_PAGETABLE_MASK_PAE));
-
-        if((pdpe & 1) == 0) {
-            DPRINTF("page entry not present in PDP\n");
-            goto out_unmap_pdp;
-        }
-    } else {
-        pdpe = pmle;
     }
 
-    /* Page Directory */
+    if (pt_levels == 4) {
+        virt &= 0x0000ffffffffffffull;
+        mask =  0x0000ff8000000000ull;
+    } else if (pt_levels == 3) {
+        virt &= 0x00000000ffffffffull;
+        mask =  0x0000007fc0000000ull;
+    } else {
+        virt &= 0x00000000ffffffffull;
+        mask =  0x00000000ffc00000ull;
+    }
+    size = (pt_levels == 2 ? 4 : 8);
 
-    pd = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, pdpe >> 
PAGE_SHIFT);
-    if (pd == NULL) {
-        DPRINTF("failed to map PD\n");
-        goto out_unmap_pdp;
+    /* Walk the pagetables */
+    for (level = pt_levels; level > 0; level--) {
+        paddr += ((virt & mask) >> (ffsll(mask) - 1)) * size;
+        map = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, 
+                                   paddr >>PAGE_SHIFT);
+        if (!map) 
+            return 0;
+        memcpy(&pte, map + (paddr & (PAGE_SIZE - 1)), size);
+        munmap(map, PAGE_SIZE);
+        if (!(pte & 1)) 
+            return 0;
+        paddr = pte & 0x000ffffffffff000ull;
+        if (level == 2 && (pte & PTE_PSE)) {
+            mask = ((mask ^ ~-mask) >> 1); /* All bits below first set bit */
+            return ((paddr & ~mask) | (virt & mask)) >> PAGE_SHIFT;
+        }
+        mask >>= (pt_levels == 2 ? 10 : 9);
     }
-
-    if (pt_levels >= 3)
-        pde = *(unsigned long long *)(pd + 8 * ((virt >> 
L2_PAGETABLE_SHIFT_PAE) & L2_PAGETABLE_MASK_PAE));
-    else
-        pde = *(unsigned long *)(pd + 4 * ((virt >> L2_PAGETABLE_SHIFT) & 
L2_PAGETABLE_MASK));
-
-    if ((pde & 1) == 0) {
-        DPRINTF("page entry not present in PD\n");
-        goto out_unmap_pd;
-    }
-
-    /* Page Table */
-
-    if (pde & 0x00000080) { /* 4M page (or 2M in PAE mode) */
-        DPRINTF("Cannot currently cope with 2/4M pages\n");
-        exit(-1);
-    } else { /* 4k page */
-        pt = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ,
-                                  pde >> PAGE_SHIFT);
-
-        if (pt == NULL) {
-            DPRINTF("failed to map PT\n");
-            goto out_unmap_pd;
-        }
-
-        if (pt_levels >= 3)
-            pte = *(unsigned long long *)(pt + 8 * ((virt >> 
L1_PAGETABLE_SHIFT_PAE) & L1_PAGETABLE_MASK_PAE));
-        else
-            pte = *(unsigned long *)(pt + 4 * ((virt >> L1_PAGETABLE_SHIFT) & 
L1_PAGETABLE_MASK));
-
-        if ((pte & 1) == 0) {
-            DPRINTF("page entry not present in PT\n");
-            goto out_unmap_pt;
-        }
-
-        if (pt_levels >= 3)
-            mfn = (pte & L0_PAGETABLE_MASK_PAE) >> PAGE_SHIFT;
-        else
-            mfn = (pte & L0_PAGETABLE_MASK) >> PAGE_SHIFT;
-    }
-
- out_unmap_pt:
-    munmap(pt, PAGE_SIZE);
- out_unmap_pd:
-    munmap(pd, PAGE_SIZE);
- out_unmap_pdp:
-    munmap(pdppage, PAGE_SIZE);
- out_unmap_pml:
-    munmap(pml, PAGE_SIZE);
- out:
-    return mfn;
+    return paddr >> PAGE_SHIFT;
 }
 
 /*
diff -r 5ce75a8eec7f -r 34f52eafd4e3 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Mon Jan 05 10:47:51 2009 +0000
+++ b/tools/libxc/xenctrl.h     Mon Jan 05 11:08:25 2009 +0000
@@ -716,8 +716,8 @@ void *xc_map_foreign_batch(int xc_handle
 
 /**
  * Translates a virtual address in the context of a given domain and
- * vcpu returning the machine page frame number of the associated
- * page.
+ * vcpu returning the GFN containing the address (that is, an MFN for 
+ * PV guests, a PFN for HVM guests).  Returns 0 for failure.
  *
  * @parm xc_handle a handle on an open hypervisor interface
  * @parm dom the domain to perform the translation in

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Make xc_translate_foreign_address aware of compat-mode guests and, Xen patchbot-unstable <=