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

[Xen-devel] [PATCH 22/22] vixen: dom0 builder support



From: Anthony Liguori <aliguori@xxxxxxxxxx>

The dom0 builder requires a number of modifications in order to be
able to launch unprivileged guests.  The console and store pages
must be mapped in a specific location within the guest's initial
page table.

We also have to setup the start info to be what's expected for
unprivileged guests and supress the normal logic to give dom0
increased permissions.

We have to pass around the console and store pages which involves
touching a number of places including the PVH builder.

Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>
---
 xen/arch/x86/dom0_build.c         |  7 +++-
 xen/arch/x86/guest/vixen.c        | 65 +++++++++++++++++++++++++++++++-
 xen/arch/x86/hvm/dom0_build.c     |  4 +-
 xen/arch/x86/pv/dom0_build.c      | 79 ++++++++++++++++++++++++++++++++++-----
 xen/arch/x86/setup.c              | 12 +++++-
 xen/include/asm-x86/dom0_build.h  |  8 +++-
 xen/include/asm-x86/guest/vixen.h |  5 ++-
 xen/include/asm-x86/setup.h       |  4 +-
 8 files changed, 164 insertions(+), 20 deletions(-)

diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
index 88810db..df9d3f8 100644
--- a/xen/arch/x86/dom0_build.c
+++ b/xen/arch/x86/dom0_build.c
@@ -464,7 +464,9 @@ int __init dom0_setup_permissions(struct domain *d)
 int __init construct_dom0(struct domain *d, const module_t *image,
                           unsigned long image_headroom, module_t *initrd,
                           void *(*bootstrap_map)(const module_t *),
-                          char *cmdline)
+                          char *cmdline,
+                          xen_pfn_t store_mfn, uint32_t store_evtchn,
+                          xen_pfn_t console_mfn, uint32_t console_evtchn)
 {
     int rc;
 
@@ -484,7 +486,8 @@ int __init construct_dom0(struct domain *d, const module_t 
*image,
 #endif
 
     rc = (is_hvm_domain(d) ? dom0_construct_pvh : dom0_construct_pv)
-         (d, image, image_headroom, initrd, bootstrap_map, cmdline);
+         (d, image, image_headroom, initrd, bootstrap_map, cmdline,
+          store_mfn, store_evtchn, console_mfn, console_evtchn);
     if ( rc )
         return rc;
 
diff --git a/xen/arch/x86/guest/vixen.c b/xen/arch/x86/guest/vixen.c
index eeffafa..08619d1 100644
--- a/xen/arch/x86/guest/vixen.c
+++ b/xen/arch/x86/guest/vixen.c
@@ -280,6 +280,23 @@ bool vixen_ring_process(uint16_t port)
     return true;
 }
 
+static int hvm_get_parameter(int idx, uint64_t *value)
+{
+    struct xen_hvm_param xhv;
+    int r;
+
+    xhv.domid = DOMID_SELF;
+    xhv.index = idx;
+    r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+    if (r < 0) {
+        printk("Cannot get hvm parameter %d: %d!\n",
+               idx, r);
+        return r;
+    }
+    *value = xhv.value;
+    return r;
+}
+
 static int hvm_set_parameter(int idx, uint64_t value)
 {
     struct xen_hvm_param xhv;
@@ -390,8 +407,54 @@ bool vixen_has_per_cpu_notifications(void)
 }
 
 void __init
-vixen_transform(struct domain *dom0)
+vixen_transform(struct domain *dom0,
+                xen_pfn_t *pstore_mfn, uint32_t *pstore_evtchn,
+                xen_pfn_t *pconsole_mfn, uint32_t *pconsole_evtchn)
 {
+    uint64_t v = 0;
+    long rc;
+    struct evtchn_unmask unmask;
+    struct evtchn_alloc_unbound alloc;
+
+    /* Setup Xenstore */
+    hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+    *pstore_evtchn = unmask.port = v;
+    HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
+
+    hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
+    *pstore_mfn = v;
+
+    printk("Vixen Xenstore evtchn is %d, pfn is 0x%" PRIx64 "\n",
+           *pstore_evtchn, *pstore_mfn);
+
+    /* Setup Xencons */
+    alloc.dom = DOMID_SELF;
+    alloc.remote_dom = DOMID_SELF;
+
+    rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc);
+    if ( rc )
+    {
+        printk("Failed to alloc unbound event channel: %ld\n", rc);
+        *pconsole_evtchn = 0;
+        *pconsole_mfn = 0;
+    }
+    else
+    {
+        void *console_data;
+
+        console_data = alloc_xenheap_page();
+
+        *pconsole_evtchn = alloc.port;
+        *pconsole_mfn = virt_to_mfn(console_data);
+
+        memset(console_data, 0, 4096);
+        vixen_xencons_iface = console_data;
+        vixen_xencons_port = alloc.port;
+    }
+
+    printk("Vixen Xencons evtchn is %d, pfn is 0x%" PRIx64 "\n",
+           *pconsole_evtchn, *pconsole_mfn);
+
     /* Setup event channel forwarding */
     alloc_direct_apic_vector(&vixen_evtchn_vector, vixen_evtchn_notify);
     printk("Vixen evtchn vector is %d\n", vixen_evtchn_vector);
diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
index 4338965..b2ca64f 100644
--- a/xen/arch/x86/hvm/dom0_build.c
+++ b/xen/arch/x86/hvm/dom0_build.c
@@ -1064,7 +1064,9 @@ int __init dom0_construct_pvh(struct domain *d, const 
module_t *image,
                               unsigned long image_headroom,
                               module_t *initrd,
                               void *(*bootstrap_map)(const module_t *),
-                              char *cmdline)
+                              char *cmdline,
+                              xen_pfn_t store_mfn, uint32_t store_evtchn,
+                              xen_pfn_t console_mfn, uint32_t console_evtchn)
 {
     paddr_t entry, start_info;
     int rc;
diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c
index 09c765a..c69f573 100644
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -7,6 +7,7 @@
 #include <xen/console.h>
 #include <xen/domain.h>
 #include <xen/domain_page.h>
+#include <xen/event.h>
 #include <xen/init.h>
 #include <xen/libelf.h>
 #include <xen/multiboot.h>
@@ -276,7 +277,9 @@ int __init dom0_construct_pv(struct domain *d,
                              unsigned long image_headroom,
                              module_t *initrd,
                              void *(*bootstrap_map)(const module_t *),
-                             char *cmdline)
+                             char *cmdline,
+                             xen_pfn_t store_mfn, uint32_t store_evtchn,
+                             xen_pfn_t console_mfn, uint32_t console_evtchn)
 {
     int i, cpu, rc, compatible, compat32, order, machine;
     struct cpu_user_regs *regs;
@@ -299,6 +302,7 @@ int __init dom0_construct_pv(struct domain *d,
     l3_pgentry_t *l3tab = NULL, *l3start = NULL;
     l2_pgentry_t *l2tab = NULL, *l2start = NULL;
     l1_pgentry_t *l1tab = NULL, *l1start = NULL;
+    xen_pfn_t saved_pfn = ~0UL;
 
     /*
      * This fully describes the memory layout of the initial domain. All
@@ -441,8 +445,24 @@ int __init dom0_construct_pv(struct domain *d,
         vphysmap_end = vphysmap_start;
     vstartinfo_start = round_pgup(vphysmap_end);
     vstartinfo_end   = (vstartinfo_start +
-                        sizeof(struct start_info) +
-                        sizeof(struct dom0_vga_console_info));
+                        sizeof(struct start_info));
+    if ( !is_vixen() )
+        vstartinfo_end += sizeof(struct dom0_vga_console_info);
+    vstartinfo_end   = round_pgup(vstartinfo_end);
+
+    if ( is_vixen() ) {
+        struct page_info *pg;
+
+        saved_pfn = (vstartinfo_end - v_start) / PAGE_SIZE;
+
+        pg = mfn_to_page(store_mfn);
+        share_xen_page_with_guest(pg, d, XENSHARE_writable);
+        vstartinfo_end   += PAGE_SIZE;
+
+        pg = mfn_to_page(console_mfn);
+        share_xen_page_with_guest(pg, d, XENSHARE_writable);
+        vstartinfo_end   += PAGE_SIZE;
+    }
 
     vpt_start        = round_pgup(vstartinfo_end);
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
@@ -634,7 +654,13 @@ int __init dom0_construct_pv(struct domain *d,
             *l2tab = l2e_from_paddr(__pa(l1start), L2_PROT);
             l2tab++;
         }
-        if ( count < initrd_pfn || count >= initrd_pfn + PFN_UP(initrd_len) )
+        if ( count == saved_pfn ) {
+            mfn = store_mfn;
+            pfn++;
+        } else if ( count == saved_pfn + 1 ) {
+            mfn = console_mfn;
+            pfn++;
+        } else if ( count < initrd_pfn || count >= initrd_pfn + 
PFN_UP(initrd_len) )
             mfn = pfn++;
         else
             mfn = initrd_mfn++;
@@ -737,7 +763,8 @@ int __init dom0_construct_pv(struct domain *d,
 
     si->shared_info = virt_to_maddr(d->shared_info);
 
-    si->flags        = SIF_PRIVILEGED | SIF_INITDOMAIN;
+    si->flags        = is_vixen() ? 0 : (SIF_PRIVILEGED | SIF_INITDOMAIN);
+
     if ( !vinitrd_start && initrd_len )
         si->flags   |= SIF_MOD_START_PFN;
     si->flags       |= (xen_processor_pmbits << 8) & SIF_PM_MASK;
@@ -818,6 +845,32 @@ int __init dom0_construct_pv(struct domain *d,
         }
     }
 
+    if ( is_vixen() )
+    {
+        dom0_update_physmap(d, saved_pfn, store_mfn, vphysmap_start);
+        dom0_update_physmap(d, saved_pfn + 1, console_mfn, vphysmap_start);
+
+        rc = evtchn_alloc_proxy(d, store_evtchn, ECS_INTERDOMAIN);
+        if ( rc )
+        {
+            printk("Vixen: failed to reserve Xenstore event channel %d => 
%d\n",
+                   store_evtchn, rc);
+            goto out;
+        }
+        rc = evtchn_alloc_proxy(d, console_evtchn, ECS_INTERDOMAIN);
+        if ( rc )
+        {
+            printk("Vixen: failed to reserve Console event channel %d => %d\n",
+                   console_evtchn, rc);
+            goto out;
+        }
+
+        si->store_mfn = store_mfn;
+        si->store_evtchn = store_evtchn;
+        si->console.domU.mfn = console_mfn;
+        si->console.domU.evtchn = console_evtchn;
+    }
+
     if ( initrd_len != 0 )
     {
         si->mod_start = vinitrd_start ?: initrd_pfn;
@@ -828,14 +881,15 @@ int __init dom0_construct_pv(struct domain *d,
     if ( cmdline != NULL )
         strlcpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line));
 
-    if ( fill_console_start_info((void *)(si + 1)) )
+    if ( !is_vixen() && fill_console_start_info((void *)(si + 1)) )
     {
         si->console.dom0.info_off  = sizeof(struct start_info);
         si->console.dom0.info_size = sizeof(struct dom0_vga_console_info);
     }
 
     if ( is_pv_32bit_domain(d) )
-        xlat_start_info(si, XLAT_start_info_console_dom0);
+        xlat_start_info(si, is_vixen() ? XLAT_start_info_console_domU :
+                                         XLAT_start_info_console_dom0);
 
     /* Return to idle domain's page tables. */
     mapcache_override_current(NULL);
@@ -873,9 +927,11 @@ int __init dom0_construct_pv(struct domain *d,
     if ( test_bit(XENFEAT_supervisor_mode_kernel, parms.f_required) )
         panic("Dom0 requires supervisor-mode execution");
 
-    rc = dom0_setup_permissions(d);
-    BUG_ON(rc != 0);
-
+    if ( !is_vixen() )
+    {
+        rc = dom0_setup_permissions(d);
+        BUG_ON(rc != 0);
+    }
     if ( elf_check_broken(&elf) )
         printk(" Xen warning: dom0 kernel broken ELF: %s\n",
                elf_check_broken(&elf));
@@ -886,6 +942,9 @@ int __init dom0_construct_pv(struct domain *d,
     v->is_initialised = 1;
     clear_bit(_VPF_down, &v->pause_flags);
 
+    if ( is_vixen() )
+        d->max_pages = d->tot_pages;
+
     return 0;
 
 out:
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 1b89844..c49eeea 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -663,6 +663,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         .stop_bits = 1
     };
     struct xen_arch_domainconfig config = { .emulation_flags = 0 };
+    xen_pfn_t store_mfn = 0, console_mfn = 0;
+    uint32_t store_evtchn = 0, console_evtchn = 0;
 
     /* Critical region without IDT or TSS.  Any fault is deadly! */
 
@@ -1595,6 +1597,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         config.emulation_flags = XEN_X86_EMU_LAPIC|XEN_X86_EMU_IOAPIC;
     }
 
+    if ( is_vixen() )
+        config.emulation_flags = XEN_X86_EMU_PIT;
+
     /* Create initial domain 0. */
     dom0 = domain_create(dom0_domid, domcr_flags, 0, &config);
     if ( IS_ERR(dom0) || (alloc_dom0_vcpu0(dom0) == NULL) )
@@ -1604,7 +1609,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     dom0->target = NULL;
 
     if ( is_vixen() )
-        vixen_transform(dom0);
+        vixen_transform(dom0, &store_mfn, &store_evtchn,
+                        &console_mfn, &console_evtchn);
 
     /* Grab the DOM0 command line. */
     cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
@@ -1667,7 +1673,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     if ( construct_dom0(dom0, mod, modules_headroom,
                         (initrdidx > 0) && (initrdidx < mbi->mods_count)
                         ? mod + initrdidx : NULL,
-                        bootstrap_map, cmdline) != 0)
+                        bootstrap_map, cmdline,
+                        store_mfn, store_evtchn,
+                        console_mfn, console_evtchn) != 0)
         panic("Could not set up DOM0 guest OS");
 
     if ( cpu_has_smap )
