Xenner uses its own special PV device to communicate between qemu and the guest xenner kernel. This patch implements that device.
Signed-off-by: Alexander Graf <ag...@suse.de> --- hw/xenner_emudev.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ hw/xenner_emudev.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 0 deletions(-) create mode 100644 hw/xenner_emudev.c create mode 100644 hw/xenner_emudev.h diff --git a/hw/xenner_emudev.c b/hw/xenner_emudev.c new file mode 100644 index 0000000..dea617e --- /dev/null +++ b/hw/xenner_emudev.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) Red Hat 2007 + * Copyright (C) Novell Inc. 2010 + * + * Author(s): Gerd Hoffmann <kra...@redhat.com> + * Alexander Graf <ag...@suse.de> + * + * Xenner communication device + * + * 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 <inttypes.h> + +#include "xenner_emudev.h" + +void emudev_write_entry(struct emudev_state *e, uint32_t value) +{ + e->entry = value; +} + +void emudev_write_value(struct emudev_state *e, uint32_t value) +{ + uint16_t type, index; + int high_32; + + type = e->entry >> 16; + high_32 = type & EMUDEV_CONF_HIGH_32; + type &= ~EMUDEV_CONF_HIGH_32; + index = e->entry & 0xffff; + switch (type) { + case EMUDEV_CONF_GRANT_TABLE_PFNS: + if (index < EMUDEV_CONF_GRANT_TABLE_COUNT) + e->gnttab[index] = value; + break; + case EMUDEV_CONF_EVTCHN_TO_PIN: + if (index < EMUDEV_CONF_EVTCHN_TO_PIN_COUNT) + e->evtchn[index] = value; + break; + case EMUDEV_CONF_COMMAND_RESULT: + if (index < EMUDEV_CONF_COMMAND_RESULT_COUNT) + e->result[index] = value; + break; + default: + if (type >= EMUDEV_CONF_SIMPLE_COUNT) { + break; + } + if (high_32) { + e->config[type] = (e->config[type] & 0x00000000ffffffffULL) + | ((uint64_t)value << 32); + } else { + e->config[type] = (e->config[type] & 0xffffffff00000000ULL) + | ((uint64_t)value); + } + break; + } +} + +uint32_t emudev_read_value(struct emudev_state *e) +{ + uint16_t type, index; + int high_32; + uint64_t r = -1; + + type = e->entry >> 16; + high_32 = type & EMUDEV_CONF_HIGH_32; + type &= ~EMUDEV_CONF_HIGH_32; + index = e->entry & 0xffff; + switch (type) { + case EMUDEV_CONF_GRANT_TABLE_PFNS: + if (index < EMUDEV_CONF_GRANT_TABLE_COUNT) { + r = e->gnttab[index]; + } + break; + case EMUDEV_CONF_EVTCHN_TO_PIN: + if (index < EMUDEV_CONF_EVTCHN_TO_PIN_COUNT) { + r = e->evtchn[index]; + } + break; + case EMUDEV_CONF_COMMAND_RESULT: + if (index < EMUDEV_CONF_COMMAND_RESULT_COUNT) { + r = e->result[index]; + } + break; + default: + if (type < EMUDEV_CONF_SIMPLE_COUNT) { + r = e->config[type]; + } + break; + } + + if (high_32) { + return (uint32_t)(r >> 32); + } + + return (uint32_t)r; +} diff --git a/hw/xenner_emudev.h b/hw/xenner_emudev.h new file mode 100644 index 0000000..e6b8676 --- /dev/null +++ b/hw/xenner_emudev.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) Red Hat 2007 + * Copyright (C) Novell Inc. 2010 + * + * Author(s): Gerd Hoffmann <kra...@redhat.com> + * Alexander Graf <ag...@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/>. + */ + +#ifndef __XENNER_EMUDEV_H__ +#define __XENNER_EMUDEV_H__ 1 + +/* + * I/O ports for the virtual emu device + * - CONF_ENTRY (write) + * bits 31 .. 16 -- config type + * bits 15 .. 0 -- config index + * - CONF_VALUE (read/write) + * 32bit config value + * - COMMAND (write) + * bits 32 .. 16 -- command + * bits 15 .. 0 -- argument + */ +#define EMUDEV_REG_BASE (0xe0) +#define EMUDEV_REG_CONF_ENTRY (EMUDEV_REG_BASE) +#define EMUDEV_REG_CONF_VALUE (EMUDEV_REG_BASE+4) +#define EMUDEV_REG_COMMAND (EMUDEV_REG_BASE+8) +#define EMUDEV_REG_RESERVED (EMUDEV_REG_BASE+12) + +/* simple entries, read */ +#define EMUDEV_CONF_DEBUG_LEVEL 0x00 +#define EMUDEV_CONF_EMU_START_PFN 0x01 +#define EMUDEV_CONF_EMU_PAGE_COUNT 0x02 +#define EMUDEV_CONF_M2P_START_PFN 0x03 +#define EMUDEV_CONF_M2P_PAGE_COUNT 0x04 +#define EMUDEV_CONF_GUEST_START_PFN 0x05 +#define EMUDEV_CONF_GUEST_PAGE_COUNT 0x06 +#define EMUDEV_CONF_TOTAL_PAGE_COUNT 0x07 +#define EMUDEV_CONF_NR_VCPUS 0x08 +#define EMUDEV_CONF_HVM_XENSTORE_PFN 0x09 +#define EMUDEV_CONF_HVM_XENSTORE_EVTCHN 0x0a +#define EMUDEV_CONF_MFN_CONSOLE 0x0b +#define EMUDEV_CONF_MFN_XENSTORE 0x0c +#define EMUDEV_CONF_PFN_START_INFO 0x0d +#define EMUDEV_CONF_PV_VIRT_ENTRY 0x10 +#define EMUDEV_CONF_PV_VIRT_BASE 0x11 +#define EMUDEV_CONF_HYPERCALL_PAGE 0x12 +#define EMUDEV_CONF_EVTCH_CONSOLE 0x13 +#define EMUDEV_CONF_EVTCH_XENSTORE 0x14 +#define EMUDEV_CONF_PFN_INIT_PT 0x15 +#define EMUDEV_CONF_PFN_CMDLINE 0x16 +#define EMUDEV_CONF_PFN_INITRD 0x17 +#define EMUDEV_CONF_INITRD_LEN 0x18 +#define EMUDEV_CONF_PFN_MFN_LIST 0x19 +/* simple entries, write */ +#define EMUDEV_CONF_BOOT_CTXT_PFN 0x40 +#define EMUDEV_CONF_NEXT_SECONDARY_VCPU 0x42 +#define EMUDEV_CONF_HVM_CALLBACK_IRQ 0x43 +#define EMUDEV_CONF_VMINFO_PFN 0x70 /* temporary */ +/* simple count */ +#define EMUDEV_CONF_SIMPLE_COUNT 0x80 +/* high dword marker */ +#define EMUDEV_CONF_HIGH_32 0x8000 + +/* indexed config entries */ +#define EMUDEV_CONF_GRANT_TABLE_PFNS 0x80 +#define EMUDEV_CONF_GRANT_TABLE_COUNT 16 +#define EMUDEV_CONF_EVTCHN_TO_PIN 0x81 +#define EMUDEV_CONF_EVTCHN_TO_PIN_COUNT 64 +#define EMUDEV_CONF_COMMAND_RESULT 0x82 +#define EMUDEV_CONF_COMMAND_RESULT_COUNT 64 + +/* commands */ +#define EMUDEV_CMD_NOP 1 +#define EMUDEV_CMD_WRITE_CHAR 2 +#define EMUDEV_CMD_CONFIGURATION_DONE 3 +#define EMUDEV_CMD_EVTCHN_ALLOC 4 +#define EMUDEV_CMD_EVTCHN_SEND 5 +#define EMUDEV_CMD_INIT_SECONDARY_VCPU 6 +#define EMUDEV_CMD_GUEST_SHUTDOWN 7 +#define EMUDEV_CMD_EVTCHN_CLOSE 8 + +/* --------- host side bits --------- */ + +struct emudev_state { + uint32_t entry; + uint64_t config[EMUDEV_CONF_SIMPLE_COUNT]; + uint32_t gnttab[EMUDEV_CONF_GRANT_TABLE_COUNT]; + uint32_t evtchn[EMUDEV_CONF_EVTCHN_TO_PIN_COUNT]; + uint32_t result[EMUDEV_CONF_COMMAND_RESULT_COUNT]; +}; + +void emudev_write_entry(struct emudev_state *e, uint32_t value); +void emudev_write_value(struct emudev_state *e, uint32_t value); +uint32_t emudev_read_value(struct emudev_state *e); + +#endif /* __XENNER_EMUDEV_H__ */ -- 1.6.0.2