Message ID | 1288623713-28062-34-git-send-email-agraf@suse.de |
---|---|
State | New |
Headers | show |
On Mon, 1 Nov 2010, Alexander Graf wrote: > This patch adds generic xenner functionality to qemu. > > Signed-off-by: Alexander Graf <agraf@suse.de> > --- > hw/xenner.h | 52 +++++++++++++ > hw/xenner_core.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 276 insertions(+), 0 deletions(-) > create mode 100644 hw/xenner.h > create mode 100644 hw/xenner_core.c > > diff --git a/hw/xenner.h b/hw/xenner.h > new file mode 100644 > index 0000000..241dc4c > --- /dev/null > +++ b/hw/xenner.h > @@ -0,0 +1,52 @@ > +/* > + * Copyright (C) Red Hat 2007 > + * Copyright (C) Novell Inc. 2010 > + * > + * Author(s): Gerd Hoffmann <kraxel@redhat.com> > + * Alexander Graf <agraf@suse.de> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; under version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "qemu-common.h" > + > +/* xenner_core.c */ > +struct xenner_emu_file { > + const char *filename; > + int pages; > + void *blob; > +}; > + > +void *xenner_mfn_to_ptr(xen_pfn_t pfn); > +void *xenner_get_grant_table(int index); > +void *xenner_get_vminfo(void); > +uint64_t xenner_get_config(uint32_t reg); > +uint32_t xenner_get_evtchn_pin(uint32_t reg); > +void xenner_set_config(uint32_t reg, uint64_t value); > +int xenner_load_emu_file(struct xenner_emu_file *f); > +int xenner_guest_evtchn_alloc(void); > +int xenner_guest_evtchn_release(int port); > +int xenner_core_init(int evt); > + > +/* xenner_guest_store.c */ > +void xenner_guest_store_setup(uint64_t guest_mfn, evtchn_port_t guest_evtchn); > +void xenner_guest_store_reset(void); > + > +/* xenner_pv.c */ > +int xenner_init_pv(const char *kernel_filename, > + const char *kernel_cmdline, > + const char *initrd_filename); > + > +int xenner_domain_build_pv(const char *kernel, > + const char *initrd, > + const char *cmdline); > diff --git a/hw/xenner_core.c b/hw/xenner_core.c > new file mode 100644 > index 0000000..53a9a75 > --- /dev/null > +++ b/hw/xenner_core.c > @@ -0,0 +1,224 @@ > +/* > + * Copyright (C) Red Hat 2007 > + * Copyright (C) Novell Inc. 2010 > + * > + * Author(s): Gerd Hoffmann <kraxel@redhat.com> > + * Alexander Graf <agraf@suse.de> > + * > + * Xenner Core > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; under version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "hw.h" > +#include "isa.h" > +#include "sysemu.h" > +#include "xen.h" > +#include "xen_interfaces.h" > +#include "xenner.h" > +#include "xenner_emudev.h" > +#include "loader.h" > + > +/* #define DEBUG */ > + > +static int guest_evtchndev; > +static struct emudev_state xen_emudev; > + > +/* ------------------------------------------------------------- */ > + > +static void do_emudev_command(uint16_t cmd, uint16_t arg) > +{ > + switch (cmd) { > + case EMUDEV_CMD_NOP: > + /* nop vmexit */ > + break; > + case EMUDEV_CMD_WRITE_CHAR: > +#ifdef DEBUG > + fprintf(stderr, "%c", arg); > +#endif > + break; > + case EMUDEV_CMD_CONFIGURATION_DONE: > + /* emu finisted initial EMUDEV_CONF_* setup */ > + break; > + case EMUDEV_CMD_EVTCHN_ALLOC: > + if (arg < EMUDEV_CONF_COMMAND_RESULT_COUNT) { > + xen_emudev.result[arg] = xenner_guest_evtchn_alloc(); > + } > + break; > + case EMUDEV_CMD_EVTCHN_SEND: > + xc_evtchn.notify(guest_evtchndev, arg); > + break; > + case EMUDEV_CMD_GUEST_SHUTDOWN: > + switch (arg) { > + case SHUTDOWN_poweroff: > + fprintf(stderr, "xenner emudev: guest poweroff -> powerdown\n"); > + qemu_system_powerdown_request(); > + break; > + case SHUTDOWN_reboot: > + fprintf(stderr, "xenner emudev: guest reboot -> reset\n"); > + qemu_system_reset_request(); > + vm_stop(0); > + break; > + case SHUTDOWN_suspend: > + fprintf(stderr, "xenner emudev: guest suspend -> stop vm\n"); > + vm_stop(0); > + break; > + case SHUTDOWN_crash: > + fprintf(stderr, "xenner emudev: guest crash -> reset\n"); > + vm_stop(0); > + qemu_system_reset_request(); > + break; > + } > + break; > + default: > + fprintf(stderr, "xenner emudev: cmd 0x%04x arg 0x%04x\n", cmd, arg); > + } > +} > + > +static void xenner_port_write(void *opaque, uint32_t addr, uint32_t val) > +{ > + uint16_t cmd, arg; > + > + switch (addr) { > + case EMUDEV_REG_CONF_ENTRY: > + emudev_write_entry(&xen_emudev, val); > + break; > + case EMUDEV_REG_CONF_VALUE: > + emudev_write_value(&xen_emudev, val); > + break; > + case EMUDEV_REG_COMMAND: > + cmd = val >> 16; > + arg = val & 0xffff; > + do_emudev_command(cmd, arg); > + break; > + default: > + fprintf(stderr, "io: %s, addr 0x%" PRIx16 " value 0x%" PRIx32 "\n", > + __FUNCTION__, addr, val); > + break; > + } > +} > + > +static uint32_t xenner_port_read(void *opaque, uint32_t addr) > +{ > + uint32_t val; > + > + switch (addr) { > + case EMUDEV_REG_CONF_VALUE: > + val = emudev_read_value(&xen_emudev); > + break; > + default: > + fprintf(stderr, "io: %s, addr 0x%" PRIx16 "\n", __FUNCTION__, addr); > + val = 0xffffffff; > + break; > + } > + return val; > +} > + > +/* ------------------------------------------------------------- */ > + > +void *xenner_mfn_to_ptr(xen_pfn_t pfn) > +{ > + ram_addr_t offset; > + > + offset = cpu_get_physical_page_desc(pfn << PAGE_SHIFT); > + return qemu_get_ram_ptr(offset); > +} > + > +void *xenner_get_grant_table(int index) > +{ > + uint32_t pfn; > + > + if (index > EMUDEV_CONF_GRANT_TABLE_COUNT) { > + return NULL; > + } > + pfn = xen_emudev.gnttab[index]; > + if (!pfn) { > + return NULL; > + } > + return xenner_mfn_to_ptr(pfn); > +} > + > +void *xenner_get_vminfo(void) > +{ > + uint32_t pfn; > + > + pfn = xen_emudev.config[EMUDEV_CONF_VMINFO_PFN]; > + if (!pfn) { > + return NULL; > + } > + return xenner_mfn_to_ptr(pfn); > +} > + > +uint64_t xenner_get_config(uint32_t reg) > +{ > + return xen_emudev.config[reg]; > +} > + > +uint32_t xenner_get_evtchn_pin(uint32_t reg) > +{ > + return xen_emudev.evtchn[reg]; > +} > + > +void xenner_set_config(uint32_t reg, uint64_t value) > +{ > + xen_emudev.config[reg] = value; > +} > + > +/* ------------------------------------------------------------- */ > + > +int xenner_load_emu_file(struct xenner_emu_file *f) > +{ > + int r; > + > + /* Fetch size */ > + r = get_image_size(f->filename); > + if (r <= 0) { > + fprintf(stderr, "can't find %s\n", f->filename); > + return -1; > + } > + > + /* Allocate memory */ > + f->pages = (r + PAGE_SIZE - 1) / PAGE_SIZE; > + f->blob = qemu_mallocz(f->pages * PAGE_SIZE); > + if (!f->blob) { > + return -1; > + } qemu_mallocz doesn't return NULL > + > + /* Load image */ > + r = load_image(f->filename, f->blob); > + > + return r; > +} > + > +/* ------------------------------------------------------------- */ > + > +int xenner_guest_evtchn_alloc(void) > +{ > + return xc_evtchn.bind_unbound_port(guest_evtchndev, 0); > +} > + > +int xenner_guest_evtchn_release(int port) > +{ > + return xc_evtchn.unbind(guest_evtchndev, port); > +} > + > +int xenner_core_init(int evt) > +{ > + guest_evtchndev = evt; > + xc_evtchn.domid(guest_evtchndev, xen_domid); > + > + register_ioport_write(EMUDEV_REG_BASE, 16, 4, xenner_port_write, NULL); > + register_ioport_read(EMUDEV_REG_BASE, 16, 4, xenner_port_read, NULL); > + > + return 0; > +} >
diff --git a/hw/xenner.h b/hw/xenner.h new file mode 100644 index 0000000..241dc4c --- /dev/null +++ b/hw/xenner.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) Red Hat 2007 + * Copyright (C) Novell Inc. 2010 + * + * Author(s): Gerd Hoffmann <kraxel@redhat.com> + * Alexander Graf <agraf@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu-common.h" + +/* xenner_core.c */ +struct xenner_emu_file { + const char *filename; + int pages; + void *blob; +}; + +void *xenner_mfn_to_ptr(xen_pfn_t pfn); +void *xenner_get_grant_table(int index); +void *xenner_get_vminfo(void); +uint64_t xenner_get_config(uint32_t reg); +uint32_t xenner_get_evtchn_pin(uint32_t reg); +void xenner_set_config(uint32_t reg, uint64_t value); +int xenner_load_emu_file(struct xenner_emu_file *f); +int xenner_guest_evtchn_alloc(void); +int xenner_guest_evtchn_release(int port); +int xenner_core_init(int evt); + +/* xenner_guest_store.c */ +void xenner_guest_store_setup(uint64_t guest_mfn, evtchn_port_t guest_evtchn); +void xenner_guest_store_reset(void); + +/* xenner_pv.c */ +int xenner_init_pv(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename); + +int xenner_domain_build_pv(const char *kernel, + const char *initrd, + const char *cmdline); diff --git a/hw/xenner_core.c b/hw/xenner_core.c new file mode 100644 index 0000000..53a9a75 --- /dev/null +++ b/hw/xenner_core.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) Red Hat 2007 + * Copyright (C) Novell Inc. 2010 + * + * Author(s): Gerd Hoffmann <kraxel@redhat.com> + * Alexander Graf <agraf@suse.de> + * + * Xenner Core + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "hw.h" +#include "isa.h" +#include "sysemu.h" +#include "xen.h" +#include "xen_interfaces.h" +#include "xenner.h" +#include "xenner_emudev.h" +#include "loader.h" + +/* #define DEBUG */ + +static int guest_evtchndev; +static struct emudev_state xen_emudev; + +/* ------------------------------------------------------------- */ + +static void do_emudev_command(uint16_t cmd, uint16_t arg) +{ + switch (cmd) { + case EMUDEV_CMD_NOP: + /* nop vmexit */ + break; + case EMUDEV_CMD_WRITE_CHAR: +#ifdef DEBUG + fprintf(stderr, "%c", arg); +#endif + break; + case EMUDEV_CMD_CONFIGURATION_DONE: + /* emu finisted initial EMUDEV_CONF_* setup */ + break; + case EMUDEV_CMD_EVTCHN_ALLOC: + if (arg < EMUDEV_CONF_COMMAND_RESULT_COUNT) { + xen_emudev.result[arg] = xenner_guest_evtchn_alloc(); + } + break; + case EMUDEV_CMD_EVTCHN_SEND: + xc_evtchn.notify(guest_evtchndev, arg); + break; + case EMUDEV_CMD_GUEST_SHUTDOWN: + switch (arg) { + case SHUTDOWN_poweroff: + fprintf(stderr, "xenner emudev: guest poweroff -> powerdown\n"); + qemu_system_powerdown_request(); + break; + case SHUTDOWN_reboot: + fprintf(stderr, "xenner emudev: guest reboot -> reset\n"); + qemu_system_reset_request(); + vm_stop(0); + break; + case SHUTDOWN_suspend: + fprintf(stderr, "xenner emudev: guest suspend -> stop vm\n"); + vm_stop(0); + break; + case SHUTDOWN_crash: + fprintf(stderr, "xenner emudev: guest crash -> reset\n"); + vm_stop(0); + qemu_system_reset_request(); + break; + } + break; + default: + fprintf(stderr, "xenner emudev: cmd 0x%04x arg 0x%04x\n", cmd, arg); + } +} + +static void xenner_port_write(void *opaque, uint32_t addr, uint32_t val) +{ + uint16_t cmd, arg; + + switch (addr) { + case EMUDEV_REG_CONF_ENTRY: + emudev_write_entry(&xen_emudev, val); + break; + case EMUDEV_REG_CONF_VALUE: + emudev_write_value(&xen_emudev, val); + break; + case EMUDEV_REG_COMMAND: + cmd = val >> 16; + arg = val & 0xffff; + do_emudev_command(cmd, arg); + break; + default: + fprintf(stderr, "io: %s, addr 0x%" PRIx16 " value 0x%" PRIx32 "\n", + __FUNCTION__, addr, val); + break; + } +} + +static uint32_t xenner_port_read(void *opaque, uint32_t addr) +{ + uint32_t val; + + switch (addr) { + case EMUDEV_REG_CONF_VALUE: + val = emudev_read_value(&xen_emudev); + break; + default: + fprintf(stderr, "io: %s, addr 0x%" PRIx16 "\n", __FUNCTION__, addr); + val = 0xffffffff; + break; + } + return val; +} + +/* ------------------------------------------------------------- */ + +void *xenner_mfn_to_ptr(xen_pfn_t pfn) +{ + ram_addr_t offset; + + offset = cpu_get_physical_page_desc(pfn << PAGE_SHIFT); + return qemu_get_ram_ptr(offset); +} + +void *xenner_get_grant_table(int index) +{ + uint32_t pfn; + + if (index > EMUDEV_CONF_GRANT_TABLE_COUNT) { + return NULL; + } + pfn = xen_emudev.gnttab[index]; + if (!pfn) { + return NULL; + } + return xenner_mfn_to_ptr(pfn); +} + +void *xenner_get_vminfo(void) +{ + uint32_t pfn; + + pfn = xen_emudev.config[EMUDEV_CONF_VMINFO_PFN]; + if (!pfn) { + return NULL; + } + return xenner_mfn_to_ptr(pfn); +} + +uint64_t xenner_get_config(uint32_t reg) +{ + return xen_emudev.config[reg]; +} + +uint32_t xenner_get_evtchn_pin(uint32_t reg) +{ + return xen_emudev.evtchn[reg]; +} + +void xenner_set_config(uint32_t reg, uint64_t value) +{ + xen_emudev.config[reg] = value; +} + +/* ------------------------------------------------------------- */ + +int xenner_load_emu_file(struct xenner_emu_file *f) +{ + int r; + + /* Fetch size */ + r = get_image_size(f->filename); + if (r <= 0) { + fprintf(stderr, "can't find %s\n", f->filename); + return -1; + } + + /* Allocate memory */ + f->pages = (r + PAGE_SIZE - 1) / PAGE_SIZE; + f->blob = qemu_mallocz(f->pages * PAGE_SIZE); + if (!f->blob) { + return -1; + } + + /* Load image */ + r = load_image(f->filename, f->blob); + + return r; +} + +/* ------------------------------------------------------------- */ + +int xenner_guest_evtchn_alloc(void) +{ + return xc_evtchn.bind_unbound_port(guest_evtchndev, 0); +} + +int xenner_guest_evtchn_release(int port) +{ + return xc_evtchn.unbind(guest_evtchndev, port); +} + +int xenner_core_init(int evt) +{ + guest_evtchndev = evt; + xc_evtchn.domid(guest_evtchndev, xen_domid); + + register_ioport_write(EMUDEV_REG_BASE, 16, 4, xenner_port_write, NULL); + register_ioport_read(EMUDEV_REG_BASE, 16, 4, xenner_port_read, NULL); + + return 0; +}
This patch adds generic xenner functionality to qemu. Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/xenner.h | 52 +++++++++++++ hw/xenner_core.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 276 insertions(+), 0 deletions(-) create mode 100644 hw/xenner.h create mode 100644 hw/xenner_core.c