From d5fdb85e3d2c319603f87f3205689ed5659f621d Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Wed, 7 May 2014 13:43:37 +0000 Subject: xen: move Xen PV machine files to hw/xenpv Signed-off-by: Wei Liu Signed-off-by: Stefano Stabellini --- hw/i386/Makefile.objs | 2 +- hw/i386/xen_domainbuild.c | 299 --------------------------------------------- hw/i386/xen_domainbuild.h | 13 -- hw/i386/xen_machine_pv.c | 109 ----------------- hw/xenpv/Makefile.objs | 2 + hw/xenpv/xen_domainbuild.c | 299 +++++++++++++++++++++++++++++++++++++++++++++ hw/xenpv/xen_domainbuild.h | 13 ++ hw/xenpv/xen_machine_pv.c | 109 +++++++++++++++++ 8 files changed, 424 insertions(+), 422 deletions(-) delete mode 100644 hw/i386/xen_domainbuild.c delete mode 100644 hw/i386/xen_domainbuild.h delete mode 100644 hw/i386/xen_machine_pv.c create mode 100644 hw/xenpv/Makefile.objs create mode 100644 hw/xenpv/xen_domainbuild.c create mode 100644 hw/xenpv/xen_domainbuild.h create mode 100644 hw/xenpv/xen_machine_pv.c diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 3df1612651..f9899a3e83 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/ obj-y += multiboot.o smbios.o obj-y += pc.o pc_piix.o pc_q35.o obj-y += pc_sysfw.o -obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o +obj-$(CONFIG_XEN) += ../xenpv/ obj-y += kvmvapic.o obj-y += acpi-build.o diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c deleted file mode 100644 index c0ab7537df..0000000000 --- a/hw/i386/xen_domainbuild.c +++ /dev/null @@ -1,299 +0,0 @@ -#include -#include "hw/xen/xen_backend.h" -#include "xen_domainbuild.h" -#include "qemu/timer.h" -#include "qemu/log.h" - -#include - -static int xenstore_domain_mkdir(char *path) -{ - struct xs_permissions perms_ro[] = {{ - .id = 0, /* set owner: dom0 */ - },{ - .id = xen_domid, - .perms = XS_PERM_READ, - }}; - struct xs_permissions perms_rw[] = {{ - .id = 0, /* set owner: dom0 */ - },{ - .id = xen_domid, - .perms = XS_PERM_READ | XS_PERM_WRITE, - }}; - const char *writable[] = { "device", "control", "error", NULL }; - char subpath[256]; - int i; - - 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_ro, 2)) { - fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__); - return -1; - } - - for (i = 0; writable[i]; i++) { - snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]); - if (!xs_mkdir(xenstore, 0, subpath)) { - fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath); - return -1; - } - if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) { - fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__); - return -1; - } - } - return 0; -} - -int xenstore_domain_init1(const char *kernel, const char *ramdisk, - const char *cmdline) -{ - char *dom, uuid_string[42], vm[256], path[256]; - int i; - - snprintf(uuid_string, sizeof(uuid_string), UUID_FMT, - qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3], - qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7], - qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11], - qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]); - dom = xs_get_domain_path(xenstore, xen_domid); - snprintf(vm, sizeof(vm), "/vm/%s", uuid_string); - - 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", uuid_string); - 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; -} - -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); - - 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 ((rc != 1) || (info.domid != xen_domid)) { - qemu_log("xen: domain %d is gone\n", xen_domid); - goto quit; - } - if (info.dying) { - qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid, - info.crashed ? "crashed" : "", - info.shutdown ? "shutdown" : ""); - goto quit; - } - - timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); - return; - -quit: - qemu_system_shutdown_request(); -} - -static int xen_domain_watcher(void) -{ - int qemu_running = 1; - int fd[2], i, n, rc; - char byte; - - if (pipe(fd) != 0) { - qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno)); - return -1; - } - if (fork() != 0) - return 0; /* not child */ - - /* close all file handles, except stdio/out/err, - * our watch pipe and the xen interface handle */ - n = getdtablesize(); - for (i = 3; i < n; i++) { - if (i == fd[0]) - continue; - if (i == xc_fd(xen_xc)) { - continue; - } - close(i); - } - - /* ignore term signals */ - signal(SIGINT, SIG_IGN); - signal(SIGTERM, SIG_IGN); - - /* wait for qemu exiting */ - while (qemu_running) { - rc = read(fd[0], &byte, 1); - switch (rc) { - case -1: - if (errno == EINTR) - continue; - qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno)); - qemu_running = 0; - break; - case 0: - /* EOF -> qemu exited */ - qemu_running = 0; - break; - default: - qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__); - break; - } - } - - /* cleanup */ - qemu_log("%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; - - memcpy(uuid, qemu_uuid, sizeof(uuid)); - rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_create() failed\n"); - goto err; - } - qemu_log("xen: created domain %d\n", xen_domid); - atexit(xen_domain_cleanup); - if (xen_domain_watcher() == -1) { - goto err; - } - - 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; - } - -#if 0 - rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n"); - goto err; - } -#endif - - 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); - - qemu_log("xen: unpausing domain %d\n", xen_domid); - rc = xc_domain_unpause(xen_xc, xen_domid); - if (rc < 0) { - fprintf(stderr, "xen: xc_domain_unpause() failed\n"); - goto err; - } - - xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL); - timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); - return 0; - -err: - return -1; -} diff --git a/hw/i386/xen_domainbuild.h b/hw/i386/xen_domainbuild.h deleted file mode 100644 index 29a91ea7b1..0000000000 --- a/hw/i386/xen_domainbuild.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef QEMU_HW_XEN_DOMAINBUILD_H -#define QEMU_HW_XEN_DOMAINBUILD_H 1 - -#include "hw/xen/xen_common.h" - -int xenstore_domain_init1(const char *kernel, const char *ramdisk, - const char *cmdline); -int xenstore_domain_init2(int xenstore_port, int xenstore_mfn, - int console_port, int console_mfn); -int xen_domain_build_pv(const char *kernel, const char *ramdisk, - const char *cmdline); - -#endif /* QEMU_HW_XEN_DOMAINBUILD_H */ diff --git a/hw/i386/xen_machine_pv.c b/hw/i386/xen_machine_pv.c deleted file mode 100644 index 9adb57fc14..0000000000 --- a/hw/i386/xen_machine_pv.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * QEMU Xen PV Machine - * - * Copyright (c) 2007 Red Hat - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/hw.h" -#include "hw/boards.h" -#include "hw/xen/xen_backend.h" -#include "xen_domainbuild.h" -#include "sysemu/blockdev.h" - -static void xen_init_pv(QEMUMachineInitArgs *args) -{ - const char *kernel_filename = args->kernel_filename; - const char *kernel_cmdline = args->kernel_cmdline; - const char *initrd_filename = args->initrd_filename; - DriveInfo *dinfo; - int i; - - /* Initialize backend core & drivers */ - if (xen_be_init() != 0) { - fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__); - exit(1); - } - - switch (xen_mode) { - case XEN_ATTACH: - /* nothing to do, xend handles everything */ - break; - case XEN_CREATE: - if (xen_domain_build_pv(kernel_filename, initrd_filename, - kernel_cmdline) < 0) { - fprintf(stderr, "xen pv domain creation failed\n"); - exit(1); - } - break; - case XEN_EMULATE: - fprintf(stderr, "xen emulation not implemented (yet)\n"); - exit(1); - break; - } - - xen_be_register("console", &xen_console_ops); - xen_be_register("vkbd", &xen_kbdmouse_ops); - xen_be_register("vfb", &xen_framebuffer_ops); - xen_be_register("qdisk", &xen_blkdev_ops); - xen_be_register("qnic", &xen_netdev_ops); - - /* configure framebuffer */ - if (xenfb_enabled) { - xen_config_dev_vfb(0, "vnc"); - xen_config_dev_vkbd(0); - } - - /* configure disks */ - for (i = 0; i < 16; i++) { - dinfo = drive_get(IF_XEN, 0, i); - if (!dinfo) - continue; - xen_config_dev_blk(dinfo); - } - - /* configure nics */ - for (i = 0; i < nb_nics; i++) { - if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen")) - continue; - xen_config_dev_nic(nd_table + i); - } - - /* config cleanup hook */ - atexit(xen_config_cleanup); - - /* setup framebuffer */ - xen_init_display(xen_domid); -} - -static QEMUMachine xenpv_machine = { - .name = "xenpv", - .desc = "Xen Para-virtualized PC", - .init = xen_init_pv, - .max_cpus = 1, - .default_machine_opts = "accel=xen", -}; - -static void xenpv_machine_init(void) -{ - qemu_register_machine(&xenpv_machine); -} - -machine_init(xenpv_machine_init); diff --git a/hw/xenpv/Makefile.objs b/hw/xenpv/Makefile.objs new file mode 100644 index 0000000000..49f6e9e3c5 --- /dev/null +++ b/hw/xenpv/Makefile.objs @@ -0,0 +1,2 @@ +# Xen PV machine support +obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c new file mode 100644 index 0000000000..c0ab7537df --- /dev/null +++ b/hw/xenpv/xen_domainbuild.c @@ -0,0 +1,299 @@ +#include +#include "hw/xen/xen_backend.h" +#include "xen_domainbuild.h" +#include "qemu/timer.h" +#include "qemu/log.h" + +#include + +static int xenstore_domain_mkdir(char *path) +{ + struct xs_permissions perms_ro[] = {{ + .id = 0, /* set owner: dom0 */ + },{ + .id = xen_domid, + .perms = XS_PERM_READ, + }}; + struct xs_permissions perms_rw[] = {{ + .id = 0, /* set owner: dom0 */ + },{ + .id = xen_domid, + .perms = XS_PERM_READ | XS_PERM_WRITE, + }}; + const char *writable[] = { "device", "control", "error", NULL }; + char subpath[256]; + int i; + + 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_ro, 2)) { + fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__); + return -1; + } + + for (i = 0; writable[i]; i++) { + snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]); + if (!xs_mkdir(xenstore, 0, subpath)) { + fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath); + return -1; + } + if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) { + fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__); + return -1; + } + } + return 0; +} + +int xenstore_domain_init1(const char *kernel, const char *ramdisk, + const char *cmdline) +{ + char *dom, uuid_string[42], vm[256], path[256]; + int i; + + snprintf(uuid_string, sizeof(uuid_string), UUID_FMT, + qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3], + qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7], + qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11], + qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]); + dom = xs_get_domain_path(xenstore, xen_domid); + snprintf(vm, sizeof(vm), "/vm/%s", uuid_string); + + 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", uuid_string); + 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; +} + +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); + + 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 ((rc != 1) || (info.domid != xen_domid)) { + qemu_log("xen: domain %d is gone\n", xen_domid); + goto quit; + } + if (info.dying) { + qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid, + info.crashed ? "crashed" : "", + info.shutdown ? "shutdown" : ""); + goto quit; + } + + timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); + return; + +quit: + qemu_system_shutdown_request(); +} + +static int xen_domain_watcher(void) +{ + int qemu_running = 1; + int fd[2], i, n, rc; + char byte; + + if (pipe(fd) != 0) { + qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno)); + return -1; + } + if (fork() != 0) + return 0; /* not child */ + + /* close all file handles, except stdio/out/err, + * our watch pipe and the xen interface handle */ + n = getdtablesize(); + for (i = 3; i < n; i++) { + if (i == fd[0]) + continue; + if (i == xc_fd(xen_xc)) { + continue; + } + close(i); + } + + /* ignore term signals */ + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + + /* wait for qemu exiting */ + while (qemu_running) { + rc = read(fd[0], &byte, 1); + switch (rc) { + case -1: + if (errno == EINTR) + continue; + qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno)); + qemu_running = 0; + break; + case 0: + /* EOF -> qemu exited */ + qemu_running = 0; + break; + default: + qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__); + break; + } + } + + /* cleanup */ + qemu_log("%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; + + memcpy(uuid, qemu_uuid, sizeof(uuid)); + rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid); + if (rc < 0) { + fprintf(stderr, "xen: xc_domain_create() failed\n"); + goto err; + } + qemu_log("xen: created domain %d\n", xen_domid); + atexit(xen_domain_cleanup); + if (xen_domain_watcher() == -1) { + goto err; + } + + 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; + } + +#if 0 + rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256); + if (rc < 0) { + fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n"); + goto err; + } +#endif + + 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); + + qemu_log("xen: unpausing domain %d\n", xen_domid); + rc = xc_domain_unpause(xen_xc, xen_domid); + if (rc < 0) { + fprintf(stderr, "xen: xc_domain_unpause() failed\n"); + goto err; + } + + xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL); + timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); + return 0; + +err: + return -1; +} diff --git a/hw/xenpv/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h new file mode 100644 index 0000000000..29a91ea7b1 --- /dev/null +++ b/hw/xenpv/xen_domainbuild.h @@ -0,0 +1,13 @@ +#ifndef QEMU_HW_XEN_DOMAINBUILD_H +#define QEMU_HW_XEN_DOMAINBUILD_H 1 + +#include "hw/xen/xen_common.h" + +int xenstore_domain_init1(const char *kernel, const char *ramdisk, + const char *cmdline); +int xenstore_domain_init2(int xenstore_port, int xenstore_mfn, + int console_port, int console_mfn); +int xen_domain_build_pv(const char *kernel, const char *ramdisk, + const char *cmdline); + +#endif /* QEMU_HW_XEN_DOMAINBUILD_H */ diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c new file mode 100644 index 0000000000..9adb57fc14 --- /dev/null +++ b/hw/xenpv/xen_machine_pv.c @@ -0,0 +1,109 @@ +/* + * QEMU Xen PV Machine + * + * Copyright (c) 2007 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/hw.h" +#include "hw/boards.h" +#include "hw/xen/xen_backend.h" +#include "xen_domainbuild.h" +#include "sysemu/blockdev.h" + +static void xen_init_pv(QEMUMachineInitArgs *args) +{ + const char *kernel_filename = args->kernel_filename; + const char *kernel_cmdline = args->kernel_cmdline; + const char *initrd_filename = args->initrd_filename; + DriveInfo *dinfo; + int i; + + /* Initialize backend core & drivers */ + if (xen_be_init() != 0) { + fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__); + exit(1); + } + + switch (xen_mode) { + case XEN_ATTACH: + /* nothing to do, xend handles everything */ + break; + case XEN_CREATE: + if (xen_domain_build_pv(kernel_filename, initrd_filename, + kernel_cmdline) < 0) { + fprintf(stderr, "xen pv domain creation failed\n"); + exit(1); + } + break; + case XEN_EMULATE: + fprintf(stderr, "xen emulation not implemented (yet)\n"); + exit(1); + break; + } + + xen_be_register("console", &xen_console_ops); + xen_be_register("vkbd", &xen_kbdmouse_ops); + xen_be_register("vfb", &xen_framebuffer_ops); + xen_be_register("qdisk", &xen_blkdev_ops); + xen_be_register("qnic", &xen_netdev_ops); + + /* configure framebuffer */ + if (xenfb_enabled) { + xen_config_dev_vfb(0, "vnc"); + xen_config_dev_vkbd(0); + } + + /* configure disks */ + for (i = 0; i < 16; i++) { + dinfo = drive_get(IF_XEN, 0, i); + if (!dinfo) + continue; + xen_config_dev_blk(dinfo); + } + + /* configure nics */ + for (i = 0; i < nb_nics; i++) { + if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen")) + continue; + xen_config_dev_nic(nd_table + i); + } + + /* config cleanup hook */ + atexit(xen_config_cleanup); + + /* setup framebuffer */ + xen_init_display(xen_domid); +} + +static QEMUMachine xenpv_machine = { + .name = "xenpv", + .desc = "Xen Para-virtualized PC", + .init = xen_init_pv, + .max_cpus = 1, + .default_machine_opts = "accel=xen", +}; + +static void xenpv_machine_init(void) +{ + qemu_register_machine(&xenpv_machine); +} + +machine_init(xenpv_machine_init); -- cgit v1.2.3