Create a block of reserved PFNs in shadow translate mode guests, and
authorsos22@douglas.cl.cam.ac.uk <sos22@douglas.cl.cam.ac.uk>
Thu, 26 Jan 2006 18:40:13 +0000 (19:40 +0100)
committersos22@douglas.cl.cam.ac.uk <sos22@douglas.cl.cam.ac.uk>
Thu, 26 Jan 2006 18:40:13 +0000 (19:40 +0100)
move the shared info and grant table pfns into that block.  This
allows us to remove the get_gnttablist dom0 op, and simplifies the
domain creation code slightly.  Having the reserved block managed by
Xen may also make it slightly easier to handle the case where the
grant table needs to be extended at run time.

Suggested-by: kaf24
Signed-off-by: Steven Smith, sos22@cam.ac.uk
tools/libxc/xc_linux_build.c
tools/libxc/xc_misc.c
tools/libxc/xc_private.c
tools/libxc/xc_private.h
tools/libxc/xenctrl.h
xen/arch/x86/dom0_ops.c
xen/arch/x86/mm.c
xen/include/asm-x86/config.h
xen/include/public/dom0_ops.h
xen/include/public/xen.h
xen/include/xen/sched.h

index 3c80b5e994a8027afbc6b5183a9faf3e23728635..30e7abd5acc1d3b7b2ce91614a7a844f04b5beb1 100644 (file)
@@ -610,7 +610,7 @@ static int setup_guest(int xc_handle,
         goto error_out;
     }
 
