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-devel

[Xen-devel] [PATCH 13/13] xen: pv domain builder.

To: qemu-devel@xxxxxxxxxx, xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 13/13] xen: pv domain builder.
From: Gerd Hoffmann <kraxel@xxxxxxxxxx>
Date: Thu, 21 Aug 2008 18:27:34 +0200
Cc: Gerd Hoffmann <kraxel@xxxxxxxxxx>
Delivery-date: Thu, 21 Aug 2008 09:34:48 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1219336054-15919-1-git-send-email-kraxel@xxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1219336054-15919-1-git-send-email-kraxel@xxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
This adds domain building support for paravirtual domains to qemu.
This allows booting xen guests directly with qemu, without Xend
and the management stack.

Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx>
---
 Makefile.target      |    2 +-
 configure            |    2 +-
 hw/xen_backend.h     |    3 +
 hw/xen_devconfig.c   |   29 +++++
 hw/xen_domainbuild.c |  281 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/xen_domainbuild.h |    9 ++
 hw/xen_machine_pv.c  |   34 ++++---
 7 files changed, 344 insertions(+), 16 deletions(-)
 create mode 100644 hw/xen_domainbuild.c
 create mode 100644 hw/xen_domainbuild.h

diff --git a/Makefile.target b/Makefile.target
index 7e507e4..47bfc77 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -516,7 +516,7 @@ LIBS += $(CONFIG_VNC_TLS_LIBS)
 endif
 
 # xen backend driver support
-XEN_OBJS := xen_machine_pv.o xen_backend.o xen_devconfig.o
+XEN_OBJS := xen_machine_pv.o xen_backend.o xen_devconfig.o xen_domainbuild.o
 XEN_OBJS += xen_console.o xen_framebuffer.o xen_disk.o xen_nic.o
 ifeq ($(CONFIG_XEN), yes)
   OBJS += $(XEN_OBJS)
diff --git a/configure b/configure
index 14689d2..cec0b48 100755
--- a/configure
+++ b/configure
@@ -1228,7 +1228,7 @@ fi
 if test "$xen" = "yes" ; then
   echo "CONFIG_XEN=yes" >> $config_mak
   echo "#define CONFIG_XEN 1" >> $config_h
-  echo "XEN_LIBS=-lxenstore -lxenctrl" >> $config_mak
+  echo "XEN_LIBS=-lxenstore -lxenctrl -lxenguest" >> $config_mak
 fi
 if test "$aio" = "yes" ; then
   echo "#define CONFIG_AIO 1" >> $config_h
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index f591743..70ad016 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -99,5 +99,8 @@ void xen_set_display(int domid, DisplayState *ds);
 void xen_config_cleanup(void);
 int xen_config_dev_blk(DriveInfo *disk);
 int xen_config_dev_nic(NICInfo *nic);
+int xen_config_dev_vfb(int vdev, char *type);
+int xen_config_dev_vkbd(int vdev);
+int xen_config_dev_console(int vdev);
 
 #endif /* QEMU_XEN_BACKEND_H */
diff --git a/hw/xen_devconfig.c b/hw/xen_devconfig.c
index 25d28b4..0d506ca 100644
--- a/hw/xen_devconfig.c
+++ b/hw/xen_devconfig.c
@@ -142,3 +142,32 @@ int xen_config_dev_nic(NICInfo *nic)
     /* common stuff */
     return xen_config_dev_all(fe, be);
 }
