[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Make shadow translate mode work for unprivileged, uniprocessor guests



# HG changeset patch
# User sos22@xxxxxxxxxxxxxxxxxxxx
# Node ID 43c294aea9ecbace908d321829a9f31e2c6f7a29
# Parent  860fa26845c242eac64dbef60bc2fec42cfacc8c
Make shadow translate mode work for unprivileged, uniprocessor guests
with no devices on plain 32 bit non-PAE hosts.

Signed-off-by: Steven Smith, sos22@xxxxxxxxx

diff -r 860fa26845c2 -r 43c294aea9ec tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c      Wed Jan 25 16:14:19 2006
+++ b/tools/libxc/xc_linux_build.c      Wed Jan 25 16:15:11 2006
@@ -60,16 +60,18 @@
     return 0;
 }
 
-#define alloc_pt(ltab, vltab)                                           \
+#define alloc_pt(ltab, vltab, pltab)                                    \
 do {                                                                    \
-    ltab = (uint64_t)page_array[ppt_alloc++] << PAGE_SHIFT;                  \
+    pltab = ppt_alloc++;                                                \
+    ltab = (uint64_t)page_array[pltab] << PAGE_SHIFT;                   \
+    pltab <<= PAGE_SHIFT;                                               \
     if ( vltab != NULL )                                                \
         munmap(vltab, PAGE_SIZE);                                       \
     if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,       \
                                        PROT_READ|PROT_WRITE,            \
                                        ltab >> PAGE_SHIFT)) == NULL )   \
         goto error_out;                                                 \
-    memset(vltab, 0, PAGE_SIZE);                                        \
+    memset(vltab, 0x0, PAGE_SIZE);                                      \
 } while ( 0 )
 
 #if defined(__i386__)
@@ -80,33 +82,42 @@
                            unsigned long v_end,
                            unsigned long *page_array,
                            unsigned long vpt_start,
-                           unsigned long vpt_end)
+                           unsigned long vpt_end,
+                           unsigned shadow_mode_enabled)
 {
     l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
     l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
-    unsigned long l1tab = 0;
-    unsigned long l2tab = 0;
+    unsigned long l1tab = 0, pl1tab;
+    unsigned long l2tab = 0, pl2tab;
     unsigned long ppt_alloc;
     unsigned long count;
 
     ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
-    alloc_pt(l2tab, vl2tab);
+    alloc_pt(l2tab, vl2tab, pl2tab);
     vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
     ctxt->ctrlreg[3] = l2tab;
 
     for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ )
-    {    
+    {
         if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
         {
-            alloc_pt(l1tab, vl1tab);
+            alloc_pt(l1tab, vl1tab, pl1tab);
             vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
-            *vl2e++ = l1tab | L2_PROT;
-        }
-
-        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-        if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && 
-             (count <  ((vpt_end  -dsi_v_start)>>PAGE_SHIFT)) )
-            *vl1e &= ~_PAGE_RW;
+            if (shadow_mode_enabled)
+                *vl2e = pl1tab | L2_PROT;
+            else
+                *vl2e = l1tab | L2_PROT;
+            vl2e++;
+        }
+
+        if (shadow_mode_enabled) {
+            *vl1e = (count << PAGE_SHIFT) | L1_PROT;
+        } else {
+            *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
+            if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) && 
+                 (count <  ((vpt_end  -dsi_v_start)>>PAGE_SHIFT)) )
+                *vl1e &= ~_PAGE_RW;
+        }
         vl1e++;
     }
     munmap(vl1tab, PAGE_SIZE);
@@ -127,12 +138,13 @@
                                unsigned long v_end,
                                unsigned long *page_array,
                                unsigned long vpt_start,