-    if ( (page_array = malloc((nr_pages + 1 + NR_GRANT_FRAMES) * sizeof(unsigned long))) == NULL )
+    if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
     {
         PERROR("Could not allocate memory");
         goto error_out;
@@ -651,17 +651,7 @@ static int setup_guest(int xc_handle,
         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
         page_array[physmap_pfn++]);
 
-    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 + 1 + NR_GRANT_FRAMES; count++ )
+    for ( count = 0; count < nr_pages; count++ )
     {
         if ( xc_add_mmu_update(
             xc_handle, mmu,
@@ -696,6 +686,16 @@ static int setup_guest(int xc_handle,
             PERROR("Could not enable translation mode");
             goto error_out;
         }
+
+        /* Find the shared info frame.  It's guaranteed to be at the
+           start of the PFN hole. */
+        guest_shared_info_mfn = xc_get_pfn_hole_start(xc_handle, dom);
+        if (guest_shared_info_mfn <= 0) {
+            PERROR("Cannot find shared info pfn");
+            goto error_out;
+        }
+    } else {
+        guest_shared_info_mfn = shared_info_frame;
     }
 
     /* setup page tables */
@@ -756,11 +756,9 @@ static int setup_guest(int xc_handle,
     if (shadow_mode_enabled) {
         guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT;
         guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT;
-        guest_shared_info_mfn = nr_pages;
     } else {
         guest_store_mfn = *store_mfn;
         guest_console_mfn = *console_mfn;
-        guest_shared_info_mfn = shared_info_frame;
     }
 
     start_info = xc_map_foreign_range(
index 13848fbf5f3d23788374c2064b1ca307aa790dc0..1f5ae861a54273be82b5dbcb79ed92050b8e9de3 100644 (file)
@@ -131,6 +131,14 @@ int xc_msr_write(int xc_handle, int cpu_mask, int msr, unsigned int low,
     return rc;
 }
 
+int xc_get_pfn_hole_start(int xc_handle, domid_t dom)
+{
+    struct mmuext_op op = {0};
+    op.cmd = MMUEXT_PFN_HOLE_BASE;
+    return xc_mmuext_op(xc_handle, &op, 1, dom);
+}
+
+
 /*
  * Local variables:
  * mode: C
index 8993af0b57d76610d55e6f29d64f0603996b43e9..75556f6847cad04feb3c68366fd78ecbea77031f 100644 (file)
@@ -314,35 +314,6 @@ 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 b366db69e5397b14fc6edb55fd724c6afb9a5e1f..8c19ecd2183e87ce5bcfb694c44e9636b921969a 100644 (file)
@@ -111,9 +111,6 @@ 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 91d717c55c7ea20cc8fe9303458329f5496f2ace..6585d1a6e276278a8ce77388f798eaccab147fce 100644 (file)
@@ -528,4 +528,6 @@ int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
                    unsigned long long ptr, unsigned long long val);
 int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu);
 
+int xc_get_pfn_hole_start(int xc_handle, domid_t dom);
+
 #endif
index 4a61ba4948c86d812a1d5dd77c598f3a58ad38b5..789d01899a546dc49eae8d71062aba8256e65eda 100644 (file)
@@ -330,38 +330,6 @@ 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 61a26de5808d7467271dfd346f21edcb3c411cd1..ad89d5fdec8d9e93fd1c3bc3c86b4fc246f9af8a 100644 (file)
@@ -1929,7 +1929,57 @@ int do_mmuext_op(
             }
             break;
         }
-            
+
+        case MMUEXT_PFN_HOLE_BASE:
+        {
+            if (FOREIGNDOM->start_pfn_hole) {
+                rc = FOREIGNDOM->start_pfn_hole;
+                okay = 1;
+            } else {
+                rc = FOREIGNDOM->start_pfn_hole =
+                    FOREIGNDOM->max_pages;
+                okay = 1;
+                if (shadow_mode_translate(FOREIGNDOM)) {
+                    /* Fill in a few entries in the hole.  At the
+                       moment, this means the shared info page and the
+                       grant table pages. */
+                    struct domain_mmap_cache c1, c2;
+                    unsigned long pfn, mfn, x;
+                    domain_mmap_cache_init(&c1);
+                    domain_mmap_cache_init(&c2);
+                    shadow_lock(FOREIGNDOM);
+                    pfn = FOREIGNDOM->start_pfn_hole;
+                    mfn = virt_to_phys(FOREIGNDOM->shared_info) >> PAGE_SHIFT;
+                    set_p2m_entry(FOREIGNDOM, pfn, mfn, &c1, &c2);
+                    set_pfn_from_mfn(mfn, pfn);
+                    pfn++;
+                    for (x = 0; x < NR_GRANT_FRAMES; x++) {
+                        mfn = gnttab_shared_mfn(FOREIGNDOM,
+                                                FOREIGNDOM->grant_table,
+                                                x);
+                        set_p2m_entry(FOREIGNDOM, pfn, mfn, &c1, &c2);
+                        set_pfn_from_mfn(mfn, pfn);
+                        pfn++;
+                    }
+                    shadow_unlock(FOREIGNDOM);
+                    domain_mmap_cache_destroy(&c1);
+                    domain_mmap_cache_destroy(&c2);
+                }
+            }
+            break;
+        }
+
+        case MMUEXT_PFN_HOLE_SIZE:
+        {
+            if (shadow_mode_translate(FOREIGNDOM)) {
+                rc = PFN_HOLE_SIZE;
+            } else {
+                rc = 0;
+            }
+            okay = 1;
+            break;
+        }
+
         default:
             MEM_LOG("Invalid extended pt command 0x%x", op.cmd);
             okay = 0;
@@ -2663,7 +2713,7 @@ long set_gdt(struct vcpu *v,
 
 long do_set_gdt(unsigned long *frame_list, unsigned int entries)
 {
-    int i, nr_pages = (entries + 511) / 512;
+    int nr_pages = (entries + 511) / 512;
     unsigned long frames[16];
     long ret;
 
index d5d0e0acb003c76270a1e733f83bb9ff33f0060a..b6376d3d6bc2629f6fb686030122342ed7f4ab6f 100644 (file)
@@ -60,6 +60,9 @@
 #endif
 #endif
 
+/* How large is the PFN reserved area, when we have one? */
+#define PFN_HOLE_SIZE 32
+
 #ifndef STACK_ORDER
 #define STACK_ORDER 1
 #endif
index 6d6a04594e4c535d3cd766888c2e3ddfd23a441e..6e99efcd10ed897521c0d50dd3e8081c76db7573 100644 (file)
@@ -431,16 +431,6 @@ typedef struct {
     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 */
@@ -482,7 +472,6 @@ 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;
index ca1d4d1d036b66b6b66a9444d5908a7f554c2267..0027e327e417203a82194e7f8f97cf9d8b3a9519 100644 (file)
  * cmd: MMUEXT_SET_LDT
  * linear_addr: Linear address of LDT base (NB. must be page-aligned).
  * nr_ents: Number of entries in LDT.
+ *
+ * cmd: MMUEXT_PFN_HOLE_BASE
+ * No additional arguments.  Returns the first pfn in the Xen-reserved
+ * pfn hole.  Note that we delay allocating the hole until the first
+ * time this is called.
+ *
+ * cmd: MMUEXT_PFN_HOLE_SIZE
+ * No additional arguments.  Returns the number of pfns in the
+ * Xen-reserved pfn hole.
  */
 #define MMUEXT_PIN_L1_TABLE      0
 #define MMUEXT_PIN_L2_TABLE      1
 #define MMUEXT_FLUSH_CACHE      12
 #define MMUEXT_SET_LDT          13
 #define MMUEXT_NEW_USER_BASEPTR 15
+#define MMUEXT_PFN_HOLE_BASE    16
+#define MMUEXT_PFN_HOLE_SIZE    17
 
 #ifndef __ASSEMBLY__
 struct mmuext_op {
index 0d265badb8a491f1c6e924295b3b5a27d2dc1af6..f164a7cc7a41b6c10cfc7bcfb7a8857fb6a17e41 100644 (file)
@@ -153,6 +153,9 @@ struct domain
 
     /* Control-plane tools handle for this domain. */
     xen_domain_handle_t handle;
+
+    /* Start of the PFN hole */
+    unsigned long start_pfn_hole;
 };
 
 struct domain_setup_info