+
+int xen_config_dev_vfb(int vdev, char *type)
+{
+    char fe[256], be[256];
+
+    xen_config_dev_dirs("vfb", "vfb", vdev, fe, be, sizeof(fe));
+
+    /* backend */
+    xenstore_write_str(be, "type",  type);
+
+    /* common stuff */
+    return xen_config_dev_all(fe, be);
+}
+
+int xen_config_dev_vkbd(int vdev)
+{
+    char fe[256], be[256];
+
+    xen_config_dev_dirs("vkbd", "vkbd", vdev, fe, be, sizeof(fe));
+    return xen_config_dev_all(fe, be);
+}
+
+int xen_config_dev_console(int vdev)
+{
+    char fe[256], be[256];
+
+    xen_config_dev_dirs("console", "console", vdev, fe, be, sizeof(fe));
+    return xen_config_dev_all(fe, be);
+}
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
new file mode 100644
index 0000000..deba98d
--- /dev/null
+++ b/hw/xen_domainbuild.c
@@ -0,0 +1,281 @@
+#include "xen_backend.h"
+#include "xen_domainbuild.h"
+#include "sysemu.h"
+#include "qemu-timer.h"
+
+#include <xenguest.h>
+
+/* temporary */
+static const char qemu_uuid[] = "f0c9d298-3dd9-4c20-8c90-0205ac932241";
+
+static int xenstore_domain_mkdir(char *path)
+{
+    struct xs_permissions perms = {
+       .id    = xen_domid,
+       .perms = XS_PERM_WRITE,
+    };
+
+    if (!xs_mkdir(xenstore, 0, path)) {
+        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
+       return -1;
+    }
+    if (!xs_set_permissions(xenstore, 0, path, &perms, 1)) {
+        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+       return -1;
+    }
+    return 0;
+}
+
+static int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                                 const char *cmdline)
+{
+    char *dom, vm[256], path[256];
+    int i;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    snprintf(vm,  sizeof(vm),  "/vm/%s", qemu_uuid);
+
+    xenstore_domain_mkdir(dom);
+
+    xenstore_write_str(vm, "image/ostype",  "linux");
+    if (kernel)
+        xenstore_write_str(vm, "image/kernel",  kernel);
+    if (ramdisk)
+        xenstore_write_str(vm, "image/ramdisk", ramdisk);
+    if (cmdline)
+        xenstore_write_str(vm, "image/cmdline", cmdline);
+
+    /* name + id */
+    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_str(vm,  "uuid",   qemu_uuid);
+    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_int(dom, "domid",  xen_domid);
+    xenstore_write_str(dom, "vm",     vm);
+
+    /* memory */
+    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
+    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
+    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
+
+    /* cpus */
+    for (i = 0; i < smp_cpus; i++) {
+       snprintf(path, sizeof(path), "cpu/%d/availability",i);
+       xenstore_write_str(dom, path, "online");
+    }
+    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
+    xenstore_write_int(vm, "vcpus",       smp_cpus);
+
+    /* vnc password */
+    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
+
+    free(dom);
+    return 0;
+}
+
+static int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                                 int console_port, int console_mfn)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+
+    /* signal new domain */
+    xs_introduce_domain(xenstore,
+                        xen_domid,
+                        xenstore_mfn,
+                        xenstore_port);
+
+    /* xenstore */
+    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
+    xenstore_write_int(dom, "store/port",       xenstore_port);
+
+    /* console */
+    xenstore_write_str(dom, "console/type",     "ioemu");
+    xenstore_write_int(dom, "console/limit",    128 * 1024);
+    xenstore_write_int(dom, "console/ring-ref", console_mfn);
+    xenstore_write_int(dom, "console/port",     console_port);
+    xen_config_dev_console(0);
+
+    /* devices */
+    if (1 /* FIXME */) {
+       xen_config_dev_vfb(0, "vnc");
+       xen_config_dev_vkbd(0);
+    }
+
+    free(dom);
+    return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static QEMUTimer *xen_poll;
+
+/* check domain state once per second */
+static void xen_domain_poll(void *opaque)
+{
+    struct xc_dominfo info;
+    int rc;
+
+    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
+    if ((1 != rc) || (info.domid != xen_domid)) {
+        fprintf(stderr, "xen: domain %d is gone\n", xen_domid);
+        goto quit;
+    }
+    if (info.dying) {
+        fprintf(stderr, "xen: domain %d is dying (%s%s)\n", xen_domid,
+                info.crashed  ? "crashed"  : "",
+                info.shutdown ? "shutdown" : "");
+        goto quit;
+    }
+
+    qemu_mod_timer(xen_poll, qemu_get_clock(rt_clock) + 1000);
+    return;
+
+quit:
+    qemu_system_shutdown_request();
+    return;
+}
+
+static void xen_domain_watcher(void)
+{
+    int qemu_running = 1;
+    int fd[2], i, rc;
+    char byte;
+
+    pipe(fd);
+    if (0 != fork())
+        return; /* not child */
+
+    /* close all file handles, except stdio/out/err,
+     * our watch pipe and the xen interface handle */
+    for (i = 3; i < 256; i++) {
+        if (i == fd[0])
+            continue;
+        if (i == xen_xc)
+            continue;
+        close(i);
+    }
+
+    /* wait for qemu exiting */
+    while (qemu_running) {
+        rc = read(fd[0], &byte, 1);
+        switch (rc) {
+        case -1:
+            if (EINTR == errno)
+                continue;
+            fprintf(stderr, "%s: Huh? read error: %s\n", __FUNCTION__, 
strerror(errno));
+            qemu_running = 0;
+            break;
+        case 0:
+            /* EOF -> qemu exited */
+            qemu_running = 0;
+            break;
+        default:
+            fprintf(stderr, "%s: Huh? data on the watch pipe?\n", 
__FUNCTION__);
+            break;
+        }
+    }
+
+    /* cleanup */
+    fprintf(stderr, "%s: destroy domain %d\n", __FUNCTION__, xen_domid);
+    xc_domain_destroy(xen_xc, xen_domid);
+    _exit(0);
+}
+
+/* normal cleanup */
+static void xen_domain_cleanup(void)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    if (dom) {
+        xs_rm(xenstore, 0, dom);
+        free(dom);
+    }
+    xs_release_domain(xenstore, xen_domid);
+}
+
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline)
+{
+    uint32_t ssidref = 0;
+    uint32_t flags = 0;
+    xen_domain_handle_t uuid;
+    unsigned int xenstore_port = 0, console_port = 0;
+    unsigned long xenstore_mfn = 0, console_mfn = 0;
+    int rc, i, pos, val;
+
+    for (i = 0, pos = 0; i < 16; i++, pos += 2) {
+        if (i == 4 || i == 6 || i == 8 || i == 10) {
+            /* skip dashes */
+            if ('-' != qemu_uuid[pos]) {
+                fprintf(stderr, "xen: uuid parse error");
+                goto err;
+            }
+            pos++;
+        }
+        if (1 != sscanf(qemu_uuid+pos, "%02x", &val)) {
+            fprintf(stderr, "xen: uuid parse error");
+            goto err;
+        }
+        uuid[i] = val;
+    }
+
+    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_create() failed\n");
+        goto err;
+    }
+    fprintf(stderr, "xen: created domain %d\n", xen_domid);
+    atexit(xen_domain_cleanup);
+    xen_domain_watcher();
+
+    xenstore_domain_init1(kernel, ramdisk, cmdline);
+
+    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
+        goto err;
+    }
+
+    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
+        goto err;
+    }
+
+    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
+        goto err;
+    }
+
+    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+
+    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
+                        kernel, ramdisk, cmdline,
+                        0, flags,
+                        xenstore_port, &xenstore_mfn,
+                        console_port, &console_mfn);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_linux_build() failed\n");
+        goto err;
+    }
+
+    xenstore_domain_init2(xenstore_port, xenstore_mfn,
+                          console_port, console_mfn);
+
+    rc = xc_domain_unpause(xen_xc, xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
+        goto err;
+    }
+
+    xen_poll = qemu_new_timer(rt_clock, xen_domain_poll, NULL);
+    qemu_mod_timer(xen_poll, qemu_get_clock(rt_clock) + 1000);
+    return 0;
+
+err:
+    return -1;
+}
diff --git a/hw/xen_domainbuild.h b/hw/xen_domainbuild.h
new file mode 100644
index 0000000..21ee180
--- /dev/null
+++ b/hw/xen_domainbuild.h
@@ -0,0 +1,9 @@
+#ifndef QEMU_XEN_DOMAINBUILD_H
+#define QEMU_XEN_DOMAINBUILD_H 1
+
+#include "xen_common.h"
+
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline);
+
+#endif /* QEMU_XEN_DOMAINBUILD_H */
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 9f18742..8c9f3c1 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -27,6 +27,7 @@
 #include "console.h"
 
 #include "xen_backend.h"
