diff options
246 files changed, 5032 insertions, 5952 deletions
@@ -109,4 +109,3 @@ cscope.* tags TAGS *~ -/tests/qemu-iotests/common.env diff --git a/block/archipelago.c b/block/archipelago.c index a8114b5..855655c 100644 --- a/block/archipelago.c +++ b/block/archipelago.c @@ -291,7 +291,7 @@ static int qemu_archipelago_init(BDRVArchipelagoState *s) ret = qemu_archipelago_xseg_init(s); if (ret < 0) { - error_report("Cannot initialize XSEG. Aborting...\n"); + error_report("Cannot initialize XSEG. Aborting..."); goto err_exit; } @@ -645,7 +645,7 @@ static int qemu_archipelago_create_volume(Error **errp, const char *volname, target = xseg_get_target(xseg, req); if (!target) { - error_setg(errp, "Cannot get XSEG target.\n"); + error_setg(errp, "Cannot get XSEG target."); goto err_exit; } memcpy(target, volname, targetlen); @@ -889,7 +889,7 @@ static BlockAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs, return &aio_cb->common; err_exit: - error_report("qemu_archipelago_aio_rw(): I/O Error\n"); + error_report("qemu_archipelago_aio_rw(): I/O Error"); qemu_aio_unref(aio_cb); return NULL; } diff --git a/block/nbd.c b/block/nbd.c index 697c021..6634a69 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -274,6 +274,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, */ sock = nbd_establish_connection(bs, errp); if (sock < 0) { + g_free(export); return sock; } @@ -1474,6 +1474,7 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename, uint32_t l; CPUState *cpu; uint8_t buf[1024]; + int64_t orig_addr = addr, orig_size = size; if (!has_cpu) { cpu_index = 0; @@ -1497,7 +1498,8 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename, if (l > size) l = size; if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) { - error_setg(errp, "Invalid addr 0x%016" PRIx64 "specified", addr); + error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64 + " specified", orig_addr, orig_size); goto exit; } if (fwrite(buf, 1, l, f) != l) { diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 0b8ce4b..6a74e00 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -26,7 +26,6 @@ CONFIG_APPLESMC=y CONFIG_I8259=y CONFIG_PFLASH_CFI01=y CONFIG_TPM_TIS=$(CONFIG_TPM) -CONFIG_PCI_HOTPLUG_OLD=y CONFIG_MC146818RTC=y CONFIG_PAM=y CONFIG_PCI_PIIX=y diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 4b60e69..4befde3 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -38,7 +38,6 @@ CONFIG_PTIMER=y CONFIG_I8259=y CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y -CONFIG_OPENPIC=y CONFIG_PREP=y CONFIG_MAC=y CONFIG_E500=y diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index de71e41..ab62cc7 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -38,7 +38,6 @@ CONFIG_PTIMER=y CONFIG_I8259=y CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y -CONFIG_OPENPIC=y CONFIG_PSERIES=y CONFIG_PREP=y CONFIG_MAC=y @@ -51,11 +50,5 @@ CONFIG_LIBDECNUMBER=y CONFIG_XICS=$(CONFIG_PSERIES) CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM)) # For PReP -CONFIG_I82378=y -CONFIG_I8259=y -CONFIG_I8254=y -CONFIG_PCSPK=y -CONFIG_I82374=y -CONFIG_I8257=y CONFIG_MC146818RTC=y CONFIG_ISA_TESTDEV=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index a1b3d5f..54acc4d 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -13,5 +13,4 @@ CONFIG_PTIMER=y CONFIG_I8259=y CONFIG_XILINX=y CONFIG_XILINX_ETHLITE=y -CONFIG_OPENPIC=y CONFIG_LIBDECNUMBER=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 6add04a..46b87dd 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -26,7 +26,6 @@ CONFIG_APPLESMC=y CONFIG_I8259=y CONFIG_PFLASH_CFI01=y CONFIG_TPM_TIS=$(CONFIG_TPM) -CONFIG_PCI_HOTPLUG_OLD=y CONFIG_MC146818RTC=y CONFIG_PAM=y CONFIG_PCI_PIIX=y diff --git a/device-hotplug.c b/device-hotplug.c index 833d874..68b9496 100644 --- a/device-hotplug.c +++ b/device-hotplug.c @@ -30,7 +30,7 @@ #include "sysemu/sysemu.h" #include "monitor/monitor.h" -DriveInfo *add_init_drive(const char *optstr) +static DriveInfo *add_init_drive(const char *optstr) { DriveInfo *dinfo; QemuOpts *opts; @@ -69,9 +69,8 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict) monitor_printf(mon, "OK\n"); break; default: - if (pci_drive_hot_add(mon, qdict, dinfo)) { - goto err; - } + monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); + goto err; } return; diff --git a/disas/arm.c b/disas/arm.c index 76e97a8..6165246 100644 --- a/disas/arm.c +++ b/disas/arm.c @@ -1549,10 +1549,6 @@ enum map_type { MAP_DATA }; -enum map_type last_type; -int last_mapping_sym = -1; -bfd_vma last_mapping_addr = 0; - /* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?. Returns pointer to following character of the format string and fills in *VALUEP and *WIDTHP with the extracted value and number of @@ -3878,135 +3874,11 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info) int is_data = false; unsigned int size = 4; void (*printer) (bfd_vma, struct disassemble_info *, long); -#if 0 - bfd_boolean found = false; - - if (info->disassembler_options) - { - parse_disassembler_options (info->disassembler_options); - - /* To avoid repeated parsing of these options, we remove them here. */ - info->disassembler_options = NULL; - } - - /* First check the full symtab for a mapping symbol, even if there - are no usable non-mapping symbols for this address. */ - if (info->symtab != NULL - && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) - { - bfd_vma addr; - int n; - int last_sym = -1; - enum map_type type = MAP_ARM; - - if (pc <= last_mapping_addr) - last_mapping_sym = -1; - is_thumb = (last_type == MAP_THUMB); - found = false; - /* Start scanning at the start of the function, or wherever - we finished last time. */ - n = info->symtab_pos + 1; - if (n < last_mapping_sym) - n = last_mapping_sym; - - /* Scan up to the location being disassembled. */ - for (; n < info->symtab_size; n++) - { - addr = bfd_asymbol_value (info->symtab[n]); - if (addr > pc) - break; - if ((info->section == NULL - || info->section == info->symtab[n]->section) - && get_sym_code_type (info, n, &type)) - { - last_sym = n; - found = true; - } - } - - if (!found) - { - n = info->symtab_pos; - if (n < last_mapping_sym - 1) - n = last_mapping_sym - 1; - - /* No mapping symbol found at this address. Look backwards - for a preceding one. */ - for (; n >= 0; n--) - { - if (get_sym_code_type (info, n, &type)) - { - last_sym = n; - found = true; - break; - } - } - } - - last_mapping_sym = last_sym; - last_type = type; - is_thumb = (last_type == MAP_THUMB); - is_data = (last_type == MAP_DATA); - - /* Look a little bit ahead to see if we should print out - two or four bytes of data. If there's a symbol, - mapping or otherwise, after two bytes then don't - print more. */ - if (is_data) - { - size = 4 - (pc & 3); - for (n = last_sym + 1; n < info->symtab_size; n++) - { - addr = bfd_asymbol_value (info->symtab[n]); - if (addr > pc) - { - if (addr - pc < size) - size = addr - pc; - break; - } - } - /* If the next symbol is after three bytes, we need to - print only part of the data, so that we can use either - .byte or .short. */ - if (size == 3) - size = (pc & 1) ? 1 : 2; - } - } - - if (info->symbols != NULL) - { - if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour) - { - coff_symbol_type * cs; - - cs = coffsymbol (*info->symbols); - is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT - || cs->native->u.syment.n_sclass == C_THUMBSTAT - || cs->native->u.syment.n_sclass == C_THUMBLABEL - || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC - || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC); - } - else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour - && !found) - { - /* If no mapping symbol has been found then fall back to the type - of the function symbol. */ - elf_symbol_type * es; - unsigned int type; - - es = *(elf_symbol_type **)(info->symbols); - type = ELF_ST_TYPE (es->internal_elf_sym.st_info); - - is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); - } - } -#else int little; little = (info->endian == BFD_ENDIAN_LITTLE); is_thumb |= (pc & 1); pc &= ~(bfd_vma)1; -#endif if (force_thumb) is_thumb = true; diff --git a/disas/microblaze.c b/disas/microblaze.c index ec91af3..c14ab89 100644 --- a/disas/microblaze.c +++ b/disas/microblaze.c @@ -275,7 +275,7 @@ enum microblaze_instr_type { #define MAX_OPCODES 280 -struct op_code_struct { +static struct op_code_struct { const char *name; short inst_type; /* registers and immediate values involved */ short inst_offset_type; /* immediate vals offset from PC? (= 1 for branches) */ @@ -567,10 +567,9 @@ struct op_code_struct { }; /* prefix for register names */ -char register_prefix[] = "r"; -char special_register_prefix[] = "spr"; -char fsl_register_prefix[] = "rfsl"; -char pvr_register_prefix[] = "rpvr"; +static const char register_prefix[] = "r"; +static const char fsl_register_prefix[] = "rfsl"; +static const char pvr_register_prefix[] = "rpvr"; /* #defines for valid immediate range */ @@ -738,7 +737,9 @@ get_field_special (long instr, struct op_code_struct * op) default : { if ( ((((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) & 0xE000) == REG_PVR_MASK) { - sprintf(tmpstr, "%spvr%d", register_prefix, (unsigned short)(((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) ^ REG_PVR_MASK); + sprintf(tmpstr, "%s%u", pvr_register_prefix, + (unsigned short)(((instr & IMM_MASK) >> IMM_LOW) ^ + op->immval_mask) ^ REG_PVR_MASK); return(strdup(tmpstr)); } else { strcpy(spr, "pc"); @@ -1188,7 +1188,7 @@ static void *file_ram_alloc(RAMBlock *block, error: if (mem_prealloc) { - error_report("%s\n", error_get_pretty(*errp)); + error_report("%s", error_get_pretty(*errp)); exit(1); } return NULL; @@ -1347,6 +1347,8 @@ int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp) assert(block); + newsize = TARGET_PAGE_ALIGN(newsize); + if (block->used_length == newsize) { return 0; } @@ -1443,15 +1443,17 @@ void gdb_exit(CPUArchState *env, int code) if (gdbserver_fd < 0 || s->fd < 0) { return; } +#else + if (!s->chr) { + return; + } #endif snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code); put_packet(s, buf); #ifndef CONFIG_USER_ONLY - if (s->chr) { - qemu_chr_delete(s->chr); - } + qemu_chr_delete(s->chr); #endif } diff --git a/hmp-commands.hx b/hmp-commands.hx index 81f276b..d5022d8 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1149,38 +1149,6 @@ STEXI Add drive to PCI storage controller. ETEXI -#if defined(CONFIG_PCI_HOTPLUG_OLD) - { - .name = "pci_add", - .args_type = "pci_addr:s,type:s,opts:s?", - .params = "auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", - .help = "hot-add PCI device", - .mhandler.cmd = hmp_pci_add, - }, -#endif - -STEXI -@item pci_add -@findex pci_add -Hot-add PCI device. -ETEXI - -#if defined(CONFIG_PCI_HOTPLUG_OLD) - { - .name = "pci_del", - .args_type = "pci_addr:s", - .params = "[[<domain>:]<bus>:]<slot>", - .help = "hot remove PCI device", - .mhandler.cmd = hmp_pci_del, - }, -#endif - -STEXI -@item pci_del -@findex pci_del -Hot remove PCI device. -ETEXI - { .name = "pcie_aer_inject_error", .args_type = "advisory_non_fatal:-a,correctable:-c," diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 2572747..30492ec 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -23,7 +23,7 @@ static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) { - features |= 1 << VIRTIO_9P_MOUNT_TAG; + virtio_add_feature(&features, VIRTIO_9P_MOUNT_TAG); return features; } diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index a183eee..d05c917 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -332,7 +332,6 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, tsize = read(fd, (void *)buf, bufsz); } while (tsize == -1 && errno == EINTR); close(fd); - return tsize; } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { buffer = rpath(fs_ctx, path); diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 2c3603a..58dafa9 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -7,16 +7,14 @@ #include <utime.h> #include <sys/resource.h> #include <glib.h> +#include "standard-headers/linux/virtio_9p.h" #include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-9p.h" #include "fsdev/file-op-9p.h" #include "fsdev/virtio-9p-marshal.h" #include "qemu/thread.h" #include "block/coroutine.h" -/* The feature bitmap for virtio 9P */ -/* The mount point is specified in a config variable */ -#define VIRTIO_9P_MOUNT_TAG 0 - enum { P9_TLERROR = 6, P9_RLERROR, @@ -144,10 +142,6 @@ struct V9fsPDU * 1) change user needs to set groups and stuff */ -/* from Linux's linux/virtio_9p.h */ - -/* The ID for virtio console */ -#define VIRTIO_ID_9P 9 #define MAX_REQ 128 #define MAX_TAG_LEN 32 @@ -277,14 +271,6 @@ typedef struct V9fsWriteState { int cnt; } V9fsWriteState; -struct virtio_9p_config -{ - /* number of characters in tag */ - uint16_t tag_len; - /* Variable size tag name */ - uint8_t tag[0]; -} QEMU_PACKED; - typedef struct V9fsMkState { V9fsPDU *pdu; size_t offset; diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index ee82073..b9fefa7 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -2,3 +2,4 @@ common-obj-$(CONFIG_ACPI) += core.o piix4.o ich9.o pcihp.o cpu_hotplug.o common-obj-$(CONFIG_ACPI) += memory_hotplug.o common-obj-$(CONFIG_ACPI) += acpi_interface.o common-obj-$(CONFIG_ACPI) += bios-linker-loader.o +common-obj-$(CONFIG_ACPI) += aml-build.o diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c new file mode 100644 index 0000000..876cada --- /dev/null +++ b/hw/acpi/aml-build.c @@ -0,0 +1,889 @@ +/* Support for generating ACPI tables and passing them to Guests + * + * Copyright (C) 2015 Red Hat Inc + * + * Author: Michael S. Tsirkin <mst@redhat.com> + * Author: Igor Mammedov <imammedo@redhat.com> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + + * 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 <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <stdbool.h> +#include <string.h> +#include "hw/acpi/aml-build.h" +#include "qemu/bswap.h" + +static GArray *build_alloc_array(void) +{ + return g_array_new(false, true /* clear */, 1); +} + +static void build_free_array(GArray *array) +{ + g_array_free(array, true); +} + +static void build_prepend_byte(GArray *array, uint8_t val) +{ + g_array_prepend_val(array, val); +} + +static void build_append_byte(GArray *array, uint8_t val) +{ + g_array_append_val(array, val); +} + +static void build_append_array(GArray *array, GArray *val) +{ + g_array_append_vals(array, val->data, val->len); +} + +#define ACPI_NAMESEG_LEN 4 + +static void +build_append_nameseg(GArray *array, const char *seg) +{ + /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */ + int len; + + len = strlen(seg); + assert(len <= ACPI_NAMESEG_LEN); + + g_array_append_vals(array, seg, len); + /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */ + g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len); +} + +static void +build_append_namestringv(GArray *array, const char *format, va_list ap) +{ + /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */ + char *s; + int len; + va_list va_len; + char **segs; + char **segs_iter; + int seg_count = 0; + + va_copy(va_len, ap); + len = vsnprintf(NULL, 0, format, va_len); + va_end(va_len); + len += 1; + s = g_new(typeof(*s), len); + + len = vsnprintf(s, len, format, ap); + + segs = g_strsplit(s, ".", 0); + g_free(s); + + /* count segments */ + segs_iter = segs; + while (*segs_iter) { + ++segs_iter; + ++seg_count; + } + /* + * ACPI 5.0 spec: 20.2.2 Name Objects Encoding: + * "SegCount can be from 1 to 255" + */ + assert(seg_count > 0 && seg_count <= 255); + + /* handle RootPath || PrefixPath */ + s = *segs; + while (*s == '\\' || *s == '^') { + build_append_byte(array, *s); + ++s; + } + + switch (seg_count) { + case 1: + if (!*s) { + build_append_byte(array, 0x0); /* NullName */ + } else { + build_append_nameseg(array, s); + } + break; + + case 2: + build_append_byte(array, 0x2E); /* DualNamePrefix */ + build_append_nameseg(array, s); + build_append_nameseg(array, segs[1]); + break; + default: + build_append_byte(array, 0x2F); /* MultiNamePrefix */ + build_append_byte(array, seg_count); + + /* handle the 1st segment manually due to prefix/root path */ + build_append_nameseg(array, s); + + /* add the rest of segments */ + segs_iter = segs + 1; + while (*segs_iter) { + build_append_nameseg(array, *segs_iter); + ++segs_iter; + } + break; + } + g_strfreev(segs); +} + +static void build_append_namestring(GArray *array, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + build_append_namestringv(array, format, ap); + va_end(ap); +} + +/* 5.4 Definition Block Encoding */ +enum { + PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */ + PACKAGE_LENGTH_2BYTE_SHIFT = 4, + PACKAGE_LENGTH_3BYTE_SHIFT = 12, + PACKAGE_LENGTH_4BYTE_SHIFT = 20, +}; + +static void +build_prepend_package_length(GArray *package, unsigned length, bool incl_self) +{ + uint8_t byte; + unsigned length_bytes; + + if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) { + length_bytes = 1; + } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) { + length_bytes = 2; + } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) { + length_bytes = 3; + } else { + length_bytes = 4; + } + + /* + * NamedField uses PkgLength encoding but it doesn't include length + * of PkgLength itself. + */ + if (incl_self) { + /* + * PkgLength is the length of the inclusive length of the data + * and PkgLength's length itself when used for terms with + * explitit length. + */ + length += length_bytes; + } + + switch (length_bytes) { + case 1: + byte = length; + build_prepend_byte(package, byte); + return; + case 4: + byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT; + build_prepend_byte(package, byte); + length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1; + /* fall through */ + case 3: + byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT; + build_prepend_byte(package, byte); + length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1; + /* fall through */ + case 2: + byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT; + build_prepend_byte(package, byte); + length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1; + /* fall through */ + } + /* + * Most significant two bits of byte zero indicate how many following bytes + * are in PkgLength encoding. + */ + byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length; + build_prepend_byte(package, byte); +} + +static void +build_append_pkg_length(GArray *array, unsigned length, bool incl_self) +{ + GArray *tmp = build_alloc_array(); + + build_prepend_package_length(tmp, length, incl_self); + build_append_array(array, tmp); + build_free_array(tmp); +} + +static void build_package(GArray *package, uint8_t op) +{ + build_prepend_package_length(package, package->len, true); + build_prepend_byte(package, op); +} + +static void build_extop_package(GArray *package, uint8_t op) +{ + build_package(package, op); + build_prepend_byte(package, 0x5B); /* ExtOpPrefix */ +} + +static void build_append_int_noprefix(GArray *table, uint64_t value, int size) +{ + int i; + + for (i = 0; i < size; ++i) { + build_append_byte(table, value & 0xFF); + value = value >> 8; + } +} + +static void build_append_int(GArray *table, uint64_t value) +{ + if (value == 0x00) { + build_append_byte(table, 0x00); /* ZeroOp */ + } else if (value == 0x01) { + build_append_byte(table, 0x01); /* OneOp */ + } else if (value <= 0xFF) { + build_append_byte(table, 0x0A); /* BytePrefix */ + build_append_int_noprefix(table, value, 1); + } else if (value <= 0xFFFF) { + build_append_byte(table, 0x0B); /* WordPrefix */ + build_append_int_noprefix(table, value, 2); + } else if (value <= 0xFFFFFFFF) { + build_append_byte(table, 0x0C); /* DWordPrefix */ + build_append_int_noprefix(table, value, 4); + } else { + build_append_byte(table, 0x0E); /* QWordPrefix */ + build_append_int_noprefix(table, value, 8); + } +} + +static GPtrArray *alloc_list; + +static Aml *aml_alloc(void) +{ + Aml *var = g_new0(typeof(*var), 1); + + g_ptr_array_add(alloc_list, var); + var->block_flags = AML_NO_OPCODE; + var->buf = build_alloc_array(); + return var; +} + +static Aml *aml_opcode(uint8_t op) +{ + Aml *var = aml_alloc(); + + var->op = op; + var->block_flags = AML_OPCODE; + return var; +} + +static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags) +{ + Aml *var = aml_alloc(); + + var->op = op; + var->block_flags = flags; + return var; +} + +static void aml_free(gpointer data, gpointer user_data) +{ + Aml *var = data; + build_free_array(var->buf); +} + +Aml *init_aml_allocator(void) +{ + Aml *var; + + assert(!alloc_list); + alloc_list = g_ptr_array_new(); + var = aml_alloc(); + return var; +} + +void free_aml_allocator(void) +{ + g_ptr_array_foreach(alloc_list, aml_free, NULL); + g_ptr_array_free(alloc_list, true); + alloc_list = 0; +} + +/* pack data with DefBuffer encoding */ +static void build_buffer(GArray *array, uint8_t op) +{ + GArray *data = build_alloc_array(); + + build_append_int(data, array->len); + g_array_prepend_vals(array, data->data, data->len); + build_free_array(data); + build_package(array, op); +} + +void aml_append(Aml *parent_ctx, Aml *child) +{ + switch (child->block_flags) { + case AML_OPCODE: + build_append_byte(parent_ctx->buf, child->op); + break; + case AML_EXT_PACKAGE: + build_extop_package(child->buf, child->op); + break; + case AML_PACKAGE: + build_package(child->buf, child->op); + break; + case AML_RES_TEMPLATE: + build_append_byte(child->buf, 0x79); /* EndTag */ + /* + * checksum operations are treated as succeeded if checksum + * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag] + */ + build_append_byte(child->buf, 0); + /* fall through, to pack resources in buffer */ + case AML_BUFFER: + build_buffer(child->buf, child->op); + break; + case AML_NO_OPCODE: + break; + default: + assert(0); + break; + } + build_append_array(parent_ctx->buf, child->buf); +} + +/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */ +Aml *aml_scope(const char *name_format, ...) +{ + va_list ap; + Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE); + va_start(ap, name_format); + build_append_namestringv(var->buf, name_format, ap); + va_end(ap); + return var; +} + +/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */ +Aml *aml_return(Aml *val) +{ + Aml *var = aml_opcode(0xA4 /* ReturnOp */); + aml_append(var, val); + return var; +} + +/* + * ACPI 1.0b: 16.2.3 Data Objects Encoding: + * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp + */ +Aml *aml_int(const uint64_t val) +{ + Aml *var = aml_alloc(); + build_append_int(var->buf, val); + return var; +} + +/* + * helper to construct NameString, which returns Aml object + * for using with aml_append or other aml_* terms + */ +Aml *aml_name(const char *name_format, ...) +{ + va_list ap; + Aml *var = aml_alloc(); + va_start(ap, name_format); + build_append_namestringv(var->buf, name_format, ap); + va_end(ap); + return var; +} + +/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */ +Aml *aml_name_decl(const char *name, Aml *val) +{ + Aml *var = aml_opcode(0x08 /* NameOp */); + build_append_namestring(var->buf, "%s", name); + aml_append(var, val); + return var; +} + +/* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */ +Aml *aml_arg(int pos) +{ + Aml *var; + uint8_t op = 0x68 /* ARG0 op */ + pos; + + assert(pos <= 6); + var = aml_opcode(op); + return var; +} + +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */ +Aml *aml_store(Aml *val, Aml *target) +{ + Aml *var = aml_opcode(0x70 /* StoreOp */); + aml_append(var, val); + aml_append(var, target); + return var; +} + +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */ +Aml *aml_and(Aml *arg1, Aml *arg2) +{ + Aml *var = aml_opcode(0x7B /* AndOp */); + aml_append(var, arg1); + aml_append(var, arg2); + build_append_int(var->buf, 0x00 /* NullNameOp */); + return var; +} + +/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */ +Aml *aml_notify(Aml *arg1, Aml *arg2) +{ + Aml *var = aml_opcode(0x86 /* NotifyOp */); + aml_append(var, arg1); + aml_append(var, arg2); + return var; +} + +/* helper to call method with 1 argument */ +Aml *aml_call1(const char *method, Aml *arg1) +{ + Aml *var = aml_alloc(); + build_append_namestring(var->buf, "%s", method); + aml_append(var, arg1); + return var; +} + +/* helper to call method with 2 arguments */ +Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2) +{ + Aml *var = aml_alloc(); + build_append_namestring(var->buf, "%s", method); + aml_append(var, arg1); + aml_append(var, arg2); + return var; +} + +/* helper to call method with 3 arguments */ +Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3) +{ + Aml *var = aml_alloc(); + build_append_namestring(var->buf, "%s", method); + aml_append(var, arg1); + aml_append(var, arg2); + aml_append(var, arg3); + return var; +} + +/* helper to call method with 4 arguments */ +Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4) +{ + Aml *var = aml_alloc(); + build_append_namestring(var->buf, "%s", method); + aml_append(var, arg1); + aml_append(var, arg2); + aml_append(var, arg3); + aml_append(var, arg4); + return var; +} + +/* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */ +Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, + uint8_t aln, uint8_t len) +{ + Aml *var = aml_alloc(); + build_append_byte(var->buf, 0x47); /* IO port descriptor */ + build_append_byte(var->buf, dec); + build_append_byte(var->buf, min_base & 0xff); + build_append_byte(var->buf, (min_base >> 8) & 0xff); + build_append_byte(var->buf, max_base & 0xff); + build_append_byte(var->buf, (max_base >> 8) & 0xff); + build_append_byte(var->buf, aln); + build_append_byte(var->buf, len); + return var; +} + +/* + * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor + * + * More verbose description at: + * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro) + * 6.4.2.1 IRQ Descriptor + */ +Aml *aml_irq_no_flags(uint8_t irq) +{ + uint16_t irq_mask; + Aml *var = aml_alloc(); + + assert(irq < 16); + build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */ + + irq_mask = 1U << irq; + build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */ + build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */ + return var; +} + +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */ +Aml *aml_equal(Aml *arg1, Aml *arg2) +{ + Aml *var = aml_opcode(0x93 /* LequalOp */); + aml_append(var, arg1); + aml_append(var, arg2); + build_append_int(var->buf, 0x00); /* NullNameOp */ + return var; +} + +/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */ +Aml *aml_if(Aml *predicate) +{ + Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE); + aml_append(var, predicate); + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */ +Aml *aml_method(const char *name, int arg_count) +{ + Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE); + build_append_namestring(var->buf, "%s", name); + build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */ + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */ +Aml *aml_device(const char *name_format, ...) +{ + va_list ap; + Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_PACKAGE); + va_start(ap, name_format); + build_append_namestringv(var->buf, name_format, ap); + va_end(ap); + return var; +} + +/* ACPI 1.0b: 6.4.1 ASL Macros for Resource Descriptors */ +Aml *aml_resource_template(void) +{ + /* ResourceTemplate is a buffer of Resources with EndTag at the end */ + Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE); + return var; +} + +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer */ +Aml *aml_buffer(void) +{ + Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER); + return var; +} + +/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */ +Aml *aml_package(uint8_t num_elements) +{ + Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE); + build_append_byte(var->buf, num_elements); + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */ +Aml *aml_operation_region(const char *name, AmlRegionSpace rs, + uint32_t offset, uint32_t len) +{ + Aml *var = aml_alloc(); + build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ + build_append_byte(var->buf, 0x80); /* OpRegionOp */ + build_append_namestring(var->buf, "%s", name); + build_append_byte(var->buf, rs); + build_append_int(var->buf, offset); + build_append_int(var->buf, len); + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */ +Aml *aml_named_field(const char *name, unsigned length) +{ + Aml *var = aml_alloc(); + build_append_nameseg(var->buf, name); + build_append_pkg_length(var->buf, length, false); + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */ +Aml *aml_reserved_field(unsigned length) +{ + Aml *var = aml_alloc(); + /* ReservedField := 0x00 PkgLength */ + build_append_byte(var->buf, 0x00); + build_append_pkg_length(var->buf, length, false); + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */ +Aml *aml_field(const char *name, AmlFieldFlags flags) +{ + Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE); + build_append_namestring(var->buf, "%s", name); + build_append_byte(var->buf, flags); + return var; +} + +/* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */ +Aml *aml_string(const char *name_format, ...) +{ + Aml *var = aml_opcode(0x0D /* StringPrefix */); + va_list ap, va_len; + char *s; + int len; + + va_start(ap, name_format); + va_copy(va_len, ap); + len = vsnprintf(NULL, 0, name_format, va_len); + va_end(va_len); + len += 1; + s = g_new0(typeof(*s), len); + + len = vsnprintf(s, len, name_format, ap); + va_end(ap); + + g_array_append_vals(var->buf, s, len); + build_append_byte(var->buf, 0x0); /* NullChar */ + g_free(s); + + return var; +} + +/* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */ +Aml *aml_local(int num) +{ + Aml *var; + uint8_t op = 0x60 /* Local0Op */ + num; + + assert(num <= 7); + var = aml_opcode(op); + return var; +} + +/* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */ +Aml *aml_varpackage(uint32_t num_elements) +{ + Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE); + build_append_int(var->buf, num_elements); + return var; +} + +/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */ +Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, + const char *name_format, ...) +{ + va_list ap; + Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE); + va_start(ap, name_format); + build_append_namestringv(var->buf, name_format, ap); + va_end(ap); + build_append_byte(var->buf, proc_id); /* ProcID */ + build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr)); + build_append_byte(var->buf, pblk_len); /* PblkLen */ + return var; +} + +static uint8_t Hex2Digit(char c) +{ + if (c >= 'A') { + return c - 'A' + 10; + } + + return c - '0'; +} + +/* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */ +Aml *aml_eisaid(const char *str) +{ + Aml *var = aml_alloc(); + uint32_t id; + + g_assert(strlen(str) == 7); + id = (str[0] - 0x40) << 26 | + (str[1] - 0x40) << 21 | + (str[2] - 0x40) << 16 | + Hex2Digit(str[3]) << 12 | + Hex2Digit(str[4]) << 8 | + Hex2Digit(str[5]) << 4 | + Hex2Digit(str[6]); + + build_append_byte(var->buf, 0x0C); /* DWordPrefix */ + build_append_int_noprefix(var->buf, bswap32(id), sizeof(id)); + return var; +} + +/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */ +static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlDecode dec, + uint8_t type_flags) +{ + uint8_t flags = max_fixed | min_fixed | dec; + Aml *var = aml_alloc(); + + build_append_byte(var->buf, type); + build_append_byte(var->buf, flags); + build_append_byte(var->buf, type_flags); /* Type Specific Flags */ + return var; +} + +/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */ +static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlDecode dec, + uint16_t addr_gran, uint16_t addr_min, + uint16_t addr_max, uint16_t addr_trans, + uint16_t len, uint8_t type_flags) +{ + Aml *var = aml_alloc(); + + build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */ + /* minimum length since we do not encode optional fields */ + build_append_byte(var->buf, 0x0D); + build_append_byte(var->buf, 0x0); + + aml_append(var, + aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); + build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); + build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); + build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); + build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); + build_append_int_noprefix(var->buf, len, sizeof(len)); + return var; +} + +/* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */ +static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlDecode dec, + uint32_t addr_gran, uint32_t addr_min, + uint32_t addr_max, uint32_t addr_trans, + uint32_t len, uint8_t type_flags) +{ + Aml *var = aml_alloc(); + + build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */ + /* minimum length since we do not encode optional fields */ + build_append_byte(var->buf, 23); + build_append_byte(var->buf, 0x0); + + + aml_append(var, + aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); + build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); + build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); + build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); + build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); + build_append_int_noprefix(var->buf, len, sizeof(len)); + return var; +} + +/* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */ +static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlDecode dec, + uint64_t addr_gran, uint64_t addr_min, + uint64_t addr_max, uint64_t addr_trans, + uint64_t len, uint8_t type_flags) +{ + Aml *var = aml_alloc(); + + build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */ + /* minimum length since we do not encode optional fields */ + build_append_byte(var->buf, 0x2B); + build_append_byte(var->buf, 0x0); + + aml_append(var, + aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); + build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); + build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); + build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); + build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); + build_append_int_noprefix(var->buf, len, sizeof(len)); + return var; +} + +/* + * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor + * + * More verbose description at: + * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro) + */ +Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, uint16_t addr_gran, + uint16_t addr_min, uint16_t addr_max, + uint16_t addr_trans, uint16_t len) + +{ + return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec, + addr_gran, addr_min, addr_max, addr_trans, len, 0); +} + +/* + * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor + * + * More verbose description at: + * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro) + */ +Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, AmlISARanges isa_ranges, + uint16_t addr_gran, uint16_t addr_min, + uint16_t addr_max, uint16_t addr_trans, + uint16_t len) + +{ + return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec, + addr_gran, addr_min, addr_max, addr_trans, len, + isa_ranges); +} + +/* + * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor + * + * More verbose description at: + * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro) + */ +Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlCacheble cacheable, + AmlReadAndWrite read_and_write, + uint32_t addr_gran, uint32_t addr_min, + uint32_t addr_max, uint32_t addr_trans, + uint32_t len) +{ + uint8_t flags = read_and_write | (cacheable << 1); + + return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed, + dec, addr_gran, addr_min, addr_max, + addr_trans, len, flags); +} + +/* + * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor + * + * More verbose description at: + * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro) + */ +Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlCacheble cacheable, + AmlReadAndWrite read_and_write, + uint64_t addr_gran, uint64_t addr_min, + uint64_t addr_max, uint64_t addr_trans, + uint64_t len) +{ + uint8_t flags = read_and_write | (cacheable << 1); + + return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed, + dec, addr_gran, addr_min, addr_max, + addr_trans, len, flags); +} diff --git a/hw/acpi/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c index 5cc4d90..d9382f8 100644 --- a/hw/acpi/bios-linker-loader.c +++ b/hw/acpi/bios-linker-loader.c @@ -141,6 +141,7 @@ void bios_linker_loader_add_pointer(GArray *linker, uint8_t pointer_size) { BiosLinkerLoaderEntry entry; + size_t offset = (gchar *)pointer - table->data; memset(&entry, 0, sizeof entry); strncpy(entry.pointer.dest_file, dest_file, @@ -148,7 +149,8 @@ void bios_linker_loader_add_pointer(GArray *linker, strncpy(entry.pointer.src_file, src_file, sizeof entry.pointer.src_file - 1); entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER); - entry.pointer.offset = cpu_to_le32((gchar *)pointer - table->data); + assert(table->len >= offset + pointer_size); + entry.pointer.offset = cpu_to_le32(offset); entry.pointer.size = pointer_size; assert(pointer_size == 1 || pointer_size == 2 || pointer_size == 4 || pointer_size == 8); diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 884dab3..5352e19 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -397,6 +397,20 @@ void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp) } } +void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev, + Error **errp) +{ + error_setg(errp, "acpi: device unplug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} + +void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, + Error **errp) +{ + error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} + void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) { ICH9LPCState *s = ICH9_LPC_DEVICE(adev); diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index ed39241..c6580da 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -168,7 +168,8 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, { MemStatus *mdev; Error *local_err = NULL; - int slot = object_property_get_int(OBJECT(dev), "slot", &local_err); + int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, + &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 34dedf1..612fec0 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -297,10 +297,11 @@ static const MemoryRegionOps acpi_pcihp_io_ops = { }, }; -void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus, +void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus, MemoryRegion *address_space_io, bool bridges_enabled) { - uint16_t io_size = ACPI_PCIHP_SIZE; + s->io_len = ACPI_PCIHP_SIZE; + s->io_base = ACPI_PCIHP_ADDR; s->root= root_bus; s->legacy_piix = !bridges_enabled; @@ -308,16 +309,21 @@ void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus, if (s->legacy_piix) { unsigned *bus_bsel = g_malloc(sizeof *bus_bsel); - io_size = ACPI_PCIHP_LEGACY_SIZE; + s->io_len = ACPI_PCIHP_LEGACY_SIZE; *bus_bsel = ACPI_PCIHP_BSEL_DEFAULT; object_property_add_uint32_ptr(OBJECT(root_bus), ACPI_PCIHP_PROP_BSEL, bus_bsel, NULL); } - memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s, - "acpi-pci-hotplug", io_size); - memory_region_add_subregion(address_space_io, ACPI_PCIHP_ADDR, &s->io); + memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s, + "acpi-pci-hotplug", s->io_len); + memory_region_add_subregion(address_space_io, s->io_base, &s->io); + + object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base, + &error_abort); + object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len, + &error_abort); } const VMStateDescription vmstate_acpi_pcihp_pci_status = { diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 184e7e4..d1f1179 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -370,6 +370,13 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev, } } +static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} + static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque) { PIIX4PMState *s = opaque; @@ -420,7 +427,7 @@ static void piix4_pm_add_propeties(PIIX4PMState *s) &s->io_base, NULL); } -static int piix4_pm_initfn(PCIDevice *dev) +static void piix4_pm_realize(PCIDevice *dev, Error **errp) { PIIX4PMState *s = PIIX4_PM(dev); uint8_t *pci_conf; @@ -470,7 +477,6 @@ static int piix4_pm_initfn(PCIDevice *dev) piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s); piix4_pm_add_propeties(s); - return 0; } Object *piix4_pm_find(void) @@ -556,7 +562,7 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, "acpi-gpe0", GPE_LEN); memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); - acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent, + acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent, s->use_acpi_pci_hotplug); acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu, @@ -593,7 +599,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass); - k->init = piix4_pm_initfn; + k->realize = piix4_pm_realize; k->config_write = pm_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3; @@ -610,6 +616,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) dc->hotpluggable = false; hc->plug = piix4_device_plug_cb; hc->unplug_request = piix4_device_unplug_request_cb; + hc->unplug = piix4_device_unplug_cb; adevc->ospm_status = piix4_ospm_status; } diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c index 2a4b872..7114c36 100644 --- a/hw/arm/digic_boards.c +++ b/hw/arm/digic_boards.c @@ -65,7 +65,7 @@ static void digic4_board_init(DigicBoard *board) s->digic = DIGIC(object_new(TYPE_DIGIC)); object_property_set_bool(OBJECT(s->digic), true, "realized", &err); if (err != NULL) { - error_report("Couldn't realize DIGIC SoC: %s\n", + error_report("Couldn't realize DIGIC SoC: %s", error_get_pretty(err)); exit(1); } @@ -104,13 +104,13 @@ static void digic_load_rom(DigicBoardState *s, hwaddr addr, char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, filename); if (!fn) { - error_report("Couldn't find rom image '%s'.\n", filename); + error_report("Couldn't find rom image '%s'.", filename); exit(1); } rom_size = load_image_targphys(fn, addr, max_size); if (rom_size < 0 || rom_size > max_size) { - error_report("Couldn't load rom image '%s'.\n", filename); + error_report("Couldn't load rom image '%s'.", filename); exit(1); } } diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 111ec0e..b173835 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1337,7 +1337,7 @@ static void ac97_on_reset (DeviceState *dev) mixer_reset (s); } -static int ac97_initfn (PCIDevice *dev) +static void ac97_realize(PCIDevice *dev, Error **errp) { AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev); uint8_t *c = s->dev.config; @@ -1384,7 +1384,6 @@ static int ac97_initfn (PCIDevice *dev) pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm); AUD_register_card ("ac97", &s->card); ac97_on_reset (&s->dev.qdev); - return 0; } static int ac97_init (PCIBus *bus) @@ -1403,7 +1402,7 @@ static void ac97_class_init (ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS (klass); PCIDeviceClass *k = PCI_DEVICE_CLASS (klass); - k->init = ac97_initfn; + k->realize = ac97_realize; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5; k->revision = 0x01; diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index e67d1ea..8e7bcf5 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -1016,7 +1016,7 @@ static void es1370_on_reset (void *opaque) es1370_reset (s); } -static int es1370_initfn (PCIDevice *dev) +static void es1370_realize(PCIDevice *dev, Error **errp) { ES1370State *s = DO_UPCAST (ES1370State, dev, dev); uint8_t *c = s->dev.config; @@ -1039,7 +1039,6 @@ static int es1370_initfn (PCIDevice *dev) AUD_register_card ("es1370", &s->card); es1370_reset (s); - return 0; } static int es1370_init (PCIBus *bus) @@ -1053,7 +1052,7 @@ static void es1370_class_init (ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS (klass); PCIDeviceClass *k = PCI_DEVICE_CLASS (klass); - k->init = es1370_initfn; + k->realize = es1370_realize; k->vendor_id = PCI_VENDOR_ID_ENSONIQ; k->device_id = PCI_DEVICE_ID_ENSONIQ_ES1370; k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 2885231..433463e 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -1126,7 +1126,7 @@ static void intel_hda_reset(DeviceState *dev) intel_hda_update_irq(d); } -static int intel_hda_init(PCIDevice *pci) +static void intel_hda_realize(PCIDevice *pci, Error **errp) { IntelHDAState *d = INTEL_HDA(pci); uint8_t *conf = d->pci.config; @@ -1147,8 +1147,6 @@ static int intel_hda_init(PCIDevice *pci) hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs), intel_hda_response, intel_hda_xfer); - - return 0; } static void intel_hda_exit(PCIDevice *pci) @@ -1245,7 +1243,7 @@ static void intel_hda_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = intel_hda_init; + k->realize = intel_hda_realize; k->exit = intel_hda_exit; k->vendor_id = PCI_VENDOR_ID_INTEL; k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO; diff --git a/hw/block/nand.c b/hw/block/nand.c index 1882a0c..61d2cec 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -393,7 +393,7 @@ static void nand_realize(DeviceState *dev, Error **errp) nand_init_2048(s); break; default: - error_setg(errp, "Unsupported NAND block size %#x\n", + error_setg(errp, "Unsupported NAND block size %#x", 1 << s->page_shift); return; } diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 0468297..000c38d 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -667,11 +667,11 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) memset(&blkcfg, 0, sizeof(blkcfg)); virtio_stq_p(vdev, &blkcfg.capacity, capacity); virtio_stl_p(vdev, &blkcfg.seg_max, 128 - 2); - virtio_stw_p(vdev, &blkcfg.cylinders, conf->cyls); + virtio_stw_p(vdev, &blkcfg.geometry.cylinders, conf->cyls); virtio_stl_p(vdev, &blkcfg.blk_size, blk_size); virtio_stw_p(vdev, &blkcfg.min_io_size, conf->min_io_size / blk_size); virtio_stw_p(vdev, &blkcfg.opt_io_size, conf->opt_io_size / blk_size); - blkcfg.heads = conf->heads; + blkcfg.geometry.heads = conf->heads; /* * We must ensure that the block device capacity is a multiple of * the logical block size. If that is not the case, let's use @@ -684,9 +684,9 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) * per track (cylinder). */ if (blk_getlength(s->blk) / conf->heads / conf->secs % blk_size) { - blkcfg.sectors = conf->secs & ~s->sector_mask; + blkcfg.geometry.sectors = conf->secs & ~s->sector_mask; } else { - blkcfg.sectors = conf->secs; + blkcfg.geometry.sectors = conf->secs; } blkcfg.size_max = 0; blkcfg.physical_block_exp = get_physical_block_exp(conf); @@ -711,20 +711,20 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) { VirtIOBlock *s = VIRTIO_BLK(vdev); - features |= (1 << VIRTIO_BLK_F_SEG_MAX); - features |= (1 << VIRTIO_BLK_F_GEOMETRY); - features |= (1 << VIRTIO_BLK_F_TOPOLOGY); - features |= (1 << VIRTIO_BLK_F_BLK_SIZE); - features |= (1 << VIRTIO_BLK_F_SCSI); + virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX); + virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY); + virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY); + virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE); + virtio_add_feature(&features, VIRTIO_BLK_F_SCSI); if (s->conf.config_wce) { - features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); + virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE); } if (blk_enable_write_cache(s->blk)) { - features |= (1 << VIRTIO_BLK_F_WCE); + virtio_add_feature(&features, VIRTIO_BLK_F_WCE); } if (blk_is_read_only(s->blk)) { - features |= 1 << VIRTIO_BLK_F_RO; + virtio_add_feature(&features, VIRTIO_BLK_F_RO); } return features; @@ -733,7 +733,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) { VirtIOBlock *s = VIRTIO_BLK(vdev); - uint32_t features; if (s->dataplane && !(status & (VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK))) { @@ -744,8 +743,6 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) return; } - features = vdev->guest_features; - /* A guest that supports VIRTIO_BLK_F_CONFIG_WCE must be able to send * cache flushes. Thus, the "auto writethrough" behavior is never * necessary for guests that support the VIRTIO_BLK_F_CONFIG_WCE feature. @@ -761,10 +758,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) * * s->blk would erroneously be placed in writethrough mode. */ - if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) { + if (!virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) { aio_context_acquire(blk_get_aio_context(s->blk)); blk_set_enable_write_cache(s->blk, - !!(features & (1 << VIRTIO_BLK_F_WCE))); + virtio_has_feature(vdev, VIRTIO_BLK_F_WCE)); aio_context_release(blk_get_aio_context(s->blk)); } } diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c index f05c9b4..467c3b4 100644 --- a/hw/char/serial-pci.c +++ b/hw/char/serial-pci.c @@ -48,7 +48,7 @@ typedef struct PCIMultiSerialState { uint8_t prog_if; } PCIMultiSerialState; -static int serial_pci_init(PCIDevice *dev) +static void serial_pci_realize(PCIDevice *dev, Error **errp) { PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); SerialState *s = &pci->state; @@ -57,9 +57,8 @@ static int serial_pci_init(PCIDevice *dev) s->baudbase = 115200; serial_realize_core(s, &err); if (err != NULL) { - qerror_report_err(err); - error_free(err); - return -1; + error_propagate(errp, err); + return; } pci->dev.config[PCI_CLASS_PROG] = pci->prog_if; @@ -68,7 +67,6 @@ static int serial_pci_init(PCIDevice *dev) memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8); pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); - return 0; } static void multi_serial_irq_mux(void *opaque, int n, int level) @@ -85,7 +83,7 @@ static void multi_serial_irq_mux(void *opaque, int n, int level) pci_set_irq(&pci->dev, pending); } -static int multi_serial_pci_init(PCIDevice *dev) +static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); @@ -116,9 +114,8 @@ static int multi_serial_pci_init(PCIDevice *dev) s->baudbase = 115200; serial_realize_core(s, &err); if (err != NULL) { - qerror_report_err(err); - error_free(err); - return -1; + error_propagate(errp, err); + return; } s->irq = pci->irqs[i]; pci->name[i] = g_strdup_printf("uart #%d", i+1); @@ -126,7 +123,6 @@ static int multi_serial_pci_init(PCIDevice *dev) pci->name[i], 8); memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); } - return 0; } static void serial_pci_exit(PCIDevice *dev) @@ -203,7 +199,7 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); - pc->init = serial_pci_init; + pc->realize = serial_pci_realize; pc->exit = serial_pci_exit; pc->vendor_id = PCI_VENDOR_ID_REDHAT; pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL; @@ -218,7 +214,7 @@ static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); - pc->init = multi_serial_pci_init; + pc->realize = multi_serial_pci_realize; pc->exit = multi_serial_pci_exit; pc->vendor_id = PCI_VENDOR_ID_REDHAT; pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL2; @@ -233,7 +229,7 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); - pc->init = multi_serial_pci_init; + pc->realize = multi_serial_pci_realize; pc->exit = multi_serial_pci_exit; pc->vendor_id = PCI_VENDOR_ID_REDHAT; pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL4; diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index 0adf096..4e464bd 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -60,19 +60,17 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len) qemu_chr_fe_write(dev->chardev, buf, len); } -static int spapr_vty_init(VIOsPAPRDevice *sdev) +static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp) { VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev); if (!dev->chardev) { - fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n"); - exit(1); + error_setg(errp, "chardev property not set"); + return; } qemu_chr_add_handlers(dev->chardev, vty_can_receive, vty_receive, NULL, dev); - - return 0; } /* Forward declaration */ @@ -163,7 +161,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass); - k->init = spapr_vty_init; + k->realize = spapr_vty_realize; k->dt_name = "vty"; k->dt_type = "serial"; k->dt_compatible = "hvterm1"; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 47fbb34..9a029d2 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -75,7 +75,7 @@ static VirtIOSerialPort *find_port_by_name(char *name) static bool use_multiport(VirtIOSerial *vser) { VirtIODevice *vdev = VIRTIO_DEVICE(vser); - return vdev->guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT); + return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT); } static size_t write_to_port(VirtIOSerialPort *port, @@ -474,7 +474,7 @@ static uint32_t get_features(VirtIODevice *vdev, uint32_t features) vser = VIRTIO_SERIAL(vdev); if (vser->bus.max_nr_ports > 1) { - features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT); + virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT); } return features; } diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index ba81709..570d5f0 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -991,8 +991,8 @@ int qdev_prop_check_globals(void) return ret; } -void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename, - Error **errp) +static void qdev_prop_set_globals_for_type(DeviceState *dev, + const char *typename) { GlobalProperty *prop; @@ -1005,25 +1005,22 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename, prop->used = true; object_property_parse(OBJECT(dev), prop->value, prop->property, &err); if (err != NULL) { - error_propagate(errp, err); + assert(prop->user_provided); + error_report("Warning: global %s.%s=%s ignored (%s)", + prop->driver, prop->property, prop->value, + error_get_pretty(err)); + error_free(err); return; } } } -void qdev_prop_set_globals(DeviceState *dev, Error **errp) +void qdev_prop_set_globals(DeviceState *dev) { ObjectClass *class = object_get_class(OBJECT(dev)); do { - Error *err = NULL; - - qdev_prop_set_globals_for_type(dev, object_class_get_name(class), - &err); - if (err != NULL) { - error_propagate(errp, err); - return; - } + qdev_prop_set_globals_for_type(dev, object_class_get_name(class)); class = object_class_get_parent(class); } while (class); } diff --git a/hw/core/qdev.c b/hw/core/qdev.c index a02a4cb..6be5866 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -1196,13 +1196,7 @@ static void device_initfn(Object *obj) static void device_post_init(Object *obj) { - Error *err = NULL; - qdev_prop_set_globals(DEVICE(obj), &err); - if (err) { - qerror_report_err(err); - error_free(err); - exit(EXIT_FAILURE); - } + qdev_prop_set_globals(DEVICE(obj)); } /* Unlink device from bus and free the structure. */ diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 84af593..b53c351 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -91,6 +91,8 @@ bool sysbus_has_irq(SysBusDevice *dev, int n) ObjectProperty *r; r = object_property_find(OBJECT(dev), prop, NULL); + g_free(prop); + return (r != NULL); } diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index ec923c8..8765a7e 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -3006,7 +3006,7 @@ static const TypeInfo isa_cirrus_vga_info = { * ***************************************/ -static int pci_cirrus_vga_initfn(PCIDevice *dev) +static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) { PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev); CirrusVGAState *s = &d->cirrus_vga; @@ -3017,9 +3017,9 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) Also accept 8 MB/16 MB for backward compatibility. */ if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 && s->vga.vram_size_mb != 16) { - error_report("Invalid cirrus_vga ram size '%u'", - s->vga.vram_size_mb); - return -1; + error_setg(errp, "Invalid cirrus_vga ram size '%u'", + s->vga.vram_size_mb); + return; } /* setup VGA */ vga_common_init(&s->vga, OBJECT(dev), true); @@ -3044,7 +3044,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) if (device_id == CIRRUS_ID_CLGD5446) { pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io); } - return 0; } static Property pci_vga_cirrus_properties[] = { @@ -3058,7 +3057,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_cirrus_vga_initfn; + k->realize = pci_cirrus_vga_realize; k->romfile = VGABIOS_CIRRUS_FILENAME; k->vendor_id = PCI_VENDOR_ID_CIRRUS; k->device_id = CIRRUS_ID_CLGD5446; diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 762f75d..b6d65b9 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1913,7 +1913,7 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl) qxl->vram_size = pow2ceil(qxl->vram_size); } -static int qxl_init_common(PCIQXLDevice *qxl) +static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) { uint8_t* config = qxl->pci.config; uint32_t pci_device_rev; @@ -1945,9 +1945,9 @@ static int qxl_init_common(PCIQXLDevice *qxl) io_size = pow2ceil(QXL_IO_RANGE_SIZE); break; default: - error_report("Invalid revision %d for qxl device (max %d)", - qxl->revision, QXL_DEFAULT_REVISION); - return -1; + error_setg(errp, "Invalid revision %d for qxl device (max %d)", + qxl->revision, QXL_DEFAULT_REVISION); + return; } pci_set_byte(&config[PCI_REVISION_ID], pci_device_rev); @@ -2011,9 +2011,9 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->ssd.qxl.base.sif = &qxl_interface.base; if (qemu_spice_add_display_interface(&qxl->ssd.qxl, qxl->vga.con) != 0) { - error_report("qxl interface %d.%d not supported by spice-server", - SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR); - return -1; + error_setg(errp, "qxl interface %d.%d not supported by spice-server", + SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR); + return; } qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl); @@ -2022,15 +2022,13 @@ static int qxl_init_common(PCIQXLDevice *qxl) qxl->update_area_bh = qemu_bh_new(qxl_render_update_area_bh, qxl); qxl->ssd.cursor_bh = qemu_bh_new(qemu_spice_cursor_refresh_bh, &qxl->ssd); - - return 0; } -static int qxl_init_primary(PCIDevice *dev) +static void qxl_realize_primary(PCIDevice *dev, Error **errp) { PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev); VGACommonState *vga = &qxl->vga; - int rc; + Error *local_err = NULL; qxl->id = 0; qxl_init_ramsize(qxl); @@ -2047,18 +2045,18 @@ static int qxl_init_primary(PCIDevice *dev) vga->con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl); qemu_spice_display_init_common(&qxl->ssd); - rc = qxl_init_common(qxl); - if (rc != 0) { - return rc; + qxl_realize_common(qxl, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } qxl->ssd.dcl.ops = &display_listener_ops; qxl->ssd.dcl.con = vga->con; register_displaychangelistener(&qxl->ssd.dcl); - return rc; } -static int qxl_init_secondary(PCIDevice *dev) +static void qxl_realize_secondary(PCIDevice *dev, Error **errp) { static int device_id = 1; PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev); @@ -2071,7 +2069,7 @@ static int qxl_init_secondary(PCIDevice *dev) qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); qxl->vga.con = graphic_console_init(DEVICE(dev), 0, &qxl_ops, qxl); - return qxl_init_common(qxl); + qxl_realize_common(qxl, errp); } static void qxl_pre_save(void *opaque) @@ -2284,7 +2282,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = qxl_init_primary; + k->realize = qxl_realize_primary; k->romfile = "vgabios-qxl.bin"; k->vendor_id = REDHAT_PCI_VENDOR_ID; k->device_id = QXL_DEVICE_ID_STABLE; @@ -2309,7 +2307,7 @@ static void qxl_secondary_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = qxl_init_secondary; + k->realize = qxl_realize_secondary; k->vendor_id = REDHAT_PCI_VENDOR_ID; k->device_id = QXL_DEVICE_ID_STABLE; k->class_id = PCI_CLASS_DISPLAY_OTHER; diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index 53739e4..aabfc23 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -181,6 +181,20 @@ static void pci_vga_qext_write(void *ptr, hwaddr addr, } } +static bool vga_get_big_endian_fb(Object *obj, Error **errp) +{ + PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, PCI_DEVICE(obj)); + + return d->vga.big_endian_fb; +} + +static void vga_set_big_endian_fb(Object *obj, bool value, Error **errp) +{ + PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, PCI_DEVICE(obj)); + + d->vga.big_endian_fb = value; +} + static const MemoryRegionOps pci_vga_qext_ops = { .read = pci_vga_qext_read, .write = pci_vga_qext_write, @@ -189,7 +203,7 @@ static const MemoryRegionOps pci_vga_qext_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static int pci_std_vga_initfn(PCIDevice *dev) +static void pci_std_vga_realize(PCIDevice *dev, Error **errp) { PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); VGACommonState *s = &d->vga; @@ -232,11 +246,16 @@ static int pci_std_vga_initfn(PCIDevice *dev) /* compatibility with pc-0.13 and older */ vga_init_vbe(s, OBJECT(dev), pci_address_space(dev)); } +} - return 0; +static void pci_std_vga_init(Object *obj) +{ + /* Expose framebuffer byteorder via QOM */ + object_property_add_bool(obj, "big-endian-framebuffer", + vga_get_big_endian_fb, vga_set_big_endian_fb, NULL); } -static int pci_secondary_vga_initfn(PCIDevice *dev) +static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp) { PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); VGACommonState *s = &d->vga; @@ -267,8 +286,13 @@ static int pci_secondary_vga_initfn(PCIDevice *dev) pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); pci_register_bar(&d->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); +} - return 0; +static void pci_secondary_vga_init(Object *obj) +{ + /* Expose framebuffer byteorder via QOM */ + object_property_add_bool(obj, "big-endian-framebuffer", + vga_get_big_endian_fb, vga_set_big_endian_fb, NULL); } static void pci_secondary_vga_reset(DeviceState *dev) @@ -298,7 +322,7 @@ static void vga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_std_vga_initfn; + k->realize = pci_std_vga_realize; k->romfile = "vgabios-stdvga.bin"; k->vendor_id = PCI_VENDOR_ID_QEMU; k->device_id = PCI_DEVICE_ID_QEMU_VGA; @@ -314,7 +338,7 @@ static void secondary_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_secondary_vga_initfn; + k->realize = pci_secondary_vga_realize; k->vendor_id = PCI_VENDOR_ID_QEMU; k->device_id = PCI_DEVICE_ID_QEMU_VGA; k->class_id = PCI_CLASS_DISPLAY_OTHER; @@ -327,6 +351,7 @@ static void secondary_class_init(ObjectClass *klass, void *data) static const TypeInfo vga_info = { .name = "VGA", .parent = TYPE_PCI_DEVICE, + .instance_init = pci_std_vga_init, .instance_size = sizeof(PCIVGAState), .class_init = vga_class_init, }; @@ -334,6 +359,7 @@ static const TypeInfo vga_info = { static const TypeInfo secondary_info = { .name = "secondary-vga", .parent = TYPE_PCI_DEVICE, + .instance_init = pci_secondary_vga_init, .instance_size = sizeof(PCIVGAState), .class_init = secondary_class_init, }; diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 1751f19..c17ddd1 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1298,7 +1298,7 @@ static const MemoryRegionOps vmsvga_io_ops = { }, }; -static int pci_vmsvga_initfn(PCIDevice *dev) +static void pci_vmsvga_realize(PCIDevice *dev, Error **errp) { struct pci_vmsvga_state_s *s = VMWARE_SVGA(dev); @@ -1323,8 +1323,6 @@ static int pci_vmsvga_initfn(PCIDevice *dev) /* compatibility with pc-0.13 and older */ vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev)); } - - return 0; } static Property vga_vmware_properties[] = { @@ -1338,7 +1336,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_vmsvga_initfn; + k->realize = pci_vmsvga_realize; k->romfile = "vgabios-vmware.bin"; k->vendor_id = PCI_VENDOR_ID_VMWARE; k->device_id = SVGA_PCI_DEVICE_ID; diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index 16cf77e..5be3df5 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -1566,7 +1566,7 @@ static void pl330_realize(DeviceState *dev, Error **errp) s->cfg[1] |= 5; break; default: - error_setg(errp, "Bad value for i-cache_len property: %" PRIx8 "\n", + error_setg(errp, "Bad value for i-cache_len property: %" PRIx8, s->i_cache_len); return; } @@ -1601,7 +1601,7 @@ static void pl330_realize(DeviceState *dev, Error **errp) s->cfg[CFG_CRD] |= 0x4; break; default: - error_setg(errp, "Bad value for data_width property: %" PRIx8 "\n", + error_setg(errp, "Bad value for data_width property: %" PRIx8, s->data_width); return; } diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 0803dc4..91d4d32 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -71,7 +71,7 @@ static void ich9_smbus_write_config(PCIDevice *d, uint32_t address, } } -static int ich9_smbus_initfn(PCIDevice *d) +static void ich9_smbus_realize(PCIDevice *d, Error **errp) { ICH9SMBState *s = ICH9_SMB_DEVICE(d); @@ -84,7 +84,6 @@ static int ich9_smbus_initfn(PCIDevice *d) pm_smbus_init(&d->qdev, &s->smb); pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO, &s->smb.io); - return 0; } static void ich9_smb_class_init(ObjectClass *klass, void *data) @@ -98,7 +97,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_SERIAL_SMBUS; dc->vmsd = &vmstate_ich9_smbus; dc->desc = "ICH9 SMBUS Bridge"; - k->init = ich9_smbus_initfn; + k->realize = ich9_smbus_realize; k->config_write = ich9_smbus_write_config; /* * Reason: part of ICH9 southbridge, needs to be wired up by diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index 2b678ef..e058a39 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -7,10 +7,8 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-y += kvmvapic.o obj-y += acpi-build.o -hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex \ - hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex \ +hw/i386/acpi-build.o: hw/i386/acpi-build.c \ hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex \ - hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex \ hw/i386/ssdt-tpm.hex iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 4944249..d0a5c85 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -54,6 +54,8 @@ #include "hw/i386/q35-acpi-dsdt.hex" #include "hw/i386/acpi-dsdt.hex" +#include "hw/acpi/aml-build.h" + #include "qapi/qmp/qint.h" #include "qom/qom-qobject.h" #include "exec/ram_addr.h" @@ -99,15 +101,21 @@ typedef struct AcpiPmInfo { uint32_t gpe0_blk; uint32_t gpe0_blk_len; uint32_t io_base; + uint16_t cpu_hp_io_base; + uint16_t cpu_hp_io_len; + uint16_t mem_hp_io_base; + uint16_t mem_hp_io_len; + uint16_t pcihp_io_base; + uint16_t pcihp_io_len; } AcpiPmInfo; typedef struct AcpiMiscInfo { bool has_hpet; bool has_tpm; - DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX); const unsigned char *dsdt_code; unsigned dsdt_size; uint16_t pvpanic_port; + uint16_t applesmc_io_base; } AcpiMiscInfo; typedef struct AcpiBuildPciBusHotplugState { @@ -119,7 +127,6 @@ typedef struct AcpiBuildPciBusHotplugState { static void acpi_get_dsdt(AcpiMiscInfo *info) { - uint16_t *applesmc_sta; Object *piix = piix4_pm_find(); Object *lpc = ich9_lpc_find(); assert(!!piix != !!lpc); @@ -127,17 +134,11 @@ static void acpi_get_dsdt(AcpiMiscInfo *info) if (piix) { info->dsdt_code = AcpiDsdtAmlCode; info->dsdt_size = sizeof AcpiDsdtAmlCode; - applesmc_sta = piix_dsdt_applesmc_sta; } if (lpc) { info->dsdt_code = Q35AcpiDsdtAmlCode; info->dsdt_size = sizeof Q35AcpiDsdtAmlCode; - applesmc_sta = q35_dsdt_applesmc_sta; } - - /* Patch in appropriate value for AppleSMC _STA */ - *(uint8_t *)(info->dsdt_code + *applesmc_sta) = - applesmc_find() ? 0x0b : 0x00; } static @@ -172,14 +173,26 @@ static void acpi_get_pm_info(AcpiPmInfo *pm) Object *obj = NULL; QObject *o; + pm->pcihp_io_base = 0; + pm->pcihp_io_len = 0; if (piix) { obj = piix; + pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE; + pm->pcihp_io_base = + object_property_get_int(obj, ACPI_PCIHP_IO_BASE_PROP, NULL); + pm->pcihp_io_len = + object_property_get_int(obj, ACPI_PCIHP_IO_LEN_PROP, NULL); } if (lpc) { obj = lpc; + pm->cpu_hp_io_base = ICH9_CPU_HOTPLUG_IO_BASE; } assert(obj); + pm->cpu_hp_io_len = ACPI_GPE_PROC_LEN; + pm->mem_hp_io_base = ACPI_MEMORY_HOTPLUG_BASE; + pm->mem_hp_io_len = ACPI_MEMORY_HOTPLUG_IO_LEN; + /* Fill in optional s3/s4 related properties */ o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL); if (o) { @@ -228,6 +241,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) info->has_hpet = hpet_find(); info->has_tpm = tpm_find(); info->pvpanic_port = pvpanic_port(); + info->applesmc_io_base = applesmc_port(); } static void acpi_get_pci_info(PcPciInfo *info) @@ -280,208 +294,6 @@ build_header(GArray *linker, GArray *table_data, table_data->data, h, len, &h->checksum); } -static inline GArray *build_alloc_array(void) -{ - return g_array_new(false, true /* clear */, 1); -} - -static inline void build_free_array(GArray *array) -{ - g_array_free(array, true); -} - -static inline void build_prepend_byte(GArray *array, uint8_t val) -{ - g_array_prepend_val(array, val); -} - -static inline void build_append_byte(GArray *array, uint8_t val) -{ - g_array_append_val(array, val); -} - -static inline void build_append_array(GArray *array, GArray *val) -{ - g_array_append_vals(array, val->data, val->len); -} - -#define ACPI_NAMESEG_LEN 4 - -static void GCC_FMT_ATTR(2, 3) -build_append_nameseg(GArray *array, const char *format, ...) -{ - /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */ - char s[] = "XXXX"; - int len; - va_list args; - - va_start(args, format); - len = vsnprintf(s, sizeof s, format, args); - va_end(args); - - assert(len <= ACPI_NAMESEG_LEN); - - g_array_append_vals(array, s, len); - /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */ - g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len); -} - -/* 5.4 Definition Block Encoding */ -enum { - PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */ - PACKAGE_LENGTH_2BYTE_SHIFT = 4, - PACKAGE_LENGTH_3BYTE_SHIFT = 12, - PACKAGE_LENGTH_4BYTE_SHIFT = 20, -}; - -static void build_prepend_package_length(GArray *package, unsigned min_bytes) -{ - uint8_t byte; - unsigned length = package->len; - unsigned length_bytes; - - if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) { - length_bytes = 1; - } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) { - length_bytes = 2; - } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) { - length_bytes = 3; - } else { - length_bytes = 4; - } - - /* Force length to at least min_bytes. - * This wastes memory but that's how bios did it. - */ - length_bytes = MAX(length_bytes, min_bytes); - - /* PkgLength is the length of the inclusive length of the data. */ - length += length_bytes; - - switch (length_bytes) { - case 1: - byte = length; - build_prepend_byte(package, byte); - return; - case 4: - byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT; - build_prepend_byte(package, byte); - length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1; - /* fall through */ - case 3: - byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT; - build_prepend_byte(package, byte); - length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1; - /* fall through */ - case 2: - byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT; - build_prepend_byte(package, byte); - length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1; - /* fall through */ - } - /* - * Most significant two bits of byte zero indicate how many following bytes - * are in PkgLength encoding. - */ - byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length; - build_prepend_byte(package, byte); -} - -static void build_package(GArray *package, uint8_t op, unsigned min_bytes) -{ - build_prepend_package_length(package, min_bytes); - build_prepend_byte(package, op); -} - -static void build_extop_package(GArray *package, uint8_t op) -{ - build_package(package, op, 1); - build_prepend_byte(package, 0x5B); /* ExtOpPrefix */ -} - -static void build_append_value(GArray *table, uint32_t value, int size) -{ - uint8_t prefix; - int i; - - switch (size) { - case 1: - prefix = 0x0A; /* BytePrefix */ - break; - case 2: - prefix = 0x0B; /* WordPrefix */ - break; - case 4: - prefix = 0x0C; /* DWordPrefix */ - break; - default: - assert(0); - return; - } - build_append_byte(table, prefix); - for (i = 0; i < size; ++i) { - build_append_byte(table, value & 0xFF); - value = value >> 8; - } -} - -static void build_append_int(GArray *table, uint32_t value) -{ - if (value == 0x00) { - build_append_byte(table, 0x00); /* ZeroOp */ - } else if (value == 0x01) { - build_append_byte(table, 0x01); /* OneOp */ - } else if (value <= 0xFF) { - build_append_value(table, value, 1); - } else if (value <= 0xFFFF) { - build_append_value(table, value, 2); - } else { - build_append_value(table, value, 4); - } -} - -static GArray *build_alloc_method(const char *name, uint8_t arg_count) -{ - GArray *method = build_alloc_array(); - - build_append_nameseg(method, "%s", name); - build_append_byte(method, arg_count); /* MethodFlags: ArgCount */ - - return method; -} - -static void build_append_and_cleanup_method(GArray *device, GArray *method) -{ - uint8_t op = 0x14; /* MethodOp */ - - build_package(method, op, 0); - - build_append_array(device, method); - build_free_array(method); -} - -static void build_append_notify_target_ifequal(GArray *method, - GArray *target_name, - uint32_t value, int size) -{ - GArray *notify = build_alloc_array(); - uint8_t op = 0xA0; /* IfOp */ - - build_append_byte(notify, 0x93); /* LEqualOp */ - build_append_byte(notify, 0x68); /* Arg0Op */ - build_append_value(notify, value, size); - build_append_byte(notify, 0x86); /* NotifyOp */ - build_append_array(notify, target_name); - build_append_byte(notify, 0x69); /* Arg1Op */ - - /* Pack it up */ - build_package(notify, op, 1); - - build_append_array(method, notify); - - build_free_array(notify); -} - /* End here */ #define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */ @@ -508,24 +320,6 @@ static void acpi_align_size(GArray *blob, unsigned align) g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); } -/* Set a value within table in a safe manner */ -#define ACPI_BUILD_SET_LE(table, size, off, bits, val) \ - do { \ - uint64_t ACPI_BUILD_SET_LE_val = cpu_to_le64(val); \ - memcpy(acpi_data_get_ptr(table, size, off, \ - (bits) / BITS_PER_BYTE), \ - &ACPI_BUILD_SET_LE_val, \ - (bits) / BITS_PER_BYTE); \ - } while (0) - -static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size, - unsigned off, unsigned size) -{ - assert(off + size > off); - assert(off + size <= table_size); - return table_data + off; -} - static inline void acpi_add_table(GArray *table_offsets, GArray *table_data) { uint32_t offset = cpu_to_le32(table_data->len); @@ -673,115 +467,8 @@ build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu, table_data->len - madt_start, 1); } -/* Encode a hex value */ -static inline char acpi_get_hex(uint32_t val) -{ - val &= 0x0f; - return (val <= 9) ? ('0' + val) : ('A' + val - 10); -} - -#include "hw/i386/ssdt-proc.hex" - -/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */ -#define ACPI_PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2) -#define ACPI_PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4) -#define ACPI_PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start) -#define ACPI_PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start) -#define ACPI_PROC_AML (ssdp_proc_aml + *ssdt_proc_start) - -/* 0x5B 0x82 DeviceOp PkgLength NameString */ -#define ACPI_PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1) -#define ACPI_PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start) -#define ACPI_PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start) -#define ACPI_PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start) -#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start) -#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start) - -#define ACPI_PCINOHP_OFFSET_HEX (*ssdt_pcinohp_name - *ssdt_pcinohp_start + 1) -#define ACPI_PCINOHP_OFFSET_ADR (*ssdt_pcinohp_adr - *ssdt_pcinohp_start) -#define ACPI_PCINOHP_SIZEOF (*ssdt_pcinohp_end - *ssdt_pcinohp_start) -#define ACPI_PCINOHP_AML (ssdp_pcihp_aml + *ssdt_pcinohp_start) - -#define ACPI_PCIVGA_OFFSET_HEX (*ssdt_pcivga_name - *ssdt_pcivga_start + 1) -#define ACPI_PCIVGA_OFFSET_ADR (*ssdt_pcivga_adr - *ssdt_pcivga_start) -#define ACPI_PCIVGA_SIZEOF (*ssdt_pcivga_end - *ssdt_pcivga_start) -#define ACPI_PCIVGA_AML (ssdp_pcihp_aml + *ssdt_pcivga_start) - -#define ACPI_PCIQXL_OFFSET_HEX (*ssdt_pciqxl_name - *ssdt_pciqxl_start + 1) -#define ACPI_PCIQXL_OFFSET_ADR (*ssdt_pciqxl_adr - *ssdt_pciqxl_start) -#define ACPI_PCIQXL_SIZEOF (*ssdt_pciqxl_end - *ssdt_pciqxl_start) -#define ACPI_PCIQXL_AML (ssdp_pcihp_aml + *ssdt_pciqxl_start) - -#include "hw/i386/ssdt-mem.hex" - -/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */ -#define ACPI_MEM_OFFSET_HEX (*ssdt_mem_name - *ssdt_mem_start + 2) -#define ACPI_MEM_OFFSET_ID (*ssdt_mem_id - *ssdt_mem_start + 7) -#define ACPI_MEM_SIZEOF (*ssdt_mem_end - *ssdt_mem_start) -#define ACPI_MEM_AML (ssdm_mem_aml + *ssdt_mem_start) - -#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */ -#define ACPI_SSDT_HEADER_LENGTH 36 - -#include "hw/i386/ssdt-misc.hex" -#include "hw/i386/ssdt-pcihp.hex" #include "hw/i386/ssdt-tpm.hex" -static void -build_append_notify_method(GArray *device, const char *name, - const char *format, int count) -{ - int i; - GArray *method = build_alloc_method(name, 2); - - for (i = 0; i < count; i++) { - GArray *target = build_alloc_array(); - build_append_nameseg(target, format, i); - assert(i < 256); /* Fits in 1 byte */ - build_append_notify_target_ifequal(method, target, i, 1); - build_free_array(target); - } - - build_append_and_cleanup_method(device, method); -} - -static void patch_pcihp(int slot, uint8_t *ssdt_ptr) -{ - unsigned devfn = PCI_DEVFN(slot, 0); - - ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4); - ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(devfn); - ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot; - ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot; -} - -static void patch_pcinohp(int slot, uint8_t *ssdt_ptr) -{ - unsigned devfn = PCI_DEVFN(slot, 0); - - ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX] = acpi_get_hex(devfn >> 4); - ssdt_ptr[ACPI_PCINOHP_OFFSET_HEX + 1] = acpi_get_hex(devfn); - ssdt_ptr[ACPI_PCINOHP_OFFSET_ADR + 2] = slot; -} - -static void patch_pcivga(int slot, uint8_t *ssdt_ptr) -{ - unsigned devfn = PCI_DEVFN(slot, 0); - - ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX] = acpi_get_hex(devfn >> 4); - ssdt_ptr[ACPI_PCIVGA_OFFSET_HEX + 1] = acpi_get_hex(devfn); - ssdt_ptr[ACPI_PCIVGA_OFFSET_ADR + 2] = slot; -} - -static void patch_pciqxl(int slot, uint8_t *ssdt_ptr) -{ - unsigned devfn = PCI_DEVFN(slot, 0); - - ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX] = acpi_get_hex(devfn >> 4); - ssdt_ptr[ACPI_PCIQXL_OFFSET_HEX + 1] = acpi_get_hex(devfn); - ssdt_ptr[ACPI_PCIQXL_OFFSET_ADR + 2] = slot; -} - /* Assign BSEL property to all buses. In the future, this can be changed * to only assign to buses that support hotplug. */ @@ -812,261 +499,155 @@ static void acpi_set_pci_info(void) } } -static void build_pci_bus_state_init(AcpiBuildPciBusHotplugState *state, - AcpiBuildPciBusHotplugState *parent, - bool pcihp_bridge_en) -{ - state->parent = parent; - state->device_table = build_alloc_array(); - state->notify_table = build_alloc_array(); - state->pcihp_bridge_en = pcihp_bridge_en; -} - -static void build_pci_bus_state_cleanup(AcpiBuildPciBusHotplugState *state) +static void build_append_pcihp_notify_entry(Aml *method, int slot) { - build_free_array(state->device_table); - build_free_array(state->notify_table); -} - -static void *build_pci_bus_begin(PCIBus *bus, void *parent_state) -{ - AcpiBuildPciBusHotplugState *parent = parent_state; - AcpiBuildPciBusHotplugState *child = g_malloc(sizeof *child); - - build_pci_bus_state_init(child, parent, parent->pcihp_bridge_en); + Aml *if_ctx; + int32_t devfn = PCI_DEVFN(slot, 0); - return child; + if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot))); + aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1))); + aml_append(method, if_ctx); } -static void build_pci_bus_end(PCIBus *bus, void *bus_state) +static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, + bool pcihp_bridge_en) { - AcpiBuildPciBusHotplugState *child = bus_state; - AcpiBuildPciBusHotplugState *parent = child->parent; - GArray *bus_table = build_alloc_array(); - DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX); - DECLARE_BITMAP(slot_device_present, PCI_SLOT_MAX); - DECLARE_BITMAP(slot_device_system, PCI_SLOT_MAX); - DECLARE_BITMAP(slot_device_vga, PCI_SLOT_MAX); - DECLARE_BITMAP(slot_device_qxl, PCI_SLOT_MAX); - uint8_t op; - int i; + Aml *dev, *notify_method, *method; QObject *bsel; - GArray *method; - bool bus_hotplug_support = false; - - /* - * Skip bridge subtree creation if bridge hotplug is disabled - * to make acpi tables compatible with legacy machine types. - */ - if (!child->pcihp_bridge_en && bus->parent_dev) { - return; - } - - if (bus->parent_dev) { - op = 0x82; /* DeviceOp */ - build_append_nameseg(bus_table, "S%.02X", - bus->parent_dev->devfn); - build_append_byte(bus_table, 0x08); /* NameOp */ - build_append_nameseg(bus_table, "_SUN"); - build_append_value(bus_table, PCI_SLOT(bus->parent_dev->devfn), 1); - build_append_byte(bus_table, 0x08); /* NameOp */ - build_append_nameseg(bus_table, "_ADR"); - build_append_value(bus_table, (PCI_SLOT(bus->parent_dev->devfn) << 16) | - PCI_FUNC(bus->parent_dev->devfn), 4); - } else { - op = 0x10; /* ScopeOp */; - build_append_nameseg(bus_table, "PCI0"); - } + PCIBus *sec; + int i; bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL); if (bsel) { - build_append_byte(bus_table, 0x08); /* NameOp */ - build_append_nameseg(bus_table, "BSEL"); - build_append_int(bus_table, qint_get_int(qobject_to_qint(bsel))); - memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable); - } else { - /* No bsel - no slots are hot-pluggable */ - memset(slot_hotplug_enable, 0x00, sizeof slot_hotplug_enable); - } + int64_t bsel_val = qint_get_int(qobject_to_qint(bsel)); - memset(slot_device_present, 0x00, sizeof slot_device_present); - memset(slot_device_system, 0x00, sizeof slot_device_present); - memset(slot_device_vga, 0x00, sizeof slot_device_vga); - memset(slot_device_qxl, 0x00, sizeof slot_device_qxl); + aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val))); + notify_method = aml_method("DVNT", 2); + } for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) { DeviceClass *dc; PCIDeviceClass *pc; PCIDevice *pdev = bus->devices[i]; int slot = PCI_SLOT(i); + bool hotplug_enabled_dev; bool bridge_in_acpi; if (!pdev) { + if (bsel) { /* add hotplug slots for non present devices */ + dev = aml_device("S%.02X", PCI_DEVFN(slot, 0)); + aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); + aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))); + method = aml_method("_EJ0", 1); + aml_append(method, + aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) + ); + aml_append(dev, method); + aml_append(parent_scope, dev); + + build_append_pcihp_notify_entry(notify_method, slot); + } continue; } - set_bit(slot, slot_device_present); pc = PCI_DEVICE_GET_CLASS(pdev); dc = DEVICE_GET_CLASS(pdev); /* When hotplug for bridges is enabled, bridges are * described in ACPI separately (see build_pci_bus_end). * In this case they aren't themselves hot-pluggable. + * Hotplugged bridges *are* hot-pluggable. */ - bridge_in_acpi = pc->is_bridge && child->pcihp_bridge_en; + bridge_in_acpi = pc->is_bridge && pcihp_bridge_en && + !DEVICE(pdev)->hotplugged; - if (pc->class_id == PCI_CLASS_BRIDGE_ISA || bridge_in_acpi) { - set_bit(slot, slot_device_system); + hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi; + + if (pc->class_id == PCI_CLASS_BRIDGE_ISA) { + continue; } + /* start to compose PCI slot descriptor */ + dev = aml_device("S%.02X", PCI_DEVFN(slot, 0)); + aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16))); + if (pc->class_id == PCI_CLASS_DISPLAY_VGA) { - set_bit(slot, slot_device_vga); + /* add VGA specific AML methods */ + int s3d; if (object_dynamic_cast(OBJECT(pdev), "qxl-vga")) { - set_bit(slot, slot_device_qxl); + s3d = 3; + } else { + s3d = 0; } - } - if (!dc->hotpluggable || bridge_in_acpi) { - clear_bit(slot, slot_hotplug_enable); - } - } + method = aml_method("_S1D", 0); + aml_append(method, aml_return(aml_int(0))); + aml_append(dev, method); + + method = aml_method("_S2D", 0); + aml_append(method, aml_return(aml_int(0))); + aml_append(dev, method); + + method = aml_method("_S3D", 0); + aml_append(method, aml_return(aml_int(s3d))); + aml_append(dev, method); + } else if (hotplug_enabled_dev) { + /* add _SUN/_EJ0 to make slot hotpluggable */ + aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); + + method = aml_method("_EJ0", 1); + aml_append(method, + aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) + ); + aml_append(dev, method); + + if (bsel) { + build_append_pcihp_notify_entry(notify_method, slot); + } + } else if (bridge_in_acpi) { + /* + * device is coldplugged bridge, + * add child device descriptions into its scope + */ + PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev)); - /* Append Device object for each slot */ - for (i = 0; i < PCI_SLOT_MAX; i++) { - bool can_eject = test_bit(i, slot_hotplug_enable); - bool present = test_bit(i, slot_device_present); - bool vga = test_bit(i, slot_device_vga); - bool qxl = test_bit(i, slot_device_qxl); - bool system = test_bit(i, slot_device_system); - if (can_eject) { - void *pcihp = acpi_data_push(bus_table, - ACPI_PCIHP_SIZEOF); - memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF); - patch_pcihp(i, pcihp); - bus_hotplug_support = true; - } else if (qxl) { - void *pcihp = acpi_data_push(bus_table, - ACPI_PCIQXL_SIZEOF); - memcpy(pcihp, ACPI_PCIQXL_AML, ACPI_PCIQXL_SIZEOF); - patch_pciqxl(i, pcihp); - } else if (vga) { - void *pcihp = acpi_data_push(bus_table, - ACPI_PCIVGA_SIZEOF); - memcpy(pcihp, ACPI_PCIVGA_AML, ACPI_PCIVGA_SIZEOF); - patch_pcivga(i, pcihp); - } else if (system) { - /* Nothing to do: system devices are in DSDT or in SSDT above. */ - } else if (present) { - void *pcihp = acpi_data_push(bus_table, - ACPI_PCINOHP_SIZEOF); - memcpy(pcihp, ACPI_PCINOHP_AML, ACPI_PCINOHP_SIZEOF); - patch_pcinohp(i, pcihp); + build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en); } + /* slot descriptor has been composed, add it into parent context */ + aml_append(parent_scope, dev); } if (bsel) { - method = build_alloc_method("DVNT", 2); - - for (i = 0; i < PCI_SLOT_MAX; i++) { - GArray *notify; - uint8_t op; - - if (!test_bit(i, slot_hotplug_enable)) { - continue; - } - - notify = build_alloc_array(); - op = 0xA0; /* IfOp */ - - build_append_byte(notify, 0x7B); /* AndOp */ - build_append_byte(notify, 0x68); /* Arg0Op */ - build_append_int(notify, 0x1U << i); - build_append_byte(notify, 0x00); /* NullName */ - build_append_byte(notify, 0x86); /* NotifyOp */ - build_append_nameseg(notify, "S%.02X", PCI_DEVFN(i, 0)); - build_append_byte(notify, 0x69); /* Arg1Op */ - - /* Pack it up */ - build_package(notify, op, 0); - - build_append_array(method, notify); - - build_free_array(notify); - } - - build_append_and_cleanup_method(bus_table, method); + aml_append(parent_scope, notify_method); } /* Append PCNT method to notify about events on local and child buses. * Add unconditionally for root since DSDT expects it. */ - if (bus_hotplug_support || child->notify_table->len || !bus->parent_dev) { - method = build_alloc_method("PCNT", 0); - - /* If bus supports hotplug select it and notify about local events */ - if (bsel) { - build_append_byte(method, 0x70); /* StoreOp */ - build_append_int(method, qint_get_int(qobject_to_qint(bsel))); - build_append_nameseg(method, "BNUM"); - build_append_nameseg(method, "DVNT"); - build_append_nameseg(method, "PCIU"); - build_append_int(method, 1); /* Device Check */ - build_append_nameseg(method, "DVNT"); - build_append_nameseg(method, "PCID"); - build_append_int(method, 3); /* Eject Request */ - } - - /* Notify about child bus events in any case */ - build_append_array(method, child->notify_table); - - build_append_and_cleanup_method(bus_table, method); + method = aml_method("PCNT", 0); - /* Append description of child buses */ - build_append_array(bus_table, child->device_table); - - /* Pack it up */ - if (bus->parent_dev) { - build_extop_package(bus_table, op); - } else { - build_package(bus_table, op, 0); - } - - /* Append our bus description to parent table */ - build_append_array(parent->device_table, bus_table); - - /* Also tell parent how to notify us, invoking PCNT method. - * At the moment this is not needed for root as we have a single root. - */ - if (bus->parent_dev) { - build_append_byte(parent->notify_table, '^'); /* ParentPrefixChar */ - build_append_byte(parent->notify_table, 0x2E); /* DualNamePrefix */ - build_append_nameseg(parent->notify_table, "S%.02X", - bus->parent_dev->devfn); - build_append_nameseg(parent->notify_table, "PCNT"); - } + /* If bus supports hotplug select it and notify about local events */ + if (bsel) { + int64_t bsel_val = qint_get_int(qobject_to_qint(bsel)); + aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM"))); + aml_append(method, + aml_call2("DVNT", aml_name("PCIU"), aml_int(1) /* Device Check */) + ); + aml_append(method, + aml_call2("DVNT", aml_name("PCID"), aml_int(3)/* Eject Request */) + ); } - qobject_decref(bsel); - build_free_array(bus_table); - build_pci_bus_state_cleanup(child); - g_free(child); -} - -static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size) -{ - ACPI_BUILD_SET_LE(start, size, acpi_pci32_start[0], 32, pci->w32.begin); - - ACPI_BUILD_SET_LE(start, size, acpi_pci32_end[0], 32, pci->w32.end - 1); + /* Notify about child bus events in any case */ + if (pcihp_bridge_en) { + QLIST_FOREACH(sec, &bus->child, sibling) { + int32_t devfn = sec->parent_dev->devfn; - if (pci->w64.end || pci->w64.begin) { - ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 1); - ACPI_BUILD_SET_LE(start, size, acpi_pci64_start[0], 64, pci->w64.begin); - ACPI_BUILD_SET_LE(start, size, acpi_pci64_end[0], 64, pci->w64.end - 1); - ACPI_BUILD_SET_LE(start, size, acpi_pci64_length[0], 64, pci->w64.end - pci->w64.begin); - } else { - ACPI_BUILD_SET_LE(start, size, acpi_pci64_valid[0], 8, 0); + aml_append(method, aml_name("^S%.02X.PCNT", devfn)); + } } + aml_append(parent_scope, method); } static void @@ -1077,112 +658,337 @@ build_ssdt(GArray *table_data, GArray *linker, MachineState *machine = MACHINE(qdev_get_machine()); uint32_t nr_mem = machine->ram_slots; unsigned acpi_cpus = guest_info->apic_id_limit; - int ssdt_start = table_data->len; - uint8_t *ssdt_ptr; + Aml *ssdt, *sb_scope, *scope, *pkg, *dev, *method, *crs, *field, *ifctx; int i; + ssdt = init_aml_allocator(); /* The current AML generator can cover the APIC ID range [0..255], * inclusive, for VCPU hotplug. */ QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256); g_assert(acpi_cpus <= ACPI_CPU_HOTPLUG_ID_LIMIT); - /* Copy header and patch values in the S3_ / S4_ / S5_ packages */ - ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml)); - memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml)); - if (pm->s3_disabled) { - ssdt_ptr[acpi_s3_name[0]] = 'X'; + /* Reserve space for header */ + acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader)); + + scope = aml_scope("\\_SB.PCI0"); + /* build PCI0._CRS */ + crs = aml_resource_template(); + aml_append(crs, + aml_word_bus_number(aml_min_fixed, aml_max_fixed, aml_pos_decode, + 0x0000, 0x0000, 0x00FF, 0x0000, 0x0100)); + aml_append(crs, aml_io(aml_decode16, 0x0CF8, 0x0CF8, 0x01, 0x08)); + + aml_append(crs, + aml_word_io(aml_min_fixed, aml_max_fixed, + aml_pos_decode, aml_entire_range, + 0x0000, 0x0000, 0x0CF7, 0x0000, 0x0CF8)); + aml_append(crs, + aml_word_io(aml_min_fixed, aml_max_fixed, + aml_pos_decode, aml_entire_range, + 0x0000, 0x0D00, 0xFFFF, 0x0000, 0xF300)); + aml_append(crs, + aml_dword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed, + aml_cacheable, aml_ReadWrite, + 0, 0x000A0000, 0x000BFFFF, 0, 0x00020000)); + aml_append(crs, + aml_dword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed, + aml_non_cacheable, aml_ReadWrite, + 0, pci->w32.begin, pci->w32.end - 1, 0, + pci->w32.end - pci->w32.begin)); + if (pci->w64.begin) { + aml_append(crs, + aml_qword_memory(aml_pos_decode, aml_min_fixed, aml_max_fixed, + aml_cacheable, aml_ReadWrite, + 0, pci->w64.begin, pci->w64.end - 1, 0, + pci->w64.end - pci->w64.begin)); } - if (pm->s4_disabled) { - ssdt_ptr[acpi_s4_name[0]] = 'X'; - } else { - ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt_ptr[acpi_s4_pkg[0] + 3] = - pm->s4_val; + aml_append(scope, aml_name_decl("_CRS", crs)); + + /* reserve GPE0 block resources */ + dev = aml_device("GPE0"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); + aml_append(dev, aml_name_decl("_UID", aml_string("GPE0 resources"))); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + crs = aml_resource_template(); + aml_append(crs, + aml_io(aml_decode16, pm->gpe0_blk, pm->gpe0_blk, 1, pm->gpe0_blk_len) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + + /* reserve PCIHP resources */ + if (pm->pcihp_io_len) { + dev = aml_device("PHPR"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06"))); + aml_append(dev, + aml_name_decl("_UID", aml_string("PCI Hotplug resources"))); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + crs = aml_resource_template(); + aml_append(crs, + aml_io(aml_decode16, pm->pcihp_io_base, pm->pcihp_io_base, 1, + pm->pcihp_io_len) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + } + aml_append(ssdt, scope); + + /* create S3_ / S4_ / S5_ packages if necessary */ + scope = aml_scope("\\"); + if (!pm->s3_disabled) { + pkg = aml_package(4); + aml_append(pkg, aml_int(1)); /* PM1a_CNT.SLP_TYP */ + aml_append(pkg, aml_int(1)); /* PM1b_CNT.SLP_TYP, FIXME: not impl. */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(scope, aml_name_decl("_S3", pkg)); } - patch_pci_windows(pci, ssdt_ptr, sizeof(ssdp_misc_aml)); + if (!pm->s4_disabled) { + pkg = aml_package(4); + aml_append(pkg, aml_int(pm->s4_val)); /* PM1a_CNT.SLP_TYP */ + /* PM1b_CNT.SLP_TYP, FIXME: not impl. */ + aml_append(pkg, aml_int(pm->s4_val)); + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(scope, aml_name_decl("_S4", pkg)); + } - ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), - ssdt_isa_pest[0], 16, misc->pvpanic_port); + pkg = aml_package(4); + aml_append(pkg, aml_int(0)); /* PM1a_CNT.SLP_TYP */ + aml_append(pkg, aml_int(0)); /* PM1b_CNT.SLP_TYP not impl. */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(pkg, aml_int(0)); /* reserved */ + aml_append(scope, aml_name_decl("_S5", pkg)); + aml_append(ssdt, scope); + + if (misc->applesmc_io_base) { + scope = aml_scope("\\_SB.PCI0.ISA"); + dev = aml_device("SMC"); + + aml_append(dev, aml_name_decl("_HID", aml_eisaid("APP0001"))); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + + crs = aml_resource_template(); + aml_append(crs, + aml_io(aml_decode16, misc->applesmc_io_base, misc->applesmc_io_base, + 0x01, APPLESMC_MAX_DATA_LENGTH) + ); + aml_append(crs, aml_irq_no_flags(6)); + aml_append(dev, aml_name_decl("_CRS", crs)); + + aml_append(scope, dev); + aml_append(ssdt, scope); + } - ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), - ssdt_mctrl_nr_slots[0], 32, nr_mem); + if (misc->pvpanic_port) { + scope = aml_scope("\\_SB.PCI0.ISA"); - { - GArray *sb_scope = build_alloc_array(); - uint8_t op = 0x10; /* ScopeOp */ + dev = aml_device("PEVR"); + aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); + + crs = aml_resource_template(); + aml_append(crs, + aml_io(aml_decode16, misc->pvpanic_port, misc->pvpanic_port, 1, 1) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); - build_append_nameseg(sb_scope, "_SB"); + aml_append(dev, aml_operation_region("PEOR", aml_system_io, + misc->pvpanic_port, 1)); + field = aml_field("PEOR", aml_byte_acc); + aml_append(field, aml_named_field("PEPT", 8)); + aml_append(dev, field); + + method = aml_method("RDPT", 0); + aml_append(method, aml_store(aml_name("PEPT"), aml_local(0))); + aml_append(method, aml_return(aml_local(0))); + aml_append(dev, method); + + method = aml_method("WRPT", 1); + aml_append(method, aml_store(aml_arg(0), aml_name("PEPT"))); + aml_append(dev, method); + + aml_append(scope, dev); + aml_append(ssdt, scope); + } + + sb_scope = aml_scope("_SB"); + { + /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */ + dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE)); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06"))); + aml_append(dev, + aml_name_decl("_UID", aml_string("CPU Hotplug resources")) + ); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + crs = aml_resource_template(); + aml_append(crs, + aml_io(aml_decode16, pm->cpu_hp_io_base, pm->cpu_hp_io_base, 1, + pm->cpu_hp_io_len) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(sb_scope, dev); + /* declare CPU hotplug MMIO region and PRS field to access it */ + aml_append(sb_scope, aml_operation_region( + "PRST", aml_system_io, pm->cpu_hp_io_base, pm->cpu_hp_io_len)); + field = aml_field("PRST", aml_byte_acc); + aml_append(field, aml_named_field("PRS", 256)); + aml_append(sb_scope, field); /* build Processor object for each processor */ for (i = 0; i < acpi_cpus; i++) { - uint8_t *proc = acpi_data_push(sb_scope, ACPI_PROC_SIZEOF); - memcpy(proc, ACPI_PROC_AML, ACPI_PROC_SIZEOF); - proc[ACPI_PROC_OFFSET_CPUHEX] = acpi_get_hex(i >> 4); - proc[ACPI_PROC_OFFSET_CPUHEX+1] = acpi_get_hex(i); - proc[ACPI_PROC_OFFSET_CPUID1] = i; - proc[ACPI_PROC_OFFSET_CPUID2] = i; + dev = aml_processor(i, 0, 0, "CP%.02X", i); + + method = aml_method("_MAT", 0); + aml_append(method, aml_return(aml_call1("CPMA", aml_int(i)))); + aml_append(dev, method); + + method = aml_method("_STA", 0); + aml_append(method, aml_return(aml_call1("CPST", aml_int(i)))); + aml_append(dev, method); + + method = aml_method("_EJ0", 1); + aml_append(method, + aml_return(aml_call2("CPEJ", aml_int(i), aml_arg(0))) + ); + aml_append(dev, method); + + aml_append(sb_scope, dev); } /* build this code: * Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...} */ /* Arg0 = Processor ID = APIC ID */ - build_append_notify_method(sb_scope, "NTFY", "CP%0.02X", acpi_cpus); - - /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */ - build_append_byte(sb_scope, 0x08); /* NameOp */ - build_append_nameseg(sb_scope, "CPON"); - - { - GArray *package = build_alloc_array(); - uint8_t op; - - /* - * Note: The ability to create variable-sized packages was first introduced in ACPI 2.0. ACPI 1.0 only - * allowed fixed-size packages with up to 255 elements. - * Windows guests up to win2k8 fail when VarPackageOp is used. - */ - if (acpi_cpus <= 255) { - op = 0x12; /* PackageOp */ - build_append_byte(package, acpi_cpus); /* NumElements */ - } else { - op = 0x13; /* VarPackageOp */ - build_append_int(package, acpi_cpus); /* VarNumElements */ - } - - for (i = 0; i < acpi_cpus; i++) { - uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00; - build_append_byte(package, b); - } - - build_package(package, op, 2); - build_append_array(sb_scope, package); - build_free_array(package); + method = aml_method("NTFY", 2); + for (i = 0; i < acpi_cpus; i++) { + ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i))); + aml_append(ifctx, + aml_notify(aml_name("CP%.02X", i), aml_arg(1)) + ); + aml_append(method, ifctx); } + aml_append(sb_scope, method); + + /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" + * + * Note: The ability to create variable-sized packages was first + * introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages + * ith up to 255 elements. Windows guests up to win2k8 fail when + * VarPackageOp is used. + */ + pkg = acpi_cpus <= 255 ? aml_package(acpi_cpus) : + aml_varpackage(acpi_cpus); - if (nr_mem) { - assert(nr_mem <= ACPI_MAX_RAM_SLOTS); - /* build memory devices */ - for (i = 0; i < nr_mem; i++) { - char id[3]; - uint8_t *mem = acpi_data_push(sb_scope, ACPI_MEM_SIZEOF); - - snprintf(id, sizeof(id), "%02X", i); - memcpy(mem, ACPI_MEM_AML, ACPI_MEM_SIZEOF); - memcpy(mem + ACPI_MEM_OFFSET_HEX, id, 2); - memcpy(mem + ACPI_MEM_OFFSET_ID, id, 2); - } + for (i = 0; i < acpi_cpus; i++) { + uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00; + aml_append(pkg, aml_int(b)); + } + aml_append(sb_scope, aml_name_decl("CPON", pkg)); + + /* build memory devices */ + assert(nr_mem <= ACPI_MAX_RAM_SLOTS); + scope = aml_scope("\\_SB.PCI0." stringify(MEMORY_HOTPLUG_DEVICE)); + aml_append(scope, + aml_name_decl(stringify(MEMORY_SLOTS_NUMBER), aml_int(nr_mem)) + ); + + crs = aml_resource_template(); + aml_append(crs, + aml_io(aml_decode16, pm->mem_hp_io_base, pm->mem_hp_io_base, 0, + pm->mem_hp_io_len) + ); + aml_append(scope, aml_name_decl("_CRS", crs)); + + aml_append(scope, aml_operation_region( + stringify(MEMORY_HOTPLUG_IO_REGION), aml_system_io, + pm->mem_hp_io_base, pm->mem_hp_io_len) + ); + + field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc); + aml_append(field, /* read only */ + aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32)); + aml_append(field, /* read only */ + aml_named_field(stringify(MEMORY_SLOT_ADDR_HIGH), 32)); + aml_append(field, /* read only */ + aml_named_field(stringify(MEMORY_SLOT_SIZE_LOW), 32)); + aml_append(field, /* read only */ + aml_named_field(stringify(MEMORY_SLOT_SIZE_HIGH), 32)); + aml_append(field, /* read only */ + aml_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32)); + aml_append(scope, field); + + field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc); + aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */)); + aml_append(field, /* 1 if enabled, read only */ + aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1)); + aml_append(field, + /*(read) 1 if has a insert event. (write) 1 to clear event */ + aml_named_field(stringify(MEMORY_SLOT_INSERT_EVENT), 1)); + aml_append(scope, field); + + field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc); + aml_append(field, /* DIMM selector, write only */ + aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32)); + aml_append(field, /* _OST event code, write only */ + aml_named_field(stringify(MEMORY_SLOT_OST_EVENT), 32)); + aml_append(field, /* _OST status code, write only */ + aml_named_field(stringify(MEMORY_SLOT_OST_STATUS), 32)); + aml_append(scope, field); + + aml_append(sb_scope, scope); + + for (i = 0; i < nr_mem; i++) { + #define BASEPATH "\\_SB.PCI0." stringify(MEMORY_HOTPLUG_DEVICE) "." + const char *s; + + dev = aml_device("MP%02X", i); + aml_append(dev, aml_name_decl("_UID", aml_string("0x%02X", i))); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C80"))); + + method = aml_method("_CRS", 0); + s = BASEPATH stringify(MEMORY_SLOT_CRS_METHOD); + aml_append(method, aml_return(aml_call1(s, aml_name("_UID")))); + aml_append(dev, method); + + method = aml_method("_STA", 0); + s = BASEPATH stringify(MEMORY_SLOT_STATUS_METHOD); + aml_append(method, aml_return(aml_call1(s, aml_name("_UID")))); + aml_append(dev, method); + + method = aml_method("_PXM", 0); + s = BASEPATH stringify(MEMORY_SLOT_PROXIMITY_METHOD); + aml_append(method, aml_return(aml_call1(s, aml_name("_UID")))); + aml_append(dev, method); + + method = aml_method("_OST", 3); + s = BASEPATH stringify(MEMORY_SLOT_OST_METHOD); + aml_append(method, aml_return(aml_call4( + s, aml_name("_UID"), aml_arg(0), aml_arg(1), aml_arg(2) + ))); + aml_append(dev, method); + + aml_append(sb_scope, dev); + } - /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) { - * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... - */ - build_append_notify_method(sb_scope, - stringify(MEMORY_SLOT_NOTIFY_METHOD), - "MP%0.02X", nr_mem); + /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) { + * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... + */ + method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2); + for (i = 0; i < nr_mem; i++) { + ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i))); + aml_append(ifctx, + aml_notify(aml_name("MP%.02X", i), aml_arg(1)) + ); + aml_append(method, ifctx); } + aml_append(sb_scope, method); { - AcpiBuildPciBusHotplugState hotplug_state; Object *pci_host; PCIBus *bus = NULL; bool ambiguous; @@ -1192,26 +998,22 @@ build_ssdt(GArray *table_data, GArray *linker, bus = PCI_HOST_BRIDGE(pci_host)->bus; } - build_pci_bus_state_init(&hotplug_state, NULL, pm->pcihp_bridge_en); - if (bus) { + Aml *scope = aml_scope("PCI0"); /* Scan all PCI buses. Generate tables to support hotplug. */ - pci_for_each_bus_depth_first(bus, build_pci_bus_begin, - build_pci_bus_end, &hotplug_state); + build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); + aml_append(sb_scope, scope); } - - build_append_array(sb_scope, hotplug_state.device_table); - build_pci_bus_state_cleanup(&hotplug_state); } - - build_package(sb_scope, op, 3); - build_append_array(table_data, sb_scope); - build_free_array(sb_scope); + aml_append(ssdt, sb_scope); } + /* copy AML table into ACPI tables blob and patch header there */ + g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len); build_header(linker, table_data, - (void *)(table_data->data + ssdt_start), - "SSDT", table_data->len - ssdt_start, 1); + (void *)(table_data->data + table_data->len - ssdt->buf->len), + "SSDT", ssdt->buf->len, 1); + free_aml_allocator(); } static void @@ -1513,7 +1315,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) { void *linker_data = bios_linker_loader_cleanup(tables->linker); g_free(linker_data); - g_array_free(tables->rsdp, mfre); + g_array_free(tables->rsdp, true); g_array_free(tables->table_data, true); g_array_free(tables->tcpalog, mfre); } @@ -1522,10 +1324,12 @@ typedef struct AcpiBuildState { /* Copy of table in RAM (for patching). */ ram_addr_t table_ram; - uint32_t table_size; /* Is table patched? */ uint8_t patched; PcGuestInfo *guest_info; + void *rsdp; + ram_addr_t rsdp_ram; + ram_addr_t linker_ram; } AcpiBuildState; static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg) @@ -1574,6 +1378,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) PcPciInfo pci; uint8_t *u; size_t aml_len = 0; + GArray *tables_blob = tables->table_data; acpi_get_cpu_info(&cpu); acpi_get_pm_info(&pm); @@ -1594,74 +1399,72 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) * We place it first since it's the only table that has alignment * requirements. */ - facs = tables->table_data->len; - build_facs(tables->table_data, tables->linker, guest_info); + facs = tables_blob->len; + build_facs(tables_blob, tables->linker, guest_info); /* DSDT is pointed to by FADT */ - dsdt = tables->table_data->len; - build_dsdt(tables->table_data, tables->linker, &misc); + dsdt = tables_blob->len; + build_dsdt(tables_blob, tables->linker, &misc); /* Count the size of the DSDT and SSDT, we will need it for legacy * sizing of ACPI tables. */ - aml_len += tables->table_data->len - dsdt; + aml_len += tables_blob->len - dsdt; /* ACPI tables pointed to by RSDT */ - acpi_add_table(table_offsets, tables->table_data); - build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt); + acpi_add_table(table_offsets, tables_blob); + build_fadt(tables_blob, tables->linker, &pm, facs, dsdt); - ssdt = tables->table_data->len; - acpi_add_table(table_offsets, tables->table_data); - build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci, + ssdt = tables_blob->len; + acpi_add_table(table_offsets, tables_blob); + build_ssdt(tables_blob, tables->linker, &cpu, &pm, &misc, &pci, guest_info); - aml_len += tables->table_data->len - ssdt; + aml_len += tables_blob->len - ssdt; - acpi_add_table(table_offsets, tables->table_data); - build_madt(tables->table_data, tables->linker, &cpu, guest_info); + acpi_add_table(table_offsets, tables_blob); + build_madt(tables_blob, tables->linker, &cpu, guest_info); if (misc.has_hpet) { - acpi_add_table(table_offsets, tables->table_data); - build_hpet(tables->table_data, tables->linker); + acpi_add_table(table_offsets, tables_blob); + build_hpet(tables_blob, tables->linker); } if (misc.has_tpm) { - acpi_add_table(table_offsets, tables->table_data); - build_tpm_tcpa(tables->table_data, tables->linker, tables->tcpalog); + acpi_add_table(table_offsets, tables_blob); + build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog); - acpi_add_table(table_offsets, tables->table_data); - build_tpm_ssdt(tables->table_data, tables->linker); + acpi_add_table(table_offsets, tables_blob); + build_tpm_ssdt(tables_blob, tables->linker); } if (guest_info->numa_nodes) { - acpi_add_table(table_offsets, tables->table_data); - build_srat(tables->table_data, tables->linker, guest_info); + acpi_add_table(table_offsets, tables_blob); + build_srat(tables_blob, tables->linker, guest_info); } if (acpi_get_mcfg(&mcfg)) { - acpi_add_table(table_offsets, tables->table_data); - build_mcfg_q35(tables->table_data, tables->linker, &mcfg); + acpi_add_table(table_offsets, tables_blob); + build_mcfg_q35(tables_blob, tables->linker, &mcfg); } if (acpi_has_iommu()) { - acpi_add_table(table_offsets, tables->table_data); - build_dmar_q35(tables->table_data, tables->linker); + acpi_add_table(table_offsets, tables_blob); + build_dmar_q35(tables_blob, tables->linker); } /* Add tables supplied by user (if any) */ for (u = acpi_table_first(); u; u = acpi_table_next(u)) { unsigned len = acpi_table_len(u); - acpi_add_table(table_offsets, tables->table_data); - g_array_append_vals(tables->table_data, u, len); + acpi_add_table(table_offsets, tables_blob); + g_array_append_vals(tables_blob, u, len); } /* RSDT is pointed to by RSDP */ - rsdt = tables->table_data->len; - build_rsdt(tables->table_data, tables->linker, table_offsets); + rsdt = tables_blob->len; + build_rsdt(tables_blob, tables->linker, table_offsets); /* RSDP is in FSEG memory, so allocate it separately */ build_rsdp(tables->rsdp, tables->linker, rsdt); /* We'll expose it all to Guest so we want to reduce * chance of size changes. - * RSDP is small so it's easy to keep it immutable, no need to - * bother with alignment. * * We used to align the tables to 4k, but of course this would * too simple to be enough. 4k turned out to be too small an @@ -1685,23 +1488,23 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) guest_info->legacy_acpi_table_size + ACPI_BUILD_LEGACY_CPU_AML_SIZE * max_cpus; int legacy_table_size = - ROUND_UP(tables->table_data->len - aml_len + legacy_aml_len, + ROUND_UP(tables_blob->len - aml_len + legacy_aml_len, ACPI_BUILD_ALIGN_SIZE); - if (tables->table_data->len > legacy_table_size) { + if (tables_blob->len > legacy_table_size) { /* Should happen only with PCI bridges and -M pc-i440fx-2.0. */ error_report("Warning: migration may not work."); } - g_array_set_size(tables->table_data, legacy_table_size); + g_array_set_size(tables_blob, legacy_table_size); } else { /* Make sure we have a buffer in case we need to resize the tables. */ - if (tables->table_data->len > ACPI_BUILD_TABLE_SIZE / 2) { + if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) { /* As of QEMU 2.1, this fires with 160 VCPUs and 255 memory slots. */ error_report("Warning: ACPI tables are larger than 64k."); error_report("Warning: migration may not work."); error_report("Warning: please remove CPUs, NUMA nodes, " "memory slots or PCI bridges."); } - acpi_align_size(tables->table_data, ACPI_BUILD_TABLE_SIZE); + acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE); } acpi_align_size(tables->linker, ACPI_BUILD_ALIGN_SIZE); @@ -1710,6 +1513,17 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) g_array_free(table_offsets, true); } +static void acpi_ram_update(ram_addr_t ram, GArray *data) +{ + uint32_t size = acpi_data_len(data); + + /* Make sure RAM size is correct - in case it got changed e.g. by migration */ + qemu_ram_resize(ram, size, &error_abort); + + memcpy(qemu_get_ram_ptr(ram), data->data, size); + cpu_physical_memory_set_dirty_range_nocode(ram, size); +} + static void acpi_build_update(void *build_opaque, uint32_t offset) { AcpiBuildState *build_state = build_opaque; @@ -1725,18 +1539,15 @@ static void acpi_build_update(void *build_opaque, uint32_t offset) acpi_build(build_state->guest_info, &tables); - assert(acpi_data_len(tables.table_data) == build_state->table_size); - - /* Make sure RAM size is correct - in case it got changed by migration */ - qemu_ram_resize(build_state->table_ram, build_state->table_size, - &error_abort); + acpi_ram_update(build_state->table_ram, tables.table_data); - memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data, - build_state->table_size); - - cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram, - build_state->table_size); + if (build_state->rsdp) { + memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp)); + } else { + acpi_ram_update(build_state->rsdp_ram, tables.rsdp); + } + acpi_ram_update(build_state->linker_ram, tables.linker); acpi_build_tables_cleanup(&tables, true); } @@ -1797,19 +1608,31 @@ void acpi_setup(PcGuestInfo *guest_info) ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TABLE_MAX_SIZE); assert(build_state->table_ram != RAM_ADDR_MAX); - build_state->table_size = acpi_data_len(tables.table_data); - acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader", 0); + build_state->linker_ram = + acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0); fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data, acpi_data_len(tables.tcpalog)); - /* - * RSDP is small so it's easy to keep it immutable, no need to - * bother with ROM blobs. - */ - fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE, - tables.rsdp->data, acpi_data_len(tables.rsdp)); + if (!guest_info->rsdp_in_ram) { + /* + * Keep for compatibility with old machine types. + * Though RSDP is small, its contents isn't immutable, so + * we'll update it along with the rest of tables on guest access. + */ + uint32_t rsdp_size = acpi_data_len(tables.rsdp); + + build_state->rsdp = g_memdup(tables.rsdp->data, rsdp_size); + fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE, + acpi_build_update, build_state, + build_state->rsdp, rsdp_size); + build_state->rsdp_ram = (ram_addr_t)-1; + } else { + build_state->rsdp = NULL; + build_state->rsdp_ram = acpi_add_rom_blob(build_state, tables.rsdp, + ACPI_BUILD_RSDP_FILE, 0); + } qemu_register_reset(acpi_build_reset, build_state); acpi_build_reset(build_state); diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl index 268d870..1aff746 100644 --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl @@ -16,12 +16,12 @@ /**************************************************************** * CPU hotplug ****************************************************************/ -#define CPU_HOTPLUG_RESOURCE_DEVICE PRES Scope(\_SB) { /* Objects filled in by run-time generated SSDT */ External(NTFY, MethodObj) External(CPON, PkgObj) + External(PRS, FieldUnitObj) /* Methods called by run-time generated SSDT Processor objects */ Method(CPMA, 1, NotSerialized) { @@ -54,10 +54,6 @@ Scope(\_SB) { } #define CPU_STATUS_LEN ACPI_GPE_PROC_LEN - OperationRegion(PRST, SystemIO, CPU_STATUS_BASE, CPU_STATUS_LEN) - Field(PRST, ByteAcc, NoLock, Preserve) { - PRS, 256 - } Method(PRSC, 0) { // Local5 = active cpu bitmap Store(PRS, Local5) @@ -91,15 +87,4 @@ Scope(\_SB) { Increment(Local0) } } - - Device(CPU_HOTPLUG_RESOURCE_DEVICE) { - Name(_HID, EisaId("PNP0A06")) - Name(_UID, "CPU hotplug resources") - - Name(_CRS, ResourceTemplate() { - IO(Decode16, CPU_STATUS_BASE, CPU_STATUS_BASE, 0, CPU_STATUS_LEN) - }) - - Name(_STA, 0xB) /* present, functioning, decoding, not shown in UI */ - } } diff --git a/hw/i386/acpi-dsdt-isa.dsl b/hw/i386/acpi-dsdt-isa.dsl index deb37de..89caa16 100644 --- a/hw/i386/acpi-dsdt-isa.dsl +++ b/hw/i386/acpi-dsdt-isa.dsl @@ -16,17 +16,6 @@ /* Common legacy ISA style devices. */ Scope(\_SB.PCI0.ISA) { - Device (SMC) { - Name(_HID, EisaId("APP0001")) - /* _STA will be patched to 0x0B if AppleSMC is present */ - ACPI_EXTRACT_NAME_BYTE_CONST DSDT_APPLESMC_STA - Name(_STA, 0xF0) - Name(_CRS, ResourceTemplate () { - IO (Decode16, 0x0300, 0x0300, 0x01, 0x20) - IRQNoFlags() { 6 } - }) - } - Device(RTC) { Name(_HID, EisaId("PNP0B00")) Name(_CRS, ResourceTemplate() { diff --git a/hw/i386/acpi-dsdt-mem-hotplug.dsl b/hw/i386/acpi-dsdt-mem-hotplug.dsl index 2a36c47..1e9ec39 100644 --- a/hw/i386/acpi-dsdt-mem-hotplug.dsl +++ b/hw/i386/acpi-dsdt-mem-hotplug.dsl @@ -22,14 +22,16 @@ External(MEMORY_SLOTS_NUMBER, IntObj) /* Memory hotplug IO registers */ - OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO, - ACPI_MEMORY_HOTPLUG_BASE, - ACPI_MEMORY_HOTPLUG_IO_LEN) - - Name(_CRS, ResourceTemplate() { - IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE, - 0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO) - }) + External(MEMORY_SLOT_ADDR_LOW, FieldUnitObj) // read only + External(MEMORY_SLOT_ADDR_HIGH, FieldUnitObj) // read only + External(MEMORY_SLOT_SIZE_LOW, FieldUnitObj) // read only + External(MEMORY_SLOT_SIZE_HIGH, FieldUnitObj) // read only + External(MEMORY_SLOT_PROXIMITY, FieldUnitObj) // read only + External(MEMORY_SLOT_ENABLED, FieldUnitObj) // 1 if enabled, read only + External(MEMORY_SLOT_INSERT_EVENT, FieldUnitObj) // (read) 1 if has a insert event. (write) 1 to clear event + External(MEMORY_SLOT_SLECTOR, FieldUnitObj) // DIMM selector, write only + External(MEMORY_SLOT_OST_EVENT, FieldUnitObj) // _OST event code, write only + External(MEMORY_SLOT_OST_STATUS, FieldUnitObj) // _OST status code, write only Method(_STA, 0) { If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) { @@ -39,25 +41,7 @@ Return(0xB) } - Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) { - MEMORY_SLOT_ADDR_LOW, 32, // read only - MEMORY_SLOT_ADDR_HIGH, 32, // read only - MEMORY_SLOT_SIZE_LOW, 32, // read only - MEMORY_SLOT_SIZE_HIGH, 32, // read only - MEMORY_SLOT_PROXIMITY, 32, // read only - } - Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) { - Offset(20), - MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only - MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event - } - Mutex (MEMORY_SLOT_LOCK, 0) - Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) { - MEMORY_SLOT_SLECTOR, 32, // DIMM selector, write only - MEMORY_SLOT_OST_EVENT, 32, // _OST event code, write only - MEMORY_SLOT_OST_STATUS, 32, // _OST status code, write only - } Method(MEMORY_SLOT_SCAN_METHOD, 0) { If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) { diff --git a/hw/i386/acpi-dsdt-pci-crs.dsl b/hw/i386/acpi-dsdt-pci-crs.dsl deleted file mode 100644 index 4648e90..0000000 --- a/hw/i386/acpi-dsdt-pci-crs.dsl +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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; either version 2 of the License, or - * (at your option) any later version. - - * 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/>. - */ - -/* PCI CRS (current resources) definition. */ -Scope(\_SB.PCI0) { - - Name(CRES, ResourceTemplate() { - WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode, - 0x0000, // Address Space Granularity - 0x0000, // Address Range Minimum - 0x00FF, // Address Range Maximum - 0x0000, // Address Translation Offset - 0x0100, // Address Length - ,, ) - IO(Decode16, - 0x0CF8, // Address Range Minimum - 0x0CF8, // Address Range Maximum - 0x01, // Address Alignment - 0x08, // Address Length - ) - BOARD_SPECIFIC_PCI_RESOURSES - DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, - 0x00000000, // Address Space Granularity - 0x000A0000, // Address Range Minimum - 0x000BFFFF, // Address Range Maximum - 0x00000000, // Address Translation Offset - 0x00020000, // Address Length - ,, , AddressRangeMemory, TypeStatic) - DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, - 0x00000000, // Address Space Granularity - 0xE0000000, // Address Range Minimum - 0xFEBFFFFF, // Address Range Maximum - 0x00000000, // Address Translation Offset - 0x1EC00000, // Address Length - ,, PW32, AddressRangeMemory, TypeStatic) - }) - - Name(CR64, ResourceTemplate() { - QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, - 0x00000000, // Address Space Granularity - 0x8000000000, // Address Range Minimum - 0xFFFFFFFFFF, // Address Range Maximum - 0x00000000, // Address Translation Offset - 0x8000000000, // Address Length - ,, PW64, AddressRangeMemory, TypeStatic) - }) - - Method(_CRS, 0) { - /* Fields provided by dynamically created ssdt */ - External(P0S, IntObj) - External(P0E, IntObj) - External(P1V, IntObj) - External(P1S, BuffObj) - External(P1E, BuffObj) - External(P1L, BuffObj) - - /* fixup 32bit pci io window */ - CreateDWordField(CRES, \_SB.PCI0.PW32._MIN, PS32) - CreateDWordField(CRES, \_SB.PCI0.PW32._MAX, PE32) - CreateDWordField(CRES, \_SB.PCI0.PW32._LEN, PL32) - Store(P0S, PS32) - Store(P0E, PE32) - Store(Add(Subtract(P0E, P0S), 1), PL32) - - If (LEqual(P1V, Zero)) { - Return (CRES) - } - - /* fixup 64bit pci io window */ - CreateQWordField(CR64, \_SB.PCI0.PW64._MIN, PS64) - CreateQWordField(CR64, \_SB.PCI0.PW64._MAX, PE64) - CreateQWordField(CR64, \_SB.PCI0.PW64._LEN, PL64) - Store(P1S, PS64) - Store(P1E, PE64) - Store(P1L, PL64) - /* add window and return result */ - ConcatenateResTemplate(CRES, CR64, Local0) - Return (Local0) - } -} diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl index a611e07..a2d84ec 100644 --- a/hw/i386/acpi-dsdt.dsl +++ b/hw/i386/acpi-dsdt.dsl @@ -31,50 +31,6 @@ DefinitionBlock ( #include "acpi-dsdt-dbug.dsl" - -/**************************************************************** - * PCI Bus definition - ****************************************************************/ -#define BOARD_SPECIFIC_PCI_RESOURSES \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0x0000, \ - 0x0CF7, \ - 0x0000, \ - 0x0CF8, \ - ,, , TypeStatic) \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0x0D00, \ - 0xADFF, \ - 0x0000, \ - 0xA100, \ - ,, , TypeStatic) \ - /* 0xae00-0xae0e hole for PCI hotplug, hw/acpi/piix4.c:PCI_HOTPLUG_ADDR */ \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0xAE0F, \ - 0xAEFF, \ - 0x0000, \ - 0x00F1, \ - ,, , TypeStatic) \ - /* 0xaf00-0xaf1f hole for CPU hotplug, hw/acpi/piix4.c:PIIX4_PROC_BASE */ \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0xAF20, \ - 0xAFDF, \ - 0x0000, \ - 0x00C0, \ - ,, , TypeStatic) \ - /* 0xafe0-0xafe3 hole for ACPI.GPE0, hw/acpi/piix4.c:GPE_BASE */ \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0xAFE4, \ - 0xFFFF, \ - 0x0000, \ - 0x501C, \ - ,, , TypeStatic) - Scope(\_SB) { Device(PCI0) { Name(_HID, EisaId("PNP0A03")) @@ -85,7 +41,6 @@ DefinitionBlock ( } } -#include "acpi-dsdt-pci-crs.dsl" #include "acpi-dsdt-hpet.dsl" @@ -130,7 +85,6 @@ DefinitionBlock ( } } -#define DSDT_APPLESMC_STA piix_dsdt_applesmc_sta #include "acpi-dsdt-isa.dsl" diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated index 498b194..ecaa4a5 100644 --- a/hw/i386/acpi-dsdt.hex.generated +++ b/hw/i386/acpi-dsdt.hex.generated @@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x53, 0x44, 0x54, -0x25, -0xe, +0x9a, +0xb, 0x0, 0x0, 0x1, -0x6c, +0xf8, 0x42, 0x58, 0x50, @@ -145,405 +145,6 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x44, 0x1, 0x10, -0x4e, -0x18, -0x2e, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x8, -0x43, -0x52, -0x45, -0x53, -0x11, -0x42, -0xa, -0xa, -0x9e, -0x88, -0xd, -0x0, -0x2, -0xc, -0x0, -0x0, -0x0, -0x0, -0x0, -0xff, -0x0, -0x0, -0x0, -0x0, -0x1, -0x47, -0x1, -0xf8, -0xc, -0xf8, -0xc, -0x1, -0x8, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0x0, -0x0, -0xf7, -0xc, -0x0, -0x0, -0xf8, -0xc, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0x0, -0xd, -0xff, -0xad, -0x0, -0x0, -0x0, -0xa1, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0xf, -0xae, -0xff, -0xae, -0x0, -0x0, -0xf1, -0x0, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0x20, -0xaf, -0xdf, -0xaf, -0x0, -0x0, -0xc0, -0x0, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0xe4, -0xaf, -0xff, -0xff, -0x0, -0x0, -0x1c, -0x50, -0x87, -0x17, -0x0, -0x0, -0xc, -0x3, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0xa, -0x0, -0xff, -0xff, -0xb, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x2, -0x0, -0x87, -0x17, -0x0, -0x0, -0xc, -0x1, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0xe0, -0xff, -0xff, -0xbf, -0xfe, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0xc0, -0x1e, -0x79, -0x0, -0x8, -0x43, -0x52, -0x36, -0x34, -0x11, -0x33, -0xa, -0x30, -0x8a, -0x2b, -0x0, -0x0, -0xc, -0x3, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x80, -0x0, -0x0, -0x0, -0xff, -0xff, -0xff, -0xff, -0xff, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x80, -0x0, -0x0, -0x0, -0x79, -0x0, -0x14, -0x41, -0xa, -0x5f, -0x43, -0x52, -0x53, -0x0, -0x8a, -0x43, -0x52, -0x45, -0x53, -0xa, -0x8c, -0x50, -0x53, -0x33, -0x32, -0x8a, -0x43, -0x52, -0x45, -0x53, -0xa, -0x90, -0x50, -0x45, -0x33, -0x32, -0x8a, -0x43, -0x52, -0x45, -0x53, -0xa, -0x98, -0x50, -0x4c, -0x33, -0x32, -0x70, -0x50, -0x30, -0x53, -0x5f, -0x50, -0x53, -0x33, -0x32, -0x70, -0x50, -0x30, -0x45, -0x5f, -0x50, -0x45, -0x33, -0x32, -0x70, -0x72, -0x74, -0x50, -0x30, -0x45, -0x5f, -0x50, -0x30, -0x53, -0x5f, -0x0, -0x1, -0x0, -0x50, -0x4c, -0x33, -0x32, -0xa0, -0xc, -0x93, -0x50, -0x31, -0x56, -0x5f, -0x0, -0xa4, -0x43, -0x52, -0x45, -0x53, -0x8f, -0x43, -0x52, -0x36, -0x34, -0xa, -0xe, -0x50, -0x53, -0x36, -0x34, -0x8f, -0x43, -0x52, -0x36, -0x34, -0xa, -0x16, -0x50, -0x45, -0x36, -0x34, -0x8f, -0x43, -0x52, -0x36, -0x34, -0xa, -0x26, -0x50, -0x4c, -0x36, -0x34, -0x70, -0x50, -0x31, -0x53, -0x5f, -0x50, -0x53, -0x36, -0x34, -0x70, -0x50, -0x31, -0x45, -0x5f, -0x50, -0x45, -0x36, -0x34, -0x70, -0x50, -0x31, -0x4c, -0x5f, -0x50, -0x4c, -0x36, -0x34, -0x84, -0x43, -0x52, -0x45, -0x53, -0x43, -0x52, -0x36, -0x34, -0x60, -0xa4, -0x60, -0x10, 0x4d, 0x8, 0x5f, @@ -811,8 +412,8 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x4e, 0x1, 0x10, -0x4a, -0x1e, +0x4c, +0x1b, 0x2f, 0x3, 0x5f, @@ -829,52 +430,6 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x5f, 0x5b, 0x82, -0x2c, -0x53, -0x4d, -0x43, -0x5f, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xc, -0x6, -0x10, -0x0, -0x1, -0x8, -0x5f, -0x53, -0x54, -0x41, -0xa, -0xf0, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0x10, -0xa, -0xd, -0x47, -0x1, -0x0, -0x3, -0x0, -0x3, -0x1, -0x20, -0x22, -0x40, -0x0, -0x79, -0x0, -0x5b, -0x82, 0x2d, 0x52, 0x54, @@ -2318,8 +1873,8 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x53, 0x1, 0x10, -0x4f, -0x12, +0x4d, +0xc, 0x5f, 0x53, 0x42, @@ -2416,32 +1971,6 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x22, 0xa, 0xc8, -0x5b, -0x80, -0x50, -0x52, -0x53, -0x54, -0x1, -0xb, -0x0, -0xaf, -0xa, -0x20, -0x5b, -0x81, -0xc, -0x50, -0x52, -0x53, -0x54, -0x1, -0x50, -0x52, -0x53, -0x5f, -0x40, -0x10, 0x14, 0x4a, 0x6, @@ -2549,81 +2078,9 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x3, 0x75, 0x60, -0x5b, -0x82, -0x46, -0x4, -0x50, -0x52, -0x45, -0x53, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xc, -0x41, -0xd0, -0xa, -0x6, -0x8, -0x5f, -0x55, -0x49, -0x44, -0xd, -0x43, -0x50, -0x55, -0x20, -0x68, -0x6f, -0x74, -0x70, -0x6c, -0x75, -0x67, -0x20, -0x72, -0x65, -0x73, -0x6f, -0x75, -0x72, -0x63, -0x65, -0x73, -0x0, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0xd, -0xa, -0xa, -0x47, -0x1, -0x0, -0xaf, -0x0, -0xaf, -0x0, -0x20, -0x79, -0x0, -0x8, -0x5f, -0x53, -0x54, -0x41, -0xa, -0xb, 0x10, -0x40, -0x31, +0x44, +0x2a, 0x2e, 0x5f, 0x53, @@ -2635,8 +2092,8 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x30, 0x5b, 0x82, -0x43, -0x30, +0x47, +0x29, 0x4d, 0x48, 0x50, @@ -2686,37 +2143,6 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x65, 0x73, 0x0, -0x5b, -0x80, -0x48, -0x50, -0x4d, -0x52, -0x1, -0xb, -0x0, -0xa, -0xa, -0x18, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0xd, -0xa, -0xa, -0x47, -0x1, -0x0, -0xa, -0x0, -0xa, -0x0, -0x18, -0x79, -0x0, 0x14, 0x13, 0x5f, @@ -2738,89 +2164,12 @@ static unsigned char AcpiDsdtAmlCode[] = { 0xa, 0xb, 0x5b, -0x81, -0x1f, -0x48, -0x50, -0x4d, -0x52, -0x3, -0x4d, -0x52, -0x42, -0x4c, -0x20, -0x4d, -0x52, -0x42, -0x48, -0x20, -0x4d, -0x52, -0x4c, -0x4c, -0x20, -0x4d, -0x52, -0x4c, -0x48, -0x20, -0x4d, -0x50, -0x58, -0x5f, -0x20, -0x5b, -0x81, -0x13, -0x48, -0x50, -0x4d, -0x52, -0x1, -0x0, -0x40, -0xa, -0x4d, -0x45, -0x53, -0x5f, -0x1, -0x4d, -0x49, -0x4e, -0x53, -0x1, -0x5b, 0x1, 0x4d, 0x4c, 0x43, 0x4b, 0x0, -0x5b, -0x81, -0x15, -0x48, -0x50, -0x4d, -0x52, -0x3, -0x4d, -0x53, -0x45, -0x4c, -0x20, -0x4d, -0x4f, -0x45, -0x56, -0x20, -0x4d, -0x4f, -0x53, -0x43, -0x20, 0x14, 0x4a, 0x4, @@ -3621,6 +2970,3 @@ static unsigned char AcpiDsdtAmlCode[] = { 0x46, 0x0 }; -static unsigned short piix_dsdt_applesmc_sta[] = { -0x353 -}; diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index bd92c69..9db7c77 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -1738,7 +1738,7 @@ static void reset_assigned_device(DeviceState *dev) assigned_dev_pci_write_config(pci_dev, PCI_COMMAND, 0, 1); } -static int assigned_initfn(struct PCIDevice *pci_dev) +static void assigned_realize(struct PCIDevice *pci_dev, Error **errp) { AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev); uint8_t e_intx; @@ -1821,7 +1821,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev) assigned_dev_load_option_rom(dev); - return 0; + return; assigned_out: deassign_device(dev); @@ -1831,9 +1831,7 @@ out: exit_with_error: assert(local_err); - qerror_report_err(local_err); - error_free(local_err); - return -1; + error_propagate(errp, local_err); } static void assigned_exitfn(struct PCIDevice *pci_dev) @@ -1869,7 +1867,7 @@ static void assign_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = assigned_initfn; + k->realize = assigned_realize; k->exit = assigned_exitfn; k->config_read = assigned_dev_pci_read_config; k->config_write = assigned_dev_pci_write_config; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b229856..79eaad5 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1241,6 +1241,13 @@ FWCfgState *pc_memory_init(MachineState *machine, exit(EXIT_FAILURE); } + if (QEMU_ALIGN_UP(machine->maxram_size, + TARGET_PAGE_SIZE) != machine->maxram_size) { + error_report("maximum memory size must by aligned to multiple of " + "%d bytes", TARGET_PAGE_SIZE); + exit(EXIT_FAILURE); + } + pcms->hotplug_memory_base = ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30); @@ -1666,6 +1673,20 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev, } } +static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "acpi: device unplug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} + +static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} + static HotplugHandler *pc_get_hotpug_handler(MachineState *machine, DeviceState *dev) { @@ -1795,6 +1816,8 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->get_hotplug_handler = mc->get_hotplug_handler; mc->get_hotplug_handler = pc_get_hotpug_handler; hc->plug = pc_machine_device_plug_cb; + hc->unplug_request = pc_machine_device_unplug_request_cb; + hc->unplug = pc_machine_device_unplug_cb; } static const TypeInfo pc_machine_info = { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index de75cf0..8eab4ba 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -60,6 +60,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; static bool has_acpi_build = true; +static bool rsdp_in_ram = true; static int legacy_acpi_table_size; static bool smbios_defaults = true; static bool smbios_legacy_mode; @@ -168,6 +169,7 @@ static void pc_init1(MachineState *machine, guest_info->isapc_ram_fw = !pci_enabled; guest_info->has_reserved_memory = has_reserved_memory; + guest_info->rsdp_in_ram = rsdp_in_ram; if (smbios_defaults) { MachineClass *mc = MACHINE_GET_CLASS(machine); @@ -310,6 +312,7 @@ static void pc_init_pci(MachineState *machine) static void pc_compat_2_2(MachineState *machine) { + rsdp_in_ram = false; x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME); x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME); x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 63027ee..c0f21fe 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -50,6 +50,7 @@ #define MAX_SATA_PORTS 6 static bool has_acpi_build = true; +static bool rsdp_in_ram = true; static bool smbios_defaults = true; static bool smbios_legacy_mode; static bool smbios_uuid_encoded = true; @@ -154,6 +155,7 @@ static void pc_q35_init(MachineState *machine) guest_info->isapc_ram_fw = false; guest_info->has_acpi_build = has_acpi_build; guest_info->has_reserved_memory = has_reserved_memory; + guest_info->rsdp_in_ram = rsdp_in_ram; /* Migration was not supported in 2.0 for Q35, so do not bother * with this hack (see hw/i386/acpi-build.c). @@ -289,6 +291,7 @@ static void pc_q35_init(MachineState *machine) static void pc_compat_2_2(MachineState *machine) { + rsdp_in_ram = false; x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME); x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME); x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME); diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl index e1cee5d..16eaca3 100644 --- a/hw/i386/q35-acpi-dsdt.dsl +++ b/hw/i386/q35-acpi-dsdt.dsl @@ -48,23 +48,6 @@ DefinitionBlock ( /**************************************************************** * PCI Bus definition ****************************************************************/ -#define BOARD_SPECIFIC_PCI_RESOURSES \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0x0000, \ - 0x0CD7, \ - 0x0000, \ - 0x0CD8, \ - ,, , TypeStatic) \ - /* 0xcd8-0xcf7 hole for CPU hotplug, hw/acpi/ich9.c:ICH9_PROC_BASE */ \ - WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, \ - 0x0000, \ - 0x0D00, \ - 0xFFFF, \ - 0x0000, \ - 0xF300, \ - ,, , TypeStatic) - Scope(\_SB) { Device(PCI0) { Name(_HID, EisaId("PNP0A08")) @@ -131,7 +114,6 @@ DefinitionBlock ( } } -#include "acpi-dsdt-pci-crs.dsl" #include "acpi-dsdt-hpet.dsl" @@ -168,7 +150,6 @@ DefinitionBlock ( } } -#define DSDT_APPLESMC_STA q35_dsdt_applesmc_sta #include "acpi-dsdt-isa.dsl" diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated index 0d5b133..ed9a2cc 100644 --- a/hw/i386/q35-acpi-dsdt.hex.generated +++ b/hw/i386/q35-acpi-dsdt.hex.generated @@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x53, 0x44, 0x54, -0x13, -0x20, +0xb8, +0x1d, 0x0, 0x0, 0x1, -0x0, +0x35, 0x42, 0x58, 0x50, @@ -360,357 +360,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0xa4, 0x6b, 0x10, -0x4e, -0x15, -0x2e, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x8, -0x43, -0x52, -0x45, -0x53, -0x11, -0x42, -0x7, -0xa, -0x6e, -0x88, -0xd, -0x0, -0x2, -0xc, -0x0, -0x0, -0x0, -0x0, -0x0, -0xff, -0x0, -0x0, -0x0, -0x0, -0x1, -0x47, -0x1, -0xf8, -0xc, -0xf8, -0xc, -0x1, -0x8, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0x0, -0x0, -0xd7, -0xc, -0x0, -0x0, -0xd8, -0xc, -0x88, -0xd, -0x0, -0x1, -0xc, -0x3, -0x0, -0x0, -0x0, -0xd, -0xff, -0xff, -0x0, -0x0, -0x0, -0xf3, -0x87, -0x17, -0x0, -0x0, -0xc, -0x3, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0xa, -0x0, -0xff, -0xff, -0xb, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x2, -0x0, -0x87, -0x17, -0x0, -0x0, -0xc, -0x1, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0xe0, -0xff, -0xff, -0xbf, -0xfe, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0xc0, -0x1e, -0x79, -0x0, -0x8, -0x43, -0x52, -0x36, -0x34, -0x11, -0x33, -0xa, -0x30, -0x8a, -0x2b, -0x0, -0x0, -0xc, -0x3, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x80, -0x0, -0x0, -0x0, -0xff, -0xff, -0xff, -0xff, -0xff, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x80, -0x0, -0x0, -0x0, -0x79, -0x0, -0x14, -0x41, -0xa, -0x5f, -0x43, -0x52, -0x53, -0x0, -0x8a, -0x43, -0x52, -0x45, -0x53, -0xa, -0x5c, -0x50, -0x53, -0x33, -0x32, -0x8a, -0x43, -0x52, -0x45, -0x53, -0xa, -0x60, -0x50, -0x45, -0x33, -0x32, -0x8a, -0x43, -0x52, -0x45, -0x53, -0xa, -0x68, -0x50, -0x4c, -0x33, -0x32, -0x70, -0x50, -0x30, -0x53, -0x5f, -0x50, -0x53, -0x33, -0x32, -0x70, -0x50, -0x30, -0x45, -0x5f, -0x50, -0x45, -0x33, -0x32, -0x70, -0x72, -0x74, -0x50, -0x30, -0x45, -0x5f, -0x50, -0x30, -0x53, -0x5f, -0x0, -0x1, -0x0, -0x50, -0x4c, -0x33, -0x32, -0xa0, -0xc, -0x93, -0x50, -0x31, -0x56, -0x5f, -0x0, -0xa4, -0x43, -0x52, -0x45, -0x53, -0x8f, -0x43, -0x52, -0x36, -0x34, -0xa, -0xe, -0x50, -0x53, -0x36, -0x34, -0x8f, -0x43, -0x52, -0x36, -0x34, -0xa, -0x16, -0x50, -0x45, -0x36, -0x34, -0x8f, -0x43, -0x52, -0x36, -0x34, -0xa, -0x26, -0x50, -0x4c, -0x36, -0x34, -0x70, -0x50, -0x31, -0x53, -0x5f, -0x50, -0x53, -0x36, -0x34, -0x70, -0x50, -0x31, -0x45, -0x5f, -0x50, -0x45, -0x36, -0x34, -0x70, -0x50, -0x31, -0x4c, -0x5f, -0x50, -0x4c, -0x36, -0x34, -0x84, -0x43, -0x52, -0x45, -0x53, -0x43, -0x52, -0x36, -0x34, -0x60, -0xa4, -0x60, -0x10, 0x4d, 0x8, 0x5f, @@ -978,8 +627,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x4e, 0x1, 0x10, -0x4a, -0x1e, +0x4c, +0x1b, 0x2f, 0x3, 0x5f, @@ -996,52 +645,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x5f, 0x5b, 0x82, -0x2c, -0x53, -0x4d, -0x43, -0x5f, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xc, -0x6, -0x10, -0x0, -0x1, -0x8, -0x5f, -0x53, -0x54, -0x41, -0xa, -0xf0, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0x10, -0xa, -0xd, -0x47, -0x1, -0x0, -0x3, -0x0, -0x3, -0x1, -0x20, -0x22, -0x40, -0x0, -0x79, -0x0, -0x5b, -0x82, 0x2d, 0x52, 0x54, @@ -6959,8 +6562,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x53, 0x1, 0x10, -0x4f, -0x12, +0x4d, +0xc, 0x5f, 0x53, 0x42, @@ -7057,32 +6660,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x22, 0xa, 0xc8, -0x5b, -0x80, -0x50, -0x52, -0x53, -0x54, -0x1, -0xb, -0xd8, -0xc, -0xa, -0x20, -0x5b, -0x81, -0xc, -0x50, -0x52, -0x53, -0x54, -0x1, -0x50, -0x52, -0x53, -0x5f, -0x40, -0x10, 0x14, 0x4a, 0x6, @@ -7190,81 +6767,9 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x3, 0x75, 0x60, -0x5b, -0x82, -0x46, -0x4, -0x50, -0x52, -0x45, -0x53, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xc, -0x41, -0xd0, -0xa, -0x6, -0x8, -0x5f, -0x55, -0x49, -0x44, -0xd, -0x43, -0x50, -0x55, -0x20, -0x68, -0x6f, -0x74, -0x70, -0x6c, -0x75, -0x67, -0x20, -0x72, -0x65, -0x73, -0x6f, -0x75, -0x72, -0x63, -0x65, -0x73, -0x0, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0xd, -0xa, -0xa, -0x47, -0x1, -0xd8, -0xc, -0xd8, -0xc, -0x0, -0x20, -0x79, -0x0, -0x8, -0x5f, -0x53, -0x54, -0x41, -0xa, -0xb, 0x10, -0x40, -0x31, +0x44, +0x2a, 0x2e, 0x5f, 0x53, @@ -7276,8 +6781,8 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x30, 0x5b, 0x82, -0x43, -0x30, +0x47, +0x29, 0x4d, 0x48, 0x50, @@ -7327,37 +6832,6 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x65, 0x73, 0x0, -0x5b, -0x80, -0x48, -0x50, -0x4d, -0x52, -0x1, -0xb, -0x0, -0xa, -0xa, -0x18, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0xd, -0xa, -0xa, -0x47, -0x1, -0x0, -0xa, -0x0, -0xa, -0x0, -0x18, -0x79, -0x0, 0x14, 0x13, 0x5f, @@ -7379,89 +6853,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0xa, 0xb, 0x5b, -0x81, -0x1f, -0x48, -0x50, -0x4d, -0x52, -0x3, -0x4d, -0x52, -0x42, -0x4c, -0x20, -0x4d, -0x52, -0x42, -0x48, -0x20, -0x4d, -0x52, -0x4c, -0x4c, -0x20, -0x4d, -0x52, -0x4c, -0x48, -0x20, -0x4d, -0x50, -0x58, -0x5f, -0x20, -0x5b, -0x81, -0x13, -0x48, -0x50, -0x4d, -0x52, -0x1, -0x0, -0x40, -0xa, -0x4d, -0x45, -0x53, -0x5f, -0x1, -0x4d, -0x49, -0x4e, -0x53, -0x1, -0x5b, 0x1, 0x4d, 0x4c, 0x43, 0x4b, 0x0, -0x5b, -0x81, -0x15, -0x48, -0x50, -0x4d, -0x52, -0x3, -0x4d, -0x53, -0x45, -0x4c, -0x20, -0x4d, -0x4f, -0x45, -0x56, -0x20, -0x4d, -0x4f, -0x53, -0x43, -0x20, 0x14, 0x4a, 0x4, @@ -8211,6 +7608,3 @@ static unsigned char Q35AcpiDsdtAmlCode[] = { 0x46, 0x0 }; -static unsigned short q35_dsdt_applesmc_sta[] = { -0x3fa -}; diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl deleted file mode 100644 index 22ff5dd..0000000 --- a/hw/i386/ssdt-mem.dsl +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Memory hotplug ACPI DSDT static objects definitions - * - * Copyright ProfitBricks GmbH 2012 - * Copyright (C) 2013-2014 Red Hat Inc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/> - */ - -/* This file is the basis for the ssdt_mem[] variable in src/acpi.c. - * It defines the contents of the memory device object. At - * runtime, a dynamically generated SSDT will contain one copy of this - * AML snippet for every possible memory device in the system. The - * objects will be placed in the \_SB_ namespace. - * - * In addition to the aml code generated from this file, the - * src/acpi.c file creates a MTFY method with an entry for each memdevice: - * Method(MTFY, 2) { - * If (LEqual(Arg0, 0x00)) { Notify(MP00, Arg1) } - * If (LEqual(Arg0, 0x01)) { Notify(MP01, Arg1) } - * ... - * } - */ -#include "hw/acpi/pc-hotplug.h" - -ACPI_EXTRACT_ALL_CODE ssdm_mem_aml - -DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1) -{ - - External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_CRS_METHOD, MethodObj) - External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_STATUS_METHOD, MethodObj) - External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_OST_METHOD, MethodObj) - External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_PROXIMITY_METHOD, MethodObj) - - Scope(\_SB) { -/* v------------------ DO NOT EDIT ------------------v */ - ACPI_EXTRACT_DEVICE_START ssdt_mem_start - ACPI_EXTRACT_DEVICE_END ssdt_mem_end - ACPI_EXTRACT_DEVICE_STRING ssdt_mem_name - Device(MPAA) { - ACPI_EXTRACT_NAME_STRING ssdt_mem_id - Name(_UID, "0xAA") -/* ^------------------ DO NOT EDIT ------------------^ - * Don't change the above without also updating the C code. - */ - Name(_HID, EISAID("PNP0C80")) - - Method(_CRS, 0) { - Return(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_CRS_METHOD(_UID)) - } - - Method(_STA, 0) { - Return(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_STATUS_METHOD(_UID)) - } - - Method(_PXM, 0) { - Return(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_PROXIMITY_METHOD(_UID)) - } - - Method(_OST, 3) { - \_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_OST_METHOD(_UID, Arg0, Arg1, Arg2) - } - } - } -} diff --git a/hw/i386/ssdt-mem.hex.generated b/hw/i386/ssdt-mem.hex.generated deleted file mode 100644 index b3bfbbd..0000000 --- a/hw/i386/ssdt-mem.hex.generated +++ /dev/null @@ -1,213 +0,0 @@ -static unsigned char ssdt_mem_id[] = { -0x35 -}; -static unsigned char ssdm_mem_aml[] = { -0x53, -0x53, -0x44, -0x54, -0xc7, -0x0, -0x0, -0x0, -0x2, -0x66, -0x42, -0x58, -0x50, -0x43, -0x0, -0x0, -0x43, -0x53, -0x53, -0x44, -0x54, -0x0, -0x0, -0x0, -0x1, -0x0, -0x0, -0x0, -0x49, -0x4e, -0x54, -0x4c, -0x28, -0x8, -0x14, -0x20, -0x10, -0x42, -0xa, -0x5c, -0x5f, -0x53, -0x42, -0x5f, -0x5b, -0x82, -0x49, -0x9, -0x4d, -0x50, -0x41, -0x41, -0x8, -0x5f, -0x55, -0x49, -0x44, -0xd, -0x30, -0x78, -0x41, -0x41, -0x0, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xc, -0x41, -0xd0, -0xc, -0x80, -0x14, -0x1e, -0x5f, -0x43, -0x52, -0x53, -0x0, -0xa4, -0x5c, -0x2f, -0x4, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x4d, -0x48, -0x50, -0x44, -0x4d, -0x43, -0x52, -0x53, -0x5f, -0x55, -0x49, -0x44, -0x14, -0x1e, -0x5f, -0x53, -0x54, -0x41, -0x0, -0xa4, -0x5c, -0x2f, -0x4, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x4d, -0x48, -0x50, -0x44, -0x4d, -0x52, -0x53, -0x54, -0x5f, -0x55, -0x49, -0x44, -0x14, -0x1e, -0x5f, -0x50, -0x58, -0x4d, -0x0, -0xa4, -0x5c, -0x2f, -0x4, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x4d, -0x48, -0x50, -0x44, -0x4d, -0x50, -0x58, -0x4d, -0x5f, -0x55, -0x49, -0x44, -0x14, -0x20, -0x5f, -0x4f, -0x53, -0x54, -0x3, -0x5c, -0x2f, -0x4, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x4d, -0x48, -0x50, -0x44, -0x4d, -0x4f, -0x53, -0x54, -0x5f, -0x55, -0x49, -0x44, -0x68, -0x69, -0x6a -}; -static unsigned char ssdt_mem_start[] = { -0x2c -}; -static unsigned char ssdt_mem_end[] = { -0xc7 -}; -static unsigned char ssdt_mem_name[] = { -0x30 -}; diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl deleted file mode 100644 index 1e3baae..0000000 --- a/hw/i386/ssdt-misc.dsl +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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; either version 2 of the License, or - * (at your option) any later version. - - * 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/acpi/pc-hotplug.h" - -ACPI_EXTRACT_ALL_CODE ssdp_misc_aml - -DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1) -{ - -/**************************************************************** - * PCI memory ranges - ****************************************************************/ - - Scope(\) { - ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_start - Name(P0S, 0x12345678) - ACPI_EXTRACT_NAME_DWORD_CONST acpi_pci32_end - Name(P0E, 0x12345678) - ACPI_EXTRACT_NAME_BYTE_CONST acpi_pci64_valid - Name(P1V, 0x12) - ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_start - Name(P1S, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) - ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_end - Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) - ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length - Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) - ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots - Name(MEMORY_SLOTS_NUMBER, 0x12345678) - } - - -/**************************************************************** - * Suspend - ****************************************************************/ - - Scope(\) { - /* - * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: - * must match piix4 emulation. - */ - - ACPI_EXTRACT_NAME_STRING acpi_s3_name - Name(_S3, Package(0x04) { - One, /* PM1a_CNT.SLP_TYP */ - One, /* PM1b_CNT.SLP_TYP */ - Zero, /* reserved */ - Zero /* reserved */ - }) - ACPI_EXTRACT_NAME_STRING acpi_s4_name - ACPI_EXTRACT_PKG_START acpi_s4_pkg - Name(_S4, Package(0x04) { - 0x2, /* PM1a_CNT.SLP_TYP */ - 0x2, /* PM1b_CNT.SLP_TYP */ - Zero, /* reserved */ - Zero /* reserved */ - }) - Name(_S5, Package(0x04) { - Zero, /* PM1a_CNT.SLP_TYP */ - Zero, /* PM1b_CNT.SLP_TYP */ - Zero, /* reserved */ - Zero /* reserved */ - }) - } - - External(\_SB.PCI0, DeviceObj) - External(\_SB.PCI0.ISA, DeviceObj) - - Scope(\_SB.PCI0.ISA) { - Device(PEVT) { - Name(_HID, "QEMU0001") - /* PEST will be patched to be Zero if no such device */ - ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest - Name(PEST, 0xFFFF) - OperationRegion(PEOR, SystemIO, PEST, 0x01) - Field(PEOR, ByteAcc, NoLock, Preserve) { - PEPT, 8, - } - - Method(_STA, 0, NotSerialized) { - Store(PEST, Local0) - If (LEqual(Local0, Zero)) { - Return (0x00) - } Else { - Return (0x0F) - } - } - - Method(RDPT, 0, NotSerialized) { - Store(PEPT, Local0) - Return (Local0) - } - - Method(WRPT, 1, NotSerialized) { - Store(Arg0, PEPT) - } - - Name(_CRS, ResourceTemplate() { - IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO) - }) - - CreateWordField(_CRS, IO._MIN, IOMN) - CreateWordField(_CRS, IO._MAX, IOMX) - - Method(_INI, 0, NotSerialized) { - Store(PEST, IOMN) - Store(PEST, IOMX) - } - } - } -} diff --git a/hw/i386/ssdt-misc.hex.generated b/hw/i386/ssdt-misc.hex.generated deleted file mode 100644 index cbcf61d..0000000 --- a/hw/i386/ssdt-misc.hex.generated +++ /dev/null @@ -1,399 +0,0 @@ -static unsigned char acpi_pci64_length[] = { -0x6f -}; -static unsigned char acpi_s4_pkg[] = { -0x99 -}; -static unsigned char ssdt_mctrl_nr_slots[] = { -0x7d -}; -static unsigned char acpi_s3_name[] = { -0x86 -}; -static unsigned char acpi_pci32_start[] = { -0x2f -}; -static unsigned char acpi_pci64_valid[] = { -0x43 -}; -static unsigned char ssdp_misc_aml[] = { -0x53, -0x53, -0x44, -0x54, -0x6c, -0x1, -0x0, -0x0, -0x1, -0x3, -0x42, -0x58, -0x50, -0x43, -0x0, -0x0, -0x42, -0x58, -0x53, -0x53, -0x44, -0x54, -0x53, -0x55, -0x1, -0x0, -0x0, -0x0, -0x49, -0x4e, -0x54, -0x4c, -0x28, -0x8, -0x14, -0x20, -0x10, -0x4c, -0x5, -0x5c, -0x0, -0x8, -0x50, -0x30, -0x53, -0x5f, -0xc, -0x78, -0x56, -0x34, -0x12, -0x8, -0x50, -0x30, -0x45, -0x5f, -0xc, -0x78, -0x56, -0x34, -0x12, -0x8, -0x50, -0x31, -0x56, -0x5f, -0xa, -0x12, -0x8, -0x50, -0x31, -0x53, -0x5f, -0x11, -0xb, -0xa, -0x8, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x8, -0x50, -0x31, -0x45, -0x5f, -0x11, -0xb, -0xa, -0x8, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x8, -0x50, -0x31, -0x4c, -0x5f, -0x11, -0xb, -0xa, -0x8, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x0, -0x8, -0x4d, -0x44, -0x4e, -0x52, -0xc, -0x78, -0x56, -0x34, -0x12, -0x10, -0x29, -0x5c, -0x0, -0x8, -0x5f, -0x53, -0x33, -0x5f, -0x12, -0x6, -0x4, -0x1, -0x1, -0x0, -0x0, -0x8, -0x5f, -0x53, -0x34, -0x5f, -0x12, -0x8, -0x4, -0xa, -0x2, -0xa, -0x2, -0x0, -0x0, -0x8, -0x5f, -0x53, -0x35, -0x5f, -0x12, -0x6, -0x4, -0x0, -0x0, -0x0, -0x0, -0x10, -0x40, -0xc, -0x5c, -0x2f, -0x3, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x49, -0x53, -0x41, -0x5f, -0x5b, -0x82, -0x4d, -0xa, -0x50, -0x45, -0x56, -0x54, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xd, -0x51, -0x45, -0x4d, -0x55, -0x30, -0x30, -0x30, -0x31, -0x0, -0x8, -0x50, -0x45, -0x53, -0x54, -0xb, -0xff, -0xff, -0x5b, -0x80, -0x50, -0x45, -0x4f, -0x52, -0x1, -0x50, -0x45, -0x53, -0x54, -0x1, -0x5b, -0x81, -0xb, -0x50, -0x45, -0x4f, -0x52, -0x1, -0x50, -0x45, -0x50, -0x54, -0x8, -0x14, -0x18, -0x5f, -0x53, -0x54, -0x41, -0x0, -0x70, -0x50, -0x45, -0x53, -0x54, -0x60, -0xa0, -0x6, -0x93, -0x60, -0x0, -0xa4, -0x0, -0xa1, -0x4, -0xa4, -0xa, -0xf, -0x14, -0xe, -0x52, -0x44, -0x50, -0x54, -0x0, -0x70, -0x50, -0x45, -0x50, -0x54, -0x60, -0xa4, -0x60, -0x14, -0xc, -0x57, -0x52, -0x50, -0x54, -0x1, -0x70, -0x68, -0x50, -0x45, -0x50, -0x54, -0x8, -0x5f, -0x43, -0x52, -0x53, -0x11, -0xd, -0xa, -0xa, -0x47, -0x1, -0x0, -0x0, -0x0, -0x0, -0x1, -0x1, -0x79, -0x0, -0x8b, -0x5f, -0x43, -0x52, -0x53, -0xa, -0x2, -0x49, -0x4f, -0x4d, -0x4e, -0x8b, -0x5f, -0x43, -0x52, -0x53, -0xa, -0x4, -0x49, -0x4f, -0x4d, -0x58, -0x14, -0x18, -0x5f, -0x49, -0x4e, -0x49, -0x0, -0x70, -0x50, -0x45, -0x53, -0x54, -0x49, -0x4f, -0x4d, -0x4e, -0x70, -0x50, -0x45, -0x53, -0x54, -0x49, -0x4f, -0x4d, -0x58 -}; -static unsigned char ssdt_isa_pest[] = { -0xda -}; -static unsigned char acpi_s4_name[] = { -0x92 -}; -static unsigned char acpi_pci64_start[] = { -0x4d -}; -static unsigned char acpi_pci64_end[] = { -0x5e -}; -static unsigned char acpi_pci32_end[] = { -0x39 -}; diff --git a/hw/i386/ssdt-pcihp.dsl b/hw/i386/ssdt-pcihp.dsl deleted file mode 100644 index ac91c05..0000000 --- a/hw/i386/ssdt-pcihp.dsl +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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; either version 2 of the License, or - * (at your option) any later version. - - * 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/>. - */ - -ACPI_EXTRACT_ALL_CODE ssdp_pcihp_aml - -DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1) -{ - -/**************************************************************** - * PCI hotplug - ****************************************************************/ - - /* Objects supplied by DSDT */ - External(\_SB.PCI0, DeviceObj) - External(\_SB.PCI0.PCEJ, MethodObj) - External(BSEL, IntObj) - - Scope(\_SB.PCI0) { - - /* Bulk generated PCI hotplug devices */ - ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start - ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end - ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name - - // Extract the offsets of the device name, address dword and the slot - // name byte - we fill them in for each device. - Device(SAA) { - ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id - Name(_SUN, 0xAA) - ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr - Name(_ADR, 0xAA0000) - Method(_EJ0, 1) { - PCEJ(BSEL, _SUN) - } - } - - ACPI_EXTRACT_DEVICE_START ssdt_pcinohp_start - ACPI_EXTRACT_DEVICE_END ssdt_pcinohp_end - ACPI_EXTRACT_DEVICE_STRING ssdt_pcinohp_name - - // Extract the offsets of the device name, address dword and the slot - // name byte - we fill them in for each device. - Device(SBB) { - ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcinohp_adr - Name(_ADR, 0xAA0000) - } - - ACPI_EXTRACT_DEVICE_START ssdt_pcivga_start - ACPI_EXTRACT_DEVICE_END ssdt_pcivga_end - ACPI_EXTRACT_DEVICE_STRING ssdt_pcivga_name - - // Extract the offsets of the device name, address dword and the slot - // name byte - we fill them in for each device. - Device(SCC) { - ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcivga_adr - Name(_ADR, 0xAA0000) - Method(_S1D, 0, NotSerialized) { - Return (0x00) - } - Method(_S2D, 0, NotSerialized) { - Return (0x00) - } - Method(_S3D, 0, NotSerialized) { - Return (0x00) - } - } - - ACPI_EXTRACT_DEVICE_START ssdt_pciqxl_start - ACPI_EXTRACT_DEVICE_END ssdt_pciqxl_end - ACPI_EXTRACT_DEVICE_STRING ssdt_pciqxl_name - - // Extract the offsets of the device name, address dword and the slot - // name byte - we fill them in for each device. - Device(SDD) { - ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pciqxl_adr - Name(_ADR, 0xAA0000) - Method(_S1D, 0, NotSerialized) { - Return (0x00) - } - Method(_S2D, 0, NotSerialized) { - Return (0x00) - } - Method(_S3D, 0, NotSerialized) { - Return (0x03) // QXL - } - } - } -} diff --git a/hw/i386/ssdt-pcihp.hex.generated b/hw/i386/ssdt-pcihp.hex.generated deleted file mode 100644 index 72ffa84..0000000 --- a/hw/i386/ssdt-pcihp.hex.generated +++ /dev/null @@ -1,251 +0,0 @@ -static unsigned char ssdt_pcihp_name[] = { -0x34 -}; -static unsigned char ssdt_pcivga_end[] = { -0x99 -}; -static unsigned char ssdt_pcivga_name[] = { -0x70 -}; -static unsigned char ssdt_pcihp_adr[] = { -0x45 -}; -static unsigned char ssdt_pcinohp_end[] = { -0x6d -}; -static unsigned char ssdt_pcihp_end[] = { -0x5c -}; -static unsigned char ssdt_pciqxl_start[] = { -0x99 -}; -static unsigned char ssdt_pcinohp_name[] = { -0x5f -}; -static unsigned char ssdp_pcihp_aml[] = { -0x53, -0x53, -0x44, -0x54, -0xc6, -0x0, -0x0, -0x0, -0x1, -0x70, -0x42, -0x58, -0x50, -0x43, -0x0, -0x0, -0x42, -0x58, -0x53, -0x53, -0x44, -0x54, -0x50, -0x43, -0x1, -0x0, -0x0, -0x0, -0x49, -0x4e, -0x54, -0x4c, -0x15, -0x11, -0x13, -0x20, -0x10, -0x41, -0xa, -0x5c, -0x2e, -0x5f, -0x53, -0x42, -0x5f, -0x50, -0x43, -0x49, -0x30, -0x5b, -0x82, -0x29, -0x53, -0x41, -0x41, -0x5f, -0x8, -0x5f, -0x53, -0x55, -0x4e, -0xa, -0xaa, -0x8, -0x5f, -0x41, -0x44, -0x52, -0xc, -0x0, -0x0, -0xaa, -0x0, -0x14, -0x12, -0x5f, -0x45, -0x4a, -0x30, -0x1, -0x50, -0x43, -0x45, -0x4a, -0x42, -0x53, -0x45, -0x4c, -0x5f, -0x53, -0x55, -0x4e, -0x5b, -0x82, -0xf, -0x53, -0x42, -0x42, -0x5f, -0x8, -0x5f, -0x41, -0x44, -0x52, -0xc, -0x0, -0x0, -0xaa, -0x0, -0x5b, -0x82, -0x2a, -0x53, -0x43, -0x43, -0x5f, -0x8, -0x5f, -0x41, -0x44, -0x52, -0xc, -0x0, -0x0, -0xaa, -0x0, -0x14, -0x8, -0x5f, -0x53, -0x31, -0x44, -0x0, -0xa4, -0x0, -0x14, -0x8, -0x5f, -0x53, -0x32, -0x44, -0x0, -0xa4, -0x0, -0x14, -0x8, -0x5f, -0x53, -0x33, -0x44, -0x0, -0xa4, -0x0, -0x5b, -0x82, -0x2b, -0x53, -0x44, -0x44, -0x5f, -0x8, -0x5f, -0x41, -0x44, -0x52, -0xc, -0x0, -0x0, -0xaa, -0x0, -0x14, -0x8, -0x5f, -0x53, -0x31, -0x44, -0x0, -0xa4, -0x0, -0x14, -0x8, -0x5f, -0x53, -0x32, -0x44, -0x0, -0xa4, -0x0, -0x14, -0x9, -0x5f, -0x53, -0x33, -0x44, -0x0, -0xa4, -0xa, -0x3 -}; -static unsigned char ssdt_pciqxl_adr[] = { -0xa6 -}; -static unsigned char ssdt_pcinohp_adr[] = { -0x69 -}; -static unsigned char ssdt_pcivga_adr[] = { -0x7a -}; -static unsigned char ssdt_pciqxl_name[] = { -0x9c -}; -static unsigned char ssdt_pcivga_start[] = { -0x6d -}; -static unsigned char ssdt_pciqxl_end[] = { -0xc6 -}; -static unsigned char ssdt_pcihp_start[] = { -0x31 -}; -static unsigned char ssdt_pcihp_id[] = { -0x3e -}; -static unsigned char ssdt_pcinohp_start[] = { -0x5c -}; diff --git a/hw/i386/ssdt-proc.dsl b/hw/i386/ssdt-proc.dsl deleted file mode 100644 index 8229bfd..0000000 --- a/hw/i386/ssdt-proc.dsl +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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; either version 2 of the License, or - * (at your option) any later version. - - * 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/>. - */ - -/* This file is the basis for the ssdt table generated in src/acpi.c. - * It defines the contents of the per-cpu Processor() object. At - * runtime, a dynamically generated SSDT will contain one copy of this - * AML snippet for every possible cpu in the system. The objects will - * be placed in the \_SB_ namespace. - * - * In addition to the aml code generated from this file, the - * src/acpi.c file creates a NTFY method with an entry for each cpu: - * Method(NTFY, 2) { - * If (LEqual(Arg0, 0x00)) { Notify(CP00, Arg1) } - * If (LEqual(Arg0, 0x01)) { Notify(CP01, Arg1) } - * ... - * } - * and a CPON array with the list of active and inactive cpus: - * Name(CPON, Package() { One, One, ..., Zero, Zero, ... }) - */ - -ACPI_EXTRACT_ALL_CODE ssdp_proc_aml - -DefinitionBlock ("ssdt-proc.aml", "SSDT", 0x01, "BXPC", "BXSSDT", 0x1) -{ - ACPI_EXTRACT_PROCESSOR_START ssdt_proc_start - ACPI_EXTRACT_PROCESSOR_END ssdt_proc_end - ACPI_EXTRACT_PROCESSOR_STRING ssdt_proc_name - Processor(CPAA, 0xAA, 0x00000000, 0x0) { - ACPI_EXTRACT_NAME_BYTE_CONST ssdt_proc_id - Name(ID, 0xAA) -/* - * The src/acpi.c code requires the above ACP_EXTRACT tags so that it can update - * CPAA and 0xAA with the appropriate CPU id (see - * SD_OFFSET_CPUHEX/CPUID1/CPUID2). Don't change the above without - * also updating the C code. - */ - Name(_HID, "ACPI0007") - External(CPMA, MethodObj) - External(CPST, MethodObj) - External(CPEJ, MethodObj) - Method(_MAT, 0) { - Return (CPMA(ID)) - } - Method(_STA, 0) { - Return (CPST(ID)) - } - Method(_EJ0, 1, NotSerialized) { - CPEJ(ID, Arg0) - } - } -} diff --git a/hw/i386/ssdt-proc.hex.generated b/hw/i386/ssdt-proc.hex.generated deleted file mode 100644 index 4df0734..0000000 --- a/hw/i386/ssdt-proc.hex.generated +++ /dev/null @@ -1,134 +0,0 @@ -static unsigned char ssdt_proc_name[] = { -0x28 -}; -static unsigned char ssdp_proc_aml[] = { -0x53, -0x53, -0x44, -0x54, -0x78, -0x0, -0x0, -0x0, -0x1, -0x7d, -0x42, -0x58, -0x50, -0x43, -0x0, -0x0, -0x42, -0x58, -0x53, -0x53, -0x44, -0x54, -0x0, -0x0, -0x1, -0x0, -0x0, -0x0, -0x49, -0x4e, -0x54, -0x4c, -0x15, -0x11, -0x13, -0x20, -0x5b, -0x83, -0x42, -0x5, -0x43, -0x50, -0x41, -0x41, -0xaa, -0x0, -0x0, -0x0, -0x0, -0x0, -0x8, -0x49, -0x44, -0x5f, -0x5f, -0xa, -0xaa, -0x8, -0x5f, -0x48, -0x49, -0x44, -0xd, -0x41, -0x43, -0x50, -0x49, -0x30, -0x30, -0x30, -0x37, -0x0, -0x14, -0xf, -0x5f, -0x4d, -0x41, -0x54, -0x0, -0xa4, -0x43, -0x50, -0x4d, -0x41, -0x49, -0x44, -0x5f, -0x5f, -0x14, -0xf, -0x5f, -0x53, -0x54, -0x41, -0x0, -0xa4, -0x43, -0x50, -0x53, -0x54, -0x49, -0x44, -0x5f, -0x5f, -0x14, -0xf, -0x5f, -0x45, -0x4a, -0x30, -0x1, -0x43, -0x50, -0x45, -0x4a, -0x49, -0x44, -0x5f, -0x5f, -0x68 -}; -static unsigned char ssdt_proc_id[] = { -0x38 -}; -static unsigned char ssdt_proc_end[] = { -0x78 -}; -static unsigned char ssdt_proc_start[] = { -0x24 -}; diff --git a/hw/i386/ssdt-tpm.hex.generated b/hw/i386/ssdt-tpm.hex.generated index 4a916a8..e84dc6c 100644 --- a/hw/i386/ssdt-tpm.hex.generated +++ b/hw/i386/ssdt-tpm.hex.generated @@ -8,7 +8,7 @@ static unsigned char ssdt_tpm_aml[] = { 0x0, 0x0, 0x1, -0xf, +0x1c, 0x42, 0x58, 0x50, @@ -31,9 +31,9 @@ static unsigned char ssdt_tpm_aml[] = { 0x4e, 0x54, 0x4c, -0x15, +0x7, 0x11, -0x13, +0x14, 0x20, 0x10, 0x38, diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 0374653..66fb9d9 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -326,7 +326,7 @@ static void cmd646_pci_config_write(PCIDevice *d, uint32_t addr, uint32_t val, } /* CMD646 PCI IDE controller */ -static int pci_cmd646_ide_initfn(PCIDevice *dev) +static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); uint8_t *pci_conf = dev->config; @@ -373,7 +373,6 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d); qemu_register_reset(cmd646_reset, d); - return 0; } static void pci_cmd646_ide_exitfn(PCIDevice *dev) @@ -409,7 +408,7 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_cmd646_ide_initfn; + k->realize = pci_cmd646_ide_realize; k->exit = pci_cmd646_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_CMD; k->device_id = PCI_DEVICE_ID_CMD_646; diff --git a/hw/ide/ich.c b/hw/ide/ich.c index fb1d095..b1d8874 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -98,7 +98,7 @@ static void pci_ich9_reset(DeviceState *dev) ahci_reset(&d->ahci); } -static int pci_ich9_ahci_init(PCIDevice *dev) +static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp) { struct AHCIPCIState *d; int sata_cap_offset; @@ -123,10 +123,11 @@ static int pci_ich9_ahci_init(PCIDevice *dev) pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->ahci.mem); - sata_cap_offset = pci_add_capability(dev, PCI_CAP_ID_SATA, - ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE); + sata_cap_offset = pci_add_capability2(dev, PCI_CAP_ID_SATA, + ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE, + errp); if (sata_cap_offset < 0) { - return sata_cap_offset; + return; } sata_cap = dev->config + sata_cap_offset; @@ -139,8 +140,6 @@ static int pci_ich9_ahci_init(PCIDevice *dev) * should be PMCAP, the Intel ICH9 data sheet specifies that the ICH9 * AHCI device puts the MSI capability first, pointing to 0x80. */ msi_init(dev, ICH9_MSI_CAP_OFFSET, 1, true, false); - - return 0; } static void pci_ich9_uninit(PCIDevice *dev) @@ -158,7 +157,7 @@ static void ich_ahci_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_ich9_ahci_init; + k->realize = pci_ich9_ahci_realize; k->exit = pci_ich9_uninit; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82801IR; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index fab2abc..1b3d1c1 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -96,7 +96,7 @@ static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write) * This should accommodate the largest ATA transaction * for LBA48 (65,536 sectors) and 32K sector sizes. */ if (s->sg.size > INT32_MAX) { - error_report("IDE: sglist describes more than 2GiB.\n"); + error_report("IDE: sglist describes more than 2GiB."); break; } bm->cur_prd_addr += l; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 247dd4f..adb6649 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -147,7 +147,7 @@ static void pci_piix_init_ports(PCIIDEState *d) { } } -static int pci_piix_ide_initfn(PCIDevice *dev) +static void pci_piix_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); uint8_t *pci_conf = dev->config; @@ -162,8 +162,6 @@ static int pci_piix_ide_initfn(PCIDevice *dev) vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d); pci_piix_init_ports(d); - - return 0; } int pci_piix3_xen_ide_unplug(DeviceState *dev) @@ -237,7 +235,7 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_piix_ide_initfn; + k->realize = pci_piix_ide_realize; k->exit = pci_piix_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; @@ -257,7 +255,7 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_piix_ide_initfn; + k->realize = pci_piix_ide_realize; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; k->class_id = PCI_CLASS_STORAGE_IDE; @@ -275,7 +273,7 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_piix_ide_initfn; + k->realize = pci_piix_ide_realize; k->exit = pci_piix_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB; diff --git a/hw/ide/via.c b/hw/ide/via.c index fb3d8a0..e2da9ef 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -171,7 +171,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) { } /* via ide func */ -static int vt82c686b_ide_initfn(PCIDevice *dev) +static void vt82c686b_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); uint8_t *pci_conf = dev->config; @@ -186,8 +186,6 @@ static int vt82c686b_ide_initfn(PCIDevice *dev) vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d); vt82c686b_init_ports(d); - - return 0; } static void vt82c686b_ide_exitfn(PCIDevice *dev) @@ -214,7 +212,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = vt82c686b_ide_initfn; + k->realize = vt82c686b_ide_realize; k->exit = vt82c686b_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_IDE; diff --git a/hw/input/adb.c b/hw/input/adb.c index 34c8058..a18eea2 100644 --- a/hw/input/adb.c +++ b/hw/input/adb.c @@ -118,6 +118,17 @@ static const TypeInfo adb_bus_type_info = { .instance_size = sizeof(ADBBusState), }; +static const VMStateDescription vmstate_adb_device = { + .name = "adb_device", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_INT32(devaddr, ADBDevice), + VMSTATE_INT32(handler, ADBDevice), + VMSTATE_END_OF_LIST() + } +}; + static void adb_device_realizefn(DeviceState *dev, Error **errp) { ADBDevice *d = ADB_DEVICE(dev); @@ -301,9 +312,10 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, static const VMStateDescription vmstate_adb_kbd = { .name = "adb_kbd", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { + VMSTATE_STRUCT(parent_obj, KBDState, 0, vmstate_adb_device, ADBDevice), VMSTATE_BUFFER(data, KBDState), VMSTATE_INT32(rptr, KBDState), VMSTATE_INT32(wptr, KBDState), @@ -515,9 +527,11 @@ static void adb_mouse_reset(DeviceState *dev) static const VMStateDescription vmstate_adb_mouse = { .name = "adb_mouse", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { + VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device, + ADBDevice), VMSTATE_INT32(buttons_state, MouseState), VMSTATE_INT32(last_buttons_state, MouseState), VMSTATE_INT32(dx, MouseState), diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index 7d1f3b9..87fe2e8 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -200,11 +200,14 @@ typedef enum IRQType { IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */ } IRQType; +/* Round up to the nearest 64 IRQs so that the queue length + * won't change when moving between 32 and 64 bit hosts. + */ +#define IRQQUEUE_SIZE_BITS ((OPENPIC_MAX_IRQ + 63) & ~63) + typedef struct IRQQueue { - /* Round up to the nearest 64 IRQs so that the queue length - * won't change when moving between 32 and 64 bit hosts. - */ - unsigned long queue[BITS_TO_LONGS((OPENPIC_MAX_IRQ + 63) & ~63)]; + unsigned long *queue; + int32_t queue_size; /* Only used for VMSTATE_BITMAP */ int next; int priority; } IRQQueue; @@ -240,6 +243,15 @@ typedef struct IRQSource { #define IDR_EP 0x80000000 /* external pin */ #define IDR_CI 0x40000000 /* critical interrupt */ +typedef struct OpenPICTimer { + uint32_t tccr; /* Global timer current count register */ + uint32_t tbcr; /* Global timer base count register */ +} OpenPICTimer; + +typedef struct OpenPICMSI { + uint32_t msir; /* Shared Message Signaled Interrupt Register */ +} OpenPICMSI; + typedef struct IRQDest { int32_t ctpr; /* CPU current task priority */ IRQQueue raised; @@ -288,14 +300,9 @@ typedef struct OpenPICState { IRQDest dst[MAX_CPU]; uint32_t nb_cpus; /* Timer registers */ - struct { - uint32_t tccr; /* Global timer current count register */ - uint32_t tbcr; /* Global timer base count register */ - } timers[OPENPIC_MAX_TMR]; + OpenPICTimer timers[OPENPIC_MAX_TMR]; /* Shared MSI registers */ - struct { - uint32_t msir; /* Shared Message Signaled Interrupt Register */ - } msi[MAX_MSI]; + OpenPICMSI msi[MAX_MSI]; uint32_t max_irq; uint32_t irq_ipi0; uint32_t irq_tim0; @@ -1013,7 +1020,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr, DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x\n", __func__, idx, addr, val); - if (idx < 0) { + if (idx < 0 || idx >= opp->nb_cpus) { return; } @@ -1152,7 +1159,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr); retval = 0xFFFFFFFF; - if (idx < 0) { + if (idx < 0 || idx >= opp->nb_cpus) { return retval; } @@ -1287,132 +1294,6 @@ static const MemoryRegionOps openpic_summary_ops_be = { }, }; -static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(q->queue); i++) { - /* Always put the lower half of a 64-bit long first, in case we - * restore on a 32-bit host. The least significant bits correspond - * to lower IRQ numbers in the bitmap. - */ - qemu_put_be32(f, (uint32_t)q->queue[i]); -#if LONG_MAX > 0x7FFFFFFF - qemu_put_be32(f, (uint32_t)(q->queue[i] >> 32)); -#endif - } - - qemu_put_sbe32s(f, &q->next); - qemu_put_sbe32s(f, &q->priority); -} - -static void openpic_save(QEMUFile* f, void *opaque) -{ - OpenPICState *opp = (OpenPICState *)opaque; - unsigned int i; - - qemu_put_be32s(f, &opp->gcr); - qemu_put_be32s(f, &opp->vir); - qemu_put_be32s(f, &opp->pir); - qemu_put_be32s(f, &opp->spve); - qemu_put_be32s(f, &opp->tfrr); - - qemu_put_be32s(f, &opp->nb_cpus); - - for (i = 0; i < opp->nb_cpus; i++) { - qemu_put_sbe32s(f, &opp->dst[i].ctpr); - openpic_save_IRQ_queue(f, &opp->dst[i].raised); - openpic_save_IRQ_queue(f, &opp->dst[i].servicing); - qemu_put_buffer(f, (uint8_t *)&opp->dst[i].outputs_active, - sizeof(opp->dst[i].outputs_active)); - } - - for (i = 0; i < OPENPIC_MAX_TMR; i++) { - qemu_put_be32s(f, &opp->timers[i].tccr); - qemu_put_be32s(f, &opp->timers[i].tbcr); - } - - for (i = 0; i < opp->max_irq; i++) { - qemu_put_be32s(f, &opp->src[i].ivpr); - qemu_put_be32s(f, &opp->src[i].idr); - qemu_get_be32s(f, &opp->src[i].destmask); - qemu_put_sbe32s(f, &opp->src[i].last_cpu); - qemu_put_sbe32s(f, &opp->src[i].pending); - } -} - -static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(q->queue); i++) { - unsigned long val; - - val = qemu_get_be32(f); -#if LONG_MAX > 0x7FFFFFFF - val <<= 32; - val |= qemu_get_be32(f); -#endif - - q->queue[i] = val; - } - - qemu_get_sbe32s(f, &q->next); - qemu_get_sbe32s(f, &q->priority); -} - -static int openpic_load(QEMUFile* f, void *opaque, int version_id) -{ - OpenPICState *opp = (OpenPICState *)opaque; - unsigned int i, nb_cpus; - - if (version_id != 1) { - return -EINVAL; - } - - qemu_get_be32s(f, &opp->gcr); - qemu_get_be32s(f, &opp->vir); - qemu_get_be32s(f, &opp->pir); - qemu_get_be32s(f, &opp->spve); - qemu_get_be32s(f, &opp->tfrr); - - qemu_get_be32s(f, &nb_cpus); - if (opp->nb_cpus != nb_cpus) { - return -EINVAL; - } - assert(nb_cpus > 0 && nb_cpus <= MAX_CPU); - - for (i = 0; i < opp->nb_cpus; i++) { - qemu_get_sbe32s(f, &opp->dst[i].ctpr); - openpic_load_IRQ_queue(f, &opp->dst[i].raised); - openpic_load_IRQ_queue(f, &opp->dst[i].servicing); - qemu_get_buffer(f, (uint8_t *)&opp->dst[i].outputs_active, - sizeof(opp->dst[i].outputs_active)); - } - - for (i = 0; i < OPENPIC_MAX_TMR; i++) { - qemu_get_be32s(f, &opp->timers[i].tccr); - qemu_get_be32s(f, &opp->timers[i].tbcr); - } - - for (i = 0; i < opp->max_irq; i++) { - uint32_t val; - - val = qemu_get_be32(f); - write_IRQreg_idr(opp, i, val); - val = qemu_get_be32(f); - write_IRQreg_ivpr(opp, i, val); - - qemu_get_be32s(f, &opp->src[i].ivpr); - qemu_get_be32s(f, &opp->src[i].idr); - qemu_get_be32s(f, &opp->src[i].destmask); - qemu_get_sbe32s(f, &opp->src[i].last_cpu); - qemu_get_sbe32s(f, &opp->src[i].pending); - } - - return 0; -} - static void openpic_reset(DeviceState *d) { OpenPICState *opp = OPENPIC(d); @@ -1446,12 +1327,14 @@ static void openpic_reset(DeviceState *d) write_IRQreg_idr(opp, i, opp->idr_reset); } /* Initialise IRQ destinations */ - for (i = 0; i < MAX_CPU; i++) { + for (i = 0; i < opp->nb_cpus; i++) { opp->dst[i].ctpr = 15; - memset(&opp->dst[i].raised, 0, sizeof(IRQQueue)); opp->dst[i].raised.next = -1; - memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue)); + opp->dst[i].raised.priority = 0; + bitmap_clear(opp->dst[i].raised.queue, 0, IRQQUEUE_SIZE_BITS); opp->dst[i].servicing.next = -1; + opp->dst[i].servicing.priority = 0; + bitmap_clear(opp->dst[i].servicing.queue, 0, IRQQUEUE_SIZE_BITS); } /* Initialise timers */ for (i = 0; i < OPENPIC_MAX_TMR; i++) { @@ -1525,6 +1408,110 @@ static void map_list(OpenPICState *opp, const MemReg *list, int *count) } } +static const VMStateDescription vmstate_openpic_irq_queue = { + .name = "openpic_irq_queue", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_BITMAP(queue, IRQQueue, 0, queue_size), + VMSTATE_INT32(next, IRQQueue), + VMSTATE_INT32(priority, IRQQueue), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_openpic_irqdest = { + .name = "openpic_irqdest", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_INT32(ctpr, IRQDest), + VMSTATE_STRUCT(raised, IRQDest, 0, vmstate_openpic_irq_queue, + IRQQueue), + VMSTATE_STRUCT(servicing, IRQDest, 0, vmstate_openpic_irq_queue, + IRQQueue), + VMSTATE_UINT32_ARRAY(outputs_active, IRQDest, OPENPIC_OUTPUT_NB), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_openpic_irqsource = { + .name = "openpic_irqsource", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(ivpr, IRQSource), + VMSTATE_UINT32(idr, IRQSource), + VMSTATE_UINT32(destmask, IRQSource), + VMSTATE_INT32(last_cpu, IRQSource), + VMSTATE_INT32(pending, IRQSource), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_openpic_timer = { + .name = "openpic_timer", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(tccr, OpenPICTimer), + VMSTATE_UINT32(tbcr, OpenPICTimer), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_openpic_msi = { + .name = "openpic_msi", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_UINT32(msir, OpenPICMSI), + VMSTATE_END_OF_LIST() + } +}; + +static int openpic_post_load(void *opaque, int version_id) +{ + OpenPICState *opp = (OpenPICState *)opaque; + int i; + + /* Update internal ivpr and idr variables */ + for (i = 0; i < opp->max_irq; i++) { + write_IRQreg_idr(opp, i, opp->src[i].idr); + write_IRQreg_ivpr(opp, i, opp->src[i].ivpr); + } + + return 0; +} + +static const VMStateDescription vmstate_openpic = { + .name = "openpic", + .version_id = 3, + .minimum_version_id = 3, + .post_load = openpic_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(gcr, OpenPICState), + VMSTATE_UINT32(vir, OpenPICState), + VMSTATE_UINT32(pir, OpenPICState), + VMSTATE_UINT32(spve, OpenPICState), + VMSTATE_UINT32(tfrr, OpenPICState), + VMSTATE_UINT32(max_irq, OpenPICState), + VMSTATE_STRUCT_VARRAY_UINT32(src, OpenPICState, max_irq, 0, + vmstate_openpic_irqsource, IRQSource), + VMSTATE_UINT32_EQUAL(nb_cpus, OpenPICState), + VMSTATE_STRUCT_VARRAY_UINT32(dst, OpenPICState, nb_cpus, 0, + vmstate_openpic_irqdest, IRQDest), + VMSTATE_STRUCT_ARRAY(timers, OpenPICState, OPENPIC_MAX_TMR, 0, + vmstate_openpic_timer, OpenPICTimer), + VMSTATE_STRUCT_ARRAY(msi, OpenPICState, MAX_MSI, 0, + vmstate_openpic_msi, OpenPICMSI), + VMSTATE_UINT32(irq_ipi0, OpenPICState), + VMSTATE_UINT32(irq_tim0, OpenPICState), + VMSTATE_UINT32(irq_msi, OpenPICState), + VMSTATE_END_OF_LIST() + } +}; + static void openpic_init(Object *obj) { OpenPICState *opp = OPENPIC(obj); @@ -1631,10 +1618,12 @@ static void openpic_realize(DeviceState *dev, Error **errp) for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { sysbus_init_irq(d, &opp->dst[i].irqs[j]); } - } - register_savevm(dev, "openpic", 0, 2, - openpic_save, openpic_load, opp); + opp->dst[i].raised.queue_size = IRQQUEUE_SIZE_BITS; + opp->dst[i].raised.queue = bitmap_new(IRQQUEUE_SIZE_BITS); + opp->dst[i].servicing.queue_size = IRQQUEUE_SIZE_BITS; + opp->dst[i].servicing.queue = bitmap_new(IRQQUEUE_SIZE_BITS); + } sysbus_init_mmio(d, &opp->mem); qdev_init_gpio_in(dev, openpic_set_irq, opp->max_irq); @@ -1653,6 +1642,7 @@ static void openpic_class_init(ObjectClass *oc, void *data) dc->realize = openpic_realize; dc->props = openpic_properties; dc->reset = openpic_reset; + dc->vmsd = &vmstate_openpic; } static const TypeInfo openpic_info = { diff --git a/hw/ipack/tpci200.c b/hw/ipack/tpci200.c index b7031a0..1df02ee 100644 --- a/hw/ipack/tpci200.c +++ b/hw/ipack/tpci200.c @@ -573,7 +573,7 @@ static const MemoryRegionOps tpci200_las3_ops = { } }; -static int tpci200_initfn(PCIDevice *pci_dev) +static void tpci200_realize(PCIDevice *pci_dev, Error **errp) { TPCI200State *s = TPCI200(pci_dev); uint8_t *c = s->dev.config; @@ -609,8 +609,6 @@ static int tpci200_initfn(PCIDevice *pci_dev) ipack_bus_new_inplace(&s->bus, sizeof(s->bus), DEVICE(pci_dev), NULL, N_MODULES, tpci200_set_irq); - - return 0; } static const VMStateDescription vmstate_tpci200 = { @@ -632,7 +630,7 @@ static void tpci200_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = tpci200_initfn; + k->realize = tpci200_realize; k->vendor_id = PCI_VENDOR_ID_TEWS; k->device_id = PCI_DEVICE_ID_TEWS_TPCI200; k->class_id = PCI_CLASS_BRIDGE_OTHER; diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c index 0dc440d..9da9dfc 100644 --- a/hw/isa/i82378.c +++ b/hw/isa/i82378.c @@ -58,7 +58,7 @@ static void i82378_request_pic_irq(void *opaque, int irq, int level) qemu_set_irq(s->i8259[irq], level); } -static int i82378_initfn(PCIDevice *pci) +static void i82378_realize(PCIDevice *pci, Error **errp) { DeviceState *dev = DEVICE(pci); I82378State *s = I82378(dev); @@ -107,8 +107,6 @@ static int i82378_initfn(PCIDevice *pci) /* timer */ isa_create_simple(isabus, "mc146818rtc"); - - return 0; } static void i82378_init(Object *obj) @@ -125,7 +123,7 @@ static void i82378_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = i82378_initfn; + k->realize = i82378_realize; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82378; k->revision = 0x03; diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 231de74..dba7585 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -610,8 +610,17 @@ static void ich9_device_plug_cb(HotplugHandler *hotplug_dev, static void ich9_device_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - error_setg(errp, "acpi: device unplug request for not supported device" - " type: %s", object_get_typename(OBJECT(dev))); + ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev); + + ich9_pm_device_unplug_request_cb(&lpc->pm, dev, errp); +} + +static void ich9_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev); + + ich9_pm_device_unplug_cb(&lpc->pm, dev, errp); } static bool ich9_rst_cnt_needed(void *opaque) @@ -677,6 +686,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) dc->cannot_instantiate_with_device_add_yet = true; hc->plug = ich9_device_plug_cb; hc->unplug_request = ich9_device_unplug_request_cb; + hc->unplug = ich9_device_unplug_cb; adevc->ospm_status = ich9_pm_ospm_status; } diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index a9916df..d9522b1 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -82,7 +82,7 @@ static const VMStateDescription vmstate_piix4 = { } }; -static int piix4_initfn(PCIDevice *dev) +static void piix4_realize(PCIDevice *dev, Error **errp) { PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev); @@ -90,7 +90,6 @@ static int piix4_initfn(PCIDevice *dev) pci_address_space_io(dev)); piix4_dev = &d->dev; qemu_register_reset(piix4_reset, d); - return 0; } int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn) @@ -107,7 +106,7 @@ static void piix4_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = piix4_initfn; + k->realize = piix4_realize; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0; k->class_id = PCI_CLASS_BRIDGE_ISA; diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index b223526..b8197b1 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -245,7 +245,7 @@ static const VMStateDescription vmstate_acpi = { * just register a PCI device now, functionalities will be implemented later. */ -static int vt82c686b_ac97_initfn(PCIDevice *dev) +static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp) { VT686AC97State *s = DO_UPCAST(VT686AC97State, dev, dev); uint8_t *pci_conf = s->dev.config; @@ -255,8 +255,6 @@ static int vt82c686b_ac97_initfn(PCIDevice *dev) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM); pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); - - return 0; } void vt82c686b_ac97_init(PCIBus *bus, int devfn) @@ -272,7 +270,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = vt82c686b_ac97_initfn; + k->realize = vt82c686b_ac97_realize; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_AC97; k->revision = 0x50; @@ -288,7 +286,7 @@ static const TypeInfo via_ac97_info = { .class_init = via_ac97_class_init, }; -static int vt82c686b_mc97_initfn(PCIDevice *dev) +static void vt82c686b_mc97_realize(PCIDevice *dev, Error **errp) { VT686MC97State *s = DO_UPCAST(VT686MC97State, dev, dev); uint8_t *pci_conf = s->dev.config; @@ -297,8 +295,6 @@ static int vt82c686b_mc97_initfn(PCIDevice *dev) PCI_COMMAND_VGA_PALETTE); pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); - - return 0; } void vt82c686b_mc97_init(PCIBus *bus, int devfn) @@ -314,7 +310,7 @@ static void via_mc97_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = vt82c686b_mc97_initfn; + k->realize = vt82c686b_mc97_realize; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_MC97; k->class_id = PCI_CLASS_COMMUNICATION_OTHER; @@ -331,7 +327,7 @@ static const TypeInfo via_mc97_info = { }; /* vt82c686 pm init */ -static int vt82c686b_pm_initfn(PCIDevice *dev) +static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) { VT686PMState *s = DO_UPCAST(VT686PMState, dev, dev); uint8_t *pci_conf; @@ -361,8 +357,6 @@ static int vt82c686b_pm_initfn(PCIDevice *dev) acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_cnt_init(&s->ar, &s->io, 2); - - return 0; } I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, @@ -391,7 +385,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = vt82c686b_pm_initfn; + k->realize = vt82c686b_pm_realize; k->config_write = pm_write_config; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_ACPI; @@ -421,7 +415,7 @@ static const VMStateDescription vmstate_via = { }; /* init the PCI-to-ISA bridge */ -static int vt82c686b_initfn(PCIDevice *d) +static void vt82c686b_realize(PCIDevice *d, Error **errp) { VT82C686BState *vt82c = DO_UPCAST(VT82C686BState, dev, d); uint8_t *pci_conf; @@ -451,8 +445,6 @@ static int vt82c686b_initfn(PCIDevice *d) &vt82c->superio); qemu_register_reset(vt82c686b_reset, d); - - return 0; } ISABus *vt82c686b_init(PCIBus *bus, int devfn) @@ -469,7 +461,7 @@ static void via_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = vt82c686b_initfn; + k->realize = vt82c686b_realize; k->config_write = vt82c686b_write_config; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_ISA_BRIDGE; diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index 256c102..7f62261 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -155,6 +155,7 @@ milkymist_init(MachineState *machine) bios_name); exit(1); } + g_free(bios_filename); milkymist_uart_create(0x60000000, irq[0]); milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3], diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index a2843cd..38c59db 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -185,7 +185,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, ram_size - initrd_offset); } if (initrd_size < 0) { - error_report("qemu: could not load initrd '%s'\n", + error_report("qemu: could not load initrd '%s'", initrd_filename); exit(EXIT_FAILURE); } diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c index 6a56b07..6bd61e7 100644 --- a/hw/misc/applesmc.c +++ b/hw/misc/applesmc.c @@ -43,7 +43,6 @@ /* command/status port used by Apple SMC */ #define APPLESMC_CMD_PORT 0x4 #define APPLESMC_NR_PORTS 32 -#define APPLESMC_MAX_DATA_LENGTH 32 #define APPLESMC_READ_CMD 0x10 #define APPLESMC_WRITE_CMD 0x11 @@ -249,8 +248,8 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp) } static Property applesmc_isa_properties[] = { - DEFINE_PROP_UINT32("iobase", AppleSMCState, iobase, - APPLESMC_DEFAULT_IOBASE), + DEFINE_PROP_UINT32(APPLESMC_PROP_IO_BASE, AppleSMCState, iobase, + APPLESMC_DEFAULT_IOBASE), DEFINE_PROP_STRING("osk", AppleSMCState, osk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 47d9771..f3984e3 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -638,8 +638,8 @@ static const VMStateDescription vmstate_cuda_timer = { static const VMStateDescription vmstate_cuda = { .name = "cuda", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT8(a, CUDAState), VMSTATE_UINT8(b, CUDAState), @@ -660,6 +660,7 @@ static const VMStateDescription vmstate_cuda = { VMSTATE_UINT32(tick_offset, CUDAState), VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1, vmstate_cuda_timer, CUDATimer), + VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState), VMSTATE_END_OF_LIST() } }; diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index e0f1e88..063ad80 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -273,7 +273,7 @@ static int macio_newworld_initfn(PCIDevice *d) MacIOState *s = MACIO(d); NewWorldMacIOState *ns = NEWWORLD_MACIO(d); SysBusDevice *sysbus_dev; - MemoryRegion *timer_memory = g_new(MemoryRegion, 1); + MemoryRegion *timer_memory = NULL; int i; int cur_irq = 0; int ret = macio_common_initfn(d); @@ -301,6 +301,7 @@ static int macio_newworld_initfn(PCIDevice *d) } /* Timer */ + timer_memory = g_new(MemoryRegion, 1); memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", 0x1000); memory_region_add_subregion(&s->bar, 0x15000, timer_memory); @@ -336,20 +337,44 @@ static void macio_instance_init(Object *obj) memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem); } +static const VMStateDescription vmstate_macio_oldworld = { + .name = "macio-oldworld", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState), + VMSTATE_END_OF_LIST() + } +}; + static void macio_oldworld_class_init(ObjectClass *oc, void *data) { PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); pdc->init = macio_oldworld_initfn; pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201; + dc->vmsd = &vmstate_macio_oldworld; } +static const VMStateDescription vmstate_macio_newworld = { + .name = "macio-newworld", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState), + VMSTATE_END_OF_LIST() + } +}; + static void macio_newworld_class_init(ObjectClass *oc, void *data) { PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); pdc->init = macio_newworld_initfn; pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL; + dc->vmsd = &vmstate_macio_newworld; } static Property macio_properties[] = { diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c index 609f33f..08b604f 100644 --- a/hw/misc/milkymist-pfpu.c +++ b/hw/misc/milkymist-pfpu.c @@ -362,7 +362,7 @@ static void pfpu_start(MilkymistPFPUState *s) i = 0; while (pfpu_decode_insn(s)) { /* decode at most MICROCODE_WORDS instructions */ - if (i++ >= MICROCODE_WORDS) { + if (++i >= MICROCODE_WORDS) { error_report("milkymist_pfpu: too many instructions " "executed in microcode. No VECTOUT?"); break; diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c index c78a63e..26b9b86 100644 --- a/hw/misc/pci-testdev.c +++ b/hw/misc/pci-testdev.c @@ -233,7 +233,7 @@ static const MemoryRegionOps pci_testdev_pio_ops = { }, }; -static int pci_testdev_init(PCIDevice *pci_dev) +static void pci_testdev_realize(PCIDevice *pci_dev, Error **errp) { PCITestDevState *d = PCI_TEST_DEV(pci_dev); uint8_t *pci_conf; @@ -275,8 +275,6 @@ static int pci_testdev_init(PCIDevice *pci_dev) assert(r >= 0); test->hasnotifier = true; } - - return 0; } static void @@ -306,7 +304,7 @@ static void pci_testdev_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_testdev_init; + k->realize = pci_testdev_realize; k->exit = pci_testdev_uninit; k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_TEST; diff --git a/hw/net/e1000.c b/hw/net/e1000.c index a207e21..3405cb9 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1537,7 +1537,7 @@ static void e1000_write_config(PCIDevice *pci_dev, uint32_t address, } -static int pci_e1000_init(PCIDevice *pci_dev) +static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) { DeviceState *dev = DEVICE(pci_dev); E1000State *d = E1000(pci_dev); @@ -1581,8 +1581,6 @@ static int pci_e1000_init(PCIDevice *pci_dev) d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d); d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d); - - return 0; } static void qdev_e1000_reset(DeviceState *dev) @@ -1614,7 +1612,7 @@ static void e1000_class_init(ObjectClass *klass, void *data) E1000BaseClass *e = E1000_DEVICE_CLASS(klass); const E1000Info *info = data; - k->init = pci_e1000_init; + k->realize = pci_e1000_realize; k->exit = pci_e1000_uninit; k->romfile = "efi-e1000.rom"; k->vendor_id = PCI_VENDOR_ID_INTEL; diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 7a4f9f8..c374c1a 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -1848,7 +1848,7 @@ static NetClientInfo net_eepro100_info = { .receive = nic_receive, }; -static int e100_nic_init(PCIDevice *pci_dev) +static void e100_nic_realize(PCIDevice *pci_dev, Error **errp) { EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev); E100PCIDeviceInfo *info = eepro100_get_class(s); @@ -1892,8 +1892,6 @@ static int e100_nic_init(PCIDevice *pci_dev) memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100)); s->vmstate->name = qemu_get_queue(s->nic)->model; vmstate_register(&pci_dev->qdev, -1, s->vmstate, s); - - return 0; } static void eepro100_instance_init(Object *obj) @@ -2083,7 +2081,7 @@ static void eepro100_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_INTEL; k->class_id = PCI_CLASS_NETWORK_ETHERNET; k->romfile = "pxe-eepro100.rom"; - k->init = e100_nic_init; + k->realize = e100_nic_realize; k->exit = pci_nic_uninit; k->device_id = info->device_id; k->revision = info->revision; diff --git a/hw/net/lance.c b/hw/net/lance.c index ff7e789..4baa016 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -126,7 +126,8 @@ static int lance_init(SysBusDevice *sbd) s->phys_mem_read = ledma_memory_read; s->phys_mem_write = ledma_memory_write; - return pcnet_common_init(dev, s, &net_lance_info); + pcnet_common_init(dev, s, &net_lance_info); + return 0; } static void lance_reset(DeviceState *dev) diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index 4dea701..3492db3 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -709,7 +709,7 @@ static NetClientInfo net_ne2000_info = { .receive = ne2000_receive, }; -static int pci_ne2000_init(PCIDevice *pci_dev) +static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp) { PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev); NE2000State *s; @@ -729,8 +729,6 @@ static int pci_ne2000_init(PCIDevice *pci_dev) s->nic = qemu_new_nic(&net_ne2000_info, &s->c, object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); - - return 0; } static void pci_ne2000_exit(PCIDevice *pci_dev) @@ -763,7 +761,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_ne2000_init; + k->realize = pci_ne2000_realize; k->exit = pci_ne2000_exit; k->romfile = "efi-ne2k_pci.rom", k->vendor_id = PCI_VENDOR_ID_REALTEK; diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 5df79f0..8305d1b 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -278,7 +278,7 @@ static NetClientInfo net_pci_pcnet_info = { .link_status_changed = pcnet_set_link_status, }; -static int pci_pcnet_init(PCIDevice *pci_dev) +static void pci_pcnet_realize(PCIDevice *pci_dev, Error **errp) { PCIPCNetState *d = PCI_PCNET(pci_dev); PCNetState *s = &d->state; @@ -316,7 +316,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev) s->phys_mem_write = pci_physical_memory_write; s->dma_opaque = pci_dev; - return pcnet_common_init(DEVICE(pci_dev), s, &net_pci_pcnet_info); + pcnet_common_init(DEVICE(pci_dev), s, &net_pci_pcnet_info); } static void pci_reset(DeviceState *dev) @@ -346,7 +346,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_pcnet_init; + k->realize = pci_pcnet_realize; k->exit = pci_pcnet_uninit; k->romfile = "efi-pcnet.rom", k->vendor_id = PCI_VENDOR_ID_AMD; diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 7778b9a..bdfd38f 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -1712,7 +1712,7 @@ const VMStateDescription vmstate_pcnet = { } }; -int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) +void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) { int i; uint16_t checksum; @@ -1751,6 +1751,4 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum); s->lnkst = 0x40; /* initial link state: up */ - - return 0; } diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h index 3f12fe3..79c4c84 100644 --- a/hw/net/pcnet.h +++ b/hw/net/pcnet.h @@ -63,6 +63,6 @@ uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap); int pcnet_can_receive(NetClientState *nc); ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_); void pcnet_set_link_status(NetClientState *nc); -int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info); +void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info); extern const VMStateDescription vmstate_pcnet; #endif diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 2d1be06..f868108 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3455,7 +3455,7 @@ static NetClientInfo net_rtl8139_info = { .link_status_changed = rtl8139_set_link_status, }; -static int pci_rtl8139_init(PCIDevice *dev) +static void pci_rtl8139_realize(PCIDevice *dev, Error **errp) { RTL8139State *s = RTL8139(dev); DeviceState *d = DEVICE(dev); @@ -3496,8 +3496,6 @@ static int pci_rtl8139_init(PCIDevice *dev) s->cplus_txbuffer_offset = 0; s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s); - - return 0; } static void rtl8139_instance_init(Object *obj) @@ -3519,7 +3517,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = pci_rtl8139_init; + k->realize = pci_rtl8139_realize; k->exit = pci_rtl8139_uninit; k->romfile = "efi-rtl8139.rom"; k->vendor_id = PCI_VENDOR_ID_REALTEK; diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index c255d92..2dd5ec1 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -203,7 +203,7 @@ static void spapr_vlan_reset(VIOsPAPRDevice *sdev) dev->isopen = 0; } -static int spapr_vlan_init(VIOsPAPRDevice *sdev) +static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp) { VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev); @@ -212,8 +212,6 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev) dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf, object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev); qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); - - return 0; } static void spapr_vlan_instance_init(Object *obj) @@ -534,7 +532,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass); - k->init = spapr_vlan_init; + k->realize = spapr_vlan_realize; k->reset = spapr_vlan_reset; k->devnode = spapr_vlan_devnode; k->dt_name = "l-lan"; diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 4e3a061..cf23335 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -35,7 +35,7 @@ #include <stdio.h> -#include "hw/virtio/virtio_ring.h" +#include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-bus.h" @@ -56,7 +56,7 @@ static const int kernel_feature_bits[] = { }; /* Features supported by others. */ -const int user_feature_bits[] = { +static const int user_feature_bits[] = { VIRTIO_F_NOTIFY_ON_EMPTY, VIRTIO_RING_F_INDIRECT_DESC, VIRTIO_RING_F_EVENT_IDX, diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 45da34a..27adcc5 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -86,7 +86,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(&netcfg, config, n->config_size); - if (!(vdev->guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) && + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) && memcmp(netcfg.mac, n->mac, ETH_ALEN)) { memcpy(n->mac, netcfg.mac, ETH_ALEN); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); @@ -120,8 +120,8 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status) return; } - if (!!n->vhost_started == - (virtio_net_started(n, status) && !nc->peer->link_down)) { + if ((virtio_net_started(n, status) && !nc->peer->link_down) == + !!n->vhost_started) { return; } if (!n->vhost_started) { @@ -305,7 +305,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) info->multicast_table = str_list; info->vlan_table = get_vlan_table(n); - if (!((1 << VIRTIO_NET_F_CTRL_VLAN) & vdev->guest_features)) { + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) { info->vlan = RX_STATE_ALL; } else if (!info->vlan_table) { info->vlan = RX_STATE_NONE; @@ -446,23 +446,23 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_queue(n->nic); - features |= (1 << VIRTIO_NET_F_MAC); + virtio_add_feature(&features, VIRTIO_NET_F_MAC); if (!peer_has_vnet_hdr(n)) { - features &= ~(0x1 << VIRTIO_NET_F_CSUM); - features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4); - features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6); - features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN); + virtio_clear_feature(&features, VIRTIO_NET_F_CSUM); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO4); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO6); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_ECN); - features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM); - features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4); - features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6); - features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_CSUM); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN); } if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) { - features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO); - features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO); + virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_UFO); + virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO); } if (!get_vhost_net(nc->peer)) { @@ -477,11 +477,11 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) /* Linux kernel 2.6.25. It understood MAC (as everyone must), * but also these: */ - features |= (1 << VIRTIO_NET_F_MAC); - features |= (1 << VIRTIO_NET_F_CSUM); - features |= (1 << VIRTIO_NET_F_HOST_TSO4); - features |= (1 << VIRTIO_NET_F_HOST_TSO6); - features |= (1 << VIRTIO_NET_F_HOST_ECN); + virtio_add_feature(&features, VIRTIO_NET_F_MAC); + virtio_add_feature(&features, VIRTIO_NET_F_CSUM); + virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO4); + virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO6); + virtio_add_feature(&features, VIRTIO_NET_F_HOST_ECN); return features; } @@ -519,9 +519,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = VIRTIO_NET(vdev); int i; - virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ))); + virtio_net_set_multiqueue(n, + __virtio_has_feature(features, VIRTIO_NET_F_MQ)); - virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF))); + virtio_net_set_mrg_rx_bufs(n, + __virtio_has_feature(features, + VIRTIO_NET_F_MRG_RXBUF)); if (n->has_vnet_hdr) { n->curr_guest_offloads = @@ -538,7 +541,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) vhost_net_ack_features(get_vhost_net(nc->peer), features); } - if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) { + if (__virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) { memset(n->vlans, 0, MAX_VLAN >> 3); } else { memset(n->vlans, 0xff, MAX_VLAN >> 3); @@ -585,7 +588,7 @@ static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd, uint64_t offloads; size_t s; - if (!((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features)) { + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { return VIRTIO_NET_ERR; } @@ -1378,7 +1381,7 @@ static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f) } } - if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { qemu_put_be64(f, n->curr_guest_offloads); } } @@ -1486,7 +1489,7 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, } } - if ((1 << VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) & vdev->guest_features) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { n->curr_guest_offloads = qemu_get_be64(f); } else { n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); @@ -1513,8 +1516,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, qemu_get_subqueue(n->nic, i)->link_down = link_down; } - if (vdev->guest_features & (0x1 << VIRTIO_NET_F_GUEST_ANNOUNCE) && - vdev->guest_features & (0x1 << VIRTIO_NET_F_CTRL_VQ)) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) && + virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { n->announce_counter = SELF_ANNOUNCE_ROUNDS; timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)); } @@ -1552,7 +1555,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features) { int i, config_size = 0; - host_features |= (1 << VIRTIO_NET_F_MAC); + virtio_add_feature(&host_features, VIRTIO_NET_F_MAC); for (i = 0; feature_sizes[i].flags != 0; i++) { if (host_features & feature_sizes[i].flags) { config_size = MAX(feature_sizes[i].end, config_size); diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index a83d2a1..dfb328d 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2125,7 +2125,7 @@ static const MemoryRegionOps b1_ops = { }, }; -static int vmxnet3_pci_init(PCIDevice *pci_dev) +static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp) { DeviceState *dev = DEVICE(pci_dev); VMXNET3State *s = VMXNET3(pci_dev); @@ -2164,8 +2164,6 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev) register_savevm(dev, "vmxnet3-msix", -1, 1, vmxnet3_msix_save, vmxnet3_msix_load, s); - - return 0; } static void vmxnet3_instance_init(Object *obj) @@ -2501,7 +2499,7 @@ static void vmxnet3_class_init(ObjectClass *class, void *data) DeviceClass *dc = DEVICE_CLASS(class); PCIDeviceClass *c = PCI_DEVICE_CLASS(class); - c->init = vmxnet3_pci_init; + c->realize = vmxnet3_pci_realize; c->exit = vmxnet3_pci_uninit; c->vendor_id = PCI_VENDOR_ID_VMWARE; c->device_id = PCI_DEVICE_ID_VMWARE_VMXNET3; diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 9536f64..ad6b553 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -146,6 +146,7 @@ eth_write(void *opaque, hwaddr addr, if (!(value & CTRL_S)) { qemu_flush_queued_packets(qemu_get_queue(s->nic)); } + /* fall through */ case R_TX_LEN0: case R_TX_LEN1: case R_TX_GIE0: diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 35dc6d5..11332d1 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -132,7 +132,7 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr, rtas_st(rets, 1, (alen < 0) ? 0 : alen); } -static int spapr_nvram_init(VIOsPAPRDevice *dev) +static void spapr_nvram_realize(VIOsPAPRDevice *dev, Error **errp) { sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev); @@ -145,23 +145,22 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev) nvram->buf = g_malloc0(nvram->size); if ((nvram->size < MIN_NVRAM_SIZE) || (nvram->size > MAX_NVRAM_SIZE)) { - fprintf(stderr, "spapr-nvram must be between %d and %d bytes in size\n", - MIN_NVRAM_SIZE, MAX_NVRAM_SIZE); - return -1; + error_setg(errp, "spapr-nvram must be between %d and %d bytes in size", + MIN_NVRAM_SIZE, MAX_NVRAM_SIZE); + return; } if (nvram->blk) { int alen = blk_pread(nvram->blk, 0, nvram->buf, nvram->size); if (alen != nvram->size) { - return -1; + error_setg(errp, "can't read spapr-nvram contents"); + return; } } spapr_rtas_register(RTAS_NVRAM_FETCH, "nvram-fetch", rtas_nvram_fetch); spapr_rtas_register(RTAS_NVRAM_STORE, "nvram-store", rtas_nvram_store); - - return 0; } static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off) @@ -224,7 +223,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass); - k->init = spapr_nvram_init; + k->realize = spapr_nvram_realize; k->devnode = spapr_nvram_devnode; k->dt_name = "nvram"; k->dt_type = "nvram"; diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index a6ca940..28d0ff9 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -107,10 +107,9 @@ static int pci_dec_21154_device_init(SysBusDevice *dev) return 0; } -static int dec_21154_pci_host_init(PCIDevice *d) +static void dec_21154_pci_host_realize(PCIDevice *d, Error **errp) { /* PCI2PCI bridge same values as PearPC - check this */ - return 0; } static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) @@ -118,7 +117,7 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = dec_21154_pci_host_init; + k->realize = dec_21154_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_DEC; k->device_id = PCI_DEVICE_ID_DEC_21154; k->revision = 0x02; diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 832b6c7..312fa70 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -792,14 +792,13 @@ static int pci_pbm_init_device(SysBusDevice *dev) return 0; } -static int pbm_pci_host_init(PCIDevice *d) +static void pbm_pci_host_realize(PCIDevice *d, Error **errp) { pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); pci_set_word(d->config + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); - return 0; } static void pbm_pci_host_class_init(ObjectClass *klass, void *data) @@ -807,7 +806,7 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = pbm_pci_host_init; + k->realize = pbm_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_SUN; k->device_id = PCI_DEVICE_ID_SUN_SABRE; k->class_id = PCI_CLASS_BRIDGE_HOST; diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 56292ad..8bdd569 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -705,7 +705,7 @@ static int bonito_pcihost_initfn(SysBusDevice *dev) return 0; } -static int bonito_initfn(PCIDevice *dev) +static void bonito_realize(PCIDevice *dev, Error **errp) { PCIBonitoState *s = DO_UPCAST(PCIBonitoState, dev, dev); SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost); @@ -766,8 +766,6 @@ static int bonito_initfn(PCIDevice *dev) pci_set_byte(dev->config + PCI_MAX_LAT, 0x00); qemu_register_reset(bonito_reset, s); - - return 0; } PCIBus *bonito_init(qemu_irq *pic) @@ -799,7 +797,7 @@ static void bonito_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = bonito_initfn; + k->realize = bonito_realize; k->vendor_id = 0xdf53; k->device_id = 0x00d5; k->revision = 0x01; diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index 6c7cfdb..bfe707a 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -114,10 +114,9 @@ static int pci_grackle_init_device(SysBusDevice *dev) return 0; } -static int grackle_pci_host_init(PCIDevice *d) +static void grackle_pci_host_realize(PCIDevice *d, Error **errp) { d->config[0x09] = 0x01; - return 0; } static void grackle_pci_class_init(ObjectClass *klass, void *data) @@ -125,7 +124,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = grackle_pci_host_init; + k->realize = grackle_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_MOTOROLA; k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; k->revision = 0x00; diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index 8ea718e..723836f 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -295,14 +295,13 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error **errp) sysbus_init_ioports(sbd, 0xcfc, 4); } -static int i440fx_initfn(PCIDevice *dev) +static void i440fx_realize(PCIDevice *dev, Error **errp) { PCII440FXState *d = I440FX_PCI_DEVICE(dev); dev->config[I440FX_SMRAM] = 0x02; cpu_smm_register(&i440fx_set_smm, d); - return 0; } PCIBus *i440fx_init(PCII440FXState **pi440fx_state, @@ -631,7 +630,7 @@ static const MemoryRegionOps rcr_ops = { .endianness = DEVICE_LITTLE_ENDIAN }; -static int piix3_initfn(PCIDevice *dev) +static void piix3_realize(PCIDevice *dev, Error **errp) { PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev); @@ -644,7 +643,6 @@ static int piix3_initfn(PCIDevice *dev) &d->rcr_mem, 1); qemu_register_reset(piix3_reset, d); - return 0; } static void piix3_class_init(ObjectClass *klass, void *data) @@ -655,7 +653,7 @@ static void piix3_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; dc->hotpluggable = false; - k->init = piix3_initfn; + k->realize = piix3_realize; k->config_write = piix3_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ @@ -683,7 +681,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; dc->hotpluggable = false; - k->init = piix3_initfn; + k->realize = piix3_realize; k->config_write = piix3_write_config_xen; k->vendor_id = PCI_VENDOR_ID_INTEL; /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ @@ -708,7 +706,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = i440fx_initfn; + k->realize = i440fx_realize; k->config_write = i440fx_write_config; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_82441; diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index 574f8b2..613ba73 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -416,7 +416,7 @@ static const VMStateDescription vmstate_ppce500_pci = { #include "exec/address-spaces.h" -static int e500_pcihost_bridge_initfn(PCIDevice *d) +static void e500_pcihost_bridge_realize(PCIDevice *d, Error **errp) { PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d); PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(), @@ -430,8 +430,6 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d) memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", &ccsr->ccsr_space, 0, int128_get64(ccsr->ccsr_space.size)); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0); - - return 0; } static AddressSpace *e500_pcihost_set_iommu(PCIBus *bus, void *opaque, @@ -500,7 +498,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = e500_pcihost_bridge_initfn; + k->realize = e500_pcihost_bridge_realize; k->vendor_id = PCI_VENDOR_ID_FREESCALE; k->device_id = PCI_DEVICE_ID_MPC8533E; k->class_id = PCI_CLASS_PROCESSOR_POWERPC; diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 1de3681..6cea6ff 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -289,7 +289,7 @@ static void raven_pcihost_initfn(Object *obj) qdev_prop_set_bit(pci_dev, "multifunction", false); } -static int raven_init(PCIDevice *d) +static void raven_realize(PCIDevice *d, Error **errp) { RavenPCIState *s = RAVEN_PCI_DEVICE(d); char *filename; @@ -330,8 +330,6 @@ static int raven_init(PCIDevice *d) g_free(filename); } } - - return 0; } static const VMStateDescription vmstate_raven = { @@ -349,7 +347,7 @@ static void raven_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = raven_init; + k->realize = raven_realize; k->vendor_id = PCI_VENDOR_ID_MOTOROLA; k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN; k->revision = 0x00; diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index b20bad8..df60e61 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -390,7 +390,7 @@ static void mch_init_dmar(MCHPCIState *mch) pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu); } -static int mch_init(PCIDevice *d) +static void mch_realize(PCIDevice *d, Error **errp) { int i; MCHPCIState *mch = MCH_PCI_DEVICE(d); @@ -418,7 +418,6 @@ static int mch_init(PCIDevice *d) if (qemu_opt_get_bool(qemu_get_machine_opts(), "iommu", false)) { mch_init_dmar(mch); } - return 0; } uint64_t mch_mcfg_base(void) @@ -436,7 +435,7 @@ static void mch_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = mch_init; + k->realize = mch_realize; k->config_write = mch_write_config; dc->reset = mch_reset; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index 21f805f..53f2b59 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -315,37 +315,33 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, return h->bus; } -static int unin_main_pci_host_init(PCIDevice *d) +static void unin_main_pci_host_realize(PCIDevice *d, Error **errp) { d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer d->config[0x34] = 0x00; // capabilities_pointer - return 0; } -static int unin_agp_pci_host_init(PCIDevice *d) +static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp) { d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer // d->config[0x34] = 0x80; // capabilities_pointer - return 0; } -static int u3_agp_pci_host_init(PCIDevice *d) +static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp) { /* cache line size */ d->config[0x0C] = 0x08; /* latency timer */ d->config[0x0D] = 0x10; - return 0; } -static int unin_internal_pci_host_init(PCIDevice *d) +static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp) { d->config[0x0C] = 0x08; // cache_line_size d->config[0x0D] = 0x10; // latency_timer d->config[0x34] = 0x00; // capabilities_pointer - return 0; } static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) @@ -353,7 +349,7 @@ static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = unin_main_pci_host_init; + k->realize = unin_main_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI; k->revision = 0x00; @@ -377,7 +373,7 @@ static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = u3_agp_pci_host_init; + k->realize = u3_agp_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP; k->revision = 0x00; @@ -401,7 +397,7 @@ static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = unin_agp_pci_host_init; + k->realize = unin_agp_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP; k->revision = 0x00; @@ -425,7 +421,7 @@ static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = unin_internal_pci_host_init; + k->realize = unin_internal_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI; k->revision = 0x00; diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 71ff0de..6d23553 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -456,12 +456,11 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp); } -static int versatile_pci_host_init(PCIDevice *d) +static void versatile_pci_host_realize(PCIDevice *d, Error **errp) { pci_set_word(d->config + PCI_STATUS, PCI_STATUS_66MHZ | PCI_STATUS_DEVSEL_MEDIUM); pci_set_byte(d->config + PCI_LATENCY_TIMER, 0x10); - return 0; } static void versatile_pci_host_class_init(ObjectClass *klass, void *data) @@ -469,7 +468,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data) PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - k->init = versatile_pci_host_init; + k->realize = versatile_pci_host_realize; k->vendor_id = PCI_VENDOR_ID_XILINX; k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30; k->class_id = PCI_CLASS_PROCESSOR_CO; diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs index 80f8aa6..9f905e6 100644 --- a/hw/pci/Makefile.objs +++ b/hw/pci/Makefile.objs @@ -7,5 +7,3 @@ common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o common-obj-$(call lnot,$(CONFIG_PCI)) += pci-stub.o common-obj-$(CONFIG_ALL) += pci-stub.o - -common-obj-$(CONFIG_PCI_HOTPLUG_OLD) += pci-hotplug-old.o diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c deleted file mode 100644 index 501a918..0000000 --- a/hw/pci/pci-hotplug-old.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Deprecated PCI hotplug interface support - * This covers the old pci_add / pci_del command, whereas the more general - * device_add / device_del commands are now preferred. - * - * Copyright (c) 2004 Fabrice Bellard - * - * 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/pci/pci.h" -#include "net/net.h" -#include "hw/i386/pc.h" -#include "monitor/monitor.h" -#include "hw/scsi/scsi.h" -#include "hw/virtio/virtio-blk.h" -#include "qemu/config-file.h" -#include "sysemu/block-backend.h" -#include "qapi/error.h" - -static int pci_read_devaddr(Monitor *mon, const char *addr, - int *busp, unsigned *slotp) -{ - int dom; - - /* strip legacy tag */ - if (!strncmp(addr, "pci_addr=", 9)) { - addr += 9; - } - if (pci_parse_devaddr(addr, &dom, busp, slotp, NULL)) { - monitor_printf(mon, "Invalid pci address\n"); - return -1; - } - if (dom != 0) { - monitor_printf(mon, "Multiple PCI domains not supported, use device_add\n"); - return -1; - } - return 0; -} - -static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, - const char *devaddr, - const char *opts_str) -{ - Error *local_err = NULL; - QemuOpts *opts; - PCIBus *root = pci_find_primary_bus(); - PCIBus *bus; - int ret, devfn; - - if (!root) { - monitor_printf(mon, "no primary PCI bus (if there are multiple" - " PCI roots, you must use device_add instead)"); - return NULL; - } - - bus = pci_get_bus_devfn(&devfn, root, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - if (!qbus_is_hotpluggable(BUS(bus))) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0); - if (!opts) { - return NULL; - } - - qemu_opt_set(opts, "type", "nic", &error_abort); - - ret = net_client_init(opts, 0, &local_err); - if (local_err) { - qerror_report_err(local_err); - error_free(local_err); - return NULL; - } - if (nd_table[ret].devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - return NULL; - } - return pci_nic_init(&nd_table[ret], root, "rtl8139", devaddr); -} - -static int scsi_hot_add(Monitor *mon, DeviceState *adapter, - DriveInfo *dinfo, int printinfo) -{ - SCSIBus *scsibus; - SCSIDevice *scsidev; - Error *local_err = NULL; - - scsibus = (SCSIBus *) - object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)), - TYPE_SCSI_BUS); - if (!scsibus) { - error_report("Device is not a SCSI adapter"); - return -1; - } - - /* - * drive_init() tries to find a default for dinfo->unit. Doesn't - * work at all for hotplug though as we assign the device to a - * specific bus instead of the first bus with spare scsi ids. - * - * Ditch the calculated value and reload from option string (if - * specified). - */ - dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); - dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, - blk_by_legacy_dinfo(dinfo), - dinfo->unit, false, -1, NULL, - &local_err); - if (!scsidev) { - error_report_err(local_err); - return -1; - } - dinfo->unit = scsidev->id; - - if (printinfo) - monitor_printf(mon, "OK bus %d, unit %d\n", - scsibus->busnr, scsidev->id); - return 0; -} - -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo) -{ - int pci_bus; - unsigned slot; - PCIBus *root = pci_find_primary_bus(); - PCIDevice *dev; - const char *pci_addr = qdict_get_str(qdict, "pci_addr"); - - switch (dinfo->type) { - case IF_SCSI: - if (!root) { - monitor_printf(mon, "no primary PCI bus (if there are multiple" - " PCI roots, you must use device_add instead)"); - goto err; - } - if (pci_read_devaddr(mon, pci_addr, &pci_bus, &slot)) { - goto err; - } - dev = pci_find_device(root, pci_bus, PCI_DEVFN(slot, 0)); - if (!dev) { - monitor_printf(mon, "no pci device with address %s\n", pci_addr); - goto err; - } - if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) { - goto err; - } - break; - default: - monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); - goto err; - } - - return 0; -err: - return -1; -} - -static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, - const char *devaddr, - const char *opts) -{ - PCIDevice *dev; - DriveInfo *dinfo = NULL; - int type = -1; - char buf[128]; - PCIBus *root = pci_find_primary_bus(); - PCIBus *bus; - int devfn; - - if (get_param_value(buf, sizeof(buf), "if", opts)) { - if (!strcmp(buf, "scsi")) - type = IF_SCSI; - else if (!strcmp(buf, "virtio")) { - type = IF_VIRTIO; - } else { - monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf); - return NULL; - } - } else { - monitor_printf(mon, "no if= specified\n"); - return NULL; - } - - if (get_param_value(buf, sizeof(buf), "file", opts)) { - dinfo = add_init_drive(opts); - if (!dinfo) - return NULL; - if (dinfo->devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - return NULL; - } - } else { - dinfo = NULL; - } - - if (!root) { - monitor_printf(mon, "no primary PCI bus (if there are multiple" - " PCI roots, you must use device_add instead)"); - return NULL; - } - bus = pci_get_bus_devfn(&devfn, root, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - if (!qbus_is_hotpluggable(BUS(bus))) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - switch (type) { - case IF_SCSI: - dev = pci_create(bus, devfn, "lsi53c895a"); - if (qdev_init(&dev->qdev) < 0) - dev = NULL; - if (dev && dinfo) { - if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) { - qdev_unplug(&dev->qdev, NULL); - dev = NULL; - } - } - break; - case IF_VIRTIO: - if (!dinfo) { - monitor_printf(mon, "virtio requires a backing file/device.\n"); - return NULL; - } - dev = pci_create(bus, devfn, "virtio-blk-pci"); - if (qdev_prop_set_drive(&dev->qdev, "drive", - blk_by_legacy_dinfo(dinfo)) < 0) { - object_unparent(OBJECT(dev)); - dev = NULL; - break; - } - if (qdev_init(&dev->qdev) < 0) - dev = NULL; - break; - default: - dev = NULL; - } - return dev; -} - -void hmp_pci_add(Monitor *mon, const QDict *qdict) -{ - PCIDevice *dev = NULL; - const char *pci_addr = qdict_get_str(qdict, "pci_addr"); - const char *type = qdict_get_str(qdict, "type"); - const char *opts = qdict_get_try_str(qdict, "opts"); - - /* strip legacy tag */ - if (!strncmp(pci_addr, "pci_addr=", 9)) { - pci_addr += 9; - } - - if (!opts) { - opts = ""; - } - - if (!strcmp(pci_addr, "auto")) - pci_addr = NULL; - - if (strcmp(type, "nic") == 0) { - dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); - } else if (strcmp(type, "storage") == 0) { - dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); - } else { - monitor_printf(mon, "invalid type: %s\n", type); - } - - if (dev) { - monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n", - pci_root_bus_path(dev), - pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - } else - monitor_printf(mon, "failed to add %s\n", opts); -} - -static int pci_device_hot_remove(Monitor *mon, const char *pci_addr) -{ - PCIBus *root = pci_find_primary_bus(); - PCIDevice *d; - int bus; - unsigned slot; - Error *local_err = NULL; - - if (!root) { - monitor_printf(mon, "no primary PCI bus (if there are multiple" - " PCI roots, you must use device_del instead)"); - return -1; - } - - if (pci_read_devaddr(mon, pci_addr, &bus, &slot)) { - return -1; - } - - d = pci_find_device(root, bus, PCI_DEVFN(slot, 0)); - if (!d) { - monitor_printf(mon, "slot %d empty\n", slot); - return -1; - } - - qdev_unplug(&d->qdev, &local_err); - if (local_err) { - monitor_printf(mon, "%s\n", error_get_pretty(local_err)); - error_free(local_err); - return -1; - } - - return 0; -} - -void hmp_pci_del(Monitor *mon, const QDict *qdict) -{ - pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr")); -} diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 31b222d..cc5d946 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -115,7 +115,7 @@ static const TypeInfo pcie_bus_info = { static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); static void pci_update_mappings(PCIDevice *d); static void pci_irq_handler(void *opaque, int irq_num, int level); -static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom); +static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, Error **); static void pci_del_option_rom(PCIDevice *pdev); static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; @@ -539,8 +539,8 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev) * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL * [[<domain>:]<bus>:]<slot>.<func>, return -1 on error */ -int pci_parse_devaddr(const char *addr, int *domp, int *busp, - unsigned int *slotp, unsigned int *funcp) +static int pci_parse_devaddr(const char *addr, int *domp, int *busp, + unsigned int *slotp, unsigned int *funcp) { const char *p; char *e; @@ -598,7 +598,8 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp, return 0; } -PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr) +static PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, + const char *devaddr) { int dom, bus; unsigned slot; @@ -726,7 +727,7 @@ static void pci_init_mask_bridge(PCIDevice *d) PCI_PREF_RANGE_TYPE_MASK); } -static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev) +static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev, Error **errp) { uint8_t slot = PCI_SLOT(dev->devfn); uint8_t func; @@ -752,26 +753,25 @@ static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev) PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)]; if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) { /* function 0 should set multifunction bit */ - error_report("PCI: single function device can't be populated " - "in function %x.%x", slot, PCI_FUNC(dev->devfn)); - return -1; + error_setg(errp, "PCI: single function device can't be populated " + "in function %x.%x", slot, PCI_FUNC(dev->devfn)); + return; } - return 0; + return; } if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { - return 0; + return; } /* function 0 indicates single function, so function > 0 must be NULL */ for (func = 1; func < PCI_FUNC_MAX; ++func) { if (bus->devices[PCI_DEVFN(slot, func)]) { - error_report("PCI: %x.0 indicates single function, " - "but %x.%x is already populated.", - slot, slot, func); - return -1; + error_setg(errp, "PCI: %x.0 indicates single function, " + "but %x.%x is already populated.", + slot, slot, func); + return; } } - return 0; } static void pci_config_alloc(PCIDevice *pci_dev) @@ -804,11 +804,13 @@ static void do_pci_unregister_device(PCIDevice *pci_dev) /* -1 for devfn means auto assign */ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, - const char *name, int devfn) + const char *name, int devfn, + Error **errp) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); PCIConfigReadFunc *config_read = pc->config_read; PCIConfigWriteFunc *config_write = pc->config_write; + Error *local_err = NULL; AddressSpace *dma_as; if (devfn < 0) { @@ -817,12 +819,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, if (!bus->devices[devfn]) goto found; } - error_report("PCI: no slot/function available for %s, all in use", name); + error_setg(errp, "PCI: no slot/function available for %s, all in use", + name); return NULL; found: ; } else if (bus->devices[devfn]) { - error_report("PCI: slot %d function %d not available for %s, in use by %s", - PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name); + error_setg(errp, "PCI: slot %d function %d not available for %s," + " in use by %s", + PCI_SLOT(devfn), PCI_FUNC(devfn), name, + bus->devices[devfn]->name); return NULL; } @@ -866,7 +871,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, if (pc->is_bridge) { pci_init_mask_bridge(pci_dev); } - if (pci_init_multifunction(bus, pci_dev)) { + pci_init_multifunction(bus, pci_dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); do_pci_unregister_device(pci_dev); return NULL; } @@ -897,7 +904,7 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev) pci_unregister_vga(pci_dev); } -static int pci_unregister_device(DeviceState *dev) +static void pci_qdev_unrealize(DeviceState *dev, Error **errp) { PCIDevice *pci_dev = PCI_DEVICE(dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); @@ -910,7 +917,6 @@ static int pci_unregister_device(DeviceState *dev) } do_pci_unregister_device(pci_dev); - return 0; } void pci_register_bar(PCIDevice *pci_dev, int region_num, @@ -1605,10 +1611,9 @@ static const char * const pci_nic_names[] = { }; /* Initialize a PCI NIC. */ -/* FIXME callers should check for failure, but don't */ -PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, - const char *default_model, - const char *default_devaddr) +static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, + const char *default_model, + const char *default_devaddr) { const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; PCIBus *bus; @@ -1751,12 +1756,12 @@ PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) return bus->devices[devfn]; } -static int pci_qdev_init(DeviceState *qdev) +static void pci_qdev_realize(DeviceState *qdev, Error **errp) { PCIDevice *pci_dev = (PCIDevice *)qdev; PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); + Error *local_err = NULL; PCIBus *bus; - int rc; bool is_default_rom; /* initialize cap_present for pci_is_express() and pci_config_size() */ @@ -1767,15 +1772,16 @@ static int pci_qdev_init(DeviceState *qdev) bus = PCI_BUS(qdev_get_parent_bus(qdev)); pci_dev = do_pci_register_device(pci_dev, bus, object_get_typename(OBJECT(qdev)), - pci_dev->devfn); + pci_dev->devfn, errp); if (pci_dev == NULL) - return -1; + return; - if (pc->init) { - rc = pc->init(pci_dev); - if (rc != 0) { + if (pc->realize) { + pc->realize(pci_dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); do_pci_unregister_device(pci_dev); - return rc; + return; } } @@ -1786,13 +1792,24 @@ static int pci_qdev_init(DeviceState *qdev) is_default_rom = true; } - rc = pci_add_option_rom(pci_dev, is_default_rom); - if (rc != 0) { - pci_unregister_device(DEVICE(pci_dev)); - return rc; + pci_add_option_rom(pci_dev, is_default_rom, &local_err); + if (local_err) { + error_propagate(errp, local_err); + pci_qdev_unrealize(DEVICE(pci_dev), NULL); + return; } +} - return 0; +static void pci_default_realize(PCIDevice *dev, Error **errp) +{ + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + + if (pc->init) { + if (pc->init(dev) < 0) { + error_setg(errp, "Device initialization failed"); + return; + } + } } PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, @@ -1932,7 +1949,8 @@ static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) } /* Add an option rom for the device */ -static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) +static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, + Error **errp) { int size; char *path; @@ -1941,9 +1959,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) const VMStateDescription *vmsd; if (!pdev->romfile) - return 0; + return; if (strlen(pdev->romfile) == 0) - return 0; + return; if (!pdev->rom_bar) { /* @@ -1957,7 +1975,9 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) * if the rom bar is disabled. */ if (DEVICE(pdev)->hotplugged) { - return -1; + error_setg(errp, "Hot-plugged device without ROM bar" + " can't have an option ROM"); + return; } if (class == 0x0300) { @@ -1965,7 +1985,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) } else { rom_add_option(pdev->romfile, -1); } - return 0; + return; } path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); @@ -1975,15 +1995,13 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) size = get_image_size(path); if (size < 0) { - error_report("%s: failed to find romfile \"%s\"", - __func__, pdev->romfile); + error_setg(errp, "failed to find romfile \"%s\"", pdev->romfile); g_free(path); - return -1; + return; } else if (size == 0) { - error_report("%s: ignoring empty romfile \"%s\"", - __func__, pdev->romfile); + error_setg(errp, "romfile \"%s\" is empty", pdev->romfile); g_free(path); - return -1; + return; } if (size & (size - 1)) { size = 1 << qemu_fls(size); @@ -2009,8 +2027,6 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) } pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom); - - return 0; } static void pci_del_option_rom(PCIDevice *pdev) @@ -2291,10 +2307,13 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev) static void pci_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->init = pci_qdev_init; - k->exit = pci_unregister_device; + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); + + k->realize = pci_qdev_realize; + k->unrealize = pci_qdev_unrealize; k->bus_type = TYPE_PCI_BUS; k->props = pci_props; + pc->realize = pci_default_realize; } AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 19d9920..437955d1 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -3,7 +3,7 @@ obj-y += ppc.o ppc_booke.o # IBM pSeries (sPAPR) obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o -obj-$(CONFIG_PSERIES) += spapr_pci.o +obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy) obj-y += spapr_pci_vfio.o endif diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 7e17d18..d51fb60 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -308,6 +308,7 @@ static int ppce500_load_device_tree(MachineState *machine, } fdt = load_device_tree(filename, &fdt_size); + g_free(filename); if (!fdt) { goto out; } @@ -706,17 +707,19 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params, } static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, - qemu_irq **irqs) + qemu_irq **irqs, Error **errp) { + Error *err = NULL; DeviceState *dev; CPUState *cs; - int r; dev = qdev_create(NULL, TYPE_KVM_OPENPIC); qdev_prop_set_uint32(dev, "model", params->mpic_version); - r = qdev_init(dev); - if (r) { + object_property_set_bool(OBJECT(dev), true, "realized", &err); + if (err) { + error_propagate(errp, err); + object_unparent(OBJECT(dev)); return NULL; } @@ -747,15 +750,15 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, "kernel_irqchip", true); bool irqchip_required = qemu_opt_get_bool(machine_opts, "kernel_irqchip", false); + Error *err = NULL; if (irqchip_allowed) { - dev = ppce500_init_mpic_kvm(params, irqs); + dev = ppce500_init_mpic_kvm(params, irqs, &err); } - if (irqchip_required && !dev) { - fprintf(stderr, "%s: irqchip requested but unavailable\n", - __func__); - abort(); + error_report("kernel_irqchip requested but unavailable: %s", + error_get_pretty(err)); + exit(1); } } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 23cde20..4aa979f 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -110,17 +110,20 @@ struct sPAPRMachineState { sPAPREnvironment *spapr; static XICSState *try_create_xics(const char *type, int nr_servers, - int nr_irqs) + int nr_irqs, Error **errp) { + Error *err = NULL; DeviceState *dev; dev = qdev_create(NULL, type); qdev_prop_set_uint32(dev, "nr_servers", nr_servers); qdev_prop_set_uint32(dev, "nr_irqs", nr_irqs); - if (qdev_init(dev) < 0) { + object_property_set_bool(OBJECT(dev), true, "realized", &err); + if (err) { + error_propagate(errp, err); + object_unparent(OBJECT(dev)); return NULL; } - return XICS_COMMON(dev); } @@ -134,23 +137,19 @@ static XICSState *xics_system_init(int nr_servers, int nr_irqs) "kernel_irqchip", true); bool irqchip_required = qemu_opt_get_bool(machine_opts, "kernel_irqchip", false); + Error *err = NULL; + if (irqchip_allowed) { - icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs); + icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs, &err); } - if (irqchip_required && !icp) { - perror("Failed to create in-kernel XICS\n"); - abort(); + error_report("kernel_irqchip requested but unavailable: %s", + error_get_pretty(err)); } } if (!icp) { - icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs); - } - - if (!icp) { - perror("Failed to create XICS\n"); - abort(); + icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, &error_abort); } return icp; @@ -994,6 +993,17 @@ static void spapr_create_nvram(sPAPREnvironment *spapr) spapr->nvram = (struct sPAPRNVRAM *)dev; } +static void spapr_rtc_create(sPAPREnvironment *spapr) +{ + DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); + + qdev_init_nofail(dev); + spapr->rtc = dev; + + object_property_add_alias(qdev_get_machine(), "rtc-time", + OBJECT(spapr->rtc), "date", NULL); +} + /* Returns whether we want to use VGA or not */ static int spapr_vga_init(PCIBus *pci_bus) { @@ -1011,15 +1021,39 @@ static int spapr_vga_init(PCIBus *pci_bus) } } +static int spapr_post_load(void *opaque, int version_id) +{ + sPAPREnvironment *spapr = (sPAPREnvironment *)opaque; + int err = 0; + + /* In earlier versions, there was no seperate qdev for the PAPR + * RTC, so the RTC offset was stored directly in sPAPREnvironment. + * So when migrating from those versions, poke the incoming offset + * value into the RTC device */ + if (version_id < 3) { + err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); + } + + return err; +} + +static bool version_before_3(void *opaque, int version_id) +{ + return version_id < 3; +} + static const VMStateDescription vmstate_spapr = { .name = "spapr", - .version_id = 2, + .version_id = 3, .minimum_version_id = 1, + .post_load = spapr_post_load, .fields = (VMStateField[]) { - VMSTATE_UNUSED(4), /* used to be @next_irq */ + /* used to be @next_irq */ + VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), /* RTC offset */ - VMSTATE_UINT64(rtc_offset, sPAPREnvironment), + VMSTATE_UINT64_TEST(rtc_offset, sPAPREnvironment, version_before_3), + VMSTATE_PPC_TIMEBASE_V(tb, sPAPREnvironment, 2), VMSTATE_END_OF_LIST() }, @@ -1491,6 +1525,9 @@ static void ppc_spapr_init(MachineState *machine) /* Set up EPOW events infrastructure */ spapr_events_init(spapr); + /* Set up the RTC RTAS interfaces */ + spapr_rtc_create(spapr); + /* Set up VIO bus */ spapr->vio_bus = spapr_vio_bus_init(); @@ -1759,11 +1796,22 @@ static const TypeInfo spapr_machine_info = { }, }; +#define SPAPR_COMPAT_2_2 \ + {\ + .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ + .property = "mem_win_size",\ + .value = "0x20000000",\ + } + +#define SPAPR_COMPAT_2_1 \ + SPAPR_COMPAT_2_2 + static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); static GlobalProperty compat_props[] = { HW_COMPAT_2_1, + SPAPR_COMPAT_2_1, { /* end of list */ } }; @@ -1780,12 +1828,15 @@ static const TypeInfo spapr_machine_2_1_info = { static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data) { + static GlobalProperty compat_props[] = { + SPAPR_COMPAT_2_2, + { /* end of list */ } + }; MachineClass *mc = MACHINE_CLASS(oc); mc->name = "pseries-2.2"; mc->desc = "pSeries Logical Partition (PAPR compliant) v2.2"; - mc->alias = "pseries"; - mc->is_default = 1; + mc->compat_props = compat_props; } static const TypeInfo spapr_machine_2_2_info = { @@ -1794,11 +1845,28 @@ static const TypeInfo spapr_machine_2_2_info = { .class_init = spapr_machine_2_2_class_init, }; +static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->name = "pseries-2.3"; + mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3"; + mc->alias = "pseries"; + mc->is_default = 1; +} + +static const TypeInfo spapr_machine_2_3_info = { + .name = TYPE_SPAPR_MACHINE "2.3", + .parent = TYPE_SPAPR_MACHINE, + .class_init = spapr_machine_2_3_class_init, +}; + static void spapr_machine_register_types(void) { type_register_static(&spapr_machine_info); type_register_static(&spapr_machine_2_1_info); type_register_static(&spapr_machine_2_2_info); + type_register_static(&spapr_machine_2_3_info); } type_init(spapr_machine_register_types) diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 1b6157d..283e96b 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -246,7 +246,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque) maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA); maina->hdr.section_length = cpu_to_be16(sizeof(*maina)); /* FIXME: section version, subtype and creator id? */ - qemu_get_timedate(&tm, spapr->rtc_offset); + spapr_rtc_read(spapr->rtc, &tm, NULL); year = tm.tm_year + 1900; maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24) | (to_bcd(year % 100) << 16) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 8651447..4f76f1c 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -731,12 +731,14 @@ static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu, CPU_FOREACH(cs) { set_spr(cs, SPR_LPCR, 0, LPCR_ILE); } + spapr_pci_switch_vga(true); return H_SUCCESS; case H_SET_MODE_ENDIAN_LITTLE: CPU_FOREACH(cs) { set_spr(cs, SPR_LPCR, LPCR_ILE, LPCR_ILE); } + spapr_pci_switch_vga(false); return H_SUCCESS; } diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index ba003da..f3990fd 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -25,6 +25,7 @@ #include "trace.h" #include "hw/ppc/spapr.h" +#include "hw/ppc/spapr_vio.h" #include <libfdt.h> @@ -73,9 +74,7 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; - if (tcet->bypass) { - ret.perm = IOMMU_RW; - } else if ((addr >> tcet->page_shift) < tcet->nb_table) { + if ((addr >> tcet->page_shift) < tcet->nb_table) { /* Check if we are in bound */ hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift); @@ -91,10 +90,22 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, return ret; } +static int spapr_tce_table_post_load(void *opaque, int version_id) +{ + sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); + + if (tcet->vdev) { + spapr_vio_set_bypass(tcet->vdev, tcet->bypass); + } + + return 0; +} + static const VMStateDescription vmstate_spapr_tce_table = { .name = "spapr_iommu", .version_id = 2, .minimum_version_id = 2, + .post_load = spapr_tce_table_post_load, .fields = (VMStateField []) { /* Sanity check */ VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable), @@ -132,7 +143,8 @@ static int spapr_tce_table_realize(DeviceState *dev) trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd); memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops, - "iommu-spapr", ram_size); + "iommu-spapr", + (uint64_t)tcet->nb_table << tcet->page_shift); QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); @@ -192,17 +204,11 @@ MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet) return &tcet->iommu; } -void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass) -{ - tcet->bypass = bypass; -} - static void spapr_tce_reset(DeviceState *dev) { sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev); size_t table_size = tcet->nb_table * sizeof(uint64_t); - tcet->bypass = false; memset(tcet->table, 0, table_size); } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 21b95b3..05f4fac 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -406,6 +406,258 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu, rtas_st(rets, 2, 1);/* 0 == level; 1 == edge */ } +static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu, + sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + sPAPRPHBState *sphb; + sPAPRPHBClass *spc; + uint32_t addr, option; + uint64_t buid; + int ret; + + if ((nargs != 4) || (nret != 1)) { + goto param_error_exit; + } + + buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + addr = rtas_ld(args, 0); + option = rtas_ld(args, 3); + + sphb = find_phb(spapr, buid); + if (!sphb) { + goto param_error_exit; + } + + spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); + if (!spc->eeh_set_option) { + goto param_error_exit; + } + + ret = spc->eeh_set_option(sphb, addr, option); + rtas_st(rets, 0, ret); + return; + +param_error_exit: + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +} + +static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu, + sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + sPAPRPHBState *sphb; + sPAPRPHBClass *spc; + PCIDevice *pdev; + uint32_t addr, option; + uint64_t buid; + + if ((nargs != 4) || (nret != 2)) { + goto param_error_exit; + } + + buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + sphb = find_phb(spapr, buid); + if (!sphb) { + goto param_error_exit; + } + + spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); + if (!spc->eeh_set_option) { + goto param_error_exit; + } + + /* + * We always have PE address of form "00BB0001". "BB" + * represents the bus number of PE's primary bus. + */ + option = rtas_ld(args, 3); + switch (option) { + case RTAS_GET_PE_ADDR: + addr = rtas_ld(args, 0); + pdev = find_dev(spapr, buid, addr); + if (!pdev) { + goto param_error_exit; + } + + rtas_st(rets, 1, (pci_bus_num(pdev->bus) << 16) + 1); + break; + case RTAS_GET_PE_MODE: + rtas_st(rets, 1, RTAS_PE_MODE_SHARED); + break; + default: + goto param_error_exit; + } + + rtas_st(rets, 0, RTAS_OUT_SUCCESS); + return; + +param_error_exit: + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +} + +static void rtas_ibm_read_slot_reset_state2(PowerPCCPU *cpu, + sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + sPAPRPHBState *sphb; + sPAPRPHBClass *spc; + uint64_t buid; + int state, ret; + + if ((nargs != 3) || (nret != 4 && nret != 5)) { + goto param_error_exit; + } + + buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + sphb = find_phb(spapr, buid); + if (!sphb) { + goto param_error_exit; + } + + spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); + if (!spc->eeh_get_state) { + goto param_error_exit; + } + + ret = spc->eeh_get_state(sphb, &state); + rtas_st(rets, 0, ret); + if (ret != RTAS_OUT_SUCCESS) { + return; + } + + rtas_st(rets, 1, state); + rtas_st(rets, 2, RTAS_EEH_SUPPORT); + rtas_st(rets, 3, RTAS_EEH_PE_UNAVAIL_INFO); + if (nret >= 5) { + rtas_st(rets, 4, RTAS_EEH_PE_RECOVER_INFO); + } + return; + +param_error_exit: + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +} + +static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu, + sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + sPAPRPHBState *sphb; + sPAPRPHBClass *spc; + uint32_t option; + uint64_t buid; + int ret; + + if ((nargs != 4) || (nret != 1)) { + goto param_error_exit; + } + + buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + option = rtas_ld(args, 3); + sphb = find_phb(spapr, buid); + if (!sphb) { + goto param_error_exit; + } + + spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); + if (!spc->eeh_reset) { + goto param_error_exit; + } + + ret = spc->eeh_reset(sphb, option); + rtas_st(rets, 0, ret); + return; + +param_error_exit: + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +} + +static void rtas_ibm_configure_pe(PowerPCCPU *cpu, + sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + sPAPRPHBState *sphb; + sPAPRPHBClass *spc; + uint64_t buid; + int ret; + + if ((nargs != 3) || (nret != 1)) { + goto param_error_exit; + } + + buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + sphb = find_phb(spapr, buid); + if (!sphb) { + goto param_error_exit; + } + + spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); + if (!spc->eeh_configure) { + goto param_error_exit; + } + + ret = spc->eeh_configure(sphb); + rtas_st(rets, 0, ret); + return; + +param_error_exit: + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +} + +/* To support it later */ +static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu, + sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + sPAPRPHBState *sphb; + sPAPRPHBClass *spc; + int option; + uint64_t buid; + + if ((nargs != 8) || (nret != 1)) { + goto param_error_exit; + } + + buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2); + sphb = find_phb(spapr, buid); + if (!sphb) { + goto param_error_exit; + } + + spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb); + if (!spc->eeh_set_option) { + goto param_error_exit; + } + + option = rtas_ld(args, 7); + switch (option) { + case RTAS_SLOT_TEMP_ERR_LOG: + case RTAS_SLOT_PERM_ERR_LOG: + break; + default: + goto param_error_exit; + } + + /* We don't have error log yet */ + rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND); + return; + +param_error_exit: + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +} + static int pci_spapr_swizzle(int slot, int pin) { return (slot + pin) % PCI_NUM_PINS; @@ -501,6 +753,12 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) return; } + if (sphb->index > SPAPR_PCI_MAX_INDEX) { + error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", + SPAPR_PCI_MAX_INDEX); + return; + } + sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index; sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index; @@ -669,7 +927,7 @@ static void spapr_phb_reset(DeviceState *qdev) } static Property spapr_phb_properties[] = { - DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1), + DEFINE_PROP_UINT32("index", sPAPRPHBState, index, -1), DEFINE_PROP_UINT64("buid", sPAPRPHBState, buid, -1), DEFINE_PROP_UINT32("liobn", sPAPRPHBState, dma_liobn, -1), DEFINE_PROP_UINT64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1), @@ -862,6 +1120,10 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, int bus_off, i, j; char nodename[256]; uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) }; + const uint64_t mmiosize = memory_region_size(&phb->memwindow); + const uint64_t w32max = (1ULL << 32) - SPAPR_PCI_MEM_WIN_BUS_OFFSET; + const uint64_t w32size = MIN(w32max, mmiosize); + const uint64_t w64size = (mmiosize > w32size) ? (mmiosize - w32size) : 0; struct { uint32_t hi; uint64_t child; @@ -876,9 +1138,15 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, { cpu_to_be32(b_ss(2)), cpu_to_be64(SPAPR_PCI_MEM_WIN_BUS_OFFSET), cpu_to_be64(phb->mem_win_addr), - cpu_to_be64(memory_region_size(&phb->memwindow)), + cpu_to_be64(w32size), + }, + { + cpu_to_be32(b_ss(3)), cpu_to_be64(1ULL << 32), + cpu_to_be64(phb->mem_win_addr + w32size), + cpu_to_be64(w64size) }, }; + const unsigned sizeof_ranges = (w64size ? 3 : 2) * sizeof(ranges[0]); uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 }; uint32_t interrupt_map_mask[] = { cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)}; @@ -907,7 +1175,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, _FDT(fdt_setprop_cell(fdt, bus_off, "#interrupt-cells", 0x1)); _FDT(fdt_setprop(fdt, bus_off, "used-by-rtas", NULL, 0)); _FDT(fdt_setprop(fdt, bus_off, "bus-range", &bus_range, sizeof(bus_range))); - _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof(ranges))); + _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges)); _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg))); _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1)); _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS)); @@ -958,6 +1226,25 @@ void spapr_pci_rtas_init(void) spapr_rtas_register(RTAS_IBM_CHANGE_MSI, "ibm,change-msi", rtas_ibm_change_msi); } + + spapr_rtas_register(RTAS_IBM_SET_EEH_OPTION, + "ibm,set-eeh-option", + rtas_ibm_set_eeh_option); + spapr_rtas_register(RTAS_IBM_GET_CONFIG_ADDR_INFO2, + "ibm,get-config-addr-info2", + rtas_ibm_get_config_addr_info2); + spapr_rtas_register(RTAS_IBM_READ_SLOT_RESET_STATE2, + "ibm,read-slot-reset-state2", + rtas_ibm_read_slot_reset_state2); + spapr_rtas_register(RTAS_IBM_SET_SLOT_RESET, + "ibm,set-slot-reset", + rtas_ibm_set_slot_reset); + spapr_rtas_register(RTAS_IBM_CONFIGURE_PE, + "ibm,configure-pe", + rtas_ibm_configure_pe); + spapr_rtas_register(RTAS_IBM_SLOT_ERROR_DETAIL, + "ibm,slot-error-detail", + rtas_ibm_slot_error_detail); } static void spapr_pci_register_types(void) @@ -966,3 +1253,31 @@ static void spapr_pci_register_types(void) } type_init(spapr_pci_register_types) + +static int spapr_switch_one_vga(DeviceState *dev, void *opaque) +{ + bool be = *(bool *)opaque; + + if (object_dynamic_cast(OBJECT(dev), "VGA") + || object_dynamic_cast(OBJECT(dev), "secondary-vga")) { + object_property_set_bool(OBJECT(dev), be, "big-endian-framebuffer", + &error_abort); + } + return 0; +} + +void spapr_pci_switch_vga(bool big_endian) +{ + sPAPRPHBState *sphb; + + /* + * For backward compatibility with existing guests, we switch + * the endianness of the VGA controller when changing the guest + * interrupt mode + */ + QLIST_FOREACH(sphb, &spapr->phbs, list) { + BusState *bus = &PCI_HOST_BRIDGE(sphb)->bus->qbus; + qbus_walk_children(bus, spapr_switch_one_vga, NULL, NULL, NULL, + &big_endian); + } +} diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c index 144912b..99a1be5 100644 --- a/hw/ppc/spapr_pci_vfio.c +++ b/hw/ppc/spapr_pci_vfio.c @@ -76,6 +76,117 @@ static void spapr_phb_vfio_reset(DeviceState *qdev) /* Do nothing */ } +static int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb, + unsigned int addr, int option) +{ + sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb); + struct vfio_eeh_pe_op op = { .argsz = sizeof(op) }; + int ret; + + switch (option) { + case RTAS_EEH_DISABLE: + op.op = VFIO_EEH_PE_DISABLE; + break; + case RTAS_EEH_ENABLE: { + PCIHostState *phb; + PCIDevice *pdev; + + /* + * The EEH functionality is enabled on basis of PCI device, + * instead of PE. We need check the validity of the PCI + * device address. + */ + phb = PCI_HOST_BRIDGE(sphb); + pdev = pci_find_device(phb->bus, + (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); + if (!pdev) { + return RTAS_OUT_PARAM_ERROR; + } + + op.op = VFIO_EEH_PE_ENABLE; + break; + } + case RTAS_EEH_THAW_IO: + op.op = VFIO_EEH_PE_UNFREEZE_IO; + break; + case RTAS_EEH_THAW_DMA: + op.op = VFIO_EEH_PE_UNFREEZE_DMA; + break; + default: + return RTAS_OUT_PARAM_ERROR; + } + + ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid, + VFIO_EEH_PE_OP, &op); + if (ret < 0) { + return RTAS_OUT_HW_ERROR; + } + + return RTAS_OUT_SUCCESS; +} + +static int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb, int *state) +{ + sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb); + struct vfio_eeh_pe_op op = { .argsz = sizeof(op) }; + int ret; + + op.op = VFIO_EEH_PE_GET_STATE; + ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid, + VFIO_EEH_PE_OP, &op); + if (ret < 0) { + return RTAS_OUT_PARAM_ERROR; + } + + *state = ret; + return RTAS_OUT_SUCCESS; +} + +static int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option) +{ + sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb); + struct vfio_eeh_pe_op op = { .argsz = sizeof(op) }; + int ret; + + switch (option) { + case RTAS_SLOT_RESET_DEACTIVATE: + op.op = VFIO_EEH_PE_RESET_DEACTIVATE; + break; + case RTAS_SLOT_RESET_HOT: + op.op = VFIO_EEH_PE_RESET_HOT; + break; + case RTAS_SLOT_RESET_FUNDAMENTAL: + op.op = VFIO_EEH_PE_RESET_FUNDAMENTAL; + break; + default: + return RTAS_OUT_PARAM_ERROR; + } + + ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid, + VFIO_EEH_PE_OP, &op); + if (ret < 0) { + return RTAS_OUT_HW_ERROR; + } + + return RTAS_OUT_SUCCESS; +} + +static int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb) +{ + sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb); + struct vfio_eeh_pe_op op = { .argsz = sizeof(op) }; + int ret; + + op.op = VFIO_EEH_PE_CONFIGURE; + ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid, + VFIO_EEH_PE_OP, &op); + if (ret < 0) { + return RTAS_OUT_PARAM_ERROR; + } + + return RTAS_OUT_SUCCESS; +} + static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -84,6 +195,10 @@ static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data) dc->props = spapr_phb_vfio_properties; dc->reset = spapr_phb_vfio_reset; spc->finish_realize = spapr_phb_vfio_finish_realize; + spc->eeh_set_option = spapr_phb_vfio_eeh_set_option; + spc->eeh_get_state = spapr_phb_vfio_eeh_get_state; + spc->eeh_reset = spapr_phb_vfio_eeh_reset; + spc->eeh_configure = spapr_phb_vfio_eeh_configure; } static const TypeInfo spapr_phb_vfio_info = { diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 2ec2a8e..0f1ae55 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -52,51 +52,6 @@ static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr, } } -static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct tm tm; - - if (nret != 8) { - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); - return; - } - - qemu_get_timedate(&tm, spapr->rtc_offset); - - rtas_st(rets, 0, RTAS_OUT_SUCCESS); - rtas_st(rets, 1, tm.tm_year + 1900); - rtas_st(rets, 2, tm.tm_mon + 1); - rtas_st(rets, 3, tm.tm_mday); - rtas_st(rets, 4, tm.tm_hour); - rtas_st(rets, 5, tm.tm_min); - rtas_st(rets, 6, tm.tm_sec); - rtas_st(rets, 7, 0); /* we don't do nanoseconds */ -} - -static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct tm tm; - - tm.tm_year = rtas_ld(args, 0) - 1900; - tm.tm_mon = rtas_ld(args, 1) - 1; - tm.tm_mday = rtas_ld(args, 2); - tm.tm_hour = rtas_ld(args, 3); - tm.tm_min = rtas_ld(args, 4); - tm.tm_sec = rtas_ld(args, 5); - - /* Just generate a monitor event for the change */ - qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort); - spapr->rtc_offset = qemu_timedate_diff(&tm); - - rtas_st(rets, 0, RTAS_OUT_SUCCESS); -} - static void rtas_power_off(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) @@ -400,10 +355,6 @@ static void core_rtas_register_types(void) { spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character", rtas_display_character); - spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day", - rtas_get_time_of_day); - spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day", - rtas_set_time_of_day); spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off); spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot", rtas_system_reboot); diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c new file mode 100644 index 0000000..83eb7c1 --- /dev/null +++ b/hw/ppc/spapr_rtc.c @@ -0,0 +1,212 @@ +/* + * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator + * + * RTAS Real Time Clock + * + * Copyright (c) 2010-2011 David Gibson, IBM Corporation. + * Copyright 2014 David Gibson, 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 "cpu.h" +#include "sysemu/sysemu.h" +#include "hw/ppc/spapr.h" +#include "qapi-event.h" + +#define SPAPR_RTC(obj) \ + OBJECT_CHECK(sPAPRRTCState, (obj), TYPE_SPAPR_RTC) + +typedef struct sPAPRRTCState sPAPRRTCState; +struct sPAPRRTCState { + /*< private >*/ + SysBusDevice parent_obj; + int64_t ns_offset; +}; + +#define NSEC_PER_SEC 1000000000LL + +void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns) +{ + sPAPRRTCState *rtc = SPAPR_RTC(dev); + int64_t host_ns = qemu_clock_get_ns(rtc_clock); + int64_t guest_ns; + time_t guest_s; + + assert(rtc); + + guest_ns = host_ns + rtc->ns_offset; + guest_s = guest_ns / NSEC_PER_SEC; + + if (tm) { + gmtime_r(&guest_s, tm); + } + if (ns) { + *ns = guest_ns; + } +} + +int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset) +{ + sPAPRRTCState *rtc; + + if (!dev) { + return -ENODEV; + } + + rtc = SPAPR_RTC(dev); + + rtc->ns_offset = legacy_offset * NSEC_PER_SEC; + + return 0; +} + +static void rtas_get_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, + uint32_t nret, target_ulong rets) +{ + struct tm tm; + uint32_t ns; + + if ((nargs != 0) || (nret != 8)) { + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); + return; + } + + if (!spapr->rtc) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } + + spapr_rtc_read(spapr->rtc, &tm, &ns); + + rtas_st(rets, 0, RTAS_OUT_SUCCESS); + rtas_st(rets, 1, tm.tm_year + 1900); + rtas_st(rets, 2, tm.tm_mon + 1); + rtas_st(rets, 3, tm.tm_mday); + rtas_st(rets, 4, tm.tm_hour); + rtas_st(rets, 5, tm.tm_min); + rtas_st(rets, 6, tm.tm_sec); + rtas_st(rets, 7, ns); +} + +static void rtas_set_time_of_day(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, + uint32_t nret, target_ulong rets) +{ + sPAPRRTCState *rtc; + struct tm tm; + time_t new_s; + int64_t host_ns; + + if ((nargs != 7) || (nret != 1)) { + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); + return; + } + + if (!spapr->rtc) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + return; + } + + tm.tm_year = rtas_ld(args, 0) - 1900; + tm.tm_mon = rtas_ld(args, 1) - 1; + tm.tm_mday = rtas_ld(args, 2); + tm.tm_hour = rtas_ld(args, 3); + tm.tm_min = rtas_ld(args, 4); + tm.tm_sec = rtas_ld(args, 5); + + new_s = mktimegm(&tm); + if (new_s == -1) { + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); + return; + } + + /* Generate a monitor event for the change */ + qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort); + + rtc = SPAPR_RTC(spapr->rtc); + + host_ns = qemu_clock_get_ns(rtc_clock); + + rtc->ns_offset = (new_s * NSEC_PER_SEC) - host_ns; + + rtas_st(rets, 0, RTAS_OUT_SUCCESS); +} + +static void spapr_rtc_qom_date(Object *obj, struct tm *current_tm, Error **errp) +{ + spapr_rtc_read(DEVICE(obj), current_tm, NULL); +} + +static void spapr_rtc_realize(DeviceState *dev, Error **errp) +{ + sPAPRRTCState *rtc = SPAPR_RTC(dev); + struct tm tm; + time_t host_s; + int64_t rtc_ns; + + /* Initialize the RTAS RTC from host time */ + + qemu_get_timedate(&tm, 0); + host_s = mktimegm(&tm); + rtc_ns = qemu_clock_get_ns(rtc_clock); + rtc->ns_offset = host_s * NSEC_PER_SEC - rtc_ns; + + object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date, NULL); +} + +static const VMStateDescription vmstate_spapr_rtc = { + .name = "spapr/rtc", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_INT64(ns_offset, sPAPRRTCState), + VMSTATE_END_OF_LIST() + }, +}; + +static void spapr_rtc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = spapr_rtc_realize; + dc->vmsd = &vmstate_spapr_rtc; + + spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day", + rtas_get_time_of_day); + spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day", + rtas_set_time_of_day); +} + +static const TypeInfo spapr_rtc_info = { + .name = TYPE_SPAPR_RTC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(sPAPRRTCState), + .class_size = sizeof(XICSStateClass), + .class_init = spapr_rtc_class_init, +}; + +static void spapr_rtc_register_types(void) +{ + type_register_static(&spapr_rtc_info); +} +type_init(spapr_rtc_register_types) diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 032ee1a..1360b97 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -322,6 +322,18 @@ static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev) free_crq(dev); } +void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass) +{ + if (!dev->tcet) { + return; + } + + memory_region_set_enabled(&dev->mrbypass, bypass); + memory_region_set_enabled(spapr_tce_get_iommu(dev->tcet), !bypass); + + dev->tcet->bypass = bypass; +} + static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, @@ -348,7 +360,7 @@ static void rtas_set_tce_bypass(PowerPCCPU *cpu, sPAPREnvironment *spapr, return; } - spapr_tce_set_bypass(dev->tcet, !!enable); + spapr_vio_set_bypass(dev, !!enable); rtas_st(rets, 0, RTAS_OUT_SUCCESS); } @@ -407,12 +419,13 @@ static void spapr_vio_busdev_reset(DeviceState *qdev) dev->signal_state = 0; + spapr_vio_set_bypass(dev, false); if (pc->reset) { pc->reset(dev); } } -static int spapr_vio_busdev_init(DeviceState *qdev) +static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) { VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); @@ -428,11 +441,11 @@ static int spapr_vio_busdev_init(DeviceState *qdev) VIOsPAPRDevice *other = reg_conflict(dev); if (other) { - fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n", - object_get_typename(OBJECT(qdev)), - object_get_typename(OBJECT(&other->qdev)), - dev->reg); - return -1; + error_setg(errp, "%s and %s devices conflict at address %#x", + object_get_typename(OBJECT(qdev)), + object_get_typename(OBJECT(&other->qdev)), + dev->reg); + return; } } else { /* Need to assign an address */ @@ -451,20 +464,32 @@ static int spapr_vio_busdev_init(DeviceState *qdev) dev->irq = xics_alloc(spapr->icp, 0, dev->irq, false); if (!dev->irq) { - return -1; + error_setg(errp, "can't allocate IRQ"); + return; } if (pc->rtce_window_size) { uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; + + memory_region_init(&dev->mrroot, OBJECT(dev), "iommu-spapr-root", + ram_size); + memory_region_init_alias(&dev->mrbypass, OBJECT(dev), + "iommu-spapr-bypass", get_system_memory(), + 0, ram_size); + memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1); + address_space_init(&dev->as, &dev->mrroot, qdev->id); + dev->tcet = spapr_tce_new_table(qdev, liobn, 0, SPAPR_TCE_PAGE_SHIFT, pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT, false); - address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id); + dev->tcet->vdev = dev; + memory_region_add_subregion_overlap(&dev->mrroot, 0, + spapr_tce_get_iommu(dev->tcet), 2); } - return pc->init(dev); + pc->realize(dev, errp); } static target_ulong h_vio_signal(PowerPCCPU *cpu, sPAPREnvironment *spapr, @@ -570,7 +595,7 @@ const VMStateDescription vmstate_spapr_vio = { static void vio_spapr_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->init = spapr_vio_busdev_init; + k->realize = spapr_vio_busdev_realize; k->reset = spapr_vio_busdev_reset; k->bus_type = TYPE_SPAPR_VIO_BUS; k->props = spapr_vio_props; diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h index ffd0df7..92aa9d0 100644 --- a/hw/s390x/s390-virtio-bus.h +++ b/hw/s390x/s390-virtio-bus.h @@ -19,6 +19,10 @@ #ifndef HW_S390_VIRTIO_BUS_H #define HW_S390_VIRTIO_BUS_H 1 +#include <stddef.h> + +#include "standard-headers/asm-s390/kvm_virtio.h" +#include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/virtio-blk.h" #include "hw/virtio/virtio-net.h" #include "hw/virtio/virtio-rng.h" @@ -29,28 +33,26 @@ #include "hw/virtio/vhost-scsi.h" #endif -#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */ -#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */ -#define VIRTIO_DEV_OFFS_FEATURE_LEN 2 /* 8 bits */ -#define VIRTIO_DEV_OFFS_CONFIG_LEN 3 /* 8 bits */ -#define VIRTIO_DEV_OFFS_STATUS 4 /* 8 bits */ -#define VIRTIO_DEV_OFFS_CONFIG 5 /* dynamic */ +typedef struct kvm_device_desc KvmDeviceDesc; + +#define VIRTIO_DEV_OFFS_TYPE offsetof(KvmDeviceDesc, type) +#define VIRTIO_DEV_OFFS_NUM_VQ offsetof(KvmDeviceDesc, num_vq) +#define VIRTIO_DEV_OFFS_FEATURE_LEN offsetof(KvmDeviceDesc, feature_len) +#define VIRTIO_DEV_OFFS_CONFIG_LEN offsetof(KvmDeviceDesc, config_len) +#define VIRTIO_DEV_OFFS_STATUS offsetof(KvmDeviceDesc, status) +#define VIRTIO_DEV_OFFS_CONFIG offsetof(KvmDeviceDesc, config) -#define VIRTIO_VQCONFIG_OFFS_TOKEN 0 /* 64 bits */ -#define VIRTIO_VQCONFIG_OFFS_ADDRESS 8 /* 64 bits */ -#define VIRTIO_VQCONFIG_OFFS_NUM 16 /* 16 bits */ -#define VIRTIO_VQCONFIG_LEN 24 +typedef struct kvm_vqconfig KvmVqConfig; +#define VIRTIO_VQCONFIG_OFFS_TOKEN offsetof(KvmVqConfig,token) /* 64 bit */ +#define VIRTIO_VQCONFIG_OFFS_ADDRESS offsetof(KvmVqConfig, address) /* 64 bit */ +#define VIRTIO_VQCONFIG_OFFS_NUM offsetof(KvmVqConfig, num) /* 16 bit */ +#define VIRTIO_VQCONFIG_LEN sizeof(KvmVqConfig) #define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3) -#define VIRTIO_VRING_AVAIL_IDX_OFFS 2 -#define VIRTIO_VRING_USED_IDX_OFFS 2 +#define VIRTIO_VRING_AVAIL_IDX_OFFS offsetof(struct vring_avail, idx) +#define VIRTIO_VRING_USED_IDX_OFFS offsetof(struct vring_used, idx) #define S390_DEVICE_PAGES 512 -#define VIRTIO_PARAM_MASK 0xff -#define VIRTIO_PARAM_VRING_INTERRUPT 0x0 -#define VIRTIO_PARAM_CONFIG_CHANGED 0x1 -#define VIRTIO_PARAM_DEV_ADD 0x2 - #define TYPE_VIRTIO_S390_DEVICE "virtio-s390-device" #define VIRTIO_S390_DEVICE(obj) \ OBJECT_CHECK(VirtIOS390Device, (obj), TYPE_VIRTIO_S390_DEVICE) diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h index 75b67ed..c847853 100644 --- a/hw/s390x/s390-virtio.h +++ b/hw/s390x/s390-virtio.h @@ -13,11 +13,8 @@ #define HW_S390_VIRTIO_H 1 #include "hw/nmi.h" - -#define KVM_S390_VIRTIO_NOTIFY 0 -#define KVM_S390_VIRTIO_RESET 1 -#define KVM_S390_VIRTIO_SET_STATUS 2 -#define KVM_S390_VIRTIO_CCW_NOTIFY 3 +#include "standard-headers/asm-s390/kvm_virtio.h" +#include "standard-headers/asm-s390/virtio-ccw.h" typedef int (*s390_virtio_fn)(const uint64_t *args); void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn); diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index ea236c9..ffbb9c2 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -400,8 +400,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ccw.cda + sizeof(features.features)); features.features = ldl_le_phys(&address_space_memory, ccw.cda); if (features.index < ARRAY_SIZE(dev->host_features)) { - virtio_bus_set_vdev_features(&dev->bus, features.features); - vdev->guest_features = features.features; + virtio_set_features(vdev, features.features); } else { /* * If the guest supports more feature bits, assert that it @@ -744,8 +743,8 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev) dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus, dev->host_features[0]); - dev->host_features[0] |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; - dev->host_features[0] |= 0x1 << VIRTIO_F_BAD_FEATURE; + virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE); css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, parent->hotplugged, 1); @@ -899,9 +898,8 @@ static void balloon_ccw_stats_set_poll_interval(Object *obj, struct Visitor *v, static void virtio_ccw_balloon_instance_init(Object *obj) { VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj); - object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON); - object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); - object_unref(OBJECT(&dev->vdev)); + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_BALLOON); object_property_add(obj, "guest-stats", "guest statistics", balloon_ccw_stats_get_all, NULL, NULL, dev, NULL); diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index 3639235..891424f 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -1212,24 +1212,17 @@ static void spapr_vscsi_reset(VIOsPAPRDevice *dev) } } -static int spapr_vscsi_init(VIOsPAPRDevice *dev) +static void spapr_vscsi_realize(VIOsPAPRDevice *dev, Error **errp) { VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev); - Error *err = NULL; dev->crq.SendFunc = vscsi_do_crq; scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), &vscsi_scsi_info, NULL); if (!dev->qdev.hotplugged) { - scsi_bus_legacy_handle_cmdline(&s->bus, &err); - if (err != NULL) { - error_free(err); - return -1; - } + scsi_bus_legacy_handle_cmdline(&s->bus, errp); } - - return 0; } void spapr_vscsi_create(VIOsPAPRBus *bus) @@ -1281,7 +1274,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass); - k->init = spapr_vscsi_init; + k->realize = spapr_vscsi_realize; k->reset = spapr_vscsi_reset; k->devnode = spapr_vscsi_devnode; k->dt_name = "v-scsi"; diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 618b0af..335f442 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -83,7 +83,7 @@ static int vhost_scsi_start(VHostSCSI *s) if (abi_version > VHOST_SCSI_ABI_VERSION) { error_report("vhost-scsi: The running tcm_vhost kernel abi_version:" " %d is greater than vhost_scsi userspace supports: %d, please" - " upgrade your version of QEMU\n", abi_version, + " upgrade your version of QEMU", abi_version, VHOST_SCSI_ABI_VERSION); return -ENOSYS; } @@ -141,7 +141,7 @@ static void vhost_scsi_stop(VHostSCSI *s) if (k->set_guest_notifiers) { ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); if (ret < 0) { - error_report("vhost guest notifier cleanup failed: %d\n", ret); + error_report("vhost guest notifier cleanup failed: %d", ret); } } assert(ret >= 0); @@ -186,7 +186,7 @@ static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val) ret = vhost_scsi_start(s); if (ret < 0) { - error_report("virtio-scsi: unable to start vhost: %s\n", + error_report("virtio-scsi: unable to start vhost: %s", strerror(-ret)); /* There is no userspace virtio-scsi fallback so exit */ diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 4db3b23..cfb52e8 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -13,6 +13,7 @@ * */ +#include "standard-headers/linux/virtio_ids.h" #include "hw/virtio/virtio-scsi.h" #include "qemu/error-report.h" #include "qemu/iov.h" @@ -144,7 +145,7 @@ static int virtio_scsi_parse_req(VirtIOSCSIReq *req, * * TODO: always disable this workaround for virtio 1.0 devices. */ - if ((vdev->guest_features & (1 << VIRTIO_F_ANY_LAYOUT)) == 0) { + if (!virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) { req_size = req->elem.out_sg[0].iov_len; resp_size = req->elem.in_sg[0].iov_len; } @@ -744,7 +745,7 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); VirtIODevice *vdev = VIRTIO_DEVICE(s); - if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) && + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) && dev->type != TYPE_ROM) { virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE, sense.asc | (sense.ascq << 8)); @@ -768,7 +769,7 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, aio_context_release(s->ctx); } - if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); @@ -782,7 +783,7 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, VirtIOSCSI *s = VIRTIO_SCSI(vdev); SCSIDevice *sd = SCSI_DEVICE(dev); - if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { + if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) { virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 10e5355..27b914a 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1220,7 +1220,7 @@ static Property sdhci_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static int sdhci_pci_init(PCIDevice *dev) +static void sdhci_pci_realize(PCIDevice *dev, Error **errp) { SDHCIState *s = PCI_SDHCI(dev); dev->config[PCI_CLASS_PROG] = 0x01; /* Standard Host supported DMA */ @@ -1232,7 +1232,6 @@ static int sdhci_pci_init(PCIDevice *dev) memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci", SDHC_REGISTERS_MAP_SIZE); pci_register_bar(dev, 0, 0, &s->iomem); - return 0; } static void sdhci_pci_exit(PCIDevice *dev) @@ -1246,7 +1245,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = sdhci_pci_init; + k->realize = sdhci_pci_realize; k->exit = sdhci_pci_exit; k->vendor_id = PCI_VENDOR_ID_REDHAT; k->device_id = PCI_DEVICE_ID_REDHAT_SDHCI; diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 751392e..e41ec0b 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -186,6 +186,7 @@ static void leon3_generic_hw_init(MachineState *machine) fprintf(stderr, "Can't read bios image %s\n", filename); exit(1); } + g_free(filename); /* Can directly load an application. */ if (kernel_filename != NULL) { diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c index 435142a..b087bbdd 100644 --- a/hw/timer/a9gtimer.c +++ b/hw/timer/a9gtimer.c @@ -289,7 +289,7 @@ static void a9_gtimer_realize(DeviceState *dev, Error **errp) int i; if (s->num_cpu < 1 || s->num_cpu > A9_GTIMER_MAX_CPUS) { - error_setg(errp, "%s: num-cpu must be between 1 and %d\n", + error_setg(errp, "%s: num-cpu must be between 1 and %d", __func__, A9_GTIMER_MAX_CPUS); return; } diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 0600c9a..f2b77fa 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -831,49 +831,12 @@ static const MemoryRegionOps cmos_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -static void rtc_get_date(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void rtc_get_date(Object *obj, struct tm *current_tm, Error **errp) { - Error *err = NULL; RTCState *s = MC146818_RTC(obj); - struct tm current_tm; rtc_update_time(s); - rtc_get_time(s, ¤t_tm); - visit_start_struct(v, NULL, "struct tm", name, 0, &err); - if (err) { - goto out; - } - visit_type_int32(v, ¤t_tm.tm_year, "tm_year", &err); - if (err) { - goto out_end; - } - visit_type_int32(v, ¤t_tm.tm_mon, "tm_mon", &err); - if (err) { - goto out_end; - } - visit_type_int32(v, ¤t_tm.tm_mday, "tm_mday", &err); - if (err) { - goto out_end; - } - visit_type_int32(v, ¤t_tm.tm_hour, "tm_hour", &err); - if (err) { - goto out_end; - } - visit_type_int32(v, ¤t_tm.tm_min, "tm_min", &err); - if (err) { - goto out_end; - } - visit_type_int32(v, ¤t_tm.tm_sec, "tm_sec", &err); - if (err) { - goto out_end; - } -out_end: - error_propagate(errp, err); - err = NULL; - visit_end_struct(v, errp); -out: - error_propagate(errp, err); + rtc_get_time(s, current_tm); } static void rtc_realizefn(DeviceState *dev, Error **errp) @@ -932,8 +895,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) qdev_set_legacy_instance_id(dev, base, 3); qemu_register_reset(rtc_reset, s); - object_property_add(OBJECT(s), "date", "struct tm", - rtc_get_date, NULL, NULL, s, NULL); + object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL); object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(s), "date", NULL); diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h index 2f582ca..2b35fe2 100644 --- a/hw/tpm/tpm_int.h +++ b/hw/tpm/tpm_int.h @@ -62,6 +62,7 @@ struct tpm_resp_hdr { #define TPM_FAIL 9 +#define TPM_ORD_ContinueSelfTest 0x53 #define TPM_ORD_GetTicks 0xf1 #endif /* TPM_TPM_INT_H */ diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 2bf3c6f..2a45071 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -112,21 +112,38 @@ static void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len) } } +static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t in_len) +{ + struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in; + + if (in_len >= sizeof(*hdr)) { + return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest); + } + + return false; +} + static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, const uint8_t *in, uint32_t in_len, - uint8_t *out, uint32_t out_len) + uint8_t *out, uint32_t out_len, + bool *selftest_done) { int ret; + bool is_selftest; + const struct tpm_resp_hdr *hdr; tpm_pt->tpm_op_canceled = false; tpm_pt->tpm_executing = true; + *selftest_done = false; + + is_selftest = tpm_passthrough_is_selftest(in, in_len); ret = tpm_passthrough_unix_write(tpm_pt->tpm_fd, in, in_len); if (ret != in_len) { if (!tpm_pt->tpm_op_canceled || (tpm_pt->tpm_op_canceled && errno != ECANCELED)) { error_report("tpm_passthrough: error while transmitting data " - "to TPM: %s (%i)\n", + "to TPM: %s (%i)", strerror(errno), errno); } goto err_exit; @@ -139,14 +156,19 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, if (!tpm_pt->tpm_op_canceled || (tpm_pt->tpm_op_canceled && errno != ECANCELED)) { error_report("tpm_passthrough: error while reading data from " - "TPM: %s (%i)\n", + "TPM: %s (%i)", strerror(errno), errno); } } else if (ret < sizeof(struct tpm_resp_hdr) || tpm_passthrough_get_size_from_buffer(out) != ret) { ret = -1; error_report("tpm_passthrough: received invalid response " - "packet from TPM\n"); + "packet from TPM"); + } + + if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) { + hdr = (struct tpm_resp_hdr *)out; + *selftest_done = (be32_to_cpu(hdr->errcode) == 0); } err_exit: @@ -160,13 +182,15 @@ err_exit: } static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt, - const TPMLocality *locty_data) + const TPMLocality *locty_data, + bool *selftest_done) { return tpm_passthrough_unix_tx_bufs(tpm_pt, locty_data->w_buffer.buffer, locty_data->w_offset, locty_data->r_buffer.buffer, - locty_data->r_buffer.size); + locty_data->r_buffer.size, + selftest_done); } static void tpm_passthrough_worker_thread(gpointer data, @@ -175,16 +199,19 @@ static void tpm_passthrough_worker_thread(gpointer data, TPMPassthruThreadParams *thr_parms = user_data; TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb); TPMBackendCmd cmd = (TPMBackendCmd)data; + bool selftest_done = false; DPRINTF("tpm_passthrough: processing command type %d\n", cmd); switch (cmd) { case TPM_BACKEND_CMD_PROCESS_CMD: tpm_passthrough_unix_transfer(tpm_pt, - thr_parms->tpm_state->locty_data); + thr_parms->tpm_state->locty_data, + &selftest_done); thr_parms->recv_data_callback(thr_parms->tpm_state, - thr_parms->tpm_state->locty_number); + thr_parms->tpm_state->locty_number, + selftest_done); break; case TPM_BACKEND_CMD_INIT: case TPM_BACKEND_CMD_END: @@ -282,7 +309,7 @@ static void tpm_passthrough_cancel_cmd(TPMBackend *tb) if (tpm_pt->cancel_fd >= 0) { n = write(tpm_pt->cancel_fd, "-", 1); if (n != 1) { - error_report("Canceling TPM command failed: %s\n", + error_report("Canceling TPM command failed: %s", strerror(errno)); } else { tpm_pt->tpm_op_canceled = true; @@ -413,13 +440,13 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR); if (tpm_pt->tpm_fd < 0) { - error_report("Cannot access TPM device using '%s': %s\n", + error_report("Cannot access TPM device using '%s': %s", tpm_pt->tpm_dev, strerror(errno)); goto err_free_parameters; } if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) { - error_report("'%s' is not a TPM device.\n", + error_report("'%s' is not a TPM device.", tpm_pt->tpm_dev); goto err_close_tpmdev; } diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index c0e7cd7..d0bb97f 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -14,7 +14,7 @@ * * Implementation of the TIS interface according to specs found at * http://www.trustedcomputinggroup.org. This implementation currently - * supports version 1.21, revision 1.0. + * supports version 1.3, 21 March 2013 * In the developers menu choose the PC Client section then find the TIS * specification. */ @@ -51,6 +51,8 @@ #define TPM_TIS_REG_INTF_CAPABILITY 0x14 #define TPM_TIS_REG_STS 0x18 #define TPM_TIS_REG_DATA_FIFO 0x24 +#define TPM_TIS_REG_DATA_XFIFO 0x80 +#define TPM_TIS_REG_DATA_XFIFO_END 0xbc #define TPM_TIS_REG_DID_VID 0xf00 #define TPM_TIS_REG_RID 0xf04 @@ -62,6 +64,7 @@ #define TPM_TIS_STS_TPM_GO (1 << 5) #define TPM_TIS_STS_DATA_AVAILABLE (1 << 4) #define TPM_TIS_STS_EXPECT (1 << 3) +#define TPM_TIS_STS_SELFTEST_DONE (1 << 2) #define TPM_TIS_STS_RESPONSE_RETRY (1 << 1) #define TPM_TIS_BURST_COUNT_SHIFT 8 @@ -100,8 +103,15 @@ #endif +#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28) +#define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) +#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) +#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ #define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ + TPM_TIS_CAP_DATA_TRANSFER_64B | \ + TPM_TIS_CAP_INTERFACE_VERSION1_3 | \ TPM_TIS_INTERRUPTS_SUPPORTED) #define TPM_TIS_TPM_DID 0x0001 @@ -145,6 +155,24 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string) } /* + * Set the given flags in the STS register by clearing the register but + * preserving the SELFTEST_DONE flag and then setting the new flags. + * + * The SELFTEST_DONE flag is acquired from the backend that determines it by + * peeking into TPM commands. + * + * A VM suspend/resume will preserve the flag by storing it into the VM + * device state, but the backend will not remember it when QEMU is started + * again. Therefore, we cache the flag here. Once set, it will not be unset + * except by a reset. + */ +static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) +{ + l->sts &= TPM_TIS_STS_SELFTEST_DONE; + l->sts |= flags; +} + +/* * Send a request to the TPM. */ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) @@ -255,7 +283,8 @@ static void tpm_tis_abort(TPMState *s, uint8_t locty) */ if (tis->aborting_locty == tis->next_locty) { tis->loc[tis->aborting_locty].state = TPM_TIS_STATE_READY; - tis->loc[tis->aborting_locty].sts = TPM_TIS_STS_COMMAND_READY; + tpm_tis_sts_set(&tis->loc[tis->aborting_locty], + TPM_TIS_STS_COMMAND_READY); tpm_tis_raise_irq(s, tis->aborting_locty, TPM_TIS_INT_COMMAND_READY); } @@ -300,7 +329,8 @@ static void tpm_tis_receive_bh(void *opaque) TPMTISEmuState *tis = &s->s.tis; uint8_t locty = s->locty_number; - tis->loc[locty].sts = TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE; + tpm_tis_sts_set(&tis->loc[locty], + TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); tis->loc[locty].state = TPM_TIS_STATE_COMPLETION; tis->loc[locty].r_offset = 0; tis->loc[locty].w_offset = 0; @@ -320,12 +350,20 @@ static void tpm_tis_receive_bh(void *opaque) /* * Callback from the TPM to indicate that the response was received. */ -static void tpm_tis_receive_cb(TPMState *s, uint8_t locty) +static void tpm_tis_receive_cb(TPMState *s, uint8_t locty, + bool is_selftest_done) { TPMTISEmuState *tis = &s->s.tis; + uint8_t l; assert(s->locty_number == locty); + if (is_selftest_done) { + for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { + tis->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE; + } + } + qemu_bh_schedule(tis->bh); } @@ -344,7 +382,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) ret = tis->loc[locty].r_buffer.buffer[tis->loc[locty].r_offset++]; if (tis->loc[locty].r_offset >= len) { /* got last byte */ - tis->loc[locty].sts = TPM_TIS_STS_VALID; + tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID); #ifdef RAISE_STS_IRQ tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); #endif @@ -427,6 +465,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, uint32_t val = 0xffffffff; uint8_t locty = tpm_tis_locality_from_addr(addr); uint32_t avail; + uint8_t v; if (tpm_backend_had_startup_error(s->be_driver)) { return val; @@ -475,15 +514,28 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, } break; case TPM_TIS_REG_DATA_FIFO: + case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: if (tis->active_locty == locty) { - switch (tis->loc[locty].state) { - case TPM_TIS_STATE_COMPLETION: - val = tpm_tis_data_read(s, locty); - break; - default: - val = TPM_TIS_NO_DATA_BYTE; - break; + if (size > 4 - (addr & 0x3)) { + /* prevent access beyond FIFO */ + size = 4 - (addr & 0x3); } + val = 0; + shift = 0; + while (size > 0) { + switch (tis->loc[locty].state) { + case TPM_TIS_STATE_COMPLETION: + v = tpm_tis_data_read(s, locty); + break; + default: + v = TPM_TIS_NO_DATA_BYTE; + break; + } + val |= (v << shift); + shift += 8; + size--; + } + shift = 0; /* no more adjustments */ } break; case TPM_TIS_REG_DID_VID: @@ -518,11 +570,13 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, { TPMState *s = opaque; TPMTISEmuState *tis = &s->s.tis; - uint16_t off = addr & 0xfff; + uint16_t off = addr & 0xffc; + uint8_t shift = (addr & 0x3) * 8; uint8_t locty = tpm_tis_locality_from_addr(addr); uint8_t active_locty, l; int c, set_new_locty = 1; uint16_t len; + uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0); DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); @@ -535,6 +589,15 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, return; } + val &= mask; + + if (shift) { + val <<= shift; + mask <<= shift; + } + + mask ^= 0xffffffff; + switch (off) { case TPM_TIS_REG_ACCESS: @@ -646,9 +709,10 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, break; } - tis->loc[locty].inte = (val & (TPM_TIS_INT_ENABLED | - TPM_TIS_INT_POLARITY_MASK | - TPM_TIS_INTERRUPTS_SUPPORTED)); + tis->loc[locty].inte &= mask; + tis->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | + TPM_TIS_INT_POLARITY_MASK | + TPM_TIS_INTERRUPTS_SUPPORTED)); break; case TPM_TIS_REG_INT_VECTOR: /* hard wired -- ignore */ @@ -686,7 +750,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, break; case TPM_TIS_STATE_IDLE: - tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; + tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_COMMAND_READY); tis->loc[locty].state = TPM_TIS_STATE_READY; tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); break; @@ -705,7 +769,8 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, /* shortcut to ready state with C/R set */ tis->loc[locty].state = TPM_TIS_STATE_READY; if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { - tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; + tpm_tis_sts_set(&tis->loc[locty], + TPM_TIS_STS_COMMAND_READY); tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); } tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); @@ -727,8 +792,9 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, switch (tis->loc[locty].state) { case TPM_TIS_STATE_COMPLETION: tis->loc[locty].r_offset = 0; - tis->loc[locty].sts = TPM_TIS_STS_VALID | - TPM_TIS_STS_DATA_AVAILABLE; + tpm_tis_sts_set(&tis->loc[locty], + TPM_TIS_STS_VALID| + TPM_TIS_STS_DATA_AVAILABLE); break; default: /* ignore */ @@ -737,6 +803,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, } break; case TPM_TIS_REG_DATA_FIFO: + case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: /* data fifo */ if (tis->active_locty != locty) { break; @@ -747,18 +814,28 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) { /* drop the byte */ } else { - DPRINTF("tpm_tis: Byte to send to TPM: %02x\n", (uint8_t)val); + DPRINTF("tpm_tis: Data to send to TPM: %08x (size=%d)\n", + val, size); if (tis->loc[locty].state == TPM_TIS_STATE_READY) { tis->loc[locty].state = TPM_TIS_STATE_RECEPTION; - tis->loc[locty].sts = TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID; + tpm_tis_sts_set(&tis->loc[locty], + TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); + } + + val >>= shift; + if (size > 4 - (addr & 0x3)) { + /* prevent access beyond FIFO */ + size = 4 - (addr & 0x3); } - if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) { + while ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) { tis->loc[locty].w_buffer. buffer[tis->loc[locty].w_offset++] = (uint8_t)val; + val >>= 8; + size--; } else { - tis->loc[locty].sts = TPM_TIS_STS_VALID; + tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID); } } @@ -771,11 +848,11 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, #endif len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer); if (len > tis->loc[locty].w_offset) { - tis->loc[locty].sts = TPM_TIS_STS_EXPECT | - TPM_TIS_STS_VALID; + tpm_tis_sts_set(&tis->loc[locty], + TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); } else { /* packet complete */ - tis->loc[locty].sts = TPM_TIS_STS_VALID; + tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID); } #ifdef RAISE_STS_IRQ if (needIrq) { diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h index 1a0db23..db78d51 100644 --- a/hw/tpm/tpm_tis.h +++ b/hw/tpm/tpm_tis.h @@ -41,7 +41,7 @@ typedef enum { typedef struct TPMLocality { TPMTISState state; uint8_t access; - uint8_t sts; + uint32_t sts; uint32_t inte; uint32_t ints; diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 490f2b6..4c80707 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -26,7 +26,7 @@ typedef struct EHCIPCIInfo { bool companion; } EHCIPCIInfo; -static int usb_ehci_pci_initfn(PCIDevice *dev) +static void usb_ehci_pci_realize(PCIDevice *dev, Error **errp) { EHCIPCIState *i = PCI_EHCI(dev); EHCIState *s = &i->ehci; @@ -66,8 +66,6 @@ static int usb_ehci_pci_initfn(PCIDevice *dev) usb_ehci_realize(s, DEVICE(dev), NULL); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); - - return 0; } static void usb_ehci_pci_init(Object *obj) @@ -139,7 +137,7 @@ static void ehci_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->init = usb_ehci_pci_initfn; + k->realize = usb_ehci_pci_realize; k->exit = usb_ehci_pci_exit; k->class_id = PCI_CLASS_SERIAL_USB; k->config_write = usb_ehci_pci_write_config; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 828c2a7..ba15ae0 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3576,7 +3576,7 @@ static void usb_xhci_init(XHCIState *xhci) } } -static int usb_xhci_initfn(struct PCIDevice *dev) +static void usb_xhci_realize(struct PCIDevice *dev, Error **errp) { int i, ret; @@ -3655,8 +3655,6 @@ static int usb_xhci_initfn(struct PCIDevice *dev) &xhci->mem, 0, OFF_MSIX_PBA, 0x90); } - - return 0; } static void usb_xhci_exit(PCIDevice *dev) @@ -3896,7 +3894,7 @@ static void xhci_class_init(ObjectClass *klass, void *data) dc->props = xhci_properties; dc->reset = xhci_reset; set_bit(DEVICE_CATEGORY_USB, dc->categories); - k->init = usb_xhci_initfn; + k->realize = usb_xhci_realize; k->exit = usb_xhci_exit; k->vendor_id = PCI_VENDOR_ID_NEC; k->device_id = PCI_DEVICE_ID_NEC_UPD720200; diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 9db7d8d..b012620 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -201,7 +201,7 @@ static int vfio_dma_unmap(VFIOContainer *container, }; if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { - error_report("VFIO_UNMAP_DMA: %d\n", -errno); + error_report("VFIO_UNMAP_DMA: %d", -errno); return -errno; } @@ -234,7 +234,7 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova, return 0; } - error_report("VFIO_MAP_DMA: %d\n", -errno); + error_report("VFIO_MAP_DMA: %d", -errno); return -errno; } @@ -274,7 +274,7 @@ static void vfio_iommu_map_notify(Notifier *n, void *data) iotlb->translated_addr, &xlat, &len, iotlb->perm & IOMMU_WO); if (!memory_region_is_ram(mr)) { - error_report("iommu map to non memory area %"HWADDR_PRIx"\n", + error_report("iommu map to non memory area %"HWADDR_PRIx"", xlat); return; } @@ -283,7 +283,7 @@ static void vfio_iommu_map_notify(Notifier *n, void *data) * check that it did not truncate too much. */ if (len & iotlb->addr_mask) { - error_report("iommu has granularity incompatible with target AS\n"); + error_report("iommu has granularity incompatible with target AS"); return; } @@ -566,7 +566,7 @@ static void vfio_kvm_device_add_group(VFIOGroup *group) }; if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { - error_report("Failed to create KVM VFIO device: %m\n"); + error_report("Failed to create KVM VFIO device: %m"); return; } @@ -949,6 +949,7 @@ int vfio_container_ioctl(AddressSpace *as, int32_t groupid, switch (req) { case VFIO_CHECK_EXTENSION: case VFIO_IOMMU_SPAPR_TCE_GET_INFO: + case VFIO_EEH_PE_OP: break; default: /* Return an error on unknown requests */ diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 0936f65..5c7b8c2 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -105,7 +105,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n) /* Disable guest->host notifies */ void vring_disable_notification(VirtIODevice *vdev, Vring *vring) { - if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { + if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); } } @@ -116,7 +116,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring) */ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring) { - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->vr.avail->idx; } else { vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY); @@ -135,12 +135,12 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) * interrupts. */ smp_mb(); - if ((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) && + if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && unlikely(!vring_more_avail(vdev, vring))) { return true; } - if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { + if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { return !(vring_get_avail_flags(vdev, vring) & VRING_AVAIL_F_NO_INTERRUPT); } @@ -401,7 +401,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* On success, increment avail index. */ vring->last_avail_idx++; - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { + if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { vring_avail_event(&vring->vr) = vring->last_avail_idx; } diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index ff4f200..4d68a27 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -61,7 +61,7 @@ int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type) dev->vhost_ops = &user_ops; break; default: - error_report("Unknown vhost backend type\n"); + error_report("Unknown vhost backend type"); r = -1; } diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 8a48d2a..95b0643 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -70,7 +70,7 @@ static inline void reset_stats(VirtIOBalloon *dev) static bool balloon_stats_supported(const VirtIOBalloon *s) { VirtIODevice *vdev = VIRTIO_DEVICE(s); - return vdev->guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ); + return virtio_has_feature(vdev, VIRTIO_BALLOON_F_STATS_VQ); } static bool balloon_stats_enabled(const VirtIOBalloon *s) diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index dfd2d8c..be886e7 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -109,20 +109,6 @@ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, return k->get_features(vdev, requested_features); } -/* Set the features of the plugged device. */ -void virtio_bus_set_vdev_features(VirtioBusState *bus, - uint32_t requested_features) -{ - VirtIODevice *vdev = virtio_bus_get_device(bus); - VirtioDeviceClass *k; - - assert(vdev != NULL); - k = VIRTIO_DEVICE_GET_CLASS(vdev); - if (k->set_features != NULL) { - k->set_features(vdev, requested_features); - } -} - /* Get bad features of the plugged device. */ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus) { diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 2450c13..10123f3 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -349,7 +349,7 @@ static void virtio_mmio_device_plugged(DeviceState *opaque) { VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque); - proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY); proxy->host_features = virtio_bus_get_vdev_features(&proxy->bus, proxy->host_features); } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 604cb5b..e7baf7b 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -17,6 +17,7 @@ #include <inttypes.h> +#include "standard-headers/linux/virtio_pci.h" #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-blk.h" #include "hw/virtio/virtio-net.h" @@ -35,56 +36,11 @@ #include "hw/virtio/virtio-bus.h" #include "qapi/visitor.h" -/* from Linux's linux/virtio_pci.h */ - -/* A 32-bit r/o bitmask of the features supported by the host */ -#define VIRTIO_PCI_HOST_FEATURES 0 - -/* A 32-bit r/w bitmask of features activated by the guest */ -#define VIRTIO_PCI_GUEST_FEATURES 4 - -/* A 32-bit r/w PFN for the currently selected queue */ -#define VIRTIO_PCI_QUEUE_PFN 8 - -/* A 16-bit r/o queue size for the currently selected queue */ -#define VIRTIO_PCI_QUEUE_NUM 12 - -/* A 16-bit r/w queue selector */ -#define VIRTIO_PCI_QUEUE_SEL 14 - -/* A 16-bit r/w queue notifier */ -#define VIRTIO_PCI_QUEUE_NOTIFY 16 - -/* An 8-bit device status register. */ -#define VIRTIO_PCI_STATUS 18 - -/* An 8-bit r/o interrupt status register. Reading the value will return the - * current contents of the ISR and will also clear it. This is effectively - * a read-and-acknowledge. */ -#define VIRTIO_PCI_ISR 19 - -/* MSI-X registers: only enabled if MSI-X is enabled. */ -/* A 16-bit vector for configuration changes. */ -#define VIRTIO_MSI_CONFIG_VECTOR 20 -/* A 16-bit vector for selected queue notifications. */ -#define VIRTIO_MSI_QUEUE_VECTOR 22 - -/* Config space size */ -#define VIRTIO_PCI_CONFIG_NOMSI 20 -#define VIRTIO_PCI_CONFIG_MSI 24 -#define VIRTIO_PCI_REGION_SIZE(dev) (msix_present(dev) ? \ - VIRTIO_PCI_CONFIG_MSI : \ - VIRTIO_PCI_CONFIG_NOMSI) +#define VIRTIO_PCI_REGION_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_present(dev)) /* The remaining space is defined by each driver as the per-driver * configuration space */ -#define VIRTIO_PCI_CONFIG(dev) (msix_enabled(dev) ? \ - VIRTIO_PCI_CONFIG_MSI : \ - VIRTIO_PCI_CONFIG_NOMSI) - -/* How many bits to shift physical queue address written to QUEUE_PFN. - * 12 is historical, and due to x86 page size. */ -#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 +#define VIRTIO_PCI_CONFIG_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_enabled(dev)) static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, VirtIOPCIProxy *dev); @@ -392,7 +348,7 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, { VirtIOPCIProxy *proxy = opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); + uint32_t config = VIRTIO_PCI_CONFIG_SIZE(&proxy->pci_dev); uint64_t val = 0; if (addr < config) { return virtio_ioport_read(proxy, addr); @@ -423,7 +379,7 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { VirtIOPCIProxy *proxy = opaque; - uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev); + uint32_t config = VIRTIO_PCI_CONFIG_SIZE(&proxy->pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); if (addr < config) { virtio_ioport_write(proxy, addr, val); @@ -996,8 +952,8 @@ static void virtio_pci_device_plugged(DeviceState *d) proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; } - proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; - proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; + virtio_add_feature(&proxy->host_features, VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&proxy->host_features, VIRTIO_F_BAD_FEATURE); proxy->host_features = virtio_bus_get_vdev_features(bus, proxy->host_features); } @@ -1318,9 +1274,8 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) static void virtio_balloon_pci_instance_init(Object *obj) { VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj); - object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON); - object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); - object_unref(OBJECT(&dev->vdev)); + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_BALLOON); object_property_add(obj, "guest-stats", "guest statistics", balloon_pci_stats_get_all, NULL, NULL, dev, NULL); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index d735343..3c6e430 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -155,7 +155,7 @@ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) return virtio_lduw_phys(vq->vdev, pa); } -static inline uint16_t vring_used_event(VirtQueue *vq) +static inline uint16_t vring_get_used_event(VirtQueue *vq) { return vring_avail_ring(vq, vq->vring.num); } @@ -204,7 +204,7 @@ static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) virtio_stw_phys(vdev, pa, virtio_lduw_phys(vdev, pa) & ~mask); } -static inline void vring_avail_event(VirtQueue *vq, uint16_t val) +static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val) { hwaddr pa; if (!vq->notification) { @@ -217,8 +217,8 @@ static inline void vring_avail_event(VirtQueue *vq, uint16_t val) void virtio_queue_set_notification(VirtQueue *vq, int enable) { vq->notification = enable; - if (vq->vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { - vring_avail_event(vq, vring_avail_idx(vq)); + if (virtio_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX)) { + vring_set_avail_event(vq, vring_avail_idx(vq)); } else if (enable) { vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY); } else { @@ -468,8 +468,8 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) max = vq->vring.num; i = head = virtqueue_get_head(vq, vq->last_avail_idx++); - if (vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX)) { - vring_avail_event(vq, vq->last_avail_idx); + if (virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + vring_set_avail_event(vq, vq->last_avail_idx); } if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_INDIRECT) { @@ -819,19 +819,6 @@ void virtio_irq(VirtQueue *vq) virtio_notify_vector(vq->vdev, vq->vector); } -/* Assuming a given event_idx value from the other size, if - * we have just incremented index from old to new_idx, - * should we trigger an event? */ -static inline int vring_need_event(uint16_t event, uint16_t new, uint16_t old) -{ - /* Note: Xen has similar logic for notification hold-off - * in include/xen/interface/io/ring.h with req_event and req_prod - * corresponding to event_idx + 1 and new respectively. - * Note also that req_event and req_prod in Xen start at 1, - * event indexes in virtio start at 0. */ - return (uint16_t)(new - event - 1) < (uint16_t)(new - old); -} - static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq) { uint16_t old, new; @@ -839,12 +826,12 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq) /* We need to expose used array entries before checking used event. */ smp_mb(); /* Always notify when queue is empty (when feature acknowledge) */ - if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) && - !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) { + if (virtio_has_feature(vdev, VIRTIO_F_NOTIFY_ON_EMPTY) && + !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx) { return true; } - if (!(vdev->guest_features & (1 << VIRTIO_RING_F_EVENT_IDX))) { + if (!virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { return !(vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT); } @@ -852,7 +839,7 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq) vq->signalled_used_valid = true; old = vq->signalled_used; new = vq->signalled_used = vring_used_idx(vq); - return !v || vring_need_event(vring_used_event(vq), new, old); + return !v || vring_need_event(vring_get_used_event(vq), new, old); } void virtio_notify(VirtIODevice *vdev, VirtQueue *vq) diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index 33dd6d4..b2d158f 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -408,7 +408,7 @@ static const VMStateDescription vmstate_i6300esb = { } }; -static int i6300esb_init(PCIDevice *dev) +static void i6300esb_realize(PCIDevice *dev, Error **errp) { I6300State *d = DO_UPCAST(I6300State, dev, dev); @@ -421,8 +421,6 @@ static int i6300esb_init(PCIDevice *dev) "i6300esb", 0x10); pci_register_bar(&d->dev, 0, 0, &d->io_mem); /* qemu_register_coalesced_mmio (addr, 0x10); ? */ - - return 0; } static WatchdogTimerModel model = { @@ -437,7 +435,7 @@ static void i6300esb_class_init(ObjectClass *klass, void *data) k->config_read = i6300esb_config_read; k->config_write = i6300esb_config_write; - k->init = i6300esb_init; + k->realize = i6300esb_realize; k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_ESB_9; k->class_id = PCI_CLASS_SYSTEM_OTHER; diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index de9a20f..d99c22e 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -360,15 +360,13 @@ static uint64_t xen_pt_get_bar_size(PCIIORegion *r) } static XenPTBarFlag xen_pt_bar_reg_parse(XenPCIPassthroughState *s, - XenPTRegInfo *reg) + int index) { PCIDevice *d = &s->dev; XenPTRegion *region = NULL; PCIIORegion *r; - int index = 0; /* check 64bit BAR */ - index = xen_pt_bar_offset_to_index(reg->offset); if ((0 < index) && (index < PCI_ROM_SLOT)) { int type = s->real_device.io_regions[index - 1].type; @@ -422,7 +420,7 @@ static int xen_pt_bar_reg_init(XenPCIPassthroughState *s, XenPTRegInfo *reg, } /* set BAR flag */ - s->bases[index].bar_flag = xen_pt_bar_reg_parse(s, reg); + s->bases[index].bar_flag = xen_pt_bar_reg_parse(s, index); if (s->bases[index].bar_flag == XEN_PT_BAR_FLAG_UNUSED) { reg_field = XEN_PT_INVALID_REG; } @@ -440,7 +438,7 @@ static int xen_pt_bar_reg_read(XenPCIPassthroughState *s, XenPTReg *cfg_entry, /* get BAR index */ index = xen_pt_bar_offset_to_index(reg->offset); - if (index < 0 || index >= PCI_NUM_REGIONS) { + if (index < 0 || index >= PCI_NUM_REGIONS - 1) { XEN_PT_ERR(&s->dev, "Internal error: Invalid BAR index [%d].\n", index); return -1; } diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index 37ea9ae..328d209 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -64,7 +64,7 @@ static void xtensa_sim_init(MachineState *machine) for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { - error_report("unable to find CPU definition '%s'\n", + error_report("unable to find CPU definition '%s'", cpu_model); exit(EXIT_FAILURE); } diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index d441c02..ab4d0e4 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -207,7 +207,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { - error_report("unable to find CPU definition '%s'\n", + error_report("unable to find CPU definition '%s'", cpu_model); exit(EXIT_FAILURE); } @@ -253,7 +253,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) board->flash_size / board->flash_sector_size, 4, 0x0000, 0x0000, 0x0000, 0x0000, be); if (flash == NULL) { - error_report("unable to mount pflash\n"); + error_report("unable to mount pflash"); exit(EXIT_FAILURE); } } @@ -305,7 +305,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) uint32_t dtb_addr = tswap32(cur_lowmem); if (!fdt) { - error_report("could not load DTB '%s'\n", dtb_filename); + error_report("could not load DTB '%s'", dtb_filename); exit(EXIT_FAILURE); } @@ -325,7 +325,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) lowmem_end - cur_lowmem); } if (initrd_size < 0) { - error_report("could not load initrd '%s'\n", initrd_filename); + error_report("could not load initrd '%s'", initrd_filename); exit(EXIT_FAILURE); } initrd_location.start = tswap32(cur_lowmem); @@ -351,7 +351,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (success > 0 && is_linux) { entry_point = ep; } else { - error_report("could not load kernel '%s'\n", + error_report("could not load kernel '%s'", kernel_filename); exit(EXIT_FAILURE); } diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h new file mode 100644 index 0000000..17d3beb --- /dev/null +++ b/include/hw/acpi/aml-build.h @@ -0,0 +1,191 @@ +#ifndef HW_ACPI_GEN_UTILS_H +#define HW_ACPI_GEN_UTILS_H + +#include <stdint.h> +#include <glib.h> +#include "qemu/compiler.h" + +typedef enum { + AML_NO_OPCODE = 0,/* has only data */ + AML_OPCODE, /* has opcode optionally followed by data */ + AML_PACKAGE, /* has opcode and uses PkgLength for its length */ + AML_EXT_PACKAGE, /* Same as AML_PACKAGE but also has 'ExOpPrefix' */ + AML_BUFFER, /* data encoded as 'DefBuffer' */ + AML_RES_TEMPLATE, /* encoded as ResourceTemplate macro */ +} AmlBlockFlags; + +struct Aml { + GArray *buf; + + /*< private >*/ + uint8_t op; + AmlBlockFlags block_flags; +}; +typedef struct Aml Aml; + +typedef enum { + aml_decode10 = 0, + aml_decode16 = 1, +} AmlIODecode; + +typedef enum { + aml_any_acc = 0, + aml_byte_acc = 1, + aml_word_acc = 2, + aml_dword_acc = 3, + aml_qword_acc = 4, + aml_buffer_acc = 5, +} AmlFieldFlags; + +typedef enum { + aml_system_memory = 0x00, + aml_system_io = 0x01, +} AmlRegionSpace; + +typedef enum { + aml_memory_range = 0, + aml_io_range = 1, + aml_bus_number_range = 2, +} AmlResourceType; + +typedef enum { + aml_sub_decode = 1 << 1, + aml_pos_decode = 0 +} AmlDecode; + +typedef enum { + aml_max_fixed = 1 << 3, + aml_max_not_fixed = 0, +} AmlMaxFixed; + +typedef enum { + aml_min_fixed = 1 << 2, + aml_min_not_fixed = 0 +} AmlMinFixed; + +/* + * ACPI 1.0b: Table 6-26 I/O Resource Flag (Resource Type = 1) Definitions + * _RNG field definition + */ +typedef enum { + aml_isa_only = 1, + aml_non_isa_only = 2, + aml_entire_range = 3, +} AmlISARanges; + +/* + * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions + * _MEM field definition + */ +typedef enum { + aml_non_cacheable = 0, + aml_cacheable = 1, + aml_write_combining = 2, + aml_prefetchable = 3, +} AmlCacheble; + +/* + * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions + * _RW field definition + */ +typedef enum { + aml_ReadOnly = 0, + aml_ReadWrite = 1, +} AmlReadAndWrite; + +/** + * init_aml_allocator: + * + * Called for initializing API allocator which allow to use + * AML API. + * Returns: toplevel container which accumulates all other + * AML elements for a table. + */ +Aml *init_aml_allocator(void); + +/** + * free_aml_allocator: + * + * Releases all elements used by AML API, frees associated memory + * and invalidates AML allocator. After this call @init_aml_allocator + * should be called again if AML API is to be used again. + */ +void free_aml_allocator(void); + +/** + * aml_append: + * @parent_ctx: context to which @child element is added + * @child: element that is copied into @parent_ctx context + * + * Joins Aml elements together and helps to construct AML tables + * Examle of usage: + * Aml *table = aml_def_block("SSDT", ...); + * Aml *sb = aml_scope("\_SB"); + * Aml *dev = aml_device("PCI0"); + * + * aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03"))); + * aml_append(sb, dev); + * aml_append(table, sb); + */ +void aml_append(Aml *parent_ctx, Aml *child); + +/* non block AML object primitives */ +Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_name_decl(const char *name, Aml *val); +Aml *aml_return(Aml *val); +Aml *aml_int(const uint64_t val); +Aml *aml_arg(int pos); +Aml *aml_store(Aml *val, Aml *target); +Aml *aml_and(Aml *arg1, Aml *arg2); +Aml *aml_notify(Aml *arg1, Aml *arg2); +Aml *aml_call1(const char *method, Aml *arg1); +Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2); +Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3); +Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4); +Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, + uint8_t aln, uint8_t len); +Aml *aml_operation_region(const char *name, AmlRegionSpace rs, + uint32_t offset, uint32_t len); +Aml *aml_irq_no_flags(uint8_t irq); +Aml *aml_named_field(const char *name, unsigned length); +Aml *aml_reserved_field(unsigned length); +Aml *aml_local(int num); +Aml *aml_string(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_equal(Aml *arg1, Aml *arg2); +Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, + const char *name_format, ...) GCC_FMT_ATTR(4, 5); +Aml *aml_eisaid(const char *str); +Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, uint16_t addr_gran, + uint16_t addr_min, uint16_t addr_max, + uint16_t addr_trans, uint16_t len); +Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, + AmlDecode dec, AmlISARanges isa_ranges, + uint16_t addr_gran, uint16_t addr_min, + uint16_t addr_max, uint16_t addr_trans, + uint16_t len); +Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlCacheble cacheable, + AmlReadAndWrite read_and_write, + uint32_t addr_gran, uint32_t addr_min, + uint32_t addr_max, uint32_t addr_trans, + uint32_t len); +Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, + AmlMaxFixed max_fixed, AmlCacheble cacheable, + AmlReadAndWrite read_and_write, + uint64_t addr_gran, uint64_t addr_min, + uint64_t addr_max, uint64_t addr_trans, + uint64_t len); + +/* Block AML object primitives */ +Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2); +Aml *aml_method(const char *name, int arg_count); +Aml *aml_if(Aml *predicate); +Aml *aml_package(uint8_t num_elements); +Aml *aml_buffer(void); +Aml *aml_resource_template(void); +Aml *aml_field(const char *name, AmlFieldFlags flags); +Aml *aml_varpackage(uint32_t num_elements); + +#endif diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index 12d7a7a..c2d3dba 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -63,6 +63,10 @@ extern const VMStateDescription vmstate_ich9_pm; void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp); void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp); +void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev, + Error **errp); +void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, + Error **errp); void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list); #endif /* HW_ACPI_ICH9_H */ diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h index b9db295..efa6ed7 100644 --- a/include/hw/acpi/pc-hotplug.h +++ b/include/hw/acpi/pc-hotplug.h @@ -28,6 +28,7 @@ #define ICH9_CPU_HOTPLUG_IO_BASE 0x0CD8 #define PIIX4_CPU_HOTPLUG_IO_BASE 0xaf00 +#define CPU_HOTPLUG_RESOURCE_DEVICE PRES #define ACPI_MEMORY_HOTPLUG_IO_LEN 24 #define ACPI_MEMORY_HOTPLUG_BASE 0x0a00 diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 9323838..f3526d4 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -32,6 +32,9 @@ #include "hw/acpi/acpi.h" #include "migration/vmstate.h" +#define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base" +#define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len" + typedef struct AcpiPciHpPciStatus { uint32_t up; uint32_t down; @@ -48,9 +51,11 @@ typedef struct AcpiPciHpState { PCIBus *root; MemoryRegion io; bool legacy_piix; + uint16_t io_base; + uint16_t io_len; } AcpiPciHpState; -void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root, +void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root, MemoryRegion *address_space_io, bool bridges_enabled); void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 08ab67d..1b35168 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -104,6 +104,7 @@ struct PcGuestInfo { int legacy_acpi_table_size; bool has_acpi_build; bool has_reserved_memory; + bool rsdp_in_ram; }; /* parallel.c */ diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index cf7bd34..f21ceaa 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -21,10 +21,17 @@ #define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS) #define TYPE_APPLE_SMC "isa-applesmc" +#define APPLESMC_MAX_DATA_LENGTH 32 +#define APPLESMC_PROP_IO_BASE "iobase" -static inline bool applesmc_find(void) +static inline uint16_t applesmc_port(void) { - return object_resolve_path_type("", TYPE_APPLE_SMC, NULL); + Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL); + + if (obj) { + return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL); + } + return 0; } typedef struct ISADeviceClass { diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 4ea2a0d..895d273 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -49,6 +49,10 @@ struct sPAPRPHBClass { PCIHostBridgeClass parent_class; void (*finish_realize)(sPAPRPHBState *sphb, Error **errp); + int (*eeh_set_option)(sPAPRPHBState *sphb, unsigned int addr, int option); + int (*eeh_get_state)(sPAPRPHBState *sphb, int *state); + int (*eeh_reset)(sPAPRPHBState *sphb, int option); + int (*eeh_configure)(sPAPRPHBState *sphb); }; typedef struct spapr_pci_msi { @@ -64,7 +68,7 @@ typedef struct spapr_pci_msi_mig { struct sPAPRPHBState { PCIHostState parent_obj; - int32_t index; + uint32_t index; uint64_t buid; char *dtbusname; @@ -94,19 +98,22 @@ struct sPAPRPHBVFIOState { int32_t iommugroupid; }; +#define SPAPR_PCI_MAX_INDEX 255 + #define SPAPR_PCI_BASE_BUID 0x800000020000000ULL +#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL + #define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL #define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL #define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000 -#define SPAPR_PCI_MMIO_WIN_SIZE 0x20000000 +#define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \ + SPAPR_PCI_MEM_WIN_BUS_OFFSET) #define SPAPR_PCI_IO_WIN_OFF 0x80000000 #define SPAPR_PCI_IO_WIN_SIZE 0x10000 #define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL -#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL - static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) { return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index bdee464..be2d9b8 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -185,7 +185,8 @@ typedef struct PCIINTxRoute { typedef struct PCIDeviceClass { DeviceClass parent_class; - int (*init)(PCIDevice *dev); + void (*realize)(PCIDevice *dev, Error **errp); + int (*init)(PCIDevice *dev);/* TODO convert to realize() and remove */ PCIUnregisterFunc *exit; PCIConfigReadFunc *config_read; PCIConfigWriteFunc *config_write; @@ -370,9 +371,6 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev, PCIINTxRoutingNotifier notifier); void pci_device_reset(PCIDevice *dev); -PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, - const char *default_model, - const char *default_devaddr); PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, const char *default_model, const char *default_devaddr); @@ -402,12 +400,8 @@ PCIBus *pci_device_root_bus(const PCIDevice *d); const char *pci_root_bus_path(PCIDevice *dev); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn); int pci_qdev_find_device(const char *id, PCIDevice **pdev); -PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr); void pci_bus_get_w64_range(PCIBus *bus, Range *range); -int pci_parse_devaddr(const char *addr, int *domp, int *busp, - unsigned int *slotp, unsigned int *funcp); - void pci_device_deassert_intx(PCIDevice *dev); typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 716bff4..af71e8b 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -15,6 +15,7 @@ typedef struct sPAPREnvironment { QLIST_HEAD(, sPAPRPHBState) phbs; struct sPAPRNVRAM *nvram; XICSState *icp; + DeviceState *rtc; hwaddr ram_limit; void *htab; @@ -26,7 +27,7 @@ typedef struct sPAPREnvironment { void *rtas_blob; void *fdt_skel; target_ulong entry_point; - uint64_t rtc_offset; + uint64_t rtc_offset; /* Now used only during incoming migration */ struct PPCTimebase tb; bool has_graphics; @@ -338,6 +339,39 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, int spapr_allocate_irq(int hint, bool lsi); int spapr_allocate_irq_block(int num, bool lsi, bool msi); +/* ibm,set-eeh-option */ +#define RTAS_EEH_DISABLE 0 +#define RTAS_EEH_ENABLE 1 +#define RTAS_EEH_THAW_IO 2 +#define RTAS_EEH_THAW_DMA 3 + +/* ibm,get-config-addr-info2 */ +#define RTAS_GET_PE_ADDR 0 +#define RTAS_GET_PE_MODE 1 +#define RTAS_PE_MODE_NONE 0 +#define RTAS_PE_MODE_NOT_SHARED 1 +#define RTAS_PE_MODE_SHARED 2 + +/* ibm,read-slot-reset-state2 */ +#define RTAS_EEH_PE_STATE_NORMAL 0 +#define RTAS_EEH_PE_STATE_RESET 1 +#define RTAS_EEH_PE_STATE_STOPPED_IO_DMA 2 +#define RTAS_EEH_PE_STATE_STOPPED_DMA 4 +#define RTAS_EEH_PE_STATE_UNAVAIL 5 +#define RTAS_EEH_NOT_SUPPORT 0 +#define RTAS_EEH_SUPPORT 1 +#define RTAS_EEH_PE_UNAVAIL_INFO 1000 +#define RTAS_EEH_PE_RECOVER_INFO 0 + +/* ibm,set-slot-reset */ +#define RTAS_SLOT_RESET_DEACTIVATE 0 +#define RTAS_SLOT_RESET_HOT 1 +#define RTAS_SLOT_RESET_FUNDAMENTAL 3 + +/* ibm,slot-error-detail */ +#define RTAS_SLOT_TEMP_ERR_LOG 1 +#define RTAS_SLOT_PERM_ERR_LOG 2 + /* RTAS return codes */ #define RTAS_OUT_SUCCESS 0 #define RTAS_OUT_NO_ERRORS_FOUND 1 @@ -382,8 +416,14 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi); #define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D) #define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E) #define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F) +#define RTAS_IBM_SET_EEH_OPTION (RTAS_TOKEN_BASE + 0x20) +#define RTAS_IBM_GET_CONFIG_ADDR_INFO2 (RTAS_TOKEN_BASE + 0x21) +#define RTAS_IBM_READ_SLOT_RESET_STATE2 (RTAS_TOKEN_BASE + 0x22) +#define RTAS_IBM_SET_SLOT_RESET (RTAS_TOKEN_BASE + 0x23) +#define RTAS_IBM_CONFIGURE_PE (RTAS_TOKEN_BASE + 0x24) +#define RTAS_IBM_SLOT_ERROR_DETAIL (RTAS_TOKEN_BASE + 0x25) -#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x20) +#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x26) /* RTAS ibm,get-system-parameter token values */ #define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20 @@ -463,6 +503,7 @@ struct sPAPRTCETable { bool vfio_accel; int fd; MemoryRegion iommu; + struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */ QLIST_ENTRY(sPAPRTCETable) list; }; @@ -475,10 +516,15 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, uint32_t nb_table, bool vfio_accel); MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet); -void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass); int spapr_dma_dt(void *fdt, int node_off, const char *propname, uint32_t liobn, uint64_t window, uint32_t size); int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, sPAPRTCETable *tcet); +void spapr_pci_switch_vga(bool big_endian); + +#define TYPE_SPAPR_RTC "spapr-rtc" + +void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns); +int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset); #endif /* !defined (__HW_SPAPR_H__) */ diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index 46edc2a..f95016a 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -52,7 +52,7 @@ typedef struct VIOsPAPRDeviceClass { const char *dt_name, *dt_type, *dt_compatible; target_ulong signal_mask; uint32_t rtce_window_size; - int (*init)(VIOsPAPRDevice *dev); + void (*realize)(VIOsPAPRDevice *dev, Error **errp); void (*reset)(VIOsPAPRDevice *dev); int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off); } VIOsPAPRDeviceClass; @@ -64,6 +64,8 @@ struct VIOsPAPRDevice { target_ulong signal_state; VIOsPAPR_CRQ crq; AddressSpace as; + MemoryRegion mrroot; + MemoryRegion mrbypass; sPAPRTCETable *tcet; }; @@ -139,4 +141,6 @@ extern const VMStateDescription vmstate_spapr_vio; #define VMSTATE_SPAPR_VIO(_f, _s) \ VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, VIOsPAPRDevice) +void spapr_vio_set_bypass(VIOsPAPRDevice *dev, bool bypass); + #endif /* _HW_SPAPR_VIO_H */ diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 2fdcbce..0772a56 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -180,9 +180,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); void qdev_prop_register_global(GlobalProperty *prop); void qdev_prop_register_global_list(GlobalProperty *props); int qdev_prop_check_globals(void); -void qdev_prop_set_globals(DeviceState *dev, Error **errp); -void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename, - Error **errp); +void qdev_prop_set_globals(DeviceState *dev); void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, Property *prop, const char *value); diff --git a/include/hw/virtio/dataplane/vring-accessors.h b/include/hw/virtio/dataplane/vring-accessors.h index b508b87..815c19b 100644 --- a/include/hw/virtio/dataplane/vring-accessors.h +++ b/include/hw/virtio/dataplane/vring-accessors.h @@ -1,7 +1,7 @@ #ifndef VRING_ACCESSORS_H #define VRING_ACCESSORS_H -#include "hw/virtio/virtio_ring.h" +#include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-access.h" diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h index e42c0fc..8d97db9 100644 --- a/include/hw/virtio/dataplane/vring.h +++ b/include/hw/virtio/dataplane/vring.h @@ -18,7 +18,7 @@ #define VRING_H #include "qemu-common.h" -#include "hw/virtio/virtio_ring.h" +#include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/virtio.h" typedef struct { diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h index f863bfe..4ab8f54 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -15,6 +15,7 @@ #ifndef _QEMU_VIRTIO_BALLOON_H #define _QEMU_VIRTIO_BALLOON_H +#include "standard-headers/linux/virtio_balloon.h" #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" @@ -22,39 +23,7 @@ #define VIRTIO_BALLOON(obj) \ OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON) -/* from Linux's linux/virtio_balloon.h */ - -/* The ID for virtio_balloon */ -#define VIRTIO_ID_BALLOON 5 - -/* The feature bitmap for virtio balloon */ -#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ -#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory stats virtqueue */ - -/* Size of a PFN in the balloon interface. */ -#define VIRTIO_BALLOON_PFN_SHIFT 12 - -struct virtio_balloon_config -{ - /* Number of pages host wants Guest to give up. */ - uint32_t num_pages; - /* Number of pages we've actually got in balloon. */ - uint32_t actual; -}; - -/* Memory Statistics */ -#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */ -#define VIRTIO_BALLOON_S_SWAP_OUT 1 /* Amount of memory swapped out */ -#define VIRTIO_BALLOON_S_MAJFLT 2 /* Number of major faults */ -#define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ -#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ -#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ -#define VIRTIO_BALLOON_S_NR 6 - -typedef struct VirtIOBalloonStat { - uint16_t tag; - uint64_t val; -} QEMU_PACKED VirtIOBalloonStat; +typedef struct virtio_balloon_stat VirtIOBalloonStat; typedef struct VirtIOBalloon { VirtIODevice parent_obj; diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index fc7d311..b3ffcd9 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -14,6 +14,7 @@ #ifndef _QEMU_VIRTIO_BLK_H #define _QEMU_VIRTIO_BLK_H +#include "standard-headers/linux/virtio_blk.h" #include "hw/virtio/virtio.h" #include "hw/block/block.h" #include "sysemu/iothread.h" @@ -23,88 +24,12 @@ #define VIRTIO_BLK(obj) \ OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK) -/* from Linux's linux/virtio_blk.h */ - -/* The ID for virtio_block */ -#define VIRTIO_ID_BLOCK 2 - -/* Feature bits */ -#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ -#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ -#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ -#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */ -#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ -#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ -#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ -/* #define VIRTIO_BLK_F_IDENTIFY 8 ATA IDENTIFY supported, DEPRECATED */ -#define VIRTIO_BLK_F_WCE 9 /* write cache enabled */ -#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ -#define VIRTIO_BLK_F_CONFIG_WCE 11 /* write cache configurable */ - -#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ - -struct virtio_blk_config -{ - uint64_t capacity; - uint32_t size_max; - uint32_t seg_max; - uint16_t cylinders; - uint8_t heads; - uint8_t sectors; - uint32_t blk_size; - uint8_t physical_block_exp; - uint8_t alignment_offset; - uint16_t min_io_size; - uint32_t opt_io_size; - uint8_t wce; -} QEMU_PACKED; - -/* These two define direction. */ -#define VIRTIO_BLK_T_IN 0 -#define VIRTIO_BLK_T_OUT 1 - -/* This bit says it's a scsi command, not an actual read or write. */ -#define VIRTIO_BLK_T_SCSI_CMD 2 - -/* Flush the volatile write cache */ -#define VIRTIO_BLK_T_FLUSH 4 - -/* return the device ID string */ -#define VIRTIO_BLK_T_GET_ID 8 - -/* Barrier before this op. */ -#define VIRTIO_BLK_T_BARRIER 0x80000000 - -/* This is the first element of the read scatter-gather list. */ -struct virtio_blk_outhdr -{ - /* VIRTIO_BLK_T* */ - uint32_t type; - /* io priority. */ - uint32_t ioprio; - /* Sector (ie. 512 byte offset) */ - uint64_t sector; -}; - -#define VIRTIO_BLK_S_OK 0 -#define VIRTIO_BLK_S_IOERR 1 -#define VIRTIO_BLK_S_UNSUPP 2 - /* This is the last element of the write scatter-gather list */ struct virtio_blk_inhdr { unsigned char status; }; -/* SCSI pass-through header */ -struct virtio_scsi_inhdr -{ - uint32_t errors; - uint32_t data_len; - uint32_t sense_len; - uint32_t residual; -}; - struct VirtIOBlkConf { BlockConf conf; diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 0756545..0d2e7b4 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -84,9 +84,6 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus); /* Get the features of the plugged device. */ uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus, uint32_t requested_features); -/* Set the features of the plugged device. */ -void virtio_bus_set_vdev_features(VirtioBusState *bus, - uint32_t requested_features); /* Get bad features of the plugged device. */ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus); /* Get config of the plugged device. */ diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 6ceb5aa9..4c2fe83 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -14,49 +14,15 @@ #ifndef _QEMU_VIRTIO_NET_H #define _QEMU_VIRTIO_NET_H +#include "standard-headers/linux/virtio_net.h" #include "hw/virtio/virtio.h" -#include "hw/pci/pci.h" #define TYPE_VIRTIO_NET "virtio-net-device" #define VIRTIO_NET(obj) \ OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET) -#define ETH_ALEN 6 - -/* from Linux's virtio_net.h */ - -/* The ID for virtio_net */ -#define VIRTIO_ID_NET 1 - -/* The feature bitmap for virtio net */ -#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ -#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ #define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Control channel offload * configuration support */ -#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ -#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ -#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ -#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ -#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ -#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ -#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ -#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ -#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ -#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ -#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ -#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ -#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ -#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ -#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ -#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ -#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce itself */ -#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow - * Steering */ - -#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ - -#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ -#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ #define TX_TIMER_INTERVAL 150000 /* 150 us */ @@ -77,72 +43,6 @@ typedef struct virtio_net_conf /* Maximum packet size we can receive from tap device: header + 64k */ #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10)) -struct virtio_net_config -{ - /* The config defining mac address ($ETH_ALEN bytes) */ - uint8_t mac[ETH_ALEN]; - /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ - uint16_t status; - /* Max virtqueue pairs supported by the device */ - uint16_t max_virtqueue_pairs; -} QEMU_PACKED; - -/* - * Control virtqueue data structures - * - * The control virtqueue expects a header in the first sg entry - * and an ack/status response in the last entry. Data for the - * command goes in between. - */ -struct virtio_net_ctrl_hdr { - uint8_t class; - uint8_t cmd; -}; - -typedef uint8_t virtio_net_ctrl_ack; - -#define VIRTIO_NET_OK 0 -#define VIRTIO_NET_ERR 1 - -/* - * Control the RX mode, ie. promisucous, allmulti, etc... - * All commands require an "out" sg entry containing a 1 byte - * state value, zero = disable, non-zero = enable. Commands - * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. - * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. - */ -#define VIRTIO_NET_CTRL_RX 0 - #define VIRTIO_NET_CTRL_RX_PROMISC 0 - #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 - #define VIRTIO_NET_CTRL_RX_ALLUNI 2 - #define VIRTIO_NET_CTRL_RX_NOMULTI 3 - #define VIRTIO_NET_CTRL_RX_NOUNI 4 - #define VIRTIO_NET_CTRL_RX_NOBCAST 5 - -/* - * Control the MAC - * - * The MAC filter table is managed by the hypervisor, the guest should - * assume the size is infinite. Filtering should be considered - * non-perfect, ie. based on hypervisor resources, the guest may - * received packets from sources not specified in the filter list. - * - * In addition to the class/cmd header, the TABLE_SET command requires - * two out scatterlists. Each contains a 4 byte count of entries followed - * by a concatenated byte stream of the ETH_ALEN MAC addresses. The - * first sg list contains unicast addresses, the second is for multicast. - * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature - * is available. - * - * The ADDR_SET command requests one out scatterlist, it contains a - * 6 bytes MAC address. This functionality is present if the - * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. - */ -struct virtio_net_ctrl_mac { - uint32_t entries; - uint8_t macs[][ETH_ALEN]; -}; - typedef struct VirtIONetQueue { VirtQueue *rx_vq; VirtQueue *tx_vq; @@ -199,55 +99,6 @@ typedef struct VirtIONet { int announce_counter; } VirtIONet; -#define VIRTIO_NET_CTRL_MAC 1 - #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 - #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 - -/* - * Control VLAN filtering - * - * The VLAN filter table is controlled via a simple ADD/DEL interface. - * VLAN IDs not added may be filterd by the hypervisor. Del is the - * opposite of add. Both commands expect an out entry containing a 2 - * byte VLAN ID. VLAN filterting is available with the - * VIRTIO_NET_F_CTRL_VLAN feature bit. - */ -#define VIRTIO_NET_CTRL_VLAN 2 - #define VIRTIO_NET_CTRL_VLAN_ADD 0 - #define VIRTIO_NET_CTRL_VLAN_DEL 1 - -/* - * Control link announce acknowledgement - * - * VIRTIO_NET_S_ANNOUNCE bit in the status field requests link announcement from - * guest driver. The driver is notified by config space change interrupt. The - * command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that the driver has - * received the notification. It makes the device clear the bit - * VIRTIO_NET_S_ANNOUNCE in the status field. - */ -#define VIRTIO_NET_CTRL_ANNOUNCE 3 - #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0 - -/* - * Control Multiqueue - * - * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET - * enables multiqueue, specifying the number of the transmit and - * receive queues that will be used. After the command is consumed and acked by - * the device, the device will not steer new packets on receive virtqueues - * other than specified nor read from transmit virtqueues other than specified. - * Accordingly, driver should not transmit new packets on virtqueues other than - * specified. - */ -struct virtio_net_ctrl_mq { - uint16_t virtqueue_pairs; -}; - -#define VIRTIO_NET_CTRL_MQ 4 - #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 - #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 - #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 - /* * Control network offloads * diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h index 14e85a5..7702ff4 100644 --- a/include/hw/virtio/virtio-rng.h +++ b/include/hw/virtio/virtio-rng.h @@ -14,6 +14,7 @@ #include "sysemu/rng.h" #include "sysemu/rng-random.h" +#include "standard-headers/linux/virtio_rng.h" #define TYPE_VIRTIO_RNG "virtio-rng-device" #define VIRTIO_RNG(obj) \ @@ -21,9 +22,6 @@ #define VIRTIO_RNG_GET_PARENT_CLASS(obj) \ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG) -/* The Virtio ID for the virtio rng device */ -#define VIRTIO_ID_RNG 4 - struct VirtIORNGConf { RngBackend *rng; uint64_t max_bytes; diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index c122e7a..de2c739 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -14,6 +14,7 @@ #ifndef _QEMU_VIRTIO_SCSI_H #define _QEMU_VIRTIO_SCSI_H +#include "standard-headers/linux/virtio_scsi.h" #include "hw/virtio/virtio.h" #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" @@ -28,15 +29,6 @@ #define VIRTIO_SCSI(obj) \ OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI) - -/* The ID for virtio_scsi */ -#define VIRTIO_ID_SCSI 8 - -/* Feature Bits */ -#define VIRTIO_SCSI_F_INOUT 0 -#define VIRTIO_SCSI_F_HOTPLUG 1 -#define VIRTIO_SCSI_F_CHANGE 2 - #define VIRTIO_SCSI_VQ_SIZE 128 #define VIRTIO_SCSI_CDB_SIZE 32 #define VIRTIO_SCSI_SENSE_SIZE 96 @@ -44,108 +36,14 @@ #define VIRTIO_SCSI_MAX_TARGET 255 #define VIRTIO_SCSI_MAX_LUN 16383 -/* Response codes */ -#define VIRTIO_SCSI_S_OK 0 -#define VIRTIO_SCSI_S_OVERRUN 1 -#define VIRTIO_SCSI_S_ABORTED 2 -#define VIRTIO_SCSI_S_BAD_TARGET 3 -#define VIRTIO_SCSI_S_RESET 4 -#define VIRTIO_SCSI_S_BUSY 5 -#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 -#define VIRTIO_SCSI_S_TARGET_FAILURE 7 -#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 -#define VIRTIO_SCSI_S_FAILURE 9 -#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 -#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 -#define VIRTIO_SCSI_S_INCORRECT_LUN 12 - -/* Controlq type codes. */ -#define VIRTIO_SCSI_T_TMF 0 -#define VIRTIO_SCSI_T_AN_QUERY 1 -#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 - -/* Valid TMF subtypes. */ -#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 -#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 -#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 -#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 -#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 -#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 -#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 -#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 - -/* Events. */ -#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 -#define VIRTIO_SCSI_T_NO_EVENT 0 -#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 -#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 -#define VIRTIO_SCSI_T_PARAM_CHANGE 3 - -/* Reasons for transport reset event */ -#define VIRTIO_SCSI_EVT_RESET_HARD 0 -#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 -#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 - -/* SCSI command request, followed by CDB and data-out */ -typedef struct { - uint8_t lun[8]; /* Logical Unit Number */ - uint64_t tag; /* Command identifier */ - uint8_t task_attr; /* Task attribute */ - uint8_t prio; - uint8_t crn; -} QEMU_PACKED VirtIOSCSICmdReq; - -/* Response, followed by sense data and data-in */ -typedef struct { - uint32_t sense_len; /* Sense data length */ - uint32_t resid; /* Residual bytes in data buffer */ - uint16_t status_qualifier; /* Status qualifier */ - uint8_t status; /* Command completion status */ - uint8_t response; /* Response values */ -} QEMU_PACKED VirtIOSCSICmdResp; - -/* Task Management Request */ -typedef struct { - uint32_t type; - uint32_t subtype; - uint8_t lun[8]; - uint64_t tag; -} QEMU_PACKED VirtIOSCSICtrlTMFReq; - -typedef struct { - uint8_t response; -} QEMU_PACKED VirtIOSCSICtrlTMFResp; - -/* Asynchronous notification query/subscription */ -typedef struct { - uint32_t type; - uint8_t lun[8]; - uint32_t event_requested; -} QEMU_PACKED VirtIOSCSICtrlANReq; - -typedef struct { - uint32_t event_actual; - uint8_t response; -} QEMU_PACKED VirtIOSCSICtrlANResp; - -typedef struct { - uint32_t event; - uint8_t lun[8]; - uint32_t reason; -} QEMU_PACKED VirtIOSCSIEvent; - -typedef struct { - uint32_t num_queues; - uint32_t seg_max; - uint32_t max_sectors; - uint32_t cmd_per_lun; - uint32_t event_info_size; - uint32_t sense_size; - uint32_t cdb_size; - uint16_t max_channel; - uint16_t max_target; - uint32_t max_lun; -} QEMU_PACKED VirtIOSCSIConfig; +typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq; +typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp; +typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq; +typedef struct virtio_scsi_ctrl_tmf_resp VirtIOSCSICtrlTMFResp; +typedef struct virtio_scsi_ctrl_an_req VirtIOSCSICtrlANReq; +typedef struct virtio_scsi_ctrl_an_resp VirtIOSCSICtrlANResp; +typedef struct virtio_scsi_event VirtIOSCSIEvent; +typedef struct virtio_scsi_config VirtIOSCSIConfig; struct VirtIOSCSIConf { uint32_t num_queues; diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index 11af978..ccf8459 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -15,53 +15,15 @@ #ifndef _QEMU_VIRTIO_SERIAL_H #define _QEMU_VIRTIO_SERIAL_H +#include "standard-headers/linux/virtio_console.h" #include "hw/qdev.h" #include "hw/virtio/virtio.h" -/* == Interface shared between the guest kernel and qemu == */ - -/* The Virtio ID for virtio console / serial ports */ -#define VIRTIO_ID_CONSOLE 3 - -/* Features supported */ -#define VIRTIO_CONSOLE_F_MULTIPORT 1 - -#define VIRTIO_CONSOLE_BAD_ID (~(uint32_t)0) - -struct virtio_console_config { - /* - * These two fields are used by VIRTIO_CONSOLE_F_SIZE which - * isn't implemented here yet - */ - uint16_t cols; - uint16_t rows; - - uint32_t max_nr_ports; -} QEMU_PACKED; - -struct virtio_console_control { - uint32_t id; /* Port number */ - uint16_t event; /* The kind of control event (see below) */ - uint16_t value; /* Extra information for the key */ -}; - struct virtio_serial_conf { /* Max. number of ports we can have for a virtio-serial device */ uint32_t max_virtserial_ports; }; -/* Some events for the internal messages (control packets) */ -#define VIRTIO_CONSOLE_DEVICE_READY 0 -#define VIRTIO_CONSOLE_PORT_ADD 1 -#define VIRTIO_CONSOLE_PORT_REMOVE 2 -#define VIRTIO_CONSOLE_PORT_READY 3 -#define VIRTIO_CONSOLE_CONSOLE_PORT 4 -#define VIRTIO_CONSOLE_RESIZE 5 -#define VIRTIO_CONSOLE_PORT_OPEN 6 -#define VIRTIO_CONSOLE_PORT_NAME 7 - -/* == In-qemu interface == */ - #define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port" #define VIRTIO_SERIAL_PORT(obj) \ OBJECT_CHECK(VirtIOSerialPort, (obj), TYPE_VIRTIO_SERIAL_PORT) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index f24997d..d95f8b6 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -19,56 +19,12 @@ #include "hw/qdev.h" #include "sysemu/sysemu.h" #include "qemu/event_notifier.h" -#ifdef CONFIG_VIRTFS -#include "hw/virtio/virtio-9p.h" -#endif +#include "standard-headers/linux/virtio_config.h" +#include "standard-headers/linux/virtio_ring.h" -/* from Linux's linux/virtio_config.h */ - -/* Status byte for guest to report progress, and synchronize features. */ -/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ -#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 -/* We have found a driver for the device. */ -#define VIRTIO_CONFIG_S_DRIVER 2 -/* Driver has used its parts of the config, and is happy */ -#define VIRTIO_CONFIG_S_DRIVER_OK 4 -/* We've given up on this device. */ -#define VIRTIO_CONFIG_S_FAILED 0x80 - -/* Some virtio feature bits (currently bits 28 through 31) are reserved for the - * transport being used (eg. virtio_ring), the rest are per-device feature bits. */ -#define VIRTIO_TRANSPORT_F_START 28 -#define VIRTIO_TRANSPORT_F_END 32 - -/* We notify when the ring is completely used, even if the guest is suppressing - * callbacks */ -#define VIRTIO_F_NOTIFY_ON_EMPTY 24 -/* Can the device handle any descriptor layout? */ -#define VIRTIO_F_ANY_LAYOUT 27 -/* We support indirect buffer descriptors */ -#define VIRTIO_RING_F_INDIRECT_DESC 28 -/* The Guest publishes the used index for which it expects an interrupt - * at the end of the avail ring. Host should ignore the avail->flags field. */ -/* The Host publishes the avail index for which it expects a kick - * at the end of the used ring. Guest should ignore the used->flags field. */ -#define VIRTIO_RING_F_EVENT_IDX 29 /* A guest should never accept this. It implies negotiation is broken. */ #define VIRTIO_F_BAD_FEATURE 30 -/* from Linux's linux/virtio_ring.h */ - -/* This marks a buffer as continuing via the next field. */ -#define VRING_DESC_F_NEXT 1 -/* This marks a buffer as write-only (otherwise read-only). */ -#define VRING_DESC_F_WRITE 2 -/* This means the buffer contains a list of buffer descriptors. */ -#define VRING_DESC_F_INDIRECT 4 - -/* This means don't notify other side when buffer added. */ -#define VRING_USED_F_NO_NOTIFY 1 -/* This means don't interrupt guest when buffer consumed. */ -#define VRING_AVAIL_F_NO_INTERRUPT 1 - struct VirtQueue; static inline hwaddr vring_align(hwaddr addr, @@ -263,6 +219,29 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, void virtio_queue_notify_vq(VirtQueue *vq); void virtio_irq(VirtQueue *vq); +static inline void virtio_add_feature(uint32_t *features, unsigned int fbit) +{ + assert(fbit < 32); + *features |= (1 << fbit); +} + +static inline void virtio_clear_feature(uint32_t *features, unsigned int fbit) +{ + assert(fbit < 32); + *features &= ~(1 << fbit); +} + +static inline bool __virtio_has_feature(uint32_t features, unsigned int fbit) +{ + assert(fbit < 32); + return !!(features & (1 << fbit)); +} + +static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit) +{ + return __virtio_has_feature(vdev->guest_features, fbit); +} + static inline bool virtio_is_big_endian(VirtIODevice *vdev) { assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h index b0ed04c..4356af4 100644 --- a/include/hw/xen/xen.h +++ b/include/hw/xen/xen.h @@ -32,7 +32,6 @@ int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num); void xen_piix3_set_irq(void *opaque, int irq_num, int level); void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len); void xen_hvm_inject_msi(uint64_t addr, uint32_t data); -void xen_cmos_set_s3_resume(void *opaque, int irq, int level); qemu_irq *xen_interrupt_controller_init(void); diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index c20f2d1..bc7616a 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -635,6 +635,18 @@ extern const VMStateInfo vmstate_info_bitmap; #define VMSTATE_INT32_POSITIVE_LE(_f, _s) \ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t) +#define VMSTATE_INT8_TEST(_f, _s, _t) \ + VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int8, int8_t) + +#define VMSTATE_INT16_TEST(_f, _s, _t) \ + VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int16, int16_t) + +#define VMSTATE_INT32_TEST(_f, _s, _t) \ + VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int32, int32_t) + +#define VMSTATE_INT64_TEST(_f, _s, _t) \ + VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int64, int64_t) + #define VMSTATE_UINT8_TEST(_f, _s, _t) \ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint8, uint8_t) @@ -644,6 +656,9 @@ extern const VMStateInfo vmstate_info_bitmap; #define VMSTATE_UINT32_TEST(_f, _s, _t) \ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t) +#define VMSTATE_UINT64_TEST(_f, _s, _t) \ + VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint64, uint64_t) + #define VMSTATE_FLOAT64_V(_f, _s, _v) \ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_float64, float64) diff --git a/include/net/tap.h b/include/net/tap.h index 6daeb42..5da4edc 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -28,6 +28,7 @@ #include "qemu-common.h" #include "qapi-types.h" +#include "standard-headers/linux/virtio_net.h" int tap_enable(NetClientState *nc); int tap_disable(NetClientState *nc); @@ -37,27 +38,4 @@ int tap_get_fd(NetClientState *nc); struct vhost_net; struct vhost_net *tap_get_vhost_net(NetClientState *nc); -struct virtio_net_hdr -{ -#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset -#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid - uint8_t flags; -#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame -#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) -#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) -#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP -#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set - uint8_t gso_type; - uint16_t hdr_len; - uint16_t gso_size; - uint16_t csum_start; - uint16_t csum_offset; -}; - -struct virtio_net_hdr_mrg_rxbuf -{ - struct virtio_net_hdr hdr; - uint16_t num_buffers; /* Number of merged rx buffers */ -}; - #endif /* QEMU_NET_TAP_H */ diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index 986260f..57a62d4 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -37,12 +37,12 @@ void qerror_report_err(Error *err); #define QERR_BASE_NOT_FOUND \ ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found" -#define QERR_BLOCK_JOB_NOT_READY \ - ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed" - #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" +#define QERR_BLOCK_JOB_NOT_READY \ + ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed" + #define QERR_BUS_NO_HOTPLUG \ ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging" diff --git a/include/qom/object.h b/include/qom/object.h index 8757573..d2d7748 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -1204,6 +1204,20 @@ void object_property_add_bool(Object *obj, const char *name, Error **errp); /** + * object_property_add_tm: + * @obj: the object to add a property to + * @name: the name of the property + * @get: the getter or NULL if the property is write-only. + * @errp: if an error occurs, a pointer to an area to store the error + * + * Add a read-only struct tm valued property using a getter function. + * This function will add a property of type 'struct tm'. + */ +void object_property_add_tm(Object *obj, const char *name, + void (*get)(Object *, struct tm *, Error **), + Error **errp); + +/** * object_property_add_uint8_ptr: * @obj: the object to add a property to * @name: the name of the property diff --git a/include/standard-headers/asm-s390/kvm_virtio.h b/include/standard-headers/asm-s390/kvm_virtio.h new file mode 100644 index 0000000..daad324 --- /dev/null +++ b/include/standard-headers/asm-s390/kvm_virtio.h @@ -0,0 +1,64 @@ +/* + * definition for virtio for kvm on s390 + * + * Copyright IBM Corp. 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> + */ + +#ifndef __KVM_S390_VIRTIO_H +#define __KVM_S390_VIRTIO_H + +#include "standard-headers/linux/types.h" + +struct kvm_device_desc { + /* The device type: console, network, disk etc. Type 0 terminates. */ + uint8_t type; + /* The number of virtqueues (first in config array) */ + uint8_t num_vq; + /* + * The number of bytes of feature bits. Multiply by 2: one for host + * features and one for guest acknowledgements. + */ + uint8_t feature_len; + /* The number of bytes of the config array after virtqueues. */ + uint8_t config_len; + /* A status byte, written by the Guest. */ + uint8_t status; + uint8_t config[0]; +}; + +/* + * This is how we expect the device configuration field for a virtqueue + * to be laid out in config space. + */ +struct kvm_vqconfig { + /* The token returned with an interrupt. Set by the guest */ + uint64_t token; + /* The address of the virtio ring */ + uint64_t address; + /* The number of entries in the virtio_ring */ + uint16_t num; + +}; + +#define KVM_S390_VIRTIO_NOTIFY 0 +#define KVM_S390_VIRTIO_RESET 1 +#define KVM_S390_VIRTIO_SET_STATUS 2 + +/* The alignment to use between consumer and producer parts of vring. + * This is pagesize for historical reasons. */ +#define KVM_S390_VIRTIO_RING_ALIGN 4096 + + +/* These values are supposed to be in ext_params on an interrupt */ +#define VIRTIO_PARAM_MASK 0xff +#define VIRTIO_PARAM_VRING_INTERRUPT 0x0 +#define VIRTIO_PARAM_CONFIG_CHANGED 0x1 +#define VIRTIO_PARAM_DEV_ADD 0x2 + +#endif diff --git a/include/standard-headers/asm-s390/virtio-ccw.h b/include/standard-headers/asm-s390/virtio-ccw.h new file mode 100644 index 0000000..a9a4ebf --- /dev/null +++ b/include/standard-headers/asm-s390/virtio-ccw.h @@ -0,0 +1,21 @@ +/* + * Definitions for virtio-ccw devices. + * + * Copyright IBM Corp. 2013 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + */ +#ifndef __KVM_VIRTIO_CCW_H +#define __KVM_VIRTIO_CCW_H + +/* Alignment of vring buffers. */ +#define KVM_VIRTIO_CCW_RING_ALIGN 4096 + +/* Subcode for diagnose 500 (virtio hypercall). */ +#define KVM_S390_VIRTIO_CCW_NOTIFY 3 + +#endif diff --git a/include/standard-headers/linux/if_ether.h b/include/standard-headers/linux/if_ether.h new file mode 100644 index 0000000..91cf735 --- /dev/null +++ b/include/standard-headers/linux/if_ether.h @@ -0,0 +1 @@ +#define ETH_ALEN 6 diff --git a/include/standard-headers/linux/types.h b/include/standard-headers/linux/types.h new file mode 100644 index 0000000..0526c2b --- /dev/null +++ b/include/standard-headers/linux/types.h @@ -0,0 +1,2 @@ +#include <stdint.h> +#include "qemu/compiler.h" diff --git a/include/standard-headers/linux/virtio_9p.h b/include/standard-headers/linux/virtio_9p.h new file mode 100644 index 0000000..e68f71d --- /dev/null +++ b/include/standard-headers/linux/virtio_9p.h @@ -0,0 +1,44 @@ +#ifndef _LINUX_VIRTIO_9P_H +#define _LINUX_VIRTIO_9P_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" + +/* The feature bitmap for virtio 9P */ + +/* The mount point is specified in a config variable */ +#define VIRTIO_9P_MOUNT_TAG 0 + +struct virtio_9p_config { + /* length of the tag name */ + uint16_t tag_len; + /* non-NULL terminated tag name */ + uint8_t tag[0]; +} QEMU_PACKED; + +#endif /* _LINUX_VIRTIO_9P_H */ diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/standard-headers/linux/virtio_balloon.h new file mode 100644 index 0000000..799376d --- /dev/null +++ b/include/standard-headers/linux/virtio_balloon.h @@ -0,0 +1,59 @@ +#ifndef _LINUX_VIRTIO_BALLOON_H +#define _LINUX_VIRTIO_BALLOON_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" + +/* The feature bitmap for virtio balloon */ +#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ +#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */ +#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */ + +/* Size of a PFN in the balloon interface. */ +#define VIRTIO_BALLOON_PFN_SHIFT 12 + +struct virtio_balloon_config { + /* Number of pages host wants Guest to give up. */ + uint32_t num_pages; + /* Number of pages we've actually got in balloon. */ + uint32_t actual; +}; + +#define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */ +#define VIRTIO_BALLOON_S_SWAP_OUT 1 /* Amount of memory swapped out */ +#define VIRTIO_BALLOON_S_MAJFLT 2 /* Number of major faults */ +#define VIRTIO_BALLOON_S_MINFLT 3 /* Number of minor faults */ +#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ +#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ +#define VIRTIO_BALLOON_S_NR 6 + +struct virtio_balloon_stat { + uint16_t tag; + uint64_t val; +} QEMU_PACKED; + +#endif /* _LINUX_VIRTIO_BALLOON_H */ diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h new file mode 100644 index 0000000..12016b4 --- /dev/null +++ b/include/standard-headers/linux/virtio_blk.h @@ -0,0 +1,143 @@ +#ifndef _LINUX_VIRTIO_BLK_H +#define _LINUX_VIRTIO_BLK_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" +#include "standard-headers/linux/virtio_types.h" + +/* Feature bits */ +#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ +#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ +#define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */ +#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ +#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ +#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ +#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */ + +/* Legacy feature bits */ +#ifndef VIRTIO_BLK_NO_LEGACY +#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ +#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ +#define VIRTIO_BLK_F_WCE 9 /* Writeback mode enabled after reset */ +#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */ +/* Old (deprecated) name for VIRTIO_BLK_F_WCE. */ +#define VIRTIO_BLK_F_FLUSH VIRTIO_BLK_F_WCE +#endif /* !VIRTIO_BLK_NO_LEGACY */ + +#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ + +struct virtio_blk_config { + /* The capacity (in 512-byte sectors). */ + uint64_t capacity; + /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */ + uint32_t size_max; + /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ + uint32_t seg_max; + /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */ + struct virtio_blk_geometry { + uint16_t cylinders; + uint8_t heads; + uint8_t sectors; + } geometry; + + /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ + uint32_t blk_size; + + /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */ + /* exponent for physical block per logical block. */ + uint8_t physical_block_exp; + /* alignment offset in logical blocks. */ + uint8_t alignment_offset; + /* minimum I/O size without performance penalty in logical blocks. */ + uint16_t min_io_size; + /* optimal sustained I/O size in logical blocks. */ + uint32_t opt_io_size; + + /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ + uint8_t wce; + uint8_t unused; + + /* number of vqs, only available when VIRTIO_BLK_F_MQ is set */ + uint16_t num_queues; +} QEMU_PACKED; + +/* + * Command types + * + * Usage is a bit tricky as some bits are used as flags and some are not. + * + * Rules: + * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or + * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own + * and may not be combined with any of the other flags. + */ + +/* These two define direction. */ +#define VIRTIO_BLK_T_IN 0 +#define VIRTIO_BLK_T_OUT 1 + +#ifndef VIRTIO_BLK_NO_LEGACY +/* This bit says it's a scsi command, not an actual read or write. */ +#define VIRTIO_BLK_T_SCSI_CMD 2 +#endif /* VIRTIO_BLK_NO_LEGACY */ + +/* Cache flush command */ +#define VIRTIO_BLK_T_FLUSH 4 + +/* Get device ID command */ +#define VIRTIO_BLK_T_GET_ID 8 + +#ifndef VIRTIO_BLK_NO_LEGACY +/* Barrier before this op. */ +#define VIRTIO_BLK_T_BARRIER 0x80000000 +#endif /* !VIRTIO_BLK_NO_LEGACY */ + +/* This is the first element of the read scatter-gather list. */ +struct virtio_blk_outhdr { + /* VIRTIO_BLK_T* */ + __virtio32 type; + /* io priority. */ + __virtio32 ioprio; + /* Sector (ie. 512 byte offset) */ + __virtio64 sector; +}; + +#ifndef VIRTIO_BLK_NO_LEGACY +struct virtio_scsi_inhdr { + __virtio32 errors; + __virtio32 data_len; + __virtio32 sense_len; + __virtio32 residual; +}; +#endif /* !VIRTIO_BLK_NO_LEGACY */ + +/* And this is the final byte of the write scatter-gather list. */ +#define VIRTIO_BLK_S_OK 0 +#define VIRTIO_BLK_S_IOERR 1 +#define VIRTIO_BLK_S_UNSUPP 2 +#endif /* _LINUX_VIRTIO_BLK_H */ diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h new file mode 100644 index 0000000..bcc445b --- /dev/null +++ b/include/standard-headers/linux/virtio_config.h @@ -0,0 +1,64 @@ +#ifndef _LINUX_VIRTIO_CONFIG_H +#define _LINUX_VIRTIO_CONFIG_H +/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so + * anyone can use the definitions to implement compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +/* Virtio devices use a standardized configuration space to define their + * features and pass configuration information, but each implementation can + * store and access that space differently. */ +#include "standard-headers/linux/types.h" + +/* Status byte for guest to report progress, and synchronize features. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* Driver has finished configuring features */ +#define VIRTIO_CONFIG_S_FEATURES_OK 8 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +/* Some virtio feature bits (currently bits 28 through 32) are reserved for the + * transport being used (eg. virtio_ring), the rest are per-device feature + * bits. */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 33 + +#ifndef VIRTIO_CONFIG_NO_LEGACY +/* Do we get callbacks when the ring is completely used, even if we've + * suppressed them? */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 + +/* Can the device handle any descriptor layout? */ +#define VIRTIO_F_ANY_LAYOUT 27 +#endif /* VIRTIO_CONFIG_NO_LEGACY */ + +/* v1.0 compliant. */ +#define VIRTIO_F_VERSION_1 32 + +#endif /* _LINUX_VIRTIO_CONFIG_H */ diff --git a/include/standard-headers/linux/virtio_console.h b/include/standard-headers/linux/virtio_console.h new file mode 100644 index 0000000..0dedc9e --- /dev/null +++ b/include/standard-headers/linux/virtio_console.h @@ -0,0 +1,78 @@ +/* + * This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so + * anyone can use the definitions to implement compatible drivers/servers: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) Red Hat, Inc., 2009, 2010, 2011 + * Copyright (C) Amit Shah <amit.shah@redhat.com>, 2009, 2010, 2011 + */ +#ifndef _LINUX_VIRTIO_CONSOLE_H +#define _LINUX_VIRTIO_CONSOLE_H +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" + +/* Feature bits */ +#define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ +#define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ +#define VIRTIO_CONSOLE_F_EMERG_WRITE 2 /* Does host support emergency write? */ + +#define VIRTIO_CONSOLE_BAD_ID (~(uint32_t)0) + +struct virtio_console_config { + /* colums of the screens */ + uint16_t cols; + /* rows of the screens */ + uint16_t rows; + /* max. number of ports this device can hold */ + uint32_t max_nr_ports; + /* emergency write register */ + uint32_t emerg_wr; +} QEMU_PACKED; + +/* + * A message that's passed between the Host and the Guest for a + * particular port. + */ +struct virtio_console_control { + __virtio32 id; /* Port number */ + __virtio16 event; /* The kind of control event (see below) */ + __virtio16 value; /* Extra information for the key */ +}; + +/* Some events for control messages */ +#define VIRTIO_CONSOLE_DEVICE_READY 0 +#define VIRTIO_CONSOLE_PORT_ADD 1 +#define VIRTIO_CONSOLE_PORT_REMOVE 2 +#define VIRTIO_CONSOLE_PORT_READY 3 +#define VIRTIO_CONSOLE_CONSOLE_PORT 4 +#define VIRTIO_CONSOLE_RESIZE 5 +#define VIRTIO_CONSOLE_PORT_OPEN 6 +#define VIRTIO_CONSOLE_PORT_NAME 7 + + +#endif /* _LINUX_VIRTIO_CONSOLE_H */ diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h new file mode 100644 index 0000000..284fc3a --- /dev/null +++ b/include/standard-headers/linux/virtio_ids.h @@ -0,0 +1,43 @@ +#ifndef _LINUX_VIRTIO_IDS_H +#define _LINUX_VIRTIO_IDS_H +/* + * Virtio IDs + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +#define VIRTIO_ID_NET 1 /* virtio net */ +#define VIRTIO_ID_BLOCK 2 /* virtio block */ +#define VIRTIO_ID_CONSOLE 3 /* virtio console */ +#define VIRTIO_ID_RNG 4 /* virtio rng */ +#define VIRTIO_ID_BALLOON 5 /* virtio balloon */ +#define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */ +#define VIRTIO_ID_SCSI 8 /* virtio scsi */ +#define VIRTIO_ID_9P 9 /* 9p virtio console */ +#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */ +#define VIRTIO_ID_CAIF 12 /* Virtio caif */ + +#endif /* _LINUX_VIRTIO_IDS_H */ diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h new file mode 100644 index 0000000..95faf67 --- /dev/null +++ b/include/standard-headers/linux/virtio_net.h @@ -0,0 +1,233 @@ +#ifndef _LINUX_VIRTIO_NET_H +#define _LINUX_VIRTIO_NET_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" +#include "standard-headers/linux/virtio_types.h" +#include "standard-headers/linux/if_ether.h" + +/* The feature bitmap for virtio net */ +#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ +#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ +#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ +#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ +#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ +#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ +#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ +#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ +#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ +#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the + * network */ +#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow + * Steering */ +#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ + +#ifndef VIRTIO_NET_NO_LEGACY +#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ +#endif /* VIRTIO_NET_NO_LEGACY */ + +#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ + +struct virtio_net_config { + /* The config defining mac address (if VIRTIO_NET_F_MAC) */ + uint8_t mac[ETH_ALEN]; + /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ + uint16_t status; + /* Maximum number of each of transmit and receive queues; + * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ. + * Legal values are between 1 and 0x8000 + */ + uint16_t max_virtqueue_pairs; +} QEMU_PACKED; + +#ifndef VIRTIO_NET_NO_LEGACY +/* This header comes first in the scatter-gather list. + * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must + * be the first element of the scatter-gather list. If you don't + * specify GSO or CSUM features, you can simply ignore the header. */ +struct virtio_net_hdr { +#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset +#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid + uint8_t flags; +#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame +#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) +#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) +#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP +#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set + uint8_t gso_type; + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ + __virtio16 gso_size; /* Bytes to append to hdr_len per frame */ + __virtio16 csum_start; /* Position to start checksumming from */ + __virtio16 csum_offset; /* Offset after that to place checksum */ +}; + +/* This is the version of the header to use when the MRG_RXBUF + * feature has been negotiated. */ +struct virtio_net_hdr_mrg_rxbuf { + struct virtio_net_hdr hdr; + __virtio16 num_buffers; /* Number of merged rx buffers */ +}; +#else /* ... VIRTIO_NET_NO_LEGACY */ +/* + * This header comes first in the scatter-gather list. If you don't + * specify GSO or CSUM features, you can simply ignore the header. + * + * This is bitwise-equivalent to the legacy struct virtio_net_hdr_mrg_rxbuf. + */ +struct virtio_net_hdr_v1 { +#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */ +#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ + uint8_t flags; +#define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */ +#define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */ +#define VIRTIO_NET_HDR_GSO_UDP 3 /* GSO frame, IPv4 UDP (UFO) */ +#define VIRTIO_NET_HDR_GSO_TCPV6 4 /* GSO frame, IPv6 TCP */ +#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */ + uint8_t gso_type; + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ + __virtio16 gso_size; /* Bytes to append to hdr_len per frame */ + __virtio16 csum_start; /* Position to start checksumming from */ + __virtio16 csum_offset; /* Offset after that to place checksum */ + __virtio16 num_buffers; /* Number of merged rx buffers */ +}; +#endif /* ...VIRTIO_NET_NO_LEGACY */ + +/* + * Control virtqueue data structures + * + * The control virtqueue expects a header in the first sg entry + * and an ack/status response in the last entry. Data for the + * command goes in between. + */ +struct virtio_net_ctrl_hdr { + uint8_t class; + uint8_t cmd; +} QEMU_PACKED; + +typedef uint8_t virtio_net_ctrl_ack; + +#define VIRTIO_NET_OK 0 +#define VIRTIO_NET_ERR 1 + +/* + * Control the RX mode, ie. promisucous, allmulti, etc... + * All commands require an "out" sg entry containing a 1 byte + * state value, zero = disable, non-zero = enable. Commands + * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. + * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. + */ +#define VIRTIO_NET_CTRL_RX 0 + #define VIRTIO_NET_CTRL_RX_PROMISC 0 + #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 + #define VIRTIO_NET_CTRL_RX_ALLUNI 2 + #define VIRTIO_NET_CTRL_RX_NOMULTI 3 + #define VIRTIO_NET_CTRL_RX_NOUNI 4 + #define VIRTIO_NET_CTRL_RX_NOBCAST 5 + +/* + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + __virtio32 entries; + uint8_t macs[][ETH_ALEN]; +} QEMU_PACKED; + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/* + * Control VLAN filtering + * + * The VLAN filter table is controlled via a simple ADD/DEL interface. + * VLAN IDs not added may be filterd by the hypervisor. Del is the + * opposite of add. Both commands expect an out entry containing a 2 + * byte VLAN ID. VLAN filterting is available with the + * VIRTIO_NET_F_CTRL_VLAN feature bit. + */ +#define VIRTIO_NET_CTRL_VLAN 2 + #define VIRTIO_NET_CTRL_VLAN_ADD 0 + #define VIRTIO_NET_CTRL_VLAN_DEL 1 + +/* + * Control link announce acknowledgement + * + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that + * driver has recevied the notification; device would clear the + * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives + * this command. + */ +#define VIRTIO_NET_CTRL_ANNOUNCE 3 + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0 + +/* + * Control Receive Flow Steering + * + * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET + * enables Receive Flow Steering, specifying the number of the transmit and + * receive queues that will be used. After the command is consumed and acked by + * the device, the device will not steer new packets on receive virtqueues + * other than specified nor read from transmit virtqueues other than specified. + * Accordingly, driver should not transmit new packets on virtqueues other than + * specified. + */ +struct virtio_net_ctrl_mq { + __virtio16 virtqueue_pairs; +}; + +#define VIRTIO_NET_CTRL_MQ 4 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 + +#endif /* _LINUX_VIRTIO_NET_H */ diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h new file mode 100644 index 0000000..ecdc133 --- /dev/null +++ b/include/standard-headers/linux/virtio_pci.h @@ -0,0 +1,193 @@ +/* + * Virtio PCI driver + * + * This module allows virtio devices to be used over a virtual PCI device. + * This can be used with QEMU based VMMs like KVM or Xen. + * + * Copyright IBM Corp. 2007 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUX_VIRTIO_PCI_H +#define _LINUX_VIRTIO_PCI_H + +#include "standard-headers/linux/types.h" + +#ifndef VIRTIO_PCI_NO_LEGACY + +/* A 32-bit r/o bitmask of the features supported by the host */ +#define VIRTIO_PCI_HOST_FEATURES 0 + +/* A 32-bit r/w bitmask of features activated by the guest */ +#define VIRTIO_PCI_GUEST_FEATURES 4 + +/* A 32-bit r/w PFN for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_PFN 8 + +/* A 16-bit r/o queue size for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_NUM 12 + +/* A 16-bit r/w queue selector */ +#define VIRTIO_PCI_QUEUE_SEL 14 + +/* A 16-bit r/w queue notifier */ +#define VIRTIO_PCI_QUEUE_NOTIFY 16 + +/* An 8-bit device status register. */ +#define VIRTIO_PCI_STATUS 18 + +/* An 8-bit r/o interrupt status register. Reading the value will return the + * current contents of the ISR and will also clear it. This is effectively + * a read-and-acknowledge. */ +#define VIRTIO_PCI_ISR 19 + +/* MSI-X registers: only enabled if MSI-X is enabled. */ +/* A 16-bit vector for configuration changes. */ +#define VIRTIO_MSI_CONFIG_VECTOR 20 +/* A 16-bit vector for selected queue notifications. */ +#define VIRTIO_MSI_QUEUE_VECTOR 22 + +/* The remaining space is defined by each driver as the per-driver + * configuration space */ +#define VIRTIO_PCI_CONFIG_OFF(msix_enabled) ((msix_enabled) ? 24 : 20) +/* Deprecated: please use VIRTIO_PCI_CONFIG_OFF instead */ +#define VIRTIO_PCI_CONFIG(dev) VIRTIO_PCI_CONFIG_OFF((dev)->msix_enabled) + +/* Virtio ABI version, this must match exactly */ +#define VIRTIO_PCI_ABI_VERSION 0 + +/* How many bits to shift physical queue address written to QUEUE_PFN. + * 12 is historical, and due to x86 page size. */ +#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 + +/* The alignment to use between consumer and producer parts of vring. + * x86 pagesize again. */ +#define VIRTIO_PCI_VRING_ALIGN 4096 + +#endif /* VIRTIO_PCI_NO_LEGACY */ + +/* The bit of the ISR which indicates a device configuration change. */ +#define VIRTIO_PCI_ISR_CONFIG 0x2 +/* Vector value used to disable MSI for queue */ +#define VIRTIO_MSI_NO_VECTOR 0xffff + +#ifndef VIRTIO_PCI_NO_MODERN + +/* IDs for different capabilities. Must all exist. */ + +/* Common configuration */ +#define VIRTIO_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 +/* ISR access */ +#define VIRTIO_PCI_CAP_ISR_CFG 3 +/* Device specific configuration */ +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 +/* PCI configuration access */ +#define VIRTIO_PCI_CAP_PCI_CFG 5 + +/* This is the PCI capability header: */ +struct virtio_pci_cap { + uint8_t cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + uint8_t cap_next; /* Generic PCI field: next ptr. */ + uint8_t cap_len; /* Generic PCI field: capability length */ + uint8_t cfg_type; /* Identifies the structure. */ + uint8_t bar; /* Where to find it. */ + uint8_t padding[3]; /* Pad to full dword. */ + uint32_t offset; /* Offset within bar. */ + uint32_t length; /* Length of the structure, in bytes. */ +}; + +struct virtio_pci_notify_cap { + struct virtio_pci_cap cap; + uint32_t notify_off_multiplier; /* Multiplier for queue_notify_off. */ +}; + +/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ +struct virtio_pci_common_cfg { + /* About the whole device. */ + uint32_t device_feature_select; /* read-write */ + uint32_t device_feature; /* read-only */ + uint32_t guest_feature_select; /* read-write */ + uint32_t guest_feature; /* read-write */ + uint16_t msix_config; /* read-write */ + uint16_t num_queues; /* read-only */ + uint8_t device_status; /* read-write */ + uint8_t config_generation; /* read-only */ + + /* About a specific virtqueue. */ + uint16_t queue_select; /* read-write */ + uint16_t queue_size; /* read-write, power of 2. */ + uint16_t queue_msix_vector; /* read-write */ + uint16_t queue_enable; /* read-write */ + uint16_t queue_notify_off; /* read-only */ + uint32_t queue_desc_lo; /* read-write */ + uint32_t queue_desc_hi; /* read-write */ + uint32_t queue_avail_lo; /* read-write */ + uint32_t queue_avail_hi; /* read-write */ + uint32_t queue_used_lo; /* read-write */ + uint32_t queue_used_hi; /* read-write */ +}; + +/* Macro versions of offsets for the Old Timers! */ +#define VIRTIO_PCI_CAP_VNDR 0 +#define VIRTIO_PCI_CAP_NEXT 1 +#define VIRTIO_PCI_CAP_LEN 2 +#define VIRTIO_PCI_CAP_CFG_TYPE 3 +#define VIRTIO_PCI_CAP_BAR 4 +#define VIRTIO_PCI_CAP_OFFSET 8 +#define VIRTIO_PCI_CAP_LENGTH 12 + +#define VIRTIO_PCI_NOTIFY_CAP_MULT 16 + +#define VIRTIO_PCI_COMMON_DFSELECT 0 +#define VIRTIO_PCI_COMMON_DF 4 +#define VIRTIO_PCI_COMMON_GFSELECT 8 +#define VIRTIO_PCI_COMMON_GF 12 +#define VIRTIO_PCI_COMMON_MSIX 16 +#define VIRTIO_PCI_COMMON_NUMQ 18 +#define VIRTIO_PCI_COMMON_STATUS 20 +#define VIRTIO_PCI_COMMON_CFGGENERATION 21 +#define VIRTIO_PCI_COMMON_Q_SELECT 22 +#define VIRTIO_PCI_COMMON_Q_SIZE 24 +#define VIRTIO_PCI_COMMON_Q_MSIX 26 +#define VIRTIO_PCI_COMMON_Q_ENABLE 28 +#define VIRTIO_PCI_COMMON_Q_NOFF 30 +#define VIRTIO_PCI_COMMON_Q_DESCLO 32 +#define VIRTIO_PCI_COMMON_Q_DESCHI 36 +#define VIRTIO_PCI_COMMON_Q_AVAILLO 40 +#define VIRTIO_PCI_COMMON_Q_AVAILHI 44 +#define VIRTIO_PCI_COMMON_Q_USEDLO 48 +#define VIRTIO_PCI_COMMON_Q_USEDHI 52 + +#endif /* VIRTIO_PCI_NO_MODERN */ + +#endif diff --git a/include/hw/virtio/virtio_ring.h b/include/standard-headers/linux/virtio_ring.h index 0b42e6e..cc647d6 100644 --- a/include/hw/virtio/virtio_ring.h +++ b/include/standard-headers/linux/virtio_ring.h @@ -1,10 +1,5 @@ #ifndef _LINUX_VIRTIO_RING_H #define _LINUX_VIRTIO_RING_H -/* - * This file is copied from /usr/include/linux while converting __uNN types - * to uXX_t, __inline__ to inline, and tab to spaces. - * */ - /* An interface for efficient virtio implementation, currently for use by KVM * and lguest, but hopefully others soon. Do NOT change this since it will * break existing servers and clients. @@ -36,118 +31,127 @@ * SUCH DAMAGE. * * Copyright Rusty Russell IBM Corporation 2007. */ +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_types.h" /* This marks a buffer as continuing via the next field. */ -#define VRING_DESC_F_NEXT 1 +#define VRING_DESC_F_NEXT 1 /* This marks a buffer as write-only (otherwise read-only). */ -#define VRING_DESC_F_WRITE 2 +#define VRING_DESC_F_WRITE 2 /* This means the buffer contains a list of buffer descriptors. */ -#define VRING_DESC_F_INDIRECT 4 +#define VRING_DESC_F_INDIRECT 4 /* The Host uses this in used->flags to advise the Guest: don't kick me when * you add a buffer. It's unreliable, so it's simply an optimization. Guest * will still kick if it's out of buffers. */ -#define VRING_USED_F_NO_NOTIFY 1 +#define VRING_USED_F_NO_NOTIFY 1 /* The Guest uses this in avail->flags to advise the Host: don't interrupt me * when you consume a buffer. It's unreliable, so it's simply an * optimization. */ -#define VRING_AVAIL_F_NO_INTERRUPT 1 +#define VRING_AVAIL_F_NO_INTERRUPT 1 /* We support indirect buffer descriptors */ -#define VIRTIO_RING_F_INDIRECT_DESC 28 +#define VIRTIO_RING_F_INDIRECT_DESC 28 /* The Guest publishes the used index for which it expects an interrupt * at the end of the avail ring. Host should ignore the avail->flags field. */ /* The Host publishes the avail index for which it expects a kick * at the end of the used ring. Guest should ignore the used->flags field. */ -#define VIRTIO_RING_F_EVENT_IDX 29 +#define VIRTIO_RING_F_EVENT_IDX 29 /* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ struct vring_desc { - /* Address (guest-physical). */ - uint64_t addr; - /* Length. */ - uint32_t len; - /* The flags as indicated above. */ - uint16_t flags; - /* We chain unused descriptors via this, too */ - uint16_t next; + /* Address (guest-physical). */ + __virtio64 addr; + /* Length. */ + __virtio32 len; + /* The flags as indicated above. */ + __virtio16 flags; + /* We chain unused descriptors via this, too */ + __virtio16 next; }; struct vring_avail { - uint16_t flags; - uint16_t idx; - uint16_t ring[]; + __virtio16 flags; + __virtio16 idx; + __virtio16 ring[]; }; /* u32 is used here for ids for padding reasons. */ struct vring_used_elem { - /* Index of start of used descriptor chain. */ - uint32_t id; - /* Total length of the descriptor chain which was used (written to) */ - uint32_t len; + /* Index of start of used descriptor chain. */ + __virtio32 id; + /* Total length of the descriptor chain which was used (written to) */ + __virtio32 len; }; struct vring_used { - uint16_t flags; - uint16_t idx; - struct vring_used_elem ring[]; + __virtio16 flags; + __virtio16 idx; + struct vring_used_elem ring[]; }; struct vring { - unsigned int num; + unsigned int num; - struct vring_desc *desc; + struct vring_desc *desc; - struct vring_avail *avail; + struct vring_avail *avail; - struct vring_used *used; + struct vring_used *used; }; +/* Alignment requirements for vring elements. + * When using pre-virtio 1.0 layout, these fall out naturally. + */ +#define VRING_AVAIL_ALIGN_SIZE 2 +#define VRING_USED_ALIGN_SIZE 4 +#define VRING_DESC_ALIGN_SIZE 16 + /* The standard layout for the ring is a continuous chunk of memory which looks * like this. We assume num is a power of 2. * * struct vring * { - * // The actual descriptors (16 bytes each) - * struct vring_desc desc[num]; + * // The actual descriptors (16 bytes each) + * struct vring_desc desc[num]; * - * // A ring of available descriptor heads with free-running index. - * uint16_t avail_flags; - * uint16_t avail_idx; - * uint16_t available[num]; - * uint16_t used_event_idx; + * // A ring of available descriptor heads with free-running index. + * __virtio16 avail_flags; + * __virtio16 avail_idx; + * __virtio16 available[num]; + * __virtio16 used_event_idx; * - * // Padding to the next align boundary. - * char pad[]; + * // Padding to the next align boundary. + * char pad[]; * - * // A ring of used descriptor heads with free-running index. - * uint16_t used_flags; - * uint16_t used_idx; - * struct vring_used_elem used[num]; - * uint16_t avail_event_idx; + * // A ring of used descriptor heads with free-running index. + * __virtio16 used_flags; + * __virtio16 used_idx; + * struct vring_used_elem used[num]; + * __virtio16 avail_event_idx; * }; */ /* We publish the used event index at the end of the available ring, and vice * versa. They are at the end for backwards compatibility. */ #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) -#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num]) +#define vring_avail_event(vr) (*(__virtio16 *)&(vr)->used->ring[(vr)->num]) static inline void vring_init(struct vring *vr, unsigned int num, void *p, - unsigned long align) + unsigned long align) { - vr->num = num; - vr->desc = p; - vr->avail = p + num*sizeof(struct vring_desc); - vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(uint16_t) - + align - 1) & ~(align - 1)); + vr->num = num; + vr->desc = p; + vr->avail = p + num*sizeof(struct vring_desc); + vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__virtio16) + + align-1) & ~(align - 1)); } static inline unsigned vring_size(unsigned int num, unsigned long align) { - return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num) - + align - 1) & ~(align - 1)) - + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num; + return ((sizeof(struct vring_desc) * num + sizeof(__virtio16) * (3 + num) + + align - 1) & ~(align - 1)) + + sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num; } /* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */ @@ -156,12 +160,12 @@ static inline unsigned vring_size(unsigned int num, unsigned long align) * should we trigger an event? */ static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) { - /* Note: Xen has similar logic for notification hold-off - * in include/xen/interface/io/ring.h with req_event and req_prod - * corresponding to event_idx + 1 and new_idx respectively. - * Note also that req_event and req_prod in Xen start at 1, - * event indexes in virtio start at 0. */ - return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old); + /* Note: Xen has similar logic for notification hold-off + * in include/xen/interface/io/ring.h with req_event and req_prod + * corresponding to event_idx + 1 and new_idx respectively. + * Note also that req_event and req_prod in Xen start at 1, + * event indexes in virtio start at 0. */ + return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old); } #endif /* _LINUX_VIRTIO_RING_H */ diff --git a/include/standard-headers/linux/virtio_rng.h b/include/standard-headers/linux/virtio_rng.h new file mode 100644 index 0000000..60fc798 --- /dev/null +++ b/include/standard-headers/linux/virtio_rng.h @@ -0,0 +1,8 @@ +#ifndef _LINUX_VIRTIO_RNG_H +#define _LINUX_VIRTIO_RNG_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. */ +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" + +#endif /* _LINUX_VIRTIO_RNG_H */ diff --git a/include/standard-headers/linux/virtio_scsi.h b/include/standard-headers/linux/virtio_scsi.h new file mode 100644 index 0000000..78ba9d3 --- /dev/null +++ b/include/standard-headers/linux/virtio_scsi.h @@ -0,0 +1,164 @@ +/* + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUX_VIRTIO_SCSI_H +#define _LINUX_VIRTIO_SCSI_H + +#include "standard-headers/linux/virtio_types.h" + +#define VIRTIO_SCSI_CDB_SIZE 32 +#define VIRTIO_SCSI_SENSE_SIZE 96 + +/* SCSI command request, followed by data-out */ +struct virtio_scsi_cmd_req { + uint8_t lun[8]; /* Logical Unit Number */ + __virtio64 tag; /* Command identifier */ + uint8_t task_attr; /* Task attribute */ + uint8_t prio; /* SAM command priority field */ + uint8_t crn; + uint8_t cdb[VIRTIO_SCSI_CDB_SIZE]; +} QEMU_PACKED; + +/* SCSI command request, followed by protection information */ +struct virtio_scsi_cmd_req_pi { + uint8_t lun[8]; /* Logical Unit Number */ + __virtio64 tag; /* Command identifier */ + uint8_t task_attr; /* Task attribute */ + uint8_t prio; /* SAM command priority field */ + uint8_t crn; + __virtio32 pi_bytesout; /* DataOUT PI Number of bytes */ + __virtio32 pi_bytesin; /* DataIN PI Number of bytes */ + uint8_t cdb[VIRTIO_SCSI_CDB_SIZE]; +} QEMU_PACKED; + +/* Response, followed by sense data and data-in */ +struct virtio_scsi_cmd_resp { + __virtio32 sense_len; /* Sense data length */ + __virtio32 resid; /* Residual bytes in data buffer */ + __virtio16 status_qualifier; /* Status qualifier */ + uint8_t status; /* Command completion status */ + uint8_t response; /* Response values */ + uint8_t sense[VIRTIO_SCSI_SENSE_SIZE]; +} QEMU_PACKED; + +/* Task Management Request */ +struct virtio_scsi_ctrl_tmf_req { + __virtio32 type; + __virtio32 subtype; + uint8_t lun[8]; + __virtio64 tag; +} QEMU_PACKED; + +struct virtio_scsi_ctrl_tmf_resp { + uint8_t response; +} QEMU_PACKED; + +/* Asynchronous notification query/subscription */ +struct virtio_scsi_ctrl_an_req { + __virtio32 type; + uint8_t lun[8]; + __virtio32 event_requested; +} QEMU_PACKED; + +struct virtio_scsi_ctrl_an_resp { + __virtio32 event_actual; + uint8_t response; +} QEMU_PACKED; + +struct virtio_scsi_event { + __virtio32 event; + uint8_t lun[8]; + __virtio32 reason; +} QEMU_PACKED; + +struct virtio_scsi_config { + uint32_t num_queues; + uint32_t seg_max; + uint32_t max_sectors; + uint32_t cmd_per_lun; + uint32_t event_info_size; + uint32_t sense_size; + uint32_t cdb_size; + uint16_t max_channel; + uint16_t max_target; + uint32_t max_lun; +} QEMU_PACKED; + +/* Feature Bits */ +#define VIRTIO_SCSI_F_INOUT 0 +#define VIRTIO_SCSI_F_HOTPLUG 1 +#define VIRTIO_SCSI_F_CHANGE 2 +#define VIRTIO_SCSI_F_T10_PI 3 + +/* Response codes */ +#define VIRTIO_SCSI_S_OK 0 +#define VIRTIO_SCSI_S_OVERRUN 1 +#define VIRTIO_SCSI_S_ABORTED 2 +#define VIRTIO_SCSI_S_BAD_TARGET 3 +#define VIRTIO_SCSI_S_RESET 4 +#define VIRTIO_SCSI_S_BUSY 5 +#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 +#define VIRTIO_SCSI_S_TARGET_FAILURE 7 +#define VIRTIO_SCSI_S_NEXUS_FAILURE 8 +#define VIRTIO_SCSI_S_FAILURE 9 +#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 +#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 +#define VIRTIO_SCSI_S_INCORRECT_LUN 12 + +/* Controlq type codes. */ +#define VIRTIO_SCSI_T_TMF 0 +#define VIRTIO_SCSI_T_AN_QUERY 1 +#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 + +/* Valid TMF subtypes. */ +#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 +#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 +#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 +#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET 3 +#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 +#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 +#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 +#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 + +/* Events. */ +#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 +#define VIRTIO_SCSI_T_NO_EVENT 0 +#define VIRTIO_SCSI_T_TRANSPORT_RESET 1 +#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 +#define VIRTIO_SCSI_T_PARAM_CHANGE 3 + +/* Reasons of transport reset event */ +#define VIRTIO_SCSI_EVT_RESET_HARD 0 +#define VIRTIO_SCSI_EVT_RESET_RESCAN 1 +#define VIRTIO_SCSI_EVT_RESET_REMOVED 2 + +#define VIRTIO_SCSI_S_SIMPLE 0 +#define VIRTIO_SCSI_S_ORDERED 1 +#define VIRTIO_SCSI_S_HEAD 2 +#define VIRTIO_SCSI_S_ACA 3 + + +#endif /* _LINUX_VIRTIO_SCSI_H */ diff --git a/include/standard-headers/linux/virtio_types.h b/include/standard-headers/linux/virtio_types.h new file mode 100644 index 0000000..fd0d351 --- /dev/null +++ b/include/standard-headers/linux/virtio_types.h @@ -0,0 +1,46 @@ +#ifndef _LINUX_VIRTIO_TYPES_H +#define _LINUX_VIRTIO_TYPES_H +/* Type definitions for virtio implementations. + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 2014 Red Hat, Inc. + * Author: Michael S. Tsirkin <mst@redhat.com> + */ +#include "standard-headers/linux/types.h" + +/* + * __virtio{16,32,64} have the following meaning: + * - __u{16,32,64} for virtio devices in legacy mode, accessed in native endian + * - __le{16,32,64} for standard-compliant virtio devices + */ + +typedef uint16_t __virtio16; +typedef uint32_t __virtio32; +typedef uint64_t __virtio64; + +#endif /* _LINUX_VIRTIO_TYPES_H */ diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 0c62643..7ca59b5 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -63,8 +63,6 @@ DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type); /* device-hotplug */ -DriveInfo *add_init_drive(const char *opts); - void qmp_change_blockdev(const char *device, const char *filename, const char *format, Error **errp); void hmp_commit(Monitor *mon, const QDict *qdict); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 11040b4..6e85097 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -156,11 +156,6 @@ extern int nb_option_roms; extern const char *prom_envs[MAX_PROM_ENVS]; extern unsigned int nb_prom_envs; -/* pci-hotplug */ -void hmp_pci_add(Monitor *mon, const QDict *qdict); -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo); -void hmp_pci_del(Monitor *mon, const QDict *qdict); - /* generic hotplug */ void hmp_drive_add(Monitor *mon, const QDict *qdict); diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 825f33b..540ee25 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -56,7 +56,7 @@ struct TPMBackend { QLIST_ENTRY(TPMBackend) list; }; -typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty); +typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool selftest_done); typedef struct TPMSizedBuffer { uint32_t size; diff --git a/include/ui/console.h b/include/ui/console.h index 0f97d86..6e5a867 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -36,7 +36,6 @@ typedef struct QEMUPutLEDEntry QEMUPutLEDEntry; QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); -void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry); QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute, const char *name); @@ -194,7 +193,6 @@ DisplaySurface *qemu_create_displaysurface_guestmem(int width, int height, pixman_format_code_t format, int linesize, uint64_t addr); -PixelFormat qemu_different_endianness_pixelformat(int bpp); PixelFormat qemu_default_pixelformat(int bpp); DisplaySurface *qemu_create_displaysurface(int width, int height); @@ -322,7 +320,6 @@ void qemu_console_resize(QemuConsole *con, int width, int height); void qemu_console_copy(QemuConsole *con, int src_x, int src_y, int dst_x, int dst_y, int w, int h); DisplaySurface *qemu_console_surface(QemuConsole *con); -DisplayState *qemu_console_displaystate(QemuConsole *console); /* sdl.c */ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame); @@ -366,7 +366,7 @@ static void kvm_log_stop(MemoryListener *listener, } } -static int kvm_set_migration_log(int enable) +static int kvm_set_migration_log(bool enable) { KVMState *s = kvm_state; KVMSlot *mem; diff --git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h index 75dc20b..5590f7d 100644 --- a/linux-headers/linux/virtio_config.h +++ b/linux-headers/linux/virtio_config.h @@ -1,57 +1 @@ -#ifndef _LINUX_VIRTIO_CONFIG_H -#define _LINUX_VIRTIO_CONFIG_H -/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so - * anyone can use the definitions to implement compatible drivers/servers. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of IBM nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ - -/* Virtio devices use a standardized configuration space to define their - * features and pass configuration information, but each implementation can - * store and access that space differently. */ -#include <linux/types.h> - -/* Status byte for guest to report progress, and synchronize features. */ -/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ -#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 -/* We have found a driver for the device. */ -#define VIRTIO_CONFIG_S_DRIVER 2 -/* Driver has used its parts of the config, and is happy */ -#define VIRTIO_CONFIG_S_DRIVER_OK 4 -/* We've given up on this device. */ -#define VIRTIO_CONFIG_S_FAILED 0x80 - -/* Some virtio feature bits (currently bits 28 through 31) are reserved for the - * transport being used (eg. virtio_ring), the rest are per-device feature - * bits. */ -#define VIRTIO_TRANSPORT_F_START 28 -#define VIRTIO_TRANSPORT_F_END 32 - -/* Do we get callbacks when the ring is completely used, even if we've - * suppressed them? */ -#define VIRTIO_F_NOTIFY_ON_EMPTY 24 - -/* Can the device handle any descriptor layout? */ -#define VIRTIO_F_ANY_LAYOUT 27 - -#endif /* _LINUX_VIRTIO_CONFIG_H */ +#include "standard-headers/linux/virtio_config.h" diff --git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h index 1b333e2..c6f0fb6 100644 --- a/linux-headers/linux/virtio_ring.h +++ b/linux-headers/linux/virtio_ring.h @@ -1,163 +1 @@ -#ifndef _LINUX_VIRTIO_RING_H -#define _LINUX_VIRTIO_RING_H -/* An interface for efficient virtio implementation, currently for use by KVM - * and lguest, but hopefully others soon. Do NOT change this since it will - * break existing servers and clients. - * - * This header is BSD licensed so anyone can use the definitions to implement - * compatible drivers/servers. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of IBM nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright Rusty Russell IBM Corporation 2007. */ -#include <linux/types.h> - -/* This marks a buffer as continuing via the next field. */ -#define VRING_DESC_F_NEXT 1 -/* This marks a buffer as write-only (otherwise read-only). */ -#define VRING_DESC_F_WRITE 2 -/* This means the buffer contains a list of buffer descriptors. */ -#define VRING_DESC_F_INDIRECT 4 - -/* The Host uses this in used->flags to advise the Guest: don't kick me when - * you add a buffer. It's unreliable, so it's simply an optimization. Guest - * will still kick if it's out of buffers. */ -#define VRING_USED_F_NO_NOTIFY 1 -/* The Guest uses this in avail->flags to advise the Host: don't interrupt me - * when you consume a buffer. It's unreliable, so it's simply an - * optimization. */ -#define VRING_AVAIL_F_NO_INTERRUPT 1 - -/* We support indirect buffer descriptors */ -#define VIRTIO_RING_F_INDIRECT_DESC 28 - -/* The Guest publishes the used index for which it expects an interrupt - * at the end of the avail ring. Host should ignore the avail->flags field. */ -/* The Host publishes the avail index for which it expects a kick - * at the end of the used ring. Guest should ignore the used->flags field. */ -#define VIRTIO_RING_F_EVENT_IDX 29 - -/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ -struct vring_desc { - /* Address (guest-physical). */ - __u64 addr; - /* Length. */ - __u32 len; - /* The flags as indicated above. */ - __u16 flags; - /* We chain unused descriptors via this, too */ - __u16 next; -}; - -struct vring_avail { - __u16 flags; - __u16 idx; - __u16 ring[]; -}; - -/* u32 is used here for ids for padding reasons. */ -struct vring_used_elem { - /* Index of start of used descriptor chain. */ - __u32 id; - /* Total length of the descriptor chain which was used (written to) */ - __u32 len; -}; - -struct vring_used { - __u16 flags; - __u16 idx; - struct vring_used_elem ring[]; -}; - -struct vring { - unsigned int num; - - struct vring_desc *desc; - - struct vring_avail *avail; - - struct vring_used *used; -}; - -/* The standard layout for the ring is a continuous chunk of memory which looks - * like this. We assume num is a power of 2. - * - * struct vring - * { - * // The actual descriptors (16 bytes each) - * struct vring_desc desc[num]; - * - * // A ring of available descriptor heads with free-running index. - * __u16 avail_flags; - * __u16 avail_idx; - * __u16 available[num]; - * __u16 used_event_idx; - * - * // Padding to the next align boundary. - * char pad[]; - * - * // A ring of used descriptor heads with free-running index. - * __u16 used_flags; - * __u16 used_idx; - * struct vring_used_elem used[num]; - * __u16 avail_event_idx; - * }; - */ -/* We publish the used event index at the end of the available ring, and vice - * versa. They are at the end for backwards compatibility. */ -#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) -#define vring_avail_event(vr) (*(__u16 *)&(vr)->used->ring[(vr)->num]) - -static __inline__ void vring_init(struct vring *vr, unsigned int num, void *p, - unsigned long align) -{ - vr->num = num; - vr->desc = p; - vr->avail = p + num*sizeof(struct vring_desc); - vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__u16) - + align-1) & ~(align - 1)); -} - -static __inline__ unsigned vring_size(unsigned int num, unsigned long align) -{ - return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num) - + align - 1) & ~(align - 1)) - + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num; -} - -/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */ -/* Assuming a given event_idx value from the other size, if - * we have just incremented index from old to new_idx, - * should we trigger an event? */ -static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old) -{ - /* Note: Xen has similar logic for notification hold-off - * in include/xen/interface/io/ring.h with req_event and req_prod - * corresponding to event_idx + 1 and new_idx respectively. - * Note also that req_event and req_prod in Xen start at 1, - * event indexes in virtio start at 0. */ - return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old); -} - -#endif /* _LINUX_VIRTIO_RING_H */ +#include "standard-headers/linux/virtio_ring.h" diff --git a/migration/qemu-file-buf.c b/migration/qemu-file-buf.c index e97e0bd..e56a8ad 100644 --- a/migration/qemu-file-buf.c +++ b/migration/qemu-file-buf.c @@ -2,6 +2,10 @@ * QEMU System Emulator * * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2014 IBM Corp. + * + * Authors: + * Stefan Berger <stefanb@linux.vnet.ibm.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/migration/rdma.c b/migration/rdma.c index 17d0035..42d443c 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -702,7 +702,7 @@ static void qemu_rdma_dump_id(const char *who, struct ibv_context *verbs) verbs->device->ibdev_path, port.link_layer, (port.link_layer == IBV_LINK_LAYER_INFINIBAND) ? "Infiniband" : - ((port.link_layer == IBV_LINK_LAYER_ETHERNET) + ((port.link_layer == IBV_LINK_LAYER_ETHERNET) ? "Ethernet" : "Unknown")); } @@ -737,7 +737,7 @@ static void qemu_rdma_dump_gid(const char *who, struct rdma_cm_id *id) * and validate what time of hardware it is. * * Unfortunately, this puts the user in a fix: - * + * * If the source VM connects with an IPv4 address without knowing that the * destination has bound to '[::]' the migration will unconditionally fail * unless the management software is explicitly listening on the the IPv4 @@ -745,13 +745,13 @@ static void qemu_rdma_dump_gid(const char *who, struct rdma_cm_id *id) * * If the source VM connects with an IPv6 address, then we're OK because we can * throw an error on the source (and similarly on the destination). - * + * * But in mixed environments, this will be broken for a while until it is fixed * inside linux. * * We do provide a *tiny* bit of help in this function: We can list all of the * devices in the system and check to see if all the devices are RoCE or - * Infiniband. + * Infiniband. * * If we detect that we have a *pure* RoCE environment, then we can safely * thrown an error even if the management software has specified '[::]' as the @@ -770,17 +770,17 @@ static int qemu_rdma_broken_ipv6_kernel(Error **errp, struct ibv_context *verbs) /* This bug only exists in linux, to our knowledge. */ #ifdef CONFIG_LINUX - /* + /* * Verbs are only NULL if management has bound to '[::]'. - * + * * Let's iterate through all the devices and see if there any pure IB * devices (non-ethernet). - * + * * If not, then we can safely proceed with the migration. * Otherwise, there are no guarantees until the bug is fixed in linux. */ if (!verbs) { - int num_devices, x; + int num_devices, x; struct ibv_device ** dev_list = ibv_get_device_list(&num_devices); bool roce_found = false; bool ib_found = false; @@ -825,8 +825,8 @@ static int qemu_rdma_broken_ipv6_kernel(Error **errp, struct ibv_context *verbs) /* * If we have a verbs context, that means that some other than '[::]' was - * used by the management software for binding. In which case we can actually - * warn the user about a potential broken kernel; + * used by the management software for binding. In which case we can + * actually warn the user about a potentially broken kernel. */ /* IB ports start with 1, not 0 */ @@ -1626,7 +1626,7 @@ static int qemu_rdma_exchange_get_response(RDMAContext *rdma, return -EIO; } if (head->len > RDMA_CONTROL_MAX_BUFFER - sizeof(*head)) { - error_report("too long length: %d\n", head->len); + error_report("too long length: %d", head->len); return -EINVAL; } if (sizeof(*head) + head->len != byte_len) { diff --git a/net/vhost-user.c b/net/vhost-user.c index 24e050c..1d86a2b 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -18,7 +18,6 @@ typedef struct VhostUserState { NetClientState nc; CharDriverState *chr; - bool vhostforce; VHostNetState *vhost_net; } VhostUserState; @@ -51,7 +50,7 @@ static int vhost_user_start(VhostUserState *s) options.backend_type = VHOST_BACKEND_TYPE_USER; options.net_backend = &s->nc; options.opaque = s->chr; - options.force = s->vhostforce; + options.force = true; s->vhost_net = vhost_net_init(&options); @@ -122,19 +121,18 @@ static void net_vhost_user_event(void *opaque, int event) case CHR_EVENT_OPENED: vhost_user_start(s); net_vhost_link_down(s, false); - error_report("chardev \"%s\" went up\n", s->chr->label); + error_report("chardev \"%s\" went up", s->chr->label); break; case CHR_EVENT_CLOSED: net_vhost_link_down(s, true); vhost_user_stop(s); - error_report("chardev \"%s\" went down\n", s->chr->label); + error_report("chardev \"%s\" went down", s->chr->label); break; } } static int net_vhost_user_init(NetClientState *peer, const char *device, - const char *name, CharDriverState *chr, - bool vhostforce) + const char *name, CharDriverState *chr) { NetClientState *nc; VhostUserState *s; @@ -149,7 +147,6 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, /* We don't provide a receive callback */ s->nc.receive_disabled = 1; s->chr = chr; - s->vhostforce = vhostforce; qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s); @@ -230,7 +227,6 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name, { const NetdevVhostUserOptions *vhost_user_opts; CharDriverState *chr; - bool vhostforce; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER); vhost_user_opts = opts->vhost_user; @@ -247,12 +243,6 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name, return -1; } - /* vhostforce for non-MSIX */ - if (vhost_user_opts->has_vhostforce) { - vhostforce = vhost_user_opts->vhostforce; - } else { - vhostforce = false; - } - return net_vhost_user_init(peer, "vhost_user", name, chr, vhostforce); + return net_vhost_user_init(peer, "vhost_user", name, chr); } @@ -66,7 +66,7 @@ static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp) if (nodenr >= MAX_NODES) { error_setg(errp, "Max number of NUMA nodes reached: %" - PRIu16 "\n", nodenr); + PRIu16 "", nodenr); return; } @@ -85,7 +85,7 @@ static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp) } if (node->has_mem && node->has_memdev) { - error_setg(errp, "qemu: cannot specify both mem= and memdev=\n"); + error_setg(errp, "qemu: cannot specify both mem= and memdev="); return; } @@ -94,7 +94,7 @@ static void numa_node_parse(NumaNodeOptions *node, QemuOpts *opts, Error **errp) } if (node->has_memdev != have_memdevs) { error_setg(errp, "qemu: memdev option must be specified for either " - "all or no nodes\n"); + "all or no nodes"); return; } diff --git a/pc-bios/keymaps/ru b/pc-bios/keymaps/ru index b3e7d24..8f652d5 100644 --- a/pc-bios/keymaps/ru +++ b/pc-bios/keymaps/ru @@ -4,7 +4,7 @@ map 0x419 exclam 0x02 shift at 0x03 shift quotedbl 0x03 shift altgr -numbersign 0x04 shift +numerosign 0x04 shift dollar 0x05 shift asterisk 0x05 shift altgr percent 0x06 shift diff --git a/qapi-schema.json b/qapi-schema.json index e16f8eb..8141f71 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -871,9 +871,9 @@ # @connection-id: SPICE connection id number. All channels with the same id # belong to the same SPICE session. # -# @connection-type: SPICE channel type number. "1" is the main control -# channel, filter for this one if you want to track spice -# sessions only +# @channel-type: SPICE channel type number. "1" is the main control +# channel, filter for this one if you want to track spice +# sessions only # # @channel-id: SPICE channel ID number. Usually "0", might be different when # multiple channels of the same type exist, such as multiple @@ -976,7 +976,8 @@ static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum, static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n, int *pnum) { - int res, i; + bool res; + int i; if (n <= 0) { *pnum = 0; @@ -1645,7 +1646,7 @@ static int img_convert(int argc, char **argv) if (skip_create) { int64_t output_sectors = blk_nb_sectors(out_blk); if (output_sectors < 0) { - error_report("unable to get output image length: %s\n", + error_report("unable to get output image length: %s", strerror(-output_sectors)); ret = -1; goto out; diff --git a/qemu-options.hx b/qemu-options.hx index b0345ae..837624d 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1376,11 +1376,25 @@ ETEXI DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, "-smbios file=binary\n" " load SMBIOS entry from binary file\n" - "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d][,uefi=on|off]\n" + "-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n" + " [,uefi=on|off]\n" " specify SMBIOS type 0 fields\n" "-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n" " [,uuid=uuid][,sku=str][,family=str]\n" - " specify SMBIOS type 1 fields\n", QEMU_ARCH_I386) + " specify SMBIOS type 1 fields\n" + "-smbios type=2[,manufacturer=str][,product=str][,version=str][,serial=str]\n" + " [,asset=str][,location=str]\n" + " specify SMBIOS type 2 fields\n" + "-smbios type=3[,manufacturer=str][,version=str][,serial=str][,asset=str]\n" + " [,sku=str]\n" + " specify SMBIOS type 3 fields\n" + "-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str]\n" + " [,asset=str][,part=str]\n" + " specify SMBIOS type 4 fields\n" + "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n" + " [,asset=str][,part=str]\n" + " specify SMBIOS type 17 fields\n", + QEMU_ARCH_I386) STEXI @item -smbios file=@var{binary} @findex -smbios @@ -1389,8 +1403,20 @@ Load SMBIOS entry from binary file. @item -smbios type=0[,vendor=@var{str}][,version=@var{str}][,date=@var{str}][,release=@var{%d.%d}][,uefi=on|off] Specify SMBIOS type 0 fields -@item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}] [,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}] [,family=@var{str}] +@item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}][,family=@var{str}] Specify SMBIOS type 1 fields + +@item -smbios type=2[,manufacturer=@var{str}][,product=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,location=@var{str}][,family=@var{str}] +Specify SMBIOS type 2 fields + +@item -smbios type=3[,manufacturer=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,sku=@var{str}] +Specify SMBIOS type 3 fields + +@item -smbios type=4[,sock_pfx=@var{str}][,manufacturer=@var{str}][,version=@var{str}][,serial=@var{str}][,asset=@var{str}][,part=@var{str}] +Specify SMBIOS type 4 fields + +@item -smbios type=17[,loc_pfx=@var{str}][,bank=@var{str}][,manufacturer=@var{str}][,serial=@var{str}][,asset=@var{str}][,part=@var{str}] +Specify SMBIOS type 17 fields ETEXI STEXI @@ -3181,12 +3207,30 @@ Set TB size. ETEXI DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ - "-incoming p prepare for incoming migration, listen on port p\n", + "-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \ + "-incoming rdma:host:port[,ipv4][,ipv6]\n" \ + "-incoming unix:socketpath\n" \ + " prepare for incoming migration, listen on\n" \ + " specified protocol and socket address\n" \ + "-incoming fd:fd\n" \ + "-incoming exec:cmdline\n" \ + " accept incoming migration on given file descriptor\n" \ + " or from given external command\n", QEMU_ARCH_ALL) STEXI -@item -incoming @var{port} +@item -incoming tcp:[@var{host}]:@var{port}[,to=@var{maxport}][,ipv4][,ipv6] +@item -incoming rdma:@var{host}:@var{port}[,ipv4][,ipv6] @findex -incoming -Prepare for incoming migration, listen on @var{port}. +Prepare for incoming migration, listen on a given tcp port. + +@item -incoming unix:@var{socketpath} +Prepare for incoming migration, listen on a given unix socket. + +@item -incoming fd:@var{fd} +Accept incoming migration from a given filedescriptor. + +@item -incoming exec:@var{cmdline} +Accept incoming migration as an output from specified external command. ETEXI DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \ diff --git a/qmp-commands.hx b/qmp-commands.hx index a85d847..c12334a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1,5 +1,5 @@ HXCOMM QMP dispatch table and documentation -HXCOMM Text between SQMP and EQMP is copied to the QMP documention file and +HXCOMM Text between SQMP and EQMP is copied to the QMP documentation file and HXCOMM does not show up in the other formats. SQMP @@ -1767,7 +1767,7 @@ Arguments: - "protocol": protocol name (json-string) - "password": password (json-string) -- "connected": [ keep | disconnect | fail ] (josn-string, optional) +- "connected": [ keep | disconnect | fail ] (json-string, optional) Example: @@ -2922,7 +2922,7 @@ Channels are described by a json-object, each one contain the following: - "channel-id": channel id. Usually "0", might be different needed when multiple channels of the same type exist, such as multiple display channels in a multihead setup (json-int) -- "tls": whevener the channel is encrypted (json-bool) +- "tls": whether the channel is encrypted (json-bool) Example: diff --git a/qom/object.c b/qom/object.c index 1812c73..d167038 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1543,6 +1543,85 @@ void object_property_add_bool(Object *obj, const char *name, } } +typedef struct TMProperty { + void (*get)(Object *, struct tm *, Error **); +} TMProperty; + +static void property_get_tm(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + TMProperty *prop = opaque; + Error *err = NULL; + struct tm value; + + prop->get(obj, &value, &err); + if (err) { + goto out; + } + + visit_start_struct(v, NULL, "struct tm", name, 0, &err); + if (err) { + goto out; + } + visit_type_int32(v, &value.tm_year, "tm_year", &err); + if (err) { + goto out_end; + } + visit_type_int32(v, &value.tm_mon, "tm_mon", &err); + if (err) { + goto out_end; + } + visit_type_int32(v, &value.tm_mday, "tm_mday", &err); + if (err) { + goto out_end; + } + visit_type_int32(v, &value.tm_hour, "tm_hour", &err); + if (err) { + goto out_end; + } + visit_type_int32(v, &value.tm_min, "tm_min", &err); + if (err) { + goto out_end; + } + visit_type_int32(v, &value.tm_sec, "tm_sec", &err); + if (err) { + goto out_end; + } +out_end: + error_propagate(errp, err); + err = NULL; + visit_end_struct(v, errp); +out: + error_propagate(errp, err); + +} + +static void property_release_tm(Object *obj, const char *name, + void *opaque) +{ + TMProperty *prop = opaque; + g_free(prop); +} + +void object_property_add_tm(Object *obj, const char *name, + void (*get)(Object *, struct tm *, Error **), + Error **errp) +{ + Error *local_err = NULL; + TMProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + + object_property_add(obj, name, "struct tm", + get ? property_get_tm : NULL, NULL, + property_release_tm, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + static char *qdev_get_type(Object *obj, Error **errp) { return g_strdup(object_get_typename(obj)); diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index c8e026d..f208ec9 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -28,6 +28,37 @@ if [ -z "$output" ]; then output="$PWD" fi +cp_virtio() { + from=$1 + to=$2 + virtio=$(find "$from" -name '*virtio*h') + if [ "$virtio" ]; then + rm -rf "$to" + mkdir -p "$to" + for f in $virtio; do + if + grep '#include' "$f" | grep -v -e 'linux/virtio' \ + -e 'linux/types' \ + -e 'linux/if_ether' \ + > /dev/null + then + echo "Unexpected #include in input file $f". + exit 2 + fi + + header=$(basename "$f"); + sed -e 's/__u\([0-9][0-9]*\)/uint\1_t/g' \ + -e 's/__le\([0-9][0-9]*\)/uint\1_t/g' \ + -e 's/__be\([0-9][0-9]*\)/uint\1_t/g' \ + -e 's/<linux\/\([^>]*\)>/"standard-headers\/linux\/\1"/' \ + -e 's/__bitwise__//' \ + -e 's/__attribute__((packed))/QEMU_PACKED/' \ + -e 's/__inline__/inline/' \ + "$f" > "$to/$header"; + done + fi +} + # This will pick up non-directories too (eg "Kconfig") but we will # ignore them in the next loop. ARCHLIST=$(cd "$linux/arch" && echo *) @@ -57,11 +88,13 @@ for arch in $ARCHLIST; do if [ $arch = powerpc ]; then cp "$tmpdir/include/asm/epapr_hcalls.h" "$output/linux-headers/asm-powerpc/" fi + + cp_virtio "$tmpdir/include/asm" "$output/include/standard-headers/asm-$arch" done rm -rf "$output/linux-headers/linux" mkdir -p "$output/linux-headers/linux" -for header in kvm.h kvm_para.h vfio.h vhost.h virtio_config.h virtio_ring.h \ +for header in kvm.h kvm_para.h vfio.h vhost.h \ psci.h; do cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux" done @@ -76,4 +109,21 @@ else cp "$linux/COPYING" "$output/linux-headers" fi +cat <<EOF >$output/linux-headers/linux/virtio_config.h +#include "standard-headers/linux/virtio_config.h" +EOF +cat <<EOF >$output/linux-headers/linux/virtio_ring.h +#include "standard-headers/linux/virtio_ring.h" +EOF + +cp_virtio "$tmpdir/include/linux/" "$output/include/standard-headers/linux" + +cat <<EOF >$output/include/standard-headers/linux/types.h +#include <stdint.h> +#include "qemu/compiler.h" +EOF +cat <<EOF >$output/include/standard-headers/linux/if_ether.h +#define ETH_ALEN 6 +EOF + rm -rf "$tmpdir" diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 5e347d0..8beff4c 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -24,7 +24,6 @@ stub-obj-y += mon-printf.o stub-obj-y += mon-set-error.o stub-obj-y += monitor-init.o stub-obj-y += notify-event.o -stub-obj-y += pci-drive-hot-add.o stub-obj-$(CONFIG_SPICE) += qemu-chr-open-spice.o stub-obj-y += qtest.o stub-obj-y += reset.o diff --git a/stubs/pci-drive-hot-add.c b/stubs/pci-drive-hot-add.c deleted file mode 100644 index 1d98145..0000000 --- a/stubs/pci-drive-hot-add.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <monitor/monitor.h> -#include <sysemu/sysemu.h> -#include <sysemu/blockdev.h> - -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo) -{ - /* On non-x86 we don't do PCI hotplug */ - monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); - return -1; -} diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c index 3f18996..2b560a4 100644 --- a/target-ppc/cpu-models.c +++ b/target-ppc/cpu-models.c @@ -1124,8 +1124,8 @@ POWERPC_DEF("POWER5", CPU_POWERPC_POWER5, POWER5, "POWER5") #endif - POWERPC_DEF("POWER5+", CPU_POWERPC_POWER5P, POWER5P, - "POWER5+") + POWERPC_DEF("POWER5+_v0.0", CPU_POWERPC_POWER5P_v00, POWER5P, + "POWER5+ v0.0") POWERPC_DEF("POWER5+_v2.1", CPU_POWERPC_POWER5P_v21, POWER5P, "POWER5+ v2.1") #if defined(TODO) @@ -1144,8 +1144,8 @@ "POWER8E v1.0") POWERPC_DEF("POWER8_v1.0", CPU_POWERPC_POWER8_v10, POWER8, "POWER8 v1.0") - POWERPC_DEF("970", CPU_POWERPC_970, 970, - "PowerPC 970") + POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970, + "PowerPC 970 v2.2") POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970, "PowerPC 970FX v1.0 (G5)") POWERPC_DEF("970fx_v2.0", CPU_POWERPC_970FX_v20, 970, @@ -1387,11 +1387,13 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "Dino", "POWER3" }, { "POWER3+", "631" }, { "POWER5gr", "POWER5" }, - { "POWER5gs", "POWER5+" }, + { "POWER5+", "POWER5+_v0.0" }, + { "POWER5gs", "POWER5+_v0.0" }, { "POWER7", "POWER7_v2.3" }, { "POWER7+", "POWER7+_v2.1" }, { "POWER8E", "POWER8E_v1.0" }, { "POWER8", "POWER8_v1.0" }, + { "970", "970_v2.2" }, { "970fx", "970fx_v3.1" }, { "970mp", "970mp_v1.1" }, { "Apache", "RS64" }, diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h index 290a759..ee693af 100644 --- a/target-ppc/cpu-models.h +++ b/target-ppc/cpu-models.h @@ -547,7 +547,7 @@ enum { CPU_POWERPC_POWER4P = 0x00380000, /* XXX: missing 0x003A0201 */ CPU_POWERPC_POWER5 = 0x003A0203, - CPU_POWERPC_POWER5P = 0x003B0000, + CPU_POWERPC_POWER5P_v00 = 0x003B0000, CPU_POWERPC_POWER5P_v21 = 0x003B0201, CPU_POWERPC_POWER6 = 0x003E0000, CPU_POWERPC_POWER6_5 = 0x0F000001, /* POWER6 in POWER5 mode */ @@ -561,7 +561,7 @@ enum { CPU_POWERPC_POWER8E_v10 = 0x004B0100, CPU_POWERPC_POWER8_BASE = 0x004D0000, CPU_POWERPC_POWER8_v10 = 0x004D0100, - CPU_POWERPC_970 = 0x00390202, + CPU_POWERPC_970_v22 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, CPU_POWERPC_970FX_v21 = 0x003C0201, diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index aae33a9..abc3545 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -45,6 +45,7 @@ # define TARGET_VIRT_ADDR_SPACE_BITS 64 #endif +#define TARGET_PAGE_BITS_64K 16 #define TARGET_PAGE_BITS_16M 24 #else /* defined (TARGET_PPC64) */ @@ -1623,6 +1624,7 @@ static inline int cpu_mmu_index (CPUPPCState *env) #define SPR_MPC_MD_DBRAM1 (0x32A) #define SPR_RCPU_L2U_RA3 (0x32B) #define SPR_TAR (0x32F) +#define SPR_VTB (0x351) #define SPR_440_INV0 (0x370) #define SPR_440_INV1 (0x371) #define SPR_440_INV2 (0x372) diff --git a/target-ppc/machine.c b/target-ppc/machine.c index c801b82..3921012 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -159,6 +159,7 @@ static int cpu_post_load(void *opaque, int version_id) PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; int i; + target_ulong msr; /* * We always ignore the source PVR. The user or management @@ -190,7 +191,12 @@ static int cpu_post_load(void *opaque, int version_id) /* Restore htab_base and htab_mask variables */ ppc_store_sdr1(env, env->spr[SPR_SDR1]); } - hreg_compute_hflags(env); + + /* Mark msr bits except MSR_TGPR invalid before restoring */ + msr = env->msr; + env->msr ^= ~(1ULL << MSR_TGPR); + ppc_store_msr(env, msr); + hreg_compute_mem_idx(env); return 0; diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c index a577b3a..6b12ca8 100644 --- a/target-ppc/misc_helper.c +++ b/target-ppc/misc_helper.c @@ -77,8 +77,13 @@ void helper_msr_facility_check(CPUPPCState *env, uint32_t bit, void helper_store_sdr1(CPUPPCState *env, target_ulong val) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); + if (!env->external_htab) { - ppc_store_sdr1(env, val); + if (env->spr[SPR_SDR1] != val) { + ppc_store_sdr1(env, val); + tlb_flush(CPU(cpu), 1); + } } } diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index b0278c9..7df6ede 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -350,7 +350,7 @@ uint64_t ppc_hash64_start_access(PowerPCCPU *cpu, target_ulong pte_index) void ppc_hash64_stop_access(uint64_t token) { if (kvmppc_kern_htab) { - return kvmppc_hash64_free_pteg(token); + kvmppc_hash64_free_pteg(token); } } @@ -388,6 +388,24 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr hash, return -1; } +static uint64_t ppc_hash64_page_shift(ppc_slb_t *slb) +{ + uint64_t epnshift; + + /* Page size according to the SLB, which we use to generate the + * EPN for hash table lookup.. When we implement more recent MMU + * extensions this might be different from the actual page size + * encoded in the PTE */ + if ((slb->vsid & SLB_VSID_LLP_MASK) == SLB_VSID_4K) { + epnshift = TARGET_PAGE_BITS; + } else if ((slb->vsid & SLB_VSID_LLP_MASK) == SLB_VSID_64K) { + epnshift = TARGET_PAGE_BITS_64K; + } else { + epnshift = TARGET_PAGE_BITS_16M; + } + return epnshift; +} + static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, ppc_slb_t *slb, target_ulong eaddr, ppc_hash_pte64_t *pte) @@ -396,12 +414,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, hwaddr hash; uint64_t vsid, epnshift, epnmask, epn, ptem; - /* Page size according to the SLB, which we use to generate the - * EPN for hash table lookup.. When we implement more recent MMU - * extensions this might be different from the actual page size - * encoded in the PTE */ - epnshift = (slb->vsid & SLB_VSID_L) - ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; + epnshift = ppc_hash64_page_shift(slb); epnmask = ~((1ULL << epnshift) - 1); if (slb->vsid & SLB_VSID_B) { @@ -448,12 +461,14 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env, static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte, target_ulong eaddr) { + hwaddr mask; + int target_page_bits; hwaddr rpn = pte.pte1 & HPTE64_R_RPN; - /* FIXME: Add support for SLLP extended page sizes */ - int target_page_bits = (slb->vsid & SLB_VSID_L) - ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS; - hwaddr mask = (1ULL << target_page_bits) - 1; - + /* + * We support 4K, 64K and 16M now + */ + target_page_bits = ppc_hash64_page_shift(slb); + mask = (1ULL << target_page_bits) - 1; return (rpn & ~mask) | (eaddr & mask); } @@ -617,7 +632,8 @@ void ppc_hash64_store_hpte(CPUPPCState *env, CPUState *cs = CPU(ppc_env_get_cpu(env)); if (kvmppc_kern_htab) { - return kvmppc_hash64_write_pte(env, pte_index, pte0, pte1); + kvmppc_hash64_write_pte(env, pte_index, pte0, pte1); + return; } pte_index *= HASH_PTE_SIZE_64; diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h index 49e385d..291750f 100644 --- a/target-ppc/mmu-hash64.h +++ b/target-ppc/mmu-hash64.h @@ -37,6 +37,9 @@ void ppc_hash64_store_hpte(CPUPPCState *env, target_ulong index, #define SLB_VSID_C 0x0000000000000080ULL /* class */ #define SLB_VSID_LP 0x0000000000000030ULL #define SLB_VSID_ATTR 0x0000000000000FFFULL +#define SLB_VSID_LLP_MASK (SLB_VSID_L | SLB_VSID_LP) +#define SLB_VSID_4K 0x0000000000000000ULL +#define SLB_VSID_64K 0x0000000000000110ULL /* * Hash page table definitions diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 660be7f..527c6ad 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -2036,31 +2036,26 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr) /* Special registers manipulation */ void ppc_store_sdr1(CPUPPCState *env, target_ulong value) { - PowerPCCPU *cpu = ppc_env_get_cpu(env); - qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value); assert(!env->external_htab); - if (env->spr[SPR_SDR1] != value) { - env->spr[SPR_SDR1] = value; + env->spr[SPR_SDR1] = value; #if defined(TARGET_PPC64) - if (env->mmu_model & POWERPC_MMU_64) { - target_ulong htabsize = value & SDR_64_HTABSIZE; + if (env->mmu_model & POWERPC_MMU_64) { + target_ulong htabsize = value & SDR_64_HTABSIZE; - if (htabsize > 28) { - fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx - " stored in SDR1\n", htabsize); - htabsize = 28; - } - env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1; - env->htab_base = value & SDR_64_HTABORG; - } else -#endif /* defined(TARGET_PPC64) */ - { - /* FIXME: Should check for valid HTABMASK values */ - env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF; - env->htab_base = value & SDR_32_HTABORG; + if (htabsize > 28) { + fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx + " stored in SDR1\n", htabsize); + htabsize = 28; } - tlb_flush(CPU(cpu), 1); + env->htab_mask = (1ULL << (htabsize + 18 - 7)) - 1; + env->htab_base = value & SDR_64_HTABORG; + } else +#endif /* defined(TARGET_PPC64) */ + { + /* FIXME: Should check for valid HTABMASK values */ + env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF; + env->htab_base = value & SDR_32_HTABORG; } } diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 88c18e3..2a78e99 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11214,8 +11214,9 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int i; cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR " - TARGET_FMT_lx " XER " TARGET_FMT_lx "\n", - env->nip, env->lr, env->ctr, cpu_read_xer(env)); + TARGET_FMT_lx " XER " TARGET_FMT_lx " CPU#%d\n", + env->nip, env->lr, env->ctr, cpu_read_xer(env), + cs->cpu_index); cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF " TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index df1a62c..d74f4f0 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7819,6 +7819,15 @@ static void gen_spr_power8_ebb(CPUPPCState *env) KVM_REG_PPC_BESCR, 0x00000000); } +/* Virtual Time Base */ +static void gen_spr_vtb(CPUPPCState *env) +{ + spr_register(env, SPR_VTB, "VTB", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_tbl, SPR_NOACCESS, + 0x00000000); +} + static void gen_spr_power8_fscr(CPUPPCState *env) { #if defined(CONFIG_USER_ONLY) @@ -7881,6 +7890,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version) gen_spr_power8_pmu_sup(env); gen_spr_power8_pmu_user(env); gen_spr_power8_tm(env); + gen_spr_vtb(env); } if (version < BOOK3S_CPU_POWER8) { gen_spr_book3s_dbg(env); diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index d7c57d9..508cc0a 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -211,7 +211,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu) * Before this ioctl cpu_synchronize_state() is called in common kvm * code (kvm-all) */ if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) { - error_report("Initial CPU reset failed on CPU %i\n", cs->cpu_index); + error_report("Initial CPU reset failed on CPU %i", cs->cpu_index); } } diff --git a/tests/.gitignore b/tests/.gitignore index e2e4957..0dcb618 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -5,6 +5,7 @@ check-qjson check-qlist check-qstring check-qom-interface +rcutorture test-aio test-bitops test-coroutine @@ -26,6 +27,7 @@ test-qmp-input-strict test-qmp-input-visitor test-qmp-marshal.c test-qmp-output-visitor +test-rcu-list test-rfifolock test-string-input-visitor test-string-output-visitor @@ -33,6 +35,7 @@ test-thread-pool test-throttle test-visitor-serialization test-vmstate +test-write-threshold test-x86-cpuid test-xbzrle *-test diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT Binary files differindex 010d746..1693c37 100644 --- a/tests/acpi-test-data/pc/DSDT +++ b/tests/acpi-test-data/pc/DSDT diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT Binary files differindex 558e4c8..87c3e9f 100644 --- a/tests/acpi-test-data/pc/SSDT +++ b/tests/acpi-test-data/pc/SSDT diff --git a/tests/acpi-test-data/pc/SSDT.bridge b/tests/acpi-test-data/pc/SSDT.bridge Binary files differnew file mode 100644 index 0000000..325899a --- /dev/null +++ b/tests/acpi-test-data/pc/SSDT.bridge diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT Binary files differindex 8ac32ef..e9ac11c 100644 --- a/tests/acpi-test-data/q35/DSDT +++ b/tests/acpi-test-data/q35/DSDT diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT Binary files differindex 2cb3e08..6a5c042 100644 --- a/tests/acpi-test-data/q35/SSDT +++ b/tests/acpi-test-data/q35/SSDT diff --git a/tests/acpi-test-data/q35/SSDT.bridge b/tests/acpi-test-data/q35/SSDT.bridge Binary files differnew file mode 100644 index 0000000..5fc83a0 --- /dev/null +++ b/tests/acpi-test-data/q35/SSDT.bridge diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 4d0fa84..735ac61 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -40,6 +40,7 @@ typedef struct { typedef struct { const char *machine; + const char *variant; uint32_t rsdp_addr; AcpiRsdpDescriptor rsdp_table; AcpiRsdtDescriptorRev1 rsdt_table; @@ -396,13 +397,14 @@ static void dump_aml_files(test_data *data, bool rebuild) int i; for (i = 0; i < data->tables->len; ++i) { + const char *ext = data->variant ? data->variant : ""; sdt = &g_array_index(data->tables, AcpiSdtTable, i); g_assert(sdt->aml); if (rebuild) { uint32_t signature = cpu_to_le32(sdt->header.signature); - aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine, - (gchar *)&signature); + aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, + (gchar *)&signature, ext); fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); } else { @@ -509,7 +511,7 @@ static GArray *load_expected_aml(test_data *data) { int i; AcpiSdtTable *sdt; - gchar *aml_file; + gchar *aml_file = NULL; GError *error = NULL; gboolean ret; @@ -517,6 +519,7 @@ static GArray *load_expected_aml(test_data *data) for (i = 0; i < data->tables->len; ++i) { AcpiSdtTable exp_sdt; uint32_t signature; + const char *ext = data->variant ? data->variant : ""; sdt = &g_array_index(data->tables, AcpiSdtTable, i); @@ -524,8 +527,15 @@ static GArray *load_expected_aml(test_data *data) exp_sdt.header.signature = sdt->header.signature; signature = cpu_to_le32(sdt->header.signature); - aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine, - (gchar *)&signature); + +try_again: + aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, + (gchar *)&signature, ext); + if (data->variant && !g_file_test(aml_file, G_FILE_TEST_EXISTS)) { + g_free(aml_file); + ext = ""; + goto try_again; + } exp_sdt.aml_file = aml_file; g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS)); ret = g_file_get_contents(aml_file, &exp_sdt.aml, @@ -778,6 +788,17 @@ static void test_acpi_piix4_tcg(void) free_test_data(&data); } +static void test_acpi_piix4_tcg_bridge(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = MACHINE_PC; + data.variant = ".bridge"; + test_acpi_one("-machine accel=tcg -device pci-bridge,chassis_nr=1", &data); + free_test_data(&data); +} + static void test_acpi_q35_tcg(void) { test_data data; @@ -788,6 +809,18 @@ static void test_acpi_q35_tcg(void) free_test_data(&data); } +static void test_acpi_q35_tcg_bridge(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = MACHINE_Q35; + data.variant = ".bridge"; + test_acpi_one("-machine q35,accel=tcg -device pci-bridge,chassis_nr=1", + &data); + free_test_data(&data); +} + int main(int argc, char *argv[]) { const char *arch = qtest_get_arch(); @@ -805,7 +838,9 @@ int main(int argc, char *argv[]) if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { qtest_add_func("acpi/piix4/tcg", test_acpi_piix4_tcg); + qtest_add_func("acpi/piix4/tcg/bridge", test_acpi_piix4_tcg_bridge); qtest_add_func("acpi/q35/tcg", test_acpi_q35_tcg); + qtest_add_func("acpi/q35/tcg/bridge", test_acpi_q35_tcg_bridge); } ret = g_test_run(); unlink(disk); diff --git a/tests/qemu-iotests/.gitignore b/tests/qemu-iotests/.gitignore index 0541f80..0711cbd 100644 --- a/tests/qemu-iotests/.gitignore +++ b/tests/qemu-iotests/.gitignore @@ -1,5 +1,6 @@ check.log check.time +common.env *.out.bad *.notrun socket_scm_helper @@ -134,7 +134,7 @@ static int configure_tpm(QemuOpts *opts) Error *local_err = NULL; if (!QLIST_EMPTY(&tpm_backends)) { - error_report("Only one TPM is allowed.\n"); + error_report("Only one TPM is allowed."); return 1; } diff --git a/trace/control.c b/trace/control.c index 0d30801..995beb3 100644 --- a/trace/control.c +++ b/trace/control.c @@ -126,7 +126,7 @@ static void trace_init_events(const char *fname) error_report("WARNING: trace event '%s' does not exist", line_ptr); } else if (!trace_event_get_state_static(ev)) { - error_report("WARNING: trace event '%s' is not traceable\n", + error_report("WARNING: trace event '%s' is not traceable", line_ptr); } else { trace_event_set_state_dynamic(ev, enable); diff --git a/ui/console.c b/ui/console.c index 87574a7..87af6b5 100644 --- a/ui/console.c +++ b/ui/console.c @@ -2005,18 +2005,6 @@ DisplaySurface *qemu_console_surface(QemuConsole *console) return console->surface; } -DisplayState *qemu_console_displaystate(QemuConsole *console) -{ - return console->ds; -} - -PixelFormat qemu_different_endianness_pixelformat(int bpp) -{ - pixman_format_code_t fmt = qemu_default_pixman_format(bpp, false); - PixelFormat pf = qemu_pixelformat_from_pixman(fmt); - return pf; -} - PixelFormat qemu_default_pixelformat(int bpp) { pixman_format_code_t fmt = qemu_default_pixman_format(bpp, true); @@ -121,15 +121,6 @@ static void cookey(register unsigned long *raw1) return; } -void cpkey(register unsigned long *into) -{ - register unsigned long *from, *endp; - - from = KnL, endp = &KnL[32]; - while( from < endp ) *into++ = *from++; - return; - } - void usekey(register unsigned long *from) { register unsigned long *to, *endp; @@ -36,12 +36,6 @@ void usekey(unsigned long *); * Loads the internal key register with the data in cookedkey. */ -void cpkey(unsigned long *); -/* cookedkey[32] - * Copies the contents of the internal key register into the storage - * located at &cookedkey[0]. - */ - void des(unsigned char *, unsigned char *); /* from[8] to[8] * Encrypts/Decrypts (according to the key currently loaded in the diff --git a/ui/input-legacy.c b/ui/input-legacy.c index a698a34..2d4ca19 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -143,12 +143,6 @@ QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) return entry; } -void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry) -{ - qemu_input_handler_unregister(entry->s); - g_free(entry); -} - static void legacy_mouse_event(DeviceState *dev, QemuConsole *src, InputEvent *evt) { diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index 68f3d77..c8ee203 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -342,16 +342,3 @@ void vnc_start_worker_thread(void) QEMU_THREAD_DETACHED); queue = q; /* Set global queue */ } - -void vnc_stop_worker_thread(void) -{ - if (!vnc_worker_thread_running()) - return ; - - /* Remove all jobs and wake up the thread */ - vnc_lock_queue(queue); - queue->exit = true; - vnc_unlock_queue(queue); - vnc_jobs_clear(NULL); - qemu_cond_broadcast(&queue->cond); -} diff --git a/ui/vnc-jobs.h b/ui/vnc-jobs.h index 31da103..044bf9f 100644 --- a/ui/vnc-jobs.h +++ b/ui/vnc-jobs.h @@ -40,7 +40,6 @@ void vnc_jobs_join(VncState *vs); void vnc_jobs_consume_buffer(VncState *vs); void vnc_start_worker_thread(void); -void vnc_stop_worker_thread(void); /* Locks */ static inline int vnc_trylock_display(VncDisplay *vd) diff --git a/ui/vnc_keysym.h b/ui/vnc_keysym.h index 1dc039f..7fa2bc1 100644 --- a/ui/vnc_keysym.h +++ b/ui/vnc_keysym.h @@ -404,6 +404,7 @@ static const name2keysym_t name2keysym[]={ {"breve", 0x01a2}, /* U+02D8 BREVE */ {"caron", 0x01b7}, /* U+02C7 CARON */ {"Ccaron", 0x01c8}, /* U+010C LATIN CAPITAL LETTER C WITH CARON */ +{"numerosign", 0x06b0}, /* U+2116 NUMERO SIGN */ {"Cyrillic_a", 0x06c1}, /* U+0430 CYRILLIC SMALL LETTER A */ {"Cyrillic_A", 0x06e1}, /* U+0410 CYRILLIC CAPITAL LETTER A */ {"Cyrillic_be", 0x06c2}, /* U+0431 CYRILLIC SMALL LETTER BE */ diff --git a/util/cutils.c b/util/cutils.c index c2250d1..144b25c 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -537,16 +537,17 @@ int parse_debug_env(const char *name, int max, int initial) { char *debug_env = getenv(name); char *inv = NULL; - int debug; + long debug; if (!debug_env) { return initial; } + errno = 0; debug = strtol(debug_env, &inv, 10); if (inv == debug_env) { return initial; } - if (debug < 0 || debug > max) { + if (debug < 0 || debug > max || errno != 0) { fprintf(stderr, "warning: %s not in [0, %d]", name, max); return initial; } diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 16fcec2..37ffd96 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -399,10 +399,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory) } else { int i; size_t hpagesize = fd_getpagesize(fd); + size_t numpages = DIV_ROUND_UP(memory, hpagesize); /* MAP_POPULATE silently ignores failures */ - memory = (memory + hpagesize - 1) & -hpagesize; - for (i = 0; i < (memory / hpagesize); i++) { + for (i = 0; i < numpages; i++) { memset(area + (hpagesize * i), 0, 1); } @@ -2694,29 +2694,27 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size) uint64_t slots; sz = qemu_opt_get_size(opts, "maxmem", 0); + slots = qemu_opt_get_number(opts, "slots", 0); if (sz < ram_size) { - error_report("invalid -m option value: maxmem " - "(0x%" PRIx64 ") <= initial memory (0x" - RAM_ADDR_FMT ")", sz, ram_size); + error_report("invalid value of -m option maxmem: " + "maximum memory size (0x%" PRIx64 ") must be at least " + "the initial memory size (0x" RAM_ADDR_FMT ")", + sz, ram_size); exit(EXIT_FAILURE); - } - - slots = qemu_opt_get_number(opts, "slots", 0); - if ((sz > ram_size) && !slots) { - error_report("invalid -m option value: maxmem " - "(0x%" PRIx64 ") more than initial memory (0x" - RAM_ADDR_FMT ") but no hotplug slots where " - "specified", sz, ram_size); + } else if (sz > ram_size) { + if (!slots) { + error_report("invalid value of -m option: maxmem was " + "specified, but no hotplug slots were specified"); + exit(EXIT_FAILURE); + } + } else if (slots) { + error_report("invalid value of -m option maxmem: " + "memory slots were specified but maximum memory size " + "(0x%" PRIx64 ") is equal to the initial memory size " + "(0x" RAM_ADDR_FMT ")", sz, ram_size); exit(EXIT_FAILURE); } - if ((sz <= ram_size) && slots) { - error_report("invalid -m option value: %" - PRIu64 " hotplug slots where specified but " - "maxmem (0x%" PRIx64 ") <= initial memory (0x" - RAM_ADDR_FMT ")", slots, sz, ram_size); - exit(EXIT_FAILURE); - } *maxram_size = sz; *ram_slots = slots; } else if ((!maxmem_str && slots_str) || diff --git a/xen-hvm-stub.c b/xen-hvm-stub.c index 2d98696..46867d8 100644 --- a/xen-hvm-stub.c +++ b/xen-hvm-stub.c @@ -30,10 +30,6 @@ void xen_hvm_inject_msi(uint64_t addr, uint32_t data) { } -void xen_cmos_set_s3_resume(void *opaque, int irq, int level) -{ -} - void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr) { } |