diff --git a/xen/include/asm-x86/dom0_build.h b/xen/include/asm-x86/dom0_build.h
index d83d2b4..459211c 100644
--- a/xen/include/asm-x86/dom0_build.h
+++ b/xen/include/asm-x86/dom0_build.h
@@ -18,13 +18,17 @@ int dom0_construct_pv(struct domain *d, const module_t 
*image,
                       unsigned long image_headroom,
                       module_t *initrd,
                       void *(*bootstrap_map)(const module_t *),
-                      char *cmdline);
+                      char *cmdline,
+                      xen_pfn_t store_mfn, uint32_t store_evtchn,
+                      xen_pfn_t console_mfn, uint32_t console_evtchn);
 
 int dom0_construct_pvh(struct domain *d, const module_t *image,
                        unsigned long image_headroom,
                        module_t *initrd,
                        void *(*bootstrap_map)(const module_t *),
-                       char *cmdline);
+                       char *cmdline,
+                       xen_pfn_t store_mfn, uint32_t store_evtchn,
+                       xen_pfn_t console_mfn, uint32_t console_evtchn);
 
 unsigned long dom0_paging_pages(const struct domain *d,
                                 unsigned long nr_pages);
diff --git a/xen/include/asm-x86/guest/vixen.h 
b/xen/include/asm-x86/guest/vixen.h
index f46c6ed..eca263a 100644
--- a/xen/include/asm-x86/guest/vixen.h
+++ b/xen/include/asm-x86/guest/vixen.h
@@ -80,7 +80,10 @@ bool vixen_has_per_cpu_notifications(void);
 
 void vixen_vcpu_initialize(struct vcpu *v);
 
-void __init vixen_transform(struct domain *dom0);
+void __init
+vixen_transform(struct domain *dom0,
+                xen_pfn_t *pstore_mfn, uint32_t *pstore_evtchn,
+                xen_pfn_t *pconsole_mfn, uint32_t *pconsole_evtchn);
 
 bool vixen_ring_process(uint16_t port);
 
diff --git a/xen/include/asm-x86/setup.h b/xen/include/asm-x86/setup.h
index c5b3d4e..51b207b 100644
--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -39,7 +39,9 @@ int construct_dom0(
     const module_t *kernel, unsigned long kernel_headroom,
     module_t *initrd,
     void *(*bootstrap_map)(const module_t *),
-    char *cmdline);
+    char *cmdline,
+    xen_pfn_t store_mfn, uint32_t store_evtchn,
+    xen_pfn_t console_mfn, uint32_t console_evtchn);
 void setup_io_bitmap(struct domain *d);
 
 unsigned long initial_images_nrpages(nodeid_t node);
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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