-                               unsigned long vpt_end)
+                               unsigned long vpt_end,
+                               unsigned shadow_mode_enabled)
 {
     l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL;
     l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL;
     l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL;
-    uint64_t l1tab, l2tab, l3tab;
+    uint64_t l1tab, l2tab, l3tab, pl1tab, pl2tab, pl3tab;
     unsigned long ppt_alloc, count, nmfn;
 
     /* First allocate page for page dir. */
@@ -149,7 +161,7 @@
         page_array[ppt_alloc] = nmfn;
     }
 
-    alloc_pt(l3tab, vl3tab);
+    alloc_pt(l3tab, vl3tab, pl3tab);
     vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
     ctxt->ctrlreg[3] = l3tab;
 
@@ -159,22 +171,32 @@
         {
             if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
             {
-                alloc_pt(l2tab, vl2tab);
+                alloc_pt(l2tab, vl2tab, pl2tab);
                 vl2e = &vl2tab[l2_table_offset_pae(
                     dsi_v_start + (count << PAGE_SHIFT))];
-                *vl3e++ = l2tab | L3_PROT;
+                if (shadow_mode_enabled)
+                    *vl3e = pl2tab | L3_PROT;
+                else
+                    *vl3e++ = l2tab | L3_PROT;
             }
 
-            alloc_pt(l1tab, vl1tab);
+            alloc_pt(l1tab, vl1tab, pl1tab);
             vl1e = &vl1tab[l1_table_offset_pae(
                 dsi_v_start + (count << PAGE_SHIFT))];
-            *vl2e++ = l1tab | L2_PROT;
+            if (shadow_mode_enabled)
+                *vl2e = pl1tab | L2_PROT;
+            else
+                *vl2e++ = l1tab | L2_PROT;
         }
         
-        *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
-        if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
-             (count <  ((vpt_end  -dsi_v_start)>>PAGE_SHIFT)) ) 
-            *vl1e &= ~_PAGE_RW;
+        if (shadow_mode_enabled) {
+            *vl1e = (count << PAGE_SHIFT) | L1_PROT;
+        } else {
+            *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
+            if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
+                 (count <  ((vpt_end  -dsi_v_start)>>PAGE_SHIFT)) ) 
+                *vl1e &= ~_PAGE_RW;
+        }
         vl1e++;
     }
      
@@ -203,7 +225,8 @@
                               unsigned long v_end,
                               unsigned long *page_array,
                               unsigned long vpt_start,
-                              unsigned long vpt_end)
+                              unsigned long vpt_end,
+                              int shadow_mode_enabled)
 {
     l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
     l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
@@ -247,11 +270,15 @@
             vl2e++;
         }
         
-        *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
-        if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
-             (count <  ((vpt_end  -dsi_v_start)>>PAGE_SHIFT)) ) 
-        {
-            *vl1e &= ~_PAGE_RW;
+        if (shadow_mode_enable) {
+            *vl1e = (count << PAGE_SHIFT) | L1_PROT;
+        } else {
+            *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
+            if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
+                 (count <  ((vpt_end  -dsi_v_start)>>PAGE_SHIFT)) ) 
+                {
+                    *vl1e &= ~_PAGE_RW;
+                }
         }
         vl1e++;
     }
@@ -458,6 +485,8 @@
     unsigned long vpt_start;
     unsigned long vpt_end;
     unsigned long v_end;
+    unsigned shadow_mode_enabled;
+    unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
 
     rc = probeimageformat(image, image_size, &load_funcs);
     if ( rc != 0 )
@@ -558,7 +587,7 @@
         goto error_out;
     }
 
