Make some basic cases of grant tables work in shadow translate mode.
authorsos22@douglas.cl.cam.ac.uk <sos22@douglas.cl.cam.ac.uk>
Wed, 25 Jan 2006 17:57:44 +0000 (18:57 +0100)
committersos22@douglas.cl.cam.ac.uk <sos22@douglas.cl.cam.ac.uk>
Wed, 25 Jan 2006 17:57:44 +0000 (18:57 +0100)
This is enough to get block devices to work.

Note that this involves assigning PFNs to the machine frames used for
the grant table structures.  While I'm here, I also assigned a PFN to
the shared info frame.

Signed-off-by: Steven Smith, sos22@cam.ac.uk
tools/libxc/xc_linux_build.c
tools/libxc/xc_private.c
tools/libxc/xc_private.h
xen/arch/x86/dom0_ops.c
xen/common/grant_table.c
xen/include/public/dom0_ops.h

index 27b60551f8481f1ddab16907dfc01ed91467ad37..c0b0568811bf680f753e435ed5ed567cfe8a9a34 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include "xg_private.h"
+#include "xc_private.h"
 #include <xenctrl.h>
 
 #if defined(__i386__)
@@ -32,6 +33,8 @@
 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
 #endif
 
+#define NR_GRANT_FRAMES 4
+
 #ifdef __ia64__
 #define get_tot_pages xc_get_max_pages
 #else
@@ -504,6 +507,8 @@ static int setup_guest(int xc_handle,
         goto error_out;
     }
 
+    shadow_mode_enabled = !!strstr(dsi.xen_guest_string,
+                                   "SHADOW=translate");
     /*
      * Why do we need this? The number of page-table frames depends on the 
      * size of the bootstrap address space. But the size of the address space 
@@ -587,7 +592,7 @@ static int setup_guest(int xc_handle,
         goto error_out;
     }
 
-    if ( (page_array = malloc((nr_pages + 1) * sizeof(unsigned long))) == NULL )
+    if ( (page_array = malloc((nr_pages + 1 + NR_GRANT_FRAMES) * sizeof(unsigned long))) == NULL )
     {
         PERROR("Could not allocate memory");
         goto error_out;
@@ -622,19 +627,23 @@ static int setup_guest(int xc_handle,
     if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
         goto error_out;
 
-    shadow_mode_enabled = !!strstr(dsi.xen_guest_string,
-                                   "SHADOW=translate");
-
     /* Write the phys->machine and machine->phys table entries. */
     physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
     physmap = physmap_e = xc_map_foreign_range(
         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
         page_array[physmap_pfn++]);
 
-    if (shadow_mode_enabled)
-        page_array[nr_pages] = shared_info_frame;
+    page_array[nr_pages] = shared_info_frame;
+
+    if ( xc_get_gnttab_frames(xc_handle,
+                              dom,
+                              page_array + 1 + nr_pages,
+                              NR_GRANT_FRAMES) <= 0) {
+        fprintf(stderr, "cannot get grant table frames\n");
+        goto error_out;
+    }
 
