diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 0b8ce4bbf8..6a74e00399 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/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 6add04a2f6..46b87ddb43 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 833d8748d5..68b94967c5 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/exec.c b/exec.c index c85321a38b..6a5adab502 100644 --- a/exec.c +++ b/exec.c @@ -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; } diff --git a/hmp-commands.hx b/hmp-commands.hx index 81f276b209..d5022d843c 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1147,38 +1147,6 @@ STEXI @item drive_add @findex drive_add 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|[[:]:] 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 = "[[:]:]", - .help = "hot remove PCI device", - .mhandler.cmd = hmp_pci_del, - }, -#endif - -STEXI -@item pci_del -@findex pci_del -Hot remove PCI device. ETEXI { diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 2572747629..30492ecb02 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.h b/hw/9pfs/virtio-9p.h index 2c3603aed0..58dafa9e14 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -7,16 +7,14 @@ #include #include #include +#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 ee82073338..b9fefa7635 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 0000000000..876cada4b2 --- /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 + * Author: Igor Mammedov + * + * 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 . + */ + +#include +#include +#include +#include +#include +#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 5cc4d90c16..d9382f826a 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 884dab3d45..5352e197cb 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 ed3924126f..c6580dabb7 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 34dedf1e8b..612fec03ee 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 184e7e49b9..d1f11793a0 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/audio/ac97.c b/hw/audio/ac97.c index 111ec0e848..b17383555e 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 e67d1ea165..8e7bcf503e 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 2885231a6d..433463e9c5 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/virtio-blk.c b/hw/block/virtio-blk.c index cb71772f95..1e5b918620 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 f05c9b4d86..467c3b4f9a 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/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 47fbb34bdd..9a029d2130 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 2e47f70eb4..5a4e4d5ec8 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -990,8 +990,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; @@ -1004,25 +1004,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 a02a4cb2ab..6be58669f7 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/display/cirrus_vga.c b/hw/display/cirrus_vga.c index ec923c8c4b..8765a7e1d0 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 762f75dc2d..b6d65b9487 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 53739e4f79..d67f748af4 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -189,7 +189,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 +232,9 @@ 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 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; @@ -268,7 +266,6 @@ 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_reset(DeviceState *dev) @@ -298,7 +295,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 +311,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; diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index 1751f19793..c17ddd1fcd 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/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 0803dc4d18..91d4d322ca 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 2b678ef2a6..e058a39147 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 4944249b84..d0a5c85e10 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) +static void build_append_pcihp_notify_entry(Aml *method, int slot) { - state->parent = parent; - state->device_table = build_alloc_array(); - state->notify_table = build_alloc_array(); - state->pcihp_bridge_en = pcihp_bridge_en; + Aml *if_ctx; + int32_t devfn = PCI_DEVFN(slot, 0); + + 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_state_cleanup(AcpiBuildPciBusHotplugState *state) +static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, + bool pcihp_bridge_en) { - 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); - - return child; -} - -static void build_pci_bus_end(PCIBus *bus, void *bus_state) -{ - 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); - /* 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); + 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)); + + 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); + method = aml_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); - - /* 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); -} + /* 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; -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); - - 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); - ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), - ssdt_mctrl_nr_slots[0], 32, nr_mem); + 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); + } + + if (misc->pvpanic_port) { + scope = aml_scope("\\_SB.PCI0.ISA"); + + 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)); + + 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"); { - GArray *sb_scope = build_alloc_array(); - uint8_t op = 0x10; /* ScopeOp */ - - build_append_nameseg(sb_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); + 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, ... })" */ - build_append_byte(sb_scope, 0x08); /* NameOp */ - build_append_nameseg(sb_scope, "CPON"); + /* 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); - { - GArray *package = build_alloc_array(); - uint8_t op; + 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)); - /* - * 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 */ - } + /* 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)) + ); - for (i = 0; i < acpi_cpus; i++) { - uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00; - build_append_byte(package, b); - } + 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)); - build_package(package, op, 2); - build_append_array(sb_scope, package); - build_free_array(package); + 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); } - 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); - } - - /* 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); + acpi_ram_update(build_state->table_ram, tables.table_data); - /* 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); - - 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 268d870990..1aff74627f 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 deb37de92e..89caa1649d 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 2a36c4799e..1e9ec39274 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 4648e90366..0000000000 --- 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 . - */ - -/* 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 a611e07ec8..a2d84ecf8f 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 498b194a0c..ecaa4a5480 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 bd92c69916..9db7c77605 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 b229856a26..79eaad5fec 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 de75cf0e87..8eab4ba94d 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 63027ee76b..c0f21fe725 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 e1cee5d89a..16eaca3fae 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 0d5b133150..ed9a2cc8e0 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 22ff5ddfc3..0000000000 --- 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 - */ - -/* 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 b3bfbbda09..0000000000 --- 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 1e3baaed3d..0000000000 --- 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 . - */ -#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 cbcf61dcce..0000000000 --- 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 ac91c05836..0000000000 --- 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 . - */ - -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 72ffa84800..0000000000 --- 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 8229bfd702..0000000000 --- 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 . - */ - -/* 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 4df0734c79..0000000000 --- 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 4a916a8398..e84dc6cfc0 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 c8b0322155..dafa9ec7c7 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; @@ -374,7 +374,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) @@ -410,7 +409,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 fb1d095503..b1d8874671 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/piix.c b/hw/ide/piix.c index b0172fbf59..ab930843e8 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -148,7 +148,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; @@ -163,8 +163,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) @@ -238,7 +236,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; @@ -258,7 +256,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; @@ -276,7 +274,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 4d8089de75..7a5151c5c1 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -172,7 +172,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; @@ -187,8 +187,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) @@ -215,7 +213,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/ipack/tpci200.c b/hw/ipack/tpci200.c index b7031a0b13..1df02ee859 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 0dc440df5c..9da9dfc4da 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 231de74414..dba758595f 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 a9916df20a..d9522b1f45 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 b223526bde..b8197b115d 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/misc/applesmc.c b/hw/misc/applesmc.c index 6a56b07c6b..6bd61e7828 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/pci-testdev.c b/hw/misc/pci-testdev.c index c78a63e3a7..26b9b86178 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 a207e21bcf..3405cb9ea0 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 7a4f9f8a08..c374c1a251 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 ff7e789563..4baa0169e6 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 4dea70178d..3492db3663 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 5df79f0a1f..8305d1bdf2 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 7778b9ad47..bdfd38f4ca 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 3f12fe3c13..79c4c84f07 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 2d1be06f41..f868108dfe 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/vhost_net.c b/hw/net/vhost_net.c index 4e3a061622..2ea1ef1dd0 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -35,7 +35,7 @@ #include -#include "hw/virtio/virtio_ring.h" +#include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-bus.h" diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 45da34ad61..1187ab813b 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); @@ -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 a83d2a11ff..dfb328debd 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/pci-bridge/dec.c b/hw/pci-bridge/dec.c index a6ca940d55..28d0ff9c84 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 832b6c7248..312fa703c6 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 56292adb03..8bdd56922a 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 6c7cfdbeb2..bfe707a1a1 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 8ea718e18e..723836fb0e 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 574f8b2efb..613ba73c64 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 1de3681db9..6cea6ffebb 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 b20bad8373..df60e61d4f 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 21f805f314..53f2b59ae8 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 71ff0de303..6d23553094 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 80f8aa69ac..9f905e6344 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 501a918b89..0000000000 --- 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 31b222d8c0..cc5d946b8f 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 [[:]:], return -1 on error if funcp == NULL * [[:]:]., 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/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h index ffd0df708b..92aa9d0499 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 + +#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_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 +#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) + +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 75b67eda20..c847853957 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 ea236c9b01..ffbb9c2c89 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/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 4db3b23ea3..cfb52e8fd9 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 10e5355de7..27b914aa94 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/tpm/tpm_int.h b/hw/tpm/tpm_int.h index 2f582caaee..2b35fe21ec 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 2bf3c6fd61..a94c7c5a24 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -112,14 +112,31 @@ 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) { @@ -149,6 +166,11 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, "packet from TPM\n"); } + 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: if (ret < 0) { tpm_write_fatal_error_response(out, out_len); @@ -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: diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index c0e7cd738a..d0bb97f7d9 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 @@ -144,6 +154,24 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string) #endif } +/* + * 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. */ @@ -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); } - if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) { + val >>= shift; + if (size > 4 - (addr & 0x3)) { + /* prevent access beyond FIFO */ + size = 4 - (addr & 0x3); + } + + 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 1a0db23367..db78d51e4f 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 490f2b6af9..4c80707f85 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 828c2a7d78..ba15ae0019 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/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 0936f659e5..5c7b8c20fa 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/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 8a48d2a178..95b0643448 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 dfd2d8c772..be886e75af 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 2450c13747..10123f34b2 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 604cb5b749..e7baf7b5e8 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -17,6 +17,7 @@ #include +#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 d735343ca8..3c6e430048 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 33dd6d43c0..b2d158f7ba 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/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h new file mode 100644 index 0000000000..17d3beb5a3 --- /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 +#include +#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 12d7a7af5f..c2d3dba0c7 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 b9db29576c..efa6ed7b7b 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 9323838319..f3526d4aaf 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 08ab67d7fd..1b35168e96 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 cf7bd343c7..f21ceaafc6 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/pci.h b/include/hw/pci/pci.h index bdee464e61..be2d9b8703 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/qdev-properties.h b/include/hw/qdev-properties.h index 070006c715..57ee363b89 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 b508b87900..815c19b6ef 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 e42c0fc9cc..8d97db9e2d 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 f863bfe27a..4ab8f541b0 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 fc7d311a43..b3ffcd96b8 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 0756545d4d..0d2e7b49b2 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 6ceb5aa92e..4c2fe83b6b 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 14e85a5a3a..7702ff4749 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 c122e7ae5c..de2c739d22 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 11af978a96..ccf8459829 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 f24997d218..d95f8b6d50 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/net/tap.h b/include/net/tap.h index 6daeb42b0f..5da4edc692 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/standard-headers/asm-s390/kvm_virtio.h b/include/standard-headers/asm-s390/kvm_virtio.h new file mode 100644 index 0000000000..daad3249d2 --- /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 + */ + +#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 0000000000..a9a4ebf79f --- /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 + */ +#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 0000000000..91cf735fb5 --- /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 0000000000..0526c2b87c --- /dev/null +++ b/include/standard-headers/linux/types.h @@ -0,0 +1,2 @@ +#include +#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 0000000000..e68f71dbe6 --- /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 0000000000..799376d414 --- /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 0000000000..12016b47f3 --- /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 0000000000..bcc445b3d8 --- /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 0000000000..0dedc9e6f5 --- /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 , 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 0000000000..284fc3a05f --- /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 0000000000..95faf67b48 --- /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 0000000000..ecdc133d59 --- /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 + * + * 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 similarity index 61% rename from include/hw/virtio/virtio_ring.h rename to include/standard-headers/linux/virtio_ring.h index 0b42e6eae5..cc647d61fc 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 0000000000..60fc798bde --- /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 0000000000..78ba9d3635 --- /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 0000000000..fd0d3511ff --- /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 + */ +#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 0c6264391e..7ca59b5070 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 11040b476f..6e8509735a 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 825f33bdc3..540ee25477 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/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h index 75dc20ba6f..5590f7d4a6 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 - -/* 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 1b333e2536..c6f0fb6cd9 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 - -/* 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/net/vhost-user.c b/net/vhost-user.c index 24e050c772..2435b0f826 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); @@ -133,8 +132,7 @@ static void net_vhost_user_event(void *opaque, int event) } 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); } diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index c8e026d37e..f208ec9c51 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/]*\)>/"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 <$output/linux-headers/linux/virtio_config.h +#include "standard-headers/linux/virtio_config.h" +EOF +cat <$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 <$output/include/standard-headers/linux/types.h +#include +#include "qemu/compiler.h" +EOF +cat <$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 5e347d04bd..8beff4c732 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 1d98145802..0000000000 --- a/stubs/pci-drive-hot-add.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include - -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/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT index 010d74603f..1693c3783b 100644 Binary files a/tests/acpi-test-data/pc/DSDT and b/tests/acpi-test-data/pc/DSDT differ diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT index 558e4c85b0..87c3e9fc02 100644 Binary files a/tests/acpi-test-data/pc/SSDT and b/tests/acpi-test-data/pc/SSDT differ diff --git a/tests/acpi-test-data/pc/SSDT.bridge b/tests/acpi-test-data/pc/SSDT.bridge new file mode 100644 index 0000000000..325899a757 Binary files /dev/null and b/tests/acpi-test-data/pc/SSDT.bridge differ diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT index 8ac32efc03..e9ac11c38f 100644 Binary files a/tests/acpi-test-data/q35/DSDT and b/tests/acpi-test-data/q35/DSDT differ diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT index 2cb3e08bd4..6a5c0423b9 100644 Binary files a/tests/acpi-test-data/q35/SSDT and b/tests/acpi-test-data/q35/SSDT differ diff --git a/tests/acpi-test-data/q35/SSDT.bridge b/tests/acpi-test-data/q35/SSDT.bridge new file mode 100644 index 0000000000..5fc83a0340 Binary files /dev/null and b/tests/acpi-test-data/q35/SSDT.bridge differ diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 4d0fa848b1..735ac610be 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/vl.c b/vl.c index 4063c8e8c8..b47e223a49 100644 --- a/vl.c +++ b/vl.c @@ -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); - if (sz < ram_size) { - error_report("invalid -m option value: maxmem " - "(0x%" PRIx64 ") <= initial memory (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); + if (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); + } 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) ||