-    if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
+    if ( (page_array = malloc((nr_pages + 1) * sizeof(unsigned long))) == NULL 
)
     {
         PERROR("Could not allocate memory");
         goto error_out;
@@ -593,24 +622,8 @@
     if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
         goto error_out;
 
-    /* setup page tables */
-#if defined(__i386__)
-    if (dsi.pae_kernel)
-        rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
-                                 dsi.v_start, v_end,
-                                 page_array, vpt_start, vpt_end);
-    else
-        rc = setup_pg_tables(xc_handle, dom, ctxt,
-                             dsi.v_start, v_end,
-                             page_array, vpt_start, vpt_end);
-#endif
-#if defined(__x86_64__)
-    rc = setup_pg_tables_64(xc_handle, dom, ctxt,
-                            dsi.v_start, v_end,
-                            page_array, vpt_start, vpt_end);
-#endif
-    if (0 != rc)
-        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;
@@ -618,7 +631,10 @@
         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
         page_array[physmap_pfn++]);
 
-    for ( count = 0; count < nr_pages; count++ )
+    if (shadow_mode_enabled)
+        page_array[nr_pages] = shared_info_frame;
+
+    for ( count = 0; count < nr_pages + shadow_mode_enabled; count++ )
     {
         if ( xc_add_mmu_update(
             xc_handle, mmu,
@@ -640,20 +656,58 @@
         }
     }
     munmap(physmap, PAGE_SIZE);
-    
+
+    /* Send the page update requests down to the hypervisor. */
+    if ( xc_finish_mmu_updates(xc_handle, mmu) )
+        goto error_out;
+
+    if (shadow_mode_enabled) {
+        /* Enable shadow translate mode */
+        if (xc_shadow_control(xc_handle, dom,
+                              DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE,
+                              NULL, 0, NULL) < 0) {
+            PERROR("Could not enable translation mode");
+            goto error_out;
+        }
+    }
+
+    /* setup page tables */
+#if defined(__i386__)
+    if (dsi.pae_kernel)
+        rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
+                                 dsi.v_start, v_end,
+                                 page_array, vpt_start, vpt_end,
+                                 shadow_mode_enabled);
+    else
+        rc = setup_pg_tables(xc_handle, dom, ctxt,
+                             dsi.v_start, v_end,
+                             page_array, vpt_start, vpt_end,
+                             shadow_mode_enabled);
+#endif
+#if defined(__x86_64__)
+    rc = setup_pg_tables_64(xc_handle, dom, ctxt,
+                            dsi.v_start, v_end,
+                            page_array, vpt_start, vpt_end,
+                            shadow_mode_enabled);
+#endif
+    if (0 != rc)
+        goto error_out;
+
 #if defined(__i386__)
     /*
      * Pin down l2tab addr as page dir page - causes hypervisor to provide
      * correct protection for the page
      */
-    if (dsi.pae_kernel) {
-        if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
-                       ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
-            goto error_out;
-    } else {
-        if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
-                       ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
-            goto error_out;
+    if (!shadow_mode_enabled) {
+        if (dsi.pae_kernel) {
+            if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
+                           ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
+                goto error_out;
+        } else {
+            if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
+                           ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
+                goto error_out;
+        }
     }
 #endif
 
@@ -672,24 +726,34 @@
     if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) ||
          xc_clear_domain_page(xc_handle, dom, *console_mfn) )
         goto error_out;