-    for ( count = 0; count < nr_pages + shadow_mode_enabled; count++ )
+    for ( count = 0; count < nr_pages + 1 + NR_GRANT_FRAMES; count++ )
     {
         if ( xc_add_mmu_update(
             xc_handle, mmu,
index 75556f6847cad04feb3c68366fd78ecbea77031f..8993af0b57d76610d55e6f29d64f0603996b43e9 100644 (file)
@@ -314,6 +314,35 @@ int xc_get_pfn_list(int xc_handle,
     return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
 }
 
+int xc_get_gnttab_frames(int xc_handle,
+                         uint32_t domid,
+                         unsigned long *pfn_buf,
+                         unsigned long max_pfns)
+{
+    DECLARE_DOM0_OP;
+    int ret;
+    op.cmd = DOM0_GETGNTTABLIST;
+    op.u.getgnttablist.domain   = (domid_t)domid;
+    op.u.getgnttablist.max_pfns = max_pfns;
+    op.u.getgnttablist.buffer   = pfn_buf;
+
+#ifdef VALGRIND
+    memset(pfn_buf, 0, max_pfns * sizeof(unsigned long));
+#endif
+
+    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
+    {
+        PERROR("xc_get_pfn_list: pfn_buf mlock failed");
+        return -1;
+    }
+
+    ret = do_dom0_op(xc_handle, &op);
+
+    safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long));
+
+    return (ret < 0) ? -1 : op.u.getgnttablist.num_pfns;
+}
+
 long xc_get_tot_pages(int xc_handle, uint32_t domid)
 {
     DECLARE_DOM0_OP;
index 8c19ecd2183e87ce5bcfb694c44e9636b921969a..b366db69e5397b14fc6edb55fd724c6afb9a5e1f 100644 (file)
@@ -111,6 +111,9 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
     return ret;
 }
 
+int xc_get_gnttab_frames(int xc_handle, uint32_t domid, unsigned long *pfn_buf,
+                        unsigned long max_pfns);
+
 
 /*
  * ioctl-based mfn mapping interface
index 789d01899a546dc49eae8d71062aba8256e65eda..4a61ba4948c86d812a1d5dd77c598f3a58ad38b5 100644 (file)
@@ -330,6 +330,38 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
     }
     break;
 
+    case DOM0_GETGNTTABLIST:
+    {
+        int i;
+        struct domain *d = find_domain_by_id(op->u.getgnttablist.domain);
+        unsigned long max_pfns = op->u.getgnttablist.max_pfns;
+        unsigned long pfn;
+        unsigned long *buffer = op->u.getgnttablist.buffer;
+
+        ret = -EINVAL;
+        if ( d != NULL )
+        {
+            ret = 0;
+
+            for ( i = 0; i < max_pfns && i < NR_GRANT_FRAMES; i++ )
+            {
+               pfn = gnttab_shared_mfn(d, d->grant_table, i);
+                if ( put_user(pfn, buffer) )
+                {
+                    ret = -EFAULT;
+                    break;
+                }
+                buffer++;
+            }
+
+            op->u.getgnttablist.num_pfns = i;
+            copy_to_user(u_dom0_op, op, sizeof(*op));
+
+            put_domain(d);
+        }
+    }
+    break;
+
     case DOM0_GETMEMLIST:
     {
         int i;
index 7576d715d3a6df9172143ec1b9944d4e04b95e0c..3f788ca34f720537bdd7ff4dbaea4514dca8e912 100644 (file)
@@ -481,6 +481,7 @@ gnttab_setup_table(
     gnttab_setup_table_t  op;
     struct domain        *d;
     int                   i;
+    unsigned long         mfn;
 
     if ( count != 1 )
         return -EINVAL;
@@ -520,9 +521,12 @@ gnttab_setup_table(
     {
         ASSERT(d->grant_table != NULL);
         (void)put_user(GNTST_okay, &uop->status);
-        for ( i = 0; i < op.nr_frames; i++ )
-            (void)put_user(gnttab_shared_mfn(d, d->grant_table, i),
-                           &op.frame_list[i]);
+        for ( i = 0; i < op.nr_frames; i++ ) {
+            mfn = gnttab_shared_mfn(d, d->grant_table, i);
+            if (shadow_mode_translate(d))
+                mfn = __mfn_to_gpfn(d, mfn);
+            (void)put_user(mfn, &op.frame_list[i]);
+        }
     }
 
     put_domain(d);
index 4a70a77e490a13da118c4af99e32b1be81488db8..6d6a04594e4c535d3cd766888c2e3ddfd23a441e 100644 (file)
@@ -430,7 +430,17 @@ typedef struct {
     domid_t  domain;          /* domain to be affected */
     unsigned long mfn;        /* machine frame to be initialised */
 } dom0_hypercall_init_t;
+
+#define DOM0_GETGNTTABLIST    49
+typedef struct {
+    /* IN variables. */
+    domid_t       domain;
+    unsigned long max_pfns;
+    void         *buffer;
+    /* OUT variables. */
+    unsigned long num_pfns;
+} dom0_getgnttablist_t;
+
 typedef struct {
     uint32_t cmd;
     uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
@@ -472,6 +482,7 @@ typedef struct {
         dom0_irq_permission_t    irq_permission;
         dom0_iomem_permission_t  iomem_permission;
         dom0_hypercall_init_t    hypercall_init;
+        dom0_getgnttablist_t     getgnttablist;
         uint8_t                  pad[128];
     } u;
 } dom0_op_t;