+#include "xen_domainbuild.h"
 
 /* -------------------------------------------------------------------- */
 /* variables                                                            */
@@ -90,7 +91,9 @@ static int xen_init(void)
     return 0;
 }
 
-static int xen_init_pv(DisplayState *ds)
+static int xen_init_pv(const char *kernel_filename,
+                      const char *kernel_cmdline,
+                      const char *initrd_filename)
 {
     int rc;
 
@@ -98,6 +101,19 @@ static int xen_init_pv(DisplayState *ds)
     if (rc < 0)
         return rc;
 
+    if (xen_emulate) {
+        fprintf(stderr, "xen pv emulation not implemented yet\n");
+        return -1;
+    }
+
+    if (xen_domainbuild) {
+        if (xen_domain_build_pv(kernel_filename, initrd_filename,
+                                kernel_cmdline) < 0) {
+            fprintf(stderr, "xen pv domain creation failed\n");
+            return -1;
+        }
+    }
+
     /* xenbus backend drivers */
     xen_be_register("console", &xen_console_ops);
     xen_be_register("vkbd", &xen_kbdmouse_ops);
@@ -105,9 +121,6 @@ static int xen_init_pv(DisplayState *ds)
     xen_be_register("qdisk", &xen_blkdev_ops);
     xen_be_register("qnic", &xen_netdev_ops);
 
-    /* setup framebuffer */
-    xen_set_display(xen_domid, ds);
-
     return 0;
 }
 
@@ -147,19 +160,12 @@ static void xenpv_init(ram_addr_t ram_size, int 
vga_ram_size,
     CPUState *env;
     int index,i,rc;
 
-    rc = xen_init_pv(ds);
+    rc = xen_init_pv(kernel_filename, kernel_cmdline, initrd_filename);
     if (-1 == rc)
         goto err;
 
-    if (xen_emulate) {
-        fprintf(stderr, "xen pv emulation not implemented yet\n");
-        goto err;
-    }
-    if (xen_domainbuild) {
-        fprintf(stderr, "xen pv domain creation not implemented yet\n");
-        goto err;
-    }
-
+    /* setup framebuffer */
+    xen_set_display(xen_domid, ds);
     xen_init_vnc();
 
     /* create dummy cpu, halted */
-- 
1.5.5.1


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

<Prev in Thread] Current Thread [Next in Thread>