From patchwork Mon Nov 1 15:01:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 69775 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E82F31007D3 for ; Tue, 2 Nov 2010 02:07:50 +1100 (EST) Received: from localhost ([127.0.0.1]:44291 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PCvyd-00062y-Qz for incoming@patchwork.ozlabs.org; Mon, 01 Nov 2010 11:07:15 -0400 Received: from [140.186.70.92] (port=52810 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PCvtq-0003eJ-Hj for qemu-devel@nongnu.org; Mon, 01 Nov 2010 11:02:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PCvtX-0000hV-6f for qemu-devel@nongnu.org; Mon, 01 Nov 2010 11:02:08 -0400 Received: from cantor.suse.de ([195.135.220.2]:60266 helo=mx1.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PCvtW-0000gA-PH for qemu-devel@nongnu.org; Mon, 01 Nov 2010 11:01:59 -0400 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id CAD9494A1C; Mon, 1 Nov 2010 16:01:54 +0100 (CET) From: Alexander Graf To: qemu-devel Developers Date: Mon, 1 Nov 2010 16:01:46 +0100 Message-Id: <1288623713-28062-34-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1288623713-28062-1-git-send-email-agraf@suse.de> References: <1288623713-28062-1-git-send-email-agraf@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 33/40] xenner: core X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds generic xenner functionality to qemu. Signed-off-by: Alexander Graf --- 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 + * Alexander Graf + * + * 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 . + */ + +#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 + * Alexander Graf + * + * 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 . + */ + +#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; +}