+    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(
         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
         page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
+    /*shared_info, start_info */
     memset(start_info, 0, sizeof(*start_info));
     rc = xc_version(xc_handle, XENVER_version, NULL);
     sprintf(start_info->magic, "xen-%i.%i-x86_%d%s",
             rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8,
             dsi.pae_kernel ? "p" : "");
     start_info->nr_pages     = nr_pages;
-    start_info->shared_info  = shared_info_frame << PAGE_SHIFT;
+    start_info->shared_info  = guest_shared_info_mfn << PAGE_SHIFT;
     start_info->flags        = flags;
     start_info->pt_base      = vpt_start;
     start_info->nr_pt_frames = nr_pt_pages;
     start_info->mfn_list     = vphysmap_start;
-    start_info->store_mfn    = *store_mfn;
+    start_info->store_mfn    = guest_store_mfn;
     start_info->store_evtchn = store_evtchn;
-    start_info->console_mfn   = *console_mfn;
+    start_info->console_mfn   = guest_console_mfn;
     start_info->console_evtchn = console_evtchn;
     if ( initrd_len != 0 )
     {
diff -r 860fa26845c2 -r 43c294aea9ec xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed Jan 25 16:14:19 2006
+++ b/xen/arch/x86/mm.c Wed Jan 25 16:15:11 2006
@@ -1826,6 +1826,8 @@
             break;
 
         case MMUEXT_NEW_BASEPTR:
+            if (shadow_mode_translate(current->domain))
+                mfn = __gpfn_to_mfn(current->domain, mfn);
             okay = new_guest_cr3(mfn);
             percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB;
             break;
@@ -2680,6 +2682,7 @@
     int nr_pages = (entries + 511) / 512;
     unsigned long frames[16];
     long ret;
+    int x;
 
     /* Rechecked in set_gdt, but ensures a sane limit for copy_from_user(). */
     if ( entries > FIRST_RESERVED_GDT_ENTRY )
@@ -2687,6 +2690,11 @@
     
     if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
         return -EFAULT;
+
+    if (shadow_mode_translate(current->domain)) {
+        for (x = 0; x < nr_pages; x++)
+            frames[x] = __gpfn_to_mfn(current->domain, frames[x]);
+    }
 
     LOCK_BIGLOCK(current->domain);
 
diff -r 860fa26845c2 -r 43c294aea9ec xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Wed Jan 25 16:14:19 2006
+++ b/xen/arch/x86/shadow32.c   Wed Jan 25 16:15:11 2006
@@ -1391,7 +1391,7 @@
     case DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE:
         free_shadow_pages(d);
         rc = __shadow_mode_enable(
-            d, d->arch.shadow_mode|SHM_enable|SHM_refcounts|SHM_translate);
+            d, 
d->arch.shadow_mode|SHM_enable|SHM_refcounts|SHM_translate|SHM_wr_pt_pte);
         break;
 
     default:
@@ -2643,7 +2643,8 @@
     __guest_get_l2e(v, va, &gpde);
     if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
     {
-        SH_VVLOG("shadow_fault - EXIT: L1 not present");
+        SH_VVLOG("shadow_fault - EXIT: L2 not present (%x)",
+                 l2e_get_intpte(gpde));
         perfc_incrc(shadow_fault_bail_pde_not_present);
         goto fail;
     }
@@ -2655,8 +2656,9 @@
     orig_gpte = gpte = linear_pg_table[l1_linear_offset(va)];
     if ( unlikely(!(l1e_get_flags(gpte) & _PAGE_PRESENT)) )
     {
-        SH_VVLOG("shadow_fault - EXIT: gpte not present (%" PRIpte ")",
-                 l1e_get_intpte(gpte));
+        SH_VVLOG("shadow_fault - EXIT: gpte not present (%" PRIpte ") (gpde %" 
PRIpte ")",
+                 l1e_get_intpte(gpte),
+                 l2e_get_intpte(gpde));
         perfc_incrc(shadow_fault_bail_pte_not_present);
         goto fail;
     }
diff -r 860fa26845c2 -r 43c294aea9ec xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Wed Jan 25 16:14:19 2006
+++ b/xen/include/asm-x86/shadow.h      Wed Jan 25 16:15:11 2006
@@ -490,7 +490,7 @@
 #ifndef NDEBUG
     else if ( mfn < max_page )
     {
-        SH_VLOG("mark_dirty OOR! mfn=%x pfn=%lx max=%x (dom %p)",
+        SH_VLOG("mark_dirty OOR! mfn=%lx pfn=%lx max=%x (dom %p)",
                mfn, pfn, d->arch.shadow_dirty_bitmap_size, d);
         SH_VLOG("dom=%p caf=%08x taf=%" PRtype_info, 
                 page_get_owner(pfn_to_page(mfn)),

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.