diff options
63 files changed, 878 insertions, 315 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8d14e0ffca..b3552b2c19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -932,20 +932,19 @@ K: srat|SRAT T: git git://github.com/ehabkost/qemu.git numa QAPI -M: Luiz Capitulino <lcapitulino@redhat.com> +M: Markus Armbruster <armbru@redhat.com> M: Michael Roth <mdroth@linux.vnet.ibm.com> -S: Maintained +S: Supported F: qapi/ F: tests/qapi-schema/ -T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp +T: git git://repo.or.cz/qemu/armbru.git qapi-next QAPI Schema M: Eric Blake <eblake@redhat.com> -M: Luiz Capitulino <lcapitulino@redhat.com> M: Markus Armbruster <armbru@redhat.com> S: Supported F: qapi-schema.json -T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp +T: git git://repo.or.cz/qemu/armbru.git qapi-next QObject M: Luiz Capitulino <lcapitulino@redhat.com> @@ -970,13 +969,14 @@ X: qom/cpu.c F: tests/qom-test.c QMP -M: Luiz Capitulino <lcapitulino@redhat.com> -S: Maintained +M: Markus Armbruster <armbru@redhat.com> +S: Supported F: qmp.c F: monitor.c F: qmp-commands.hx -F: QMP/ -T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp +F: docs/qmp/ +F: scripts/qmp/ +T: git git://repo.or.cz/qemu/armbru.git qapi-next SLIRP M: Jan Kiszka <jan.kiszka@siemens.com> diff --git a/backends/tpm.c b/backends/tpm.c index 4efe36736e..36c5d46f0a 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -165,17 +165,6 @@ void tpm_backend_thread_end(TPMBackendThread *tbt) } } -void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt, - GFunc func, gpointer user_data) -{ - if (!tbt->pool) { - tpm_backend_thread_create(tbt, func, user_data); - } else { - g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_TPM_RESET, - NULL); - } -} - static const TypeInfo tpm_backend_info = { .name = TYPE_TPM_BACKEND, .parent = TYPE_OBJECT, diff --git a/block/qapi.c b/block/qapi.c index 063dd1bc1f..18d2b95f54 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -523,9 +523,6 @@ static void dump_qobject(fprintf_function func_fprintf, void *f, QDECREF(value); break; } - case QTYPE_NONE: - break; - case QTYPE_MAX: default: abort(); } diff --git a/block/sheepdog.c b/block/sheepdog.c index 2d5f06a390..bd7cbed048 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -2341,6 +2341,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) if (ret < 0) { error_report("failed to create inode for snapshot: %s", error_get_pretty(local_err)); + error_free(local_err); goto cleanup; } diff --git a/docs/memory-hotplug.txt b/docs/memory-hotplug.txt index f70571df0c..56bdd0a47b 100644 --- a/docs/memory-hotplug.txt +++ b/docs/memory-hotplug.txt @@ -4,9 +4,7 @@ QEMU memory hotplug This document explains how to use the memory hotplug feature in QEMU, which is present since v2.1.0. -Please, note that memory hotunplug is not supported yet. This means -that you're able to add memory, but you're not able to remove it. -Also, proper guest support is required for memory hotplug to work. +Guest support is required for memory hotplug to work. Basic RAM hotplug ----------------- @@ -74,3 +72,22 @@ comes from regular RAM, 1GB is a 1GB hugepage page and 256MB is from -device pc-dimm,id=dimm1,memdev=mem1 \ -object memory-backend-file,id=mem2,size=256M,mem-path=/mnt/hugepages-2MB \ -device pc-dimm,id=dimm2,memdev=mem2 + + +RAM hot-unplug +--------------- + +In order to be able to hot unplug pc-dimm device, QEMU has to be told the ids +of pc-dimm device and memory backend object. The ids were assigned when you hot +plugged memory. + +Two monitor commands are used to hot unplug memory: + + - "device_del": deletes a front-end pc-dimm device + - "object_del": deletes a memory backend object + +For example, assuming that the pc-dimm device with id "dimm1" exists, and its memory +backend is "mem1", the following commands tries to remove it. + + (qemu) device_del dimm1 + (qemu) object_del mem1 diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt index b19e490eb5..6dc2cca7de 100644 --- a/docs/qmp/qmp-events.txt +++ b/docs/qmp/qmp-events.txt @@ -43,9 +43,10 @@ Data: - "msg": Informative message (e.g., reason for the corruption) (json-string) - "offset": If the corruption resulted from an image access, this - is the access offset into the image (json-int) + is the host's access offset into the image + (json-int, optional) - "size": If the corruption resulted from an image access, this - is the access size (json-int) + is the access size (json-int, optional) Example: @@ -231,6 +232,23 @@ Example: { "event": "GUEST_PANICKED", "data": { "action": "pause" } } +MEM_HOT_UNPLUG_ERROR +-------------------- +Emitted when memory hot unplug error occurs. + +Data: + +- "device": device name (json-string) +- "msg": Informative message (e.g., reason for the error) (json-string) + +Example: + +{ "event": "MEM_HOT_UNPLUG_ERROR" + "data": { "device": "dimm1", + "msg": "acpi: device unplug for unsupported device" + }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + NIC_RX_FILTER_CHANGED --------------------- diff --git a/docs/specs/acpi_mem_hotplug.txt b/docs/specs/acpi_mem_hotplug.txt index 12909940cc..3df3620ce4 100644 --- a/docs/specs/acpi_mem_hotplug.txt +++ b/docs/specs/acpi_mem_hotplug.txt @@ -2,7 +2,7 @@ QEMU<->ACPI BIOS memory hotplug interface -------------------------------------- ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add -events. +and hot-remove events. Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access): --------------------------------------------------------------- @@ -19,7 +19,9 @@ Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access): 1: Device insert event, used to distinguish device for which no device check event to OSPM was issued. It's valid only when bit 1 is set. - 2-7: reserved and should be ignored by OSPM + 2: Device remove event, used to distinguish device for which + no device eject request to OSPM was issued. + 3-7: reserved and should be ignored by OSPM [0x15-0x17] reserved write access: @@ -31,14 +33,62 @@ Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access): [0xc-0x13] reserved, writes into it are ignored [0x14] Memory device control fields bits: - 0: reserved, OSPM must clear it before writing to register + 0: reserved, OSPM must clear it before writing to register. + Due to BUG in versions prior 2.4 that field isn't cleared + when other fields are written. Keep it reserved and don't + try to reuse it. 1: if set to 1 clears device insert event, set by OSPM after it has emitted device check event for the selected memory device - 2-7: reserved, OSPM must clear them before writing to register + 2: if set to 1 clears device remove event, set by OSPM + after it has emitted device eject request for the + selected memory device + 3: if set to 1 initiates device eject, set by OSPM when it + triggers memory device removal and calls _EJ0 method + 4-7: reserved, OSPM must clear them before writing to register Selecting memory device slot beyond present range has no effect on platform: - write accesses to memory hot-plug registers not documented above are ignored - read accesses to memory hot-plug registers not documented above return all bits set to 1. + +Memory hot remove process diagram: +---------------------------------- + +-------------+ +-----------------------+ +------------------+ + | 1. QEMU | | 2. QEMU | |3. QEMU | + | device_del +---->+ device unplug request +----->+Send SCI to guest,| + | | | cb | |return control to | + +-------------+ +-----------------------+ |management | + +------------------+ + + +---------------------------------------------------------------------+ + + +---------------------+ +-------------------------+ + | OSPM: | remove event | OSPM: | + | send Eject Request, | | Scan memory devices | + | clear remove event +<-------------+ for event flags | + | | | | + +---------------------+ +-------------------------+ + | + | + +---------v--------+ +-----------------------+ + | Guest OS: | success | OSPM: | + | process Ejection +----------->+ Execute _EJ0 method, | + | request | | set eject bit in flags| + +------------------+ +-----------------------+ + |failure | + v v + +------------------------+ +-----------------------+ + | OSPM: | | QEMU: | + | set OST event & status | | call device unplug cb | + | fields | | | + +------------------------+ +-----------------------+ + | | + v v + +------------------+ +-------------------+ + |QEMU: | |QEMU: | + |Send OST QMP event| |Send device deleted| + | | |QMP event | + +------------------+ | | + +-------------------+ diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index d7945f6e2d..77ce00b908 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -26,6 +26,7 @@ #include <string.h> #include "hw/acpi/aml-build.h" #include "qemu/bswap.h" +#include "hw/acpi/bios-linker-loader.h" static GArray *build_alloc_array(void) { @@ -635,9 +636,11 @@ Aml *aml_reserved_field(unsigned length) } /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */ -Aml *aml_field(const char *name, AmlFieldFlags flags) +Aml *aml_field(const char *name, AmlAccessType type, AmlUpdateRule rule) { Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE); + uint8_t flags = rule << 5 | type; + build_append_namestring(var->buf, "%s", name); build_append_byte(var->buf, flags); return var; @@ -891,3 +894,60 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, dec, addr_gran, addr_min, addr_max, addr_trans, len, flags); } + +void +build_header(GArray *linker, GArray *table_data, + AcpiTableHeader *h, const char *sig, int len, uint8_t rev) +{ + memcpy(&h->signature, sig, 4); + h->length = cpu_to_le32(len); + h->revision = rev; + memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6); + memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4); + memcpy(h->oem_table_id + 4, sig, 4); + h->oem_revision = cpu_to_le32(1); + memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4); + h->asl_compiler_revision = cpu_to_le32(1); + h->checksum = 0; + /* Checksum to be filled in by Guest linker */ + bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE, + table_data->data, h, len, &h->checksum); +} + +void *acpi_data_push(GArray *table_data, unsigned size) +{ + unsigned off = table_data->len; + g_array_set_size(table_data, off + size); + return table_data->data + off; +} + +unsigned acpi_data_len(GArray *table) +{ +#if GLIB_CHECK_VERSION(2, 22, 0) + assert(g_array_get_element_size(table) == 1); +#endif + return table->len; +} + +void acpi_add_table(GArray *table_offsets, GArray *table_data) +{ + uint32_t offset = cpu_to_le32(table_data->len); + g_array_append_val(table_offsets, offset); +} + +void acpi_build_tables_init(AcpiBuildTables *tables) +{ + tables->rsdp = g_array_new(false, true /* clear */, 1); + tables->table_data = g_array_new(false, true /* clear */, 1); + tables->tcpalog = g_array_new(false, true /* clear */, 1); + tables->linker = bios_linker_loader_init(); +} + +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, true); + g_array_free(tables->table_data, true); + g_array_free(tables->tcpalog, mfre); +} diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 5352e197cb..84e5bb8d39 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -400,15 +400,26 @@ 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))); + if (pm->acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq, + &pm->acpi_memory_hotplug, dev, errp); + } else { + 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))); + if (pm->acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp); + } else { + 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) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index c6580dabb7..34cef1e5c3 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -2,6 +2,7 @@ #include "hw/acpi/pc-hotplug.h" #include "hw/mem/pc-dimm.h" #include "hw/boards.h" +#include "hw/qdev-core.h" #include "trace.h" #include "qapi-event.h" @@ -75,6 +76,7 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr, case 0x14: /* pack and return is_* fields */ val |= mdev->is_enabled ? 1 : 0; val |= mdev->is_inserting ? 2 : 0; + val |= mdev->is_removing ? 4 : 0; trace_mhp_acpi_read_flags(mem_st->selector, val); break; default: @@ -90,6 +92,9 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, MemHotplugState *mem_st = opaque; MemStatus *mdev; ACPIOSTInfo *info; + DeviceState *dev = NULL; + HotplugHandler *hotplug_ctrl = NULL; + Error *local_err = NULL; if (!mem_st->dev_count) { return; @@ -127,13 +132,36 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, qapi_event_send_acpi_device_ost(info, &error_abort); qapi_free_ACPIOSTInfo(info); break; - case 0x14: + case 0x14: /* set is_* fields */ mdev = &mem_st->devs[mem_st->selector]; if (data & 2) { /* clear insert event */ mdev->is_inserting = false; trace_mhp_acpi_clear_insert_evt(mem_st->selector); + } else if (data & 4) { + mdev->is_removing = false; + trace_mhp_acpi_clear_remove_evt(mem_st->selector); + } else if (data & 8) { + if (!mdev->is_enabled) { + trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector); + break; + } + + dev = DEVICE(mdev->dimm); + hotplug_ctrl = qdev_get_hotplug_handler(dev); + /* call pc-dimm unplug cb */ + hotplug_handler_unplug(hotplug_ctrl, dev, &local_err); + if (local_err) { + trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector); + qapi_event_send_mem_unplug_error(dev->id, + error_get_pretty(local_err), + &error_abort); + break; + } + trace_mhp_acpi_pc_dimm_deleted(mem_st->selector); } break; + default: + break; } } @@ -163,29 +191,51 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, memory_region_add_subregion(as, ACPI_MEMORY_HOTPLUG_BASE, &state->io); } -void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, - DeviceState *dev, Error **errp) +/** + * acpi_memory_slot_status: + * @mem_st: memory hotplug state + * @dev: device + * @errp: set in case of an error + * + * Obtain a single memory slot status. + * + * This function will be called by memory unplug request cb and unplug cb. + */ +static MemStatus * +acpi_memory_slot_status(MemHotplugState *mem_st, + DeviceState *dev, Error **errp) { - MemStatus *mdev; Error *local_err = NULL; int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err); if (local_err) { error_propagate(errp, local_err); - return; + return NULL; } if (slot >= mem_st->dev_count) { char *dev_path = object_get_canonical_path(OBJECT(dev)); - error_setg(errp, "acpi_memory_plug_cb: " + error_setg(errp, "acpi_memory_slot_status: " "device [%s] returned invalid memory slot[%d]", dev_path, slot); g_free(dev_path); + return NULL; + } + + return &mem_st->devs[slot]; +} + +void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, + DeviceState *dev, Error **errp) +{ + MemStatus *mdev; + + mdev = acpi_memory_slot_status(mem_st, dev, errp); + if (!mdev) { return; } - mdev = &mem_st->devs[slot]; mdev->dimm = dev; mdev->is_enabled = true; mdev->is_inserting = true; @@ -196,6 +246,38 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, return; } +void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, + MemHotplugState *mem_st, + DeviceState *dev, Error **errp) +{ + MemStatus *mdev; + + mdev = acpi_memory_slot_status(mem_st, dev, errp); + if (!mdev) { + return; + } + + mdev->is_removing = true; + + /* Do ACPI magic */ + ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS; + acpi_update_sci(ar, irq); +} + +void acpi_memory_unplug_cb(MemHotplugState *mem_st, + DeviceState *dev, Error **errp) +{ + MemStatus *mdev; + + mdev = acpi_memory_slot_status(mem_st, dev, errp); + if (!mdev) { + return; + } + + mdev->is_enabled = false; + mdev->dimm = NULL; +} + static const VMStateDescription vmstate_memhp_sts = { .name = "memory hotplug device state", .version_id = 1, diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index d1f11793a0..1b28481bbd 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -361,7 +361,11 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev, { PIIX4PMState *s = PIIX4_PM(hotplug_dev); - if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + if (s->acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, + dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, errp); } else { @@ -373,8 +377,15 @@ 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))); + PIIX4PMState *s = PIIX4_PM(hotplug_dev); + + if (s->acpi_memory_hotplug.is_enabled && + object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + acpi_memory_unplug_cb(&s->acpi_memory_hotplug, dev, errp); + } else { + 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) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6e6a65d49b..b0f0f84564 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -273,7 +273,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, dev->alias_required_for_version = required_for_version; } -static HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) { HotplugHandler *hotplug_ctrl = NULL; diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index a36135705c..73259e729b 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -32,7 +32,7 @@ #include "hw/i386/pc.h" #include "target-i386/cpu.h" #include "hw/timer/hpet.h" -#include "hw/i386/acpi-defs.h" +#include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" #include "hw/nvram/fw_cfg.h" #include "hw/acpi/bios-linker-loader.h" @@ -68,9 +68,6 @@ #define ACPI_BUILD_TABLE_SIZE 0x20000 -/* Reserve RAM space for tables: add another order of magnitude. */ -#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000 - /* #define DEBUG_ACPI_BUILD */ #ifdef DEBUG_ACPI_BUILD #define ACPI_BUILD_DPRINTF(fmt, ...) \ @@ -265,51 +262,8 @@ static void acpi_get_pci_info(PcPciInfo *info) NULL); } -#define ACPI_BUILD_APPNAME "Bochs" -#define ACPI_BUILD_APPNAME6 "BOCHS " -#define ACPI_BUILD_APPNAME4 "BXPC" - -#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" -#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" -#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" - -static void -build_header(GArray *linker, GArray *table_data, - AcpiTableHeader *h, const char *sig, int len, uint8_t rev) -{ - memcpy(&h->signature, sig, 4); - h->length = cpu_to_le32(len); - h->revision = rev; - memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6); - memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4); - memcpy(h->oem_table_id + 4, sig, 4); - h->oem_revision = cpu_to_le32(1); - memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4); - h->asl_compiler_revision = cpu_to_le32(1); - h->checksum = 0; - /* Checksum to be filled in by Guest linker */ - bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE, - table_data->data, h, len, &h->checksum); -} - -/* End here */ #define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */ -static inline void *acpi_data_push(GArray *table_data, unsigned size) -{ - unsigned off = table_data->len; - g_array_set_size(table_data, off + size); - return table_data->data + off; -} - -static unsigned acpi_data_len(GArray *table) -{ -#if GLIB_CHECK_VERSION(2, 22, 0) - assert(g_array_get_element_size(table) == 1); -#endif - return table->len; -} - static void acpi_align_size(GArray *blob, unsigned align) { /* Align size to multiple of given size. This reduces the chance @@ -318,12 +272,6 @@ static void acpi_align_size(GArray *blob, unsigned align) g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); } -static inline void acpi_add_table(GArray *table_offsets, GArray *table_data) -{ - uint32_t offset = cpu_to_le32(table_data->len); - g_array_append_val(table_offsets, offset); -} - /* FACS */ static void build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info) @@ -796,7 +744,7 @@ build_ssdt(GArray *table_data, GArray *linker, aml_append(dev, aml_operation_region("PEOR", aml_system_io, misc->pvpanic_port, 1)); - field = aml_field("PEOR", aml_byte_acc); + field = aml_field("PEOR", aml_byte_acc, aml_preserve); aml_append(field, aml_named_field("PEPT", 8)); aml_append(dev, field); @@ -813,7 +761,7 @@ build_ssdt(GArray *table_data, GArray *linker, aml_append(ssdt, scope); } - sb_scope = aml_scope("_SB"); + sb_scope = aml_scope("\\_SB"); { /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */ dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE)); @@ -833,7 +781,7 @@ build_ssdt(GArray *table_data, GArray *linker, /* 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); + field = aml_field("PRST", aml_byte_acc, aml_preserve); aml_append(field, aml_named_field("PRS", 256)); aml_append(sb_scope, field); @@ -907,7 +855,8 @@ build_ssdt(GArray *table_data, GArray *linker, pm->mem_hp_io_base, pm->mem_hp_io_len) ); - field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc); + field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc, + aml_preserve); aml_append(field, /* read only */ aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32)); aml_append(field, /* read only */ @@ -920,16 +869,24 @@ build_ssdt(GArray *table_data, GArray *linker, aml_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32)); aml_append(scope, field); - field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc); + field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc, + aml_write_as_zeros); 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(field, + /* (read) 1 if has a remove event. (write) 1 to clear event */ + aml_named_field(stringify(MEMORY_SLOT_REMOVE_EVENT), 1)); + aml_append(field, + /* initiates device eject, write only */ + aml_named_field(stringify(MEMORY_SLOT_EJECT), 1)); aml_append(scope, field); - field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc); + field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc, + aml_preserve); aml_append(field, /* DIMM selector, write only */ aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32)); aml_append(field, /* _OST event code, write only */ @@ -970,11 +927,17 @@ build_ssdt(GArray *table_data, GArray *linker, ))); aml_append(dev, method); + method = aml_method("_EJ0", 1); + s = BASEPATH stringify(MEMORY_SLOT_EJECT_METHOD); + aml_append(method, aml_return(aml_call2( + s, aml_name("_UID"), aml_arg(0)))); + aml_append(dev, method); + aml_append(sb_scope, dev); } /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) { - * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... + * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... } */ method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2); for (i = 0; i < nr_mem; i++) { @@ -1294,31 +1257,6 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt) } typedef -struct AcpiBuildTables { - GArray *table_data; - GArray *rsdp; - GArray *tcpalog; - GArray *linker; -} AcpiBuildTables; - -static inline void acpi_build_tables_init(AcpiBuildTables *tables) -{ - tables->rsdp = g_array_new(false, true /* clear */, 1); - tables->table_data = g_array_new(false, true /* clear */, 1); - tables->tcpalog = g_array_new(false, true /* clear */, 1); - tables->linker = bios_linker_loader_init(); -} - -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, true); - g_array_free(tables->table_data, true); - g_array_free(tables->tcpalog, mfre); -} - -typedef struct AcpiBuildState { /* Copy of table in RAM (for patching). */ MemoryRegion *table_mr; diff --git a/hw/i386/acpi-dsdt-mem-hotplug.dsl b/hw/i386/acpi-dsdt-mem-hotplug.dsl index 1e9ec39274..c2bb6a1602 100644 --- a/hw/i386/acpi-dsdt-mem-hotplug.dsl +++ b/hw/i386/acpi-dsdt-mem-hotplug.dsl @@ -29,6 +29,8 @@ 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_REMOVE_EVENT, FieldUnitObj) // (read) 1 if has a remove event. (write) 1 to clear event + External(MEMORY_SLOT_EJECT, FieldUnitObj) // initiates device eject, write only 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 @@ -55,8 +57,10 @@ If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check MEMORY_SLOT_NOTIFY_METHOD(Local0, 1) Store(1, MEMORY_SLOT_INSERT_EVENT) + } Elseif (LEqual(MEMORY_SLOT_REMOVE_EVENT, One)) { // Ejection request + MEMORY_SLOT_NOTIFY_METHOD(Local0, 3) + Store(1, MEMORY_SLOT_REMOVE_EVENT) } - // TODO: handle memory eject request Add(Local0, One, Local0) // goto next DIMM } Release(MEMORY_SLOT_LOCK) @@ -156,5 +160,12 @@ Store(Arg2, MEMORY_SLOT_OST_STATUS) Release(MEMORY_SLOT_LOCK) } + + Method(MEMORY_SLOT_EJECT_METHOD, 2) { + Acquire(MEMORY_SLOT_LOCK, 0xFFFF) + Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM + Store(1, MEMORY_SLOT_EJECT) + Release(MEMORY_SLOT_LOCK) + } } // Device() } // Scope() diff --git a/hw/i386/pc.c b/hw/i386/pc.c index a8e6be14e4..769eb25048 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1677,6 +1677,52 @@ out: error_propagate(errp, local_err); } +static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + HotplugHandlerClass *hhc; + Error *local_err = NULL; + PCMachineState *pcms = PC_MACHINE(hotplug_dev); + + if (!pcms->acpi_dev) { + error_setg(&local_err, + "memory hotplug is not enabled: missing acpi device"); + goto out; + } + + hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); + hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + +out: + error_propagate(errp, local_err); +} + +static void pc_dimm_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(hotplug_dev); + PCDIMMDevice *dimm = PC_DIMM(dev); + PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); + MemoryRegion *mr = ddc->get_memory_region(dimm); + HotplugHandlerClass *hhc; + Error *local_err = NULL; + + hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); + hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + + if (local_err) { + goto out; + } + + memory_region_del_subregion(&pcms->hotplug_memory, mr); + vmstate_unregister_ram(mr, dev); + + object_unparent(OBJECT(dev)); + + out: + error_propagate(errp, local_err); +} + static void pc_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1719,15 +1765,23 @@ 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))); + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + pc_dimm_unplug_request(hotplug_dev, dev, errp); + } else { + 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))); + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + pc_dimm_unplug(hotplug_dev, dev, errp); + } else { + 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, diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 1fe7bfb29a..212e263404 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -310,8 +310,13 @@ static void pc_init_pci(MachineState *machine) pc_init1(machine, 1, 1); } +static void pc_compat_2_3(MachineState *machine) +{ +} + static void pc_compat_2_2(MachineState *machine) { + pc_compat_2_3(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); @@ -413,6 +418,12 @@ static void pc_compat_1_2(MachineState *machine) x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI); } +static void pc_init_pci_2_3(MachineState *machine) +{ + pc_compat_2_3(machine); + pc_init_pci(machine); +} + static void pc_init_pci_2_2(MachineState *machine) { pc_compat_2_2(machine); @@ -512,19 +523,28 @@ static void pc_xen_hvm_init(MachineState *machine) .desc = "Standard PC (i440FX + PIIX, 1996)", \ .hot_add_cpu = pc_hot_add_cpu -#define PC_I440FX_2_3_MACHINE_OPTIONS \ +#define PC_I440FX_2_4_MACHINE_OPTIONS \ PC_I440FX_MACHINE_OPTIONS, \ .default_machine_opts = "firmware=bios-256k.bin", \ .default_display = "std" -static QEMUMachine pc_i440fx_machine_v2_3 = { - PC_I440FX_2_3_MACHINE_OPTIONS, - .name = "pc-i440fx-2.3", + +static QEMUMachine pc_i440fx_machine_v2_4 = { + PC_I440FX_2_4_MACHINE_OPTIONS, + .name = "pc-i440fx-2.4", .alias = "pc", .init = pc_init_pci, .is_default = 1, }; +#define PC_I440FX_2_3_MACHINE_OPTIONS PC_I440FX_2_4_MACHINE_OPTIONS + +static QEMUMachine pc_i440fx_machine_v2_3 = { + PC_I440FX_2_3_MACHINE_OPTIONS, + .name = "pc-i440fx-2.3", + .init = pc_init_pci_2_3, +}; + #define PC_I440FX_2_2_MACHINE_OPTIONS PC_I440FX_2_3_MACHINE_OPTIONS static QEMUMachine pc_i440fx_machine_v2_2 = { @@ -970,6 +990,7 @@ static QEMUMachine xenfv_machine = { static void pc_machine_init(void) { + qemu_register_pc_machine(&pc_i440fx_machine_v2_4); qemu_register_pc_machine(&pc_i440fx_machine_v2_3); qemu_register_pc_machine(&pc_i440fx_machine_v2_2); qemu_register_pc_machine(&pc_i440fx_machine_v2_1); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index dcc17c074b..e67f2dead7 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -289,8 +289,13 @@ static void pc_q35_init(MachineState *machine) } } +static void pc_compat_2_3(MachineState *machine) +{ +} + static void pc_compat_2_2(MachineState *machine) { + pc_compat_2_3(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); @@ -361,6 +366,12 @@ static void pc_compat_1_4(MachineState *machine) x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } +static void pc_q35_init_2_3(MachineState *machine) +{ + pc_compat_2_3(machine); + pc_q35_init(machine); +} + static void pc_q35_init_2_2(MachineState *machine) { pc_compat_2_2(machine); @@ -410,16 +421,24 @@ static void pc_q35_init_1_4(MachineState *machine) .hot_add_cpu = pc_hot_add_cpu, \ .units_per_default_bus = 1 -#define PC_Q35_2_3_MACHINE_OPTIONS \ +#define PC_Q35_2_4_MACHINE_OPTIONS \ PC_Q35_MACHINE_OPTIONS, \ .default_machine_opts = "firmware=bios-256k.bin", \ .default_display = "std" +static QEMUMachine pc_q35_machine_v2_4 = { + PC_Q35_2_4_MACHINE_OPTIONS, + .name = "pc-q35-2.4", + .alias = "q35", + .init = pc_q35_init, +}; + +#define PC_Q35_2_3_MACHINE_OPTIONS PC_Q35_2_4_MACHINE_OPTIONS + static QEMUMachine pc_q35_machine_v2_3 = { PC_Q35_2_3_MACHINE_OPTIONS, .name = "pc-q35-2.3", - .alias = "q35", - .init = pc_q35_init, + .init = pc_q35_init_2_3, }; #define PC_Q35_2_2_MACHINE_OPTIONS PC_Q35_2_3_MACHINE_OPTIONS @@ -506,6 +525,7 @@ static QEMUMachine pc_q35_machine_v1_4 = { static void pc_q35_machine_init(void) { + qemu_register_pc_machine(&pc_q35_machine_v2_4); qemu_register_pc_machine(&pc_q35_machine_v2_3); qemu_register_pc_machine(&pc_q35_machine_v2_2); qemu_register_pc_machine(&pc_q35_machine_v2_1); diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index cf23335ba2..47f8b89d51 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -263,6 +263,13 @@ static void vhost_net_stop_one(struct vhost_net *net, &file); assert(r >= 0); } + } else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) { + for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { + const VhostOps *vhost_ops = net->dev.vhost_ops; + int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER, + NULL); + assert(r >= 0); + } } if (net->nc->info->poll) { net->nc->info->poll(net->nc, true); diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9829ad075b..3af6faf4c8 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -440,6 +440,9 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_queue(n->nic); + /* Firstly sync all virtio-net possible supported features */ + features |= n->host_features; + virtio_add_feature(&features, VIRTIO_NET_F_MAC); if (!peer_has_vnet_hdr(n)) { @@ -1303,7 +1306,7 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue) n->multiqueue = multiqueue; - for (i = 2; i <= n->max_queues * 2 + 1; i++) { + for (i = 2; i < n->max_queues * 2 + 1; i++) { virtio_del_queue(vdev, i); } @@ -1546,7 +1549,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, vdev, idx, mask); } -void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features) +static void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features) { int i, config_size = 0; virtio_add_feature(&host_features, VIRTIO_NET_F_MAC); @@ -1579,6 +1582,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) NetClientState *nc; int i; + virtio_net_set_config_size(n, n->host_features); virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size); n->max_queues = MAX(n->nic_conf.peers.queues, 1); @@ -1715,6 +1719,7 @@ static void virtio_net_instance_init(Object *obj) } static Property virtio_net_properties[] = { + DEFINE_VIRTIO_NET_FEATURES(VirtIONet, host_features), DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf), DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer, TX_TIMER_INTERVAL), diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 031eaabca9..9935f98ae5 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -295,29 +295,37 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries, { int ret; char *name; + uint32_t bar_size = 4096; + uint32_t bar_pba_offset = bar_size / 2; + uint32_t bar_pba_size = (nentries / 8 + 1) * 8; /* * Migration compatibility dictates that this remains a 4k * BAR with the vector table in the lower half and PBA in - * the upper half. Do not use these elsewhere! + * the upper half for nentries which is lower or equal to 128. + * No need to care about using more than 65 entries for legacy + * machine types who has at most 64 queues. */ -#define MSIX_EXCLUSIVE_BAR_SIZE 4096 -#define MSIX_EXCLUSIVE_BAR_TABLE_OFFSET 0 -#define MSIX_EXCLUSIVE_BAR_PBA_OFFSET (MSIX_EXCLUSIVE_BAR_SIZE / 2) -#define MSIX_EXCLUSIVE_CAP_OFFSET 0 + if (nentries * PCI_MSIX_ENTRY_SIZE > bar_pba_offset) { + bar_pba_offset = nentries * PCI_MSIX_ENTRY_SIZE; + } - if (nentries * PCI_MSIX_ENTRY_SIZE > MSIX_EXCLUSIVE_BAR_PBA_OFFSET) { - return -EINVAL; + if (bar_pba_offset + bar_pba_size > 4096) { + bar_size = bar_pba_offset + bar_pba_size; + } + + if (bar_size & (bar_size - 1)) { + bar_size = 1 << qemu_fls(bar_size); } name = g_strdup_printf("%s-msix", dev->name); - memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, MSIX_EXCLUSIVE_BAR_SIZE); + memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, bar_size); g_free(name); ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr, - MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar, - bar_nr, MSIX_EXCLUSIVE_BAR_PBA_OFFSET, - MSIX_EXCLUSIVE_CAP_OFFSET); + 0, &dev->msix_exclusive_bar, + bar_nr, bar_pba_offset, + 0); if (ret) { return ret; } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index f5c7a99717..48f19a306d 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1615,28 +1615,32 @@ static const char * const pci_nic_names[] = { }; /* Initialize a PCI NIC. */ -static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, +PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, const char *default_model, - const char *default_devaddr, - Error **errp) + const char *default_devaddr) { const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; Error *err = NULL; PCIBus *bus; - int devfn; PCIDevice *pci_dev; DeviceState *dev; + int devfn; int i; + if (qemu_show_nic_models(nd->model, pci_nic_models)) { + exit(0); + } + i = qemu_find_nic_model(nd, pci_nic_models, default_model); - if (i < 0) - return NULL; + if (i < 0) { + exit(1); + } bus = pci_get_bus_devfn(&devfn, rootbus, devaddr); if (!bus) { error_report("Invalid PCI device address %s for device %s", devaddr, pci_nic_names[i]); - return NULL; + exit(1); } pci_dev = pci_create(bus, devfn, pci_nic_names[i]); @@ -1645,31 +1649,12 @@ static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, object_property_set_bool(OBJECT(dev), true, "realized", &err); if (err) { - error_propagate(errp, err); + error_report_err(err); object_unparent(OBJECT(dev)); - return NULL; - } - return pci_dev; -} - -PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, - const char *default_model, - const char *default_devaddr) -{ - Error *err = NULL; - PCIDevice *res; - - if (qemu_show_nic_models(nd->model, pci_nic_models)) - exit(0); - - res = pci_nic_init(nd, rootbus, default_model, default_devaddr, &err); - if (!res) { - if (err) { - error_report_err(err); - } exit(1); } - return res; + + return pci_dev; } PCIDevice *pci_vga_init(PCIBus *bus) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 644689a6ae..ac261ef050 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1825,6 +1825,38 @@ static const TypeInfo spapr_machine_info = { #define SPAPR_COMPAT_2_1 \ SPAPR_COMPAT_2_2 +static void spapr_compat_2_3(Object *obj) +{ +} + +static void spapr_compat_2_2(Object *obj) +{ + spapr_compat_2_3(obj); +} + +static void spapr_compat_2_1(Object *obj) +{ + spapr_compat_2_2(obj); +} + +static void spapr_machine_2_3_instance_init(Object *obj) +{ + spapr_compat_2_3(obj); + spapr_machine_initfn(obj); +} + +static void spapr_machine_2_2_instance_init(Object *obj) +{ + spapr_compat_2_2(obj); + spapr_machine_initfn(obj); +} + +static void spapr_machine_2_1_instance_init(Object *obj) +{ + spapr_compat_2_1(obj); + spapr_machine_initfn(obj); +} + static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1843,6 +1875,7 @@ static const TypeInfo spapr_machine_2_1_info = { .name = TYPE_SPAPR_MACHINE "2.1", .parent = TYPE_SPAPR_MACHINE, .class_init = spapr_machine_2_1_class_init, + .instance_init = spapr_machine_2_1_instance_init, }; static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data) @@ -1862,6 +1895,7 @@ static const TypeInfo spapr_machine_2_2_info = { .name = TYPE_SPAPR_MACHINE "2.2", .parent = TYPE_SPAPR_MACHINE, .class_init = spapr_machine_2_2_class_init, + .instance_init = spapr_machine_2_2_instance_init, }; static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data) @@ -1870,14 +1904,29 @@ static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data) mc->name = "pseries-2.3"; mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3"; - mc->alias = "pseries"; - mc->is_default = 1; } static const TypeInfo spapr_machine_2_3_info = { .name = TYPE_SPAPR_MACHINE "2.3", .parent = TYPE_SPAPR_MACHINE, .class_init = spapr_machine_2_3_class_init, + .instance_init = spapr_machine_2_3_instance_init, +}; + +static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->name = "pseries-2.4"; + mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4"; + mc->alias = "pseries"; + mc->is_default = 1; +} + +static const TypeInfo spapr_machine_2_4_info = { + .name = TYPE_SPAPR_MACHINE "2.4", + .parent = TYPE_SPAPR_MACHINE, + .class_init = spapr_machine_2_4_class_init, }; static void spapr_machine_register_types(void) @@ -1886,6 +1935,7 @@ static void spapr_machine_register_types(void) type_register_static(&spapr_machine_2_1_info); type_register_static(&spapr_machine_2_2_info); type_register_static(&spapr_machine_2_3_info); + type_register_static(&spapr_machine_2_4_info); } type_init(spapr_machine_register_types) diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 4f69cbbb70..0e35ac970a 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -155,7 +155,6 @@ static void s390_virtio_net_realize(VirtIOS390Device *s390_dev, Error **errp) DeviceState *vdev = DEVICE(&dev->vdev); Error *err = NULL; - virtio_net_set_config_size(&dev->vdev, s390_dev->host_features); virtio_net_set_netclient_name(&dev->vdev, qdev->id, object_get_typename(OBJECT(qdev))); qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); @@ -537,18 +536,12 @@ static unsigned virtio_s390_get_features(DeviceState *d) /**************** S390 Virtio Bus Device Descriptions *******************/ -static Property s390_virtio_net_properties[] = { - DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features), - DEFINE_PROP_END_OF_LIST(), -}; - static void s390_virtio_net_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); k->realize = s390_virtio_net_realize; - dc->props = s390_virtio_net_properties; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); } @@ -657,18 +650,12 @@ static const TypeInfo virtio_s390_device_info = { .abstract = true, }; -static Property s390_virtio_scsi_properties[] = { - DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features), - DEFINE_PROP_END_OF_LIST(), -}; - static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); k->realize = s390_virtio_scsi_realize; - dc->props = s390_virtio_scsi_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 430cc6f017..c96101aa7c 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -281,7 +281,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align, virtio_queue_set_addr(vdev, index, addr); if (!addr) { - virtio_queue_set_vector(vdev, index, 0); + virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR); } else { /* Fail if we don't have a big enough queue. */ /* TODO: Add interface to handle vring.num changing */ @@ -805,7 +805,6 @@ static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp) DeviceState *vdev = DEVICE(&dev->vdev); Error *err = NULL; - virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]); virtio_net_set_netclient_name(&dev->vdev, qdev->id, object_get_typename(OBJECT(qdev))); qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); @@ -1441,7 +1440,6 @@ static void virtio_ccw_device_unplugged(DeviceState *d) static Property virtio_ccw_net_properties[] = { DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), - DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_END_OF_LIST(), @@ -1550,7 +1548,6 @@ static const TypeInfo virtio_ccw_balloon = { static Property virtio_ccw_scsi_properties[] = { DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id), - DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index c9bea067e1..e242fefa84 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -631,6 +631,10 @@ static void virtio_scsi_set_config(VirtIODevice *vdev, static uint32_t virtio_scsi_get_features(VirtIODevice *vdev, uint32_t requested_features) { + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + + /* Firstly sync all virtio-scsi possible supported features */ + requested_features |= s->host_features; return requested_features; } @@ -945,6 +949,7 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp) static Property virtio_scsi_properties[] = { DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, parent_obj.conf), + DEFINE_VIRTIO_SCSI_FEATURES(VirtIOSCSI, host_features), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 927dc3652f..90a5fbff29 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2203,7 +2203,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, if (epid == 1) { if (xhci_fire_ctl_transfer(xhci, xfer) >= 0) { epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; - ep = xfer->packet.ep; } else { DPRINTF("xhci: error firing CTL transfer\n"); } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index c7c3f7249b..867c9d17ca 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -630,28 +630,30 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, { VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - int ret, queue_no; + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); + int ret, index, unmasked = 0; - for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { - if (!virtio_queue_get_num(vdev, queue_no)) { + while (vq) { + index = virtio_get_queue_index(vq); + if (!virtio_queue_get_num(vdev, index)) { break; } - if (virtio_queue_vector(vdev, queue_no) != vector) { - continue; - } - ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg); + ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); if (ret < 0) { goto undo; } + vq = virtio_vector_next_queue(vq); + ++unmasked; } + return 0; undo: - while (--queue_no >= 0) { - if (virtio_queue_vector(vdev, queue_no) != vector) { - continue; - } - virtio_pci_vq_vector_mask(proxy, queue_no, vector); + vq = virtio_vector_first_queue(vdev, vector); + while (vq && --unmasked >= 0) { + index = virtio_get_queue_index(vq); + virtio_pci_vq_vector_mask(proxy, index, vector); + vq = virtio_vector_next_queue(vq); } return ret; } @@ -660,16 +662,16 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) { VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - int queue_no; + VirtQueue *vq = virtio_vector_first_queue(vdev, vector); + int index; - for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { - if (!virtio_queue_get_num(vdev, queue_no)) { + while (vq) { + index = virtio_get_queue_index(vq); + if (!virtio_queue_get_num(vdev, index)) { break; } - if (virtio_queue_vector(vdev, queue_no) != vector) { - continue; - } - virtio_pci_vq_vector_mask(proxy, queue_no, vector); + virtio_pci_vq_vector_mask(proxy, index, vector); + vq = virtio_vector_next_queue(vq); } } @@ -908,6 +910,13 @@ static const TypeInfo virtio_9p_pci_info = { * virtio-pci: This is the PCIDevice which has a virtio-pci-bus. */ +static int virtio_pci_query_nvectors(DeviceState *d) +{ + VirtIOPCIProxy *proxy = VIRTIO_PCI(d); + + return proxy->nvectors; +} + /* This is called by virtio-bus just after the device is plugged. */ static void virtio_pci_device_plugged(DeviceState *d) { @@ -1078,7 +1087,6 @@ static Property virtio_scsi_pci_properties[] = { VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED), - DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), }; @@ -1360,7 +1368,6 @@ static Property virtio_net_properties[] = { DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), - DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features), DEFINE_PROP_END_OF_LIST(), }; @@ -1370,7 +1377,6 @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev); DeviceState *vdev = DEVICE(&dev->vdev); - virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features); virtio_net_set_netclient_name(&dev->vdev, qdev->id, object_get_typename(OBJECT(qdev))); qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); @@ -1498,6 +1504,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data) k->vmstate_change = virtio_pci_vmstate_change; k->device_plugged = virtio_pci_device_plugged; k->device_unplugged = virtio_pci_device_unplugged; + k->query_nvectors = virtio_pci_query_nvectors; } static const TypeInfo virtio_pci_bus_info = { diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 17c1260c0d..6985e76b64 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -89,6 +89,7 @@ struct VirtQueue VirtIODevice *vdev; EventNotifier guest_notifier; EventNotifier host_notifier; + QLIST_ENTRY(VirtQueue) node; }; /* virt queue functions */ @@ -605,7 +606,7 @@ void virtio_reset(void *opaque) vdev->vq[i].vring.used = 0; vdev->vq[i].last_avail_idx = 0; vdev->vq[i].pa = 0; - vdev->vq[i].vector = VIRTIO_NO_VECTOR; + virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR); vdev->vq[i].signalled_used = 0; vdev->vq[i].signalled_used_valid = false; vdev->vq[i].notification = true; @@ -730,6 +731,16 @@ void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) virtqueue_init(&vdev->vq[n]); } +VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector) +{ + return QLIST_FIRST(&vdev->vector_queues[vector]); +} + +VirtQueue *virtio_vector_next_queue(VirtQueue *vq) +{ + return QLIST_NEXT(vq, node); +} + int virtio_queue_get_num(VirtIODevice *vdev, int n) { return vdev->vq[n].vring.num; @@ -780,8 +791,19 @@ uint16_t virtio_queue_vector(VirtIODevice *vdev, int n) void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector) { - if (n < VIRTIO_PCI_QUEUE_MAX) + VirtQueue *vq = &vdev->vq[n]; + + if (n < VIRTIO_PCI_QUEUE_MAX) { + if (vdev->vector_queues && + vdev->vq[n].vector != VIRTIO_NO_VECTOR) { + QLIST_REMOVE(vq, node); + } vdev->vq[n].vector = vector; + if (vdev->vector_queues && + vector != VIRTIO_NO_VECTOR) { + QLIST_INSERT_HEAD(&vdev->vector_queues[vector], vq, node); + } + } } VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, @@ -1088,6 +1110,7 @@ void virtio_cleanup(VirtIODevice *vdev) qemu_del_vm_change_state_handler(vdev->vmstate); g_free(vdev->config); g_free(vdev->vq); + g_free(vdev->vector_queues); } static void virtio_vmstate_change(void *opaque, int running, RunState state) @@ -1125,7 +1148,16 @@ void virtio_instance_init_common(Object *proxy_obj, void *data, void virtio_init(VirtIODevice *vdev, const char *name, uint16_t device_id, size_t config_size) { + BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int i; + int nvectors = k->query_nvectors ? k->query_nvectors(qbus->parent) : 0; + + if (nvectors) { + vdev->vector_queues = + g_malloc0(sizeof(*vdev->vector_queues) * nvectors); + } + vdev->device_id = device_id; vdev->status = 0; vdev->isr = 0; diff --git a/include/glib-compat.h b/include/glib-compat.h index 011352b2b6..28d9f15bd3 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -115,7 +115,7 @@ static inline void g_mutex_init(CompatGMutex *mutex) static inline void g_mutex_clear(CompatGMutex *mutex) { - assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); + g_assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); if (mutex->once.retval) { g_mutex_free((GMutex *) mutex->once.retval); } @@ -155,7 +155,7 @@ static inline void g_cond_init(CompatGCond *cond) static inline void g_cond_clear(CompatGCond *cond) { - assert(cond->once.status != G_ONCE_STATUS_PROGRESS); + g_assert(cond->once.status != G_ONCE_STATUS_PROGRESS); if (cond->once.retval) { g_cond_free((GCond *) cond->once.retval); } @@ -164,7 +164,7 @@ static inline void g_cond_clear(CompatGCond *cond) static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex) { - assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); + g_assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); g_once(&cond->once, do_g_cond_new, NULL); g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval); } diff --git a/hw/i386/acpi-defs.h b/include/hw/acpi/acpi-defs.h index c4468f84e8..c4468f84e8 100644 --- a/hw/i386/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 17d3beb5a3..3947201fd1 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -4,6 +4,18 @@ #include <stdint.h> #include <glib.h> #include "qemu/compiler.h" +#include "hw/acpi/acpi-defs.h" + +/* Reserve RAM space for tables: add another order of magnitude. */ +#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000 + +#define ACPI_BUILD_APPNAME "Bochs" +#define ACPI_BUILD_APPNAME6 "BOCHS " +#define ACPI_BUILD_APPNAME4 "BXPC" + +#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" +#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" +#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" typedef enum { AML_NO_OPCODE = 0,/* has only data */ @@ -35,7 +47,13 @@ typedef enum { aml_dword_acc = 3, aml_qword_acc = 4, aml_buffer_acc = 5, -} AmlFieldFlags; +} AmlAccessType; + +typedef enum { + aml_preserve = 0, + aml_write_as_ones = 1, + aml_write_as_zeros = 2, +} AmlUpdateRule; typedef enum { aml_system_memory = 0x00, @@ -93,6 +111,14 @@ typedef enum { aml_ReadWrite = 1, } AmlReadAndWrite; +typedef +struct AcpiBuildTables { + GArray *table_data; + GArray *rsdp; + GArray *tcpalog; + GArray *linker; +} AcpiBuildTables; + /** * init_aml_allocator: * @@ -120,7 +146,7 @@ void free_aml_allocator(void); * 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 *sb = aml_scope("\\_SB"); * Aml *dev = aml_device("PCI0"); * * aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03"))); @@ -185,7 +211,16 @@ 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_field(const char *name, AmlAccessType type, AmlUpdateRule rule); Aml *aml_varpackage(uint32_t num_elements); +void +build_header(GArray *linker, GArray *table_data, + AcpiTableHeader *h, const char *sig, int len, uint8_t rev); +void *acpi_data_push(GArray *table_data, unsigned size); +unsigned acpi_data_len(GArray *table); +void acpi_add_table(GArray *table_offsets, GArray *table_data); +void acpi_build_tables_init(AcpiBuildTables *tables); +void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre); + #endif diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h index 7bbf8a0064..986223b16c 100644 --- a/include/hw/acpi/memory_hotplug.h +++ b/include/hw/acpi/memory_hotplug.h @@ -7,10 +7,17 @@ #define ACPI_MEMORY_HOTPLUG_STATUS 8 +/** + * MemStatus: + * @is_removing: the memory device in slot has been requested to be ejected. + * + * This structure stores memory device's status. + */ typedef struct MemStatus { DeviceState *dimm; bool is_enabled; bool is_inserting; + bool is_removing; uint32_t ost_event; uint32_t ost_status; } MemStatus; @@ -28,6 +35,11 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, DeviceState *dev, Error **errp); +void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, + MemHotplugState *mem_st, + DeviceState *dev, Error **errp); +void acpi_memory_unplug_cb(MemHotplugState *mem_st, + DeviceState *dev, Error **errp); extern const VMStateDescription vmstate_memory_hotplug; #define VMSTATE_MEMORY_HOTPLUG(memhp, state) \ diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h index efa6ed7b7b..0513c1c158 100644 --- a/include/hw/acpi/pc-hotplug.h +++ b/include/hw/acpi/pc-hotplug.h @@ -43,6 +43,8 @@ #define MEMORY_SLOT_PROXIMITY MPX #define MEMORY_SLOT_ENABLED MES #define MEMORY_SLOT_INSERT_EVENT MINS +#define MEMORY_SLOT_REMOVE_EVENT MRMV +#define MEMORY_SLOT_EJECT MEJ #define MEMORY_SLOT_SLECTOR MSEL #define MEMORY_SLOT_OST_EVENT MOEV #define MEMORY_SLOT_OST_STATUS MOSC @@ -51,6 +53,7 @@ #define MEMORY_SLOT_CRS_METHOD MCRS #define MEMORY_SLOT_OST_METHOD MOST #define MEMORY_SLOT_PROXIMITY_METHOD MPXM +#define MEMORY_SLOT_EJECT_METHOD MEJ0 #define MEMORY_SLOT_NOTIFY_METHOD MTFY #define MEMORY_SLOT_SCAN_METHOD MSCN diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 4e673f9d29..d4be92fbee 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -226,7 +226,7 @@ struct Property { PropertyInfo *info; int offset; uint8_t bitnr; - uint8_t qtype; + qtype_code qtype; int64_t defval; int arrayoffset; PropertyInfo *arrayinfo; @@ -266,6 +266,7 @@ int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT; void qdev_init_nofail(DeviceState *dev); void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev); void qdev_unplug(DeviceState *dev, Error **errp); void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h index 0d2e7b49b2..a4588ca4d9 100644 --- a/include/hw/virtio/virtio-bus.h +++ b/include/hw/virtio/virtio-bus.h @@ -62,6 +62,7 @@ typedef struct VirtioBusClass { * This is called by virtio-bus just before the device is unplugged. */ void (*device_unplugged)(DeviceState *d); + int (*query_nvectors)(DeviceState *d); /* * Does the transport have variable vring alignment? * (ie can it ever call virtio_queue_set_align()?) diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 4c2fe83b6b..e0dbb418ad 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -68,6 +68,7 @@ typedef struct VirtIONet { uint32_t has_vnet_hdr; size_t host_hdr_len; size_t guest_hdr_len; + uint32_t host_features; uint8_t has_ufo; int mergeable_rx_bufs; uint8_t promisc; @@ -137,7 +138,6 @@ typedef struct VirtIONet { DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \ DEFINE_PROP_STRING("tx", _state, _field.tx) -void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features); void virtio_net_set_netclient_name(VirtIONet *n, const char *name, const char *type); diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index f93b57d3e9..b42e7f1379 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -98,6 +98,7 @@ typedef struct VirtIOSCSI { bool dataplane_fenced; Error *blocker; Notifier migration_state_notifier; + uint32_t host_features; } VirtIOSCSI; typedef struct VirtIOSCSIReq { diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index d95f8b6d50..8210cb34f9 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -84,6 +84,7 @@ struct VirtIODevice VMChangeStateEntry *vmstate; char *bus_name; uint8_t device_endian; + QLIST_HEAD(, VirtQueue) *vector_queues; }; typedef struct VirtioDeviceClass { @@ -218,6 +219,8 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, bool set_handler); void virtio_queue_notify_vq(VirtQueue *vq); void virtio_irq(VirtQueue *vq); +VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); +VirtQueue *virtio_vector_next_queue(VirtQueue *vq); static inline void virtio_add_feature(uint32_t *features, unsigned int fbit) { diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index d0bbc7c4a6..84b2d9fef5 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -3,7 +3,7 @@ * * Based on ideas by Avi Kivity <avi@redhat.com> * - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009, 2015 Red Hat Inc. * * Authors: * Luiz Capitulino <lcapitulino@redhat.com> @@ -36,7 +36,8 @@ #include <assert.h> typedef enum { - QTYPE_NONE, + QTYPE_NONE, /* sentinel value, no QObject has this type code */ + QTYPE_QNULL, QTYPE_QINT, QTYPE_QSTRING, QTYPE_QDICT, @@ -110,4 +111,12 @@ static inline qtype_code qobject_type(const QObject *obj) return obj->type->code; } +extern QObject qnull_; + +static inline QObject *qnull(void) +{ + qobject_incref(&qnull_); + return &qnull_; +} + #endif /* QOBJECT_H */ diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h index 7c01a61d5e..2eefea1cc2 100644 --- a/include/sysemu/iothread.h +++ b/include/sysemu/iothread.h @@ -33,7 +33,6 @@ typedef struct { #define IOTHREAD(obj) \ OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD) -IOThread *iothread_find(const char *id); char *iothread_get_id(IOThread *iothread); AioContext *iothread_get_aio_context(IOThread *iothread); diff --git a/include/sysemu/tpm_backend_int.h b/include/sysemu/tpm_backend_int.h index 05d94d0f5b..40f693a0cc 100644 --- a/include/sysemu/tpm_backend_int.h +++ b/include/sysemu/tpm_backend_int.h @@ -32,8 +32,6 @@ void tpm_backend_thread_deliver_request(TPMBackendThread *tbt); void tpm_backend_thread_create(TPMBackendThread *tbt, GFunc func, gpointer user_data); void tpm_backend_thread_end(TPMBackendThread *tbt); -void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt, - GFunc func, gpointer user_data); typedef enum TPMBackendCmd { TPM_BACKEND_CMD_INIT = 1, diff --git a/iothread.c b/iothread.c index a1f91099bc..0416fc4268 100644 --- a/iothread.c +++ b/iothread.c @@ -114,18 +114,6 @@ static void iothread_register_types(void) type_init(iothread_register_types) -IOThread *iothread_find(const char *id) -{ - Object *container = container_get(object_get_root(), IOTHREADS_PATH); - Object *child; - - child = object_property_get_link(container, id, NULL); - if (!child) { - return NULL; - } - return (IOThread *)object_dynamic_cast(child, TYPE_IOTHREAD); -} - char *iothread_get_id(IOThread *iothread) { return object_get_canonical_path_component(OBJECT(iothread)); @@ -4471,11 +4471,12 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str) len = strlen(str); readline_set_completion_index(rs, len); if (nb_args == 2) { - NetClientState *ncs[255]; + NetClientState *ncs[MAX_QUEUE_NUM]; int count, i; count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_OPTIONS_KIND_NONE, 255); - for (i = 0; i < count; i++) { + NET_CLIENT_OPTIONS_KIND_NONE, + MAX_QUEUE_NUM); + for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { const char *name = ncs[i]->name; if (!strncmp(str, name, len)) { readline_add_completion(rs, name); @@ -4490,7 +4491,7 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str) void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str) { int len, count, i; - NetClientState *ncs[255]; + NetClientState *ncs[MAX_QUEUE_NUM]; if (nb_args != 2) { return; @@ -4499,8 +4500,8 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str) len = strlen(str); readline_set_completion_index(rs, len); count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC, - 255); - for (i = 0; i < count; i++) { + MAX_QUEUE_NUM); + for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { QemuOpts *opts; const char *name = ncs[i]->name; if (strncmp(str, name, len)) { @@ -4583,15 +4584,16 @@ void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str) void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) { - NetClientState *ncs[255]; + NetClientState *ncs[MAX_QUEUE_NUM]; int count, i, len; len = strlen(str); readline_set_completion_index(rs, len); if (nb_args == 2) { count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_OPTIONS_KIND_NONE, 255); - for (i = 0; i < count; i++) { + NET_CLIENT_OPTIONS_KIND_NONE, + MAX_QUEUE_NUM); + for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { int id; char name[16]; @@ -4606,8 +4608,9 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str) return; } else if (nb_args == 3) { count = qemu_find_net_clients_except(NULL, ncs, - NET_CLIENT_OPTIONS_KIND_NIC, 255); - for (i = 0; i < count; i++) { + NET_CLIENT_OPTIONS_KIND_NIC, + MAX_QUEUE_NUM); + for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) { int id; const char *name; diff --git a/qapi/block-core.json b/qapi/block-core.json index dcf7c04ffa..863ffea0c7 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1847,7 +1847,7 @@ # not guaranteed to be stable # # @offset: #optional, if the corruption resulted from an image access, this is -# the access offset into the image +# the host's access offset into the image # # @size: #optional, if the corruption resulted from an image access, this is # the access size diff --git a/qapi/event.json b/qapi/event.json index c51dc491e0..378dda572a 100644 --- a/qapi/event.json +++ b/qapi/event.json @@ -330,3 +330,17 @@ ## { 'event': 'VSERPORT_CHANGE', 'data': { 'id': 'str', 'open': 'bool' } } + +## +# @MEM_UNPLUG_ERROR +# +# Emitted when memory hot unplug error occurs. +# +# @device: device name +# +# @msg: Informative message +# +# Since: 2.4 +## +{ 'event': 'MEM_UNPLUG_ERROR', + 'data': { 'device': 'str', 'msg': 'str' } } @@ -24,6 +24,8 @@ struct QJSON { bool omit_comma; }; +#define QJSON(obj) OBJECT_CHECK(QJSON, (obj), TYPE_QJSON) + static void json_emit_element(QJSON *json, const char *name) { /* Check whether we need to print a , before an element */ @@ -87,7 +89,7 @@ const char *qjson_get_str(QJSON *json) QJSON *qjson_new(void) { - QJSON *json = (QJSON *)object_new(TYPE_QJSON); + QJSON *json = QJSON(object_new(TYPE_QJSON)); return json; } @@ -98,8 +100,7 @@ void qjson_finish(QJSON *json) static void qjson_initfn(Object *obj) { - QJSON *json = (QJSON *)object_dynamic_cast(obj, TYPE_QJSON); - assert(json); + QJSON *json = QJSON(obj); json->str = qstring_from_str("{ "); json->omit_comma = true; @@ -107,9 +108,8 @@ static void qjson_initfn(Object *obj) static void qjson_finalizefn(Object *obj) { - QJSON *json = (QJSON *)object_dynamic_cast(obj, TYPE_QJSON); + QJSON *json = QJSON(obj); - assert(json); qobject_decref(QOBJECT(json->str)); } diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs index c9ff59c6cc..f7595f56fe 100644 --- a/qobject/Makefile.objs +++ b/qobject/Makefile.objs @@ -1,3 +1,3 @@ -util-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o +util-obj-y = qnull.o qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o util-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o util-obj-y += qerror.o diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 4288267bd3..717cb8fde7 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -561,6 +561,8 @@ static QObject *parse_keyword(JSONParserContext *ctxt) ret = QOBJECT(qbool_from_int(true)); } else if (token_is_keyword(token, "false")) { ret = QOBJECT(qbool_from_int(false)); + } else if (token_is_keyword(token, "null")) { + ret = qnull(); } else { parse_error(ctxt, token, "invalid keyword `%s'", token_get_value(token)); goto out; diff --git a/qobject/qjson.c b/qobject/qjson.c index 12c576d548..846733dafb 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -127,6 +127,9 @@ static void to_json_list_iter(QObject *obj, void *opaque) static void to_json(const QObject *obj, QString *str, int pretty, int indent) { switch (qobject_type(obj)) { + case QTYPE_QNULL: + qstring_append(str, "null"); + break; case QTYPE_QINT: { QInt *val = qobject_to_qint(obj); char buffer[1024]; @@ -260,9 +263,8 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) } case QTYPE_QERROR: /* XXX: should QError be emitted? */ - case QTYPE_NONE: break; - case QTYPE_MAX: + default: abort(); } } diff --git a/qobject/qnull.c b/qobject/qnull.c new file mode 100644 index 0000000000..9873e266e6 --- /dev/null +++ b/qobject/qnull.c @@ -0,0 +1,29 @@ +/* + * QNull + * + * Copyright (C) 2015 Red Hat, Inc. + * + * Authors: + * Markus Armbruster <armbru@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 + * or later. See the COPYING.LIB file in the top-level directory. + */ + +#include "qemu-common.h" +#include "qapi/qmp/qobject.h" + +static void qnull_destroy_obj(QObject *obj) +{ + assert(0); +} + +static const QType qnull_type = { + .code = QTYPE_QNULL, + .destroy = qnull_destroy_obj, +}; + +QObject qnull_ = { + .type = &qnull_type, + .refcnt = 1, +}; diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index e0e848bc30..65280d29d1 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -32,6 +32,7 @@ import qmp import json +import ast import readline import sys import pprint @@ -51,6 +52,19 @@ class QMPShellError(Exception): class QMPShellBadPort(QMPShellError): pass +class FuzzyJSON(ast.NodeTransformer): + '''This extension of ast.NodeTransformer filters literal "true/false/null" + values in an AST and replaces them by proper "True/False/None" values that + Python can properly evaluate.''' + def visit_Name(self, node): + if node.id == 'true': + node.id = 'True' + if node.id == 'false': + node.id = 'False' + if node.id == 'null': + node.id = 'None' + return node + # TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and # _execute_cmd()). Let's design a better one. class QMPShell(qmp.QEMUMonitorProtocol): @@ -59,6 +73,8 @@ class QMPShell(qmp.QEMUMonitorProtocol): self._greeting = None self._completer = None self._pp = pp + self._transmode = False + self._actions = list() def __get_address(self, arg): """ @@ -88,32 +104,40 @@ class QMPShell(qmp.QEMUMonitorProtocol): # clearing everything as it doesn't seem to matter readline.set_completer_delims('') - def __build_cmd(self, cmdline): - """ - Build a QMP input object from a user provided command-line in the - following format: + def __parse_value(self, val): + try: + return int(val) + except ValueError: + pass - < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] - """ - cmdargs = cmdline.split() - qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } - for arg in cmdargs[1:]: - opt = arg.split('=') + if val.lower() == 'true': + return True + if val.lower() == 'false': + return False + if val.startswith(('{', '[')): + # Try first as pure JSON: try: - if(len(opt) > 2): - opt[1] = '='.join(opt[1:]) - value = int(opt[1]) + return json.loads(val) except ValueError: - if opt[1] == 'true': - value = True - elif opt[1] == 'false': - value = False - elif opt[1].startswith('{'): - value = json.loads(opt[1]) - else: - value = opt[1] - optpath = opt[0].split('.') - parent = qmpcmd['arguments'] + pass + # Try once again as FuzzyJSON: + try: + st = ast.parse(val, mode='eval') + return ast.literal_eval(FuzzyJSON().visit(st)) + except SyntaxError: + pass + except ValueError: + pass + return val + + def __cli_expr(self, tokens, parent): + for arg in tokens: + (key, _, val) = arg.partition('=') + if not val: + raise QMPShellError("Expected a key=value pair, got '%s'" % arg) + + value = self.__parse_value(val) + optpath = key.split('.') curpath = [] for p in optpath[:-1]: curpath.append(p) @@ -126,10 +150,58 @@ class QMPShell(qmp.QEMUMonitorProtocol): if type(parent[optpath[-1]]) is dict: raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath)) else: - raise QMPShellError('Cannot set "%s" multiple times' % opt[0]) + raise QMPShellError('Cannot set "%s" multiple times' % key) parent[optpath[-1]] = value + + def __build_cmd(self, cmdline): + """ + Build a QMP input object from a user provided command-line in the + following format: + + < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] + """ + cmdargs = cmdline.split() + + # Transactional CLI entry/exit: + if cmdargs[0] == 'transaction(': + self._transmode = True + cmdargs.pop(0) + elif cmdargs[0] == ')' and self._transmode: + self._transmode = False + if len(cmdargs) > 1: + raise QMPShellError("Unexpected input after close of Transaction sub-shell") + qmpcmd = { 'execute': 'transaction', + 'arguments': { 'actions': self._actions } } + self._actions = list() + return qmpcmd + + # Nothing to process? + if not cmdargs: + return None + + # Parse and then cache this Transactional Action + if self._transmode: + finalize = False + action = { 'type': cmdargs[0], 'data': {} } + if cmdargs[-1] == ')': + cmdargs.pop(-1) + finalize = True + self.__cli_expr(cmdargs[1:], action['data']) + self._actions.append(action) + return self.__build_cmd(')') if finalize else None + + # Standard command: parse and return it to be executed. + qmpcmd = { 'execute': cmdargs[0], 'arguments': {} } + self.__cli_expr(cmdargs[1:], qmpcmd['arguments']) return qmpcmd + def _print(self, qmp): + jsobj = json.dumps(qmp) + if self._pp is not None: + self._pp.pprint(jsobj) + else: + print str(jsobj) + def _execute_cmd(self, cmdline): try: qmpcmd = self.__build_cmd(cmdline) @@ -138,15 +210,16 @@ class QMPShell(qmp.QEMUMonitorProtocol): print 'command format: <command-name> ', print '[arg-name1=arg1] ... [arg-nameN=argN]' return True + # For transaction mode, we may have just cached the action: + if qmpcmd is None: + return True + if self._verbose: + self._print(qmpcmd) resp = self.cmd_obj(qmpcmd) if resp is None: print 'Disconnected' return False - - if self._pp is not None: - self._pp.pprint(resp) - else: - print resp + self._print(resp) return True def connect(self): @@ -158,6 +231,11 @@ class QMPShell(qmp.QEMUMonitorProtocol): version = self._greeting['QMP']['version']['qemu'] print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro']) + def get_prompt(self): + if self._transmode: + return "TRANS> " + return "(QEMU) " + def read_exec_command(self, prompt): """ Read and execute a command. @@ -177,6 +255,9 @@ class QMPShell(qmp.QEMUMonitorProtocol): else: return self._execute_cmd(cmdline) + def set_verbosity(self, verbose): + self._verbose = verbose + class HMPShell(QMPShell): def __init__(self, address): QMPShell.__init__(self, address) @@ -254,7 +335,7 @@ def die(msg): def fail_cmdline(option=None): if option: sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option) - sys.stderr.write('qemu-shell [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n') + sys.stderr.write('qemu-shell [ -v ] [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n') sys.exit(1) def main(): @@ -262,6 +343,7 @@ def main(): qemu = None hmp = False pp = None + verbose = False try: for arg in sys.argv[1:]: @@ -273,6 +355,8 @@ def main(): if pp is not None: fail_cmdline(arg) pp = pprint.PrettyPrinter(indent=4) + elif arg == "-v": + verbose = True else: if qemu is not None: fail_cmdline(arg) @@ -297,7 +381,8 @@ def main(): die('Could not connect to %s' % addr) qemu.show_banner() - while qemu.read_exec_command('(QEMU) '): + qemu.set_verbosity(verbose) + while qemu.read_exec_command(qemu.get_prompt()): pass qemu.close() diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 9907e07e22..9919b5b17b 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -2458,6 +2458,7 @@ void helper_rfe(CPUTriCoreState *env) if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) { /* raise MNG trap */ } + env->PC = env->gpr_a[11] & ~0x1; /* ICR.IE = PCXI.PIE; */ env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15); /* ICR.CCPN = PCXI.PCPN; */ @@ -2581,7 +2582,7 @@ void helper_rslcx(CPUTriCoreState *env) ((env->PCXI & MASK_PCXI_PCXO) << 6); /* {new_PCXI, A[11], A[10], A[11], D[8], D[9], D[10], D[11], A[12], A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */ - restore_context_upper(env, ea, &new_PCXI, &env->gpr_a[11]); + restore_context_lower(env, ea, &env->gpr_a[11], &new_PCXI); /* M(EA, word) = FCX; */ cpu_stl_data(env, ea, env->FCX); /* M(EA, word) = FCX; */ diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 54a48cd694..663b2a0796 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3440,7 +3440,7 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, break; case OPCM_32_BRR_LOOP: if (MASK_OP_BRR_OP2(ctx->opcode) == OPC2_32_BRR_LOOP) { - gen_loop(ctx, r1, offset * 2); + gen_loop(ctx, r2, offset * 2); } else { /* OPC2_32_BRR_LOOPU */ gen_goto_tb(ctx, 0, ctx->pc + offset * 2); @@ -3745,10 +3745,10 @@ static void decode_slr_opc(DisasContext *ctx, int op1) tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], 2); break; case OPC1_16_SLR_LD_W: - tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], cpu_gpr_a[r2], ctx->mem_idx, MO_LESW); + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], cpu_gpr_a[r2], ctx->mem_idx, MO_LESL); break; case OPC1_16_SLR_LD_W_POSTINC: - tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], cpu_gpr_a[r2], ctx->mem_idx, MO_LESW); + tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], cpu_gpr_a[r2], ctx->mem_idx, MO_LESL); tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], 4); break; } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index d3a9bc158b..2291f75fd9 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -107,7 +107,7 @@ /* BO Format */ #define MASK_OP_BO_OFF10(op) (MASK_BITS_SHIFT(op, 16, 21) + \ (MASK_BITS_SHIFT(op, 28, 31) << 6)) -#define MASK_OP_BO_OFF10_SEXT(op) (MASK_BITS_SHIFT_SEXT(op, 16, 21) + \ +#define MASK_OP_BO_OFF10_SEXT(op) (MASK_BITS_SHIFT(op, 16, 21) + \ (MASK_BITS_SHIFT_SEXT(op, 28, 31) << 6)) #define MASK_OP_BO_OP2(op) MASK_BITS_SHIFT(op, 22, 27) #define MASK_OP_BO_S2(op) MASK_BITS_SHIFT(op, 12, 15) diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT Binary files differindex 1693c3783b..c658203db9 100644 --- a/tests/acpi-test-data/pc/DSDT +++ b/tests/acpi-test-data/pc/DSDT diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT Binary files differindex 59be315237..210d6a71e5 100644 --- a/tests/acpi-test-data/pc/SSDT +++ b/tests/acpi-test-data/pc/SSDT diff --git a/tests/acpi-test-data/pc/SSDT.bridge b/tests/acpi-test-data/pc/SSDT.bridge Binary files differindex fa6136935c..6e6660b1fb 100644 --- a/tests/acpi-test-data/pc/SSDT.bridge +++ b/tests/acpi-test-data/pc/SSDT.bridge diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT Binary files differindex e9ac11c38f..4723e5954d 100644 --- a/tests/acpi-test-data/q35/DSDT +++ b/tests/acpi-test-data/q35/DSDT diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT Binary files differindex e87f5a35c1..0970c67ddb 100644 --- a/tests/acpi-test-data/q35/SSDT +++ b/tests/acpi-test-data/q35/SSDT diff --git a/tests/acpi-test-data/q35/SSDT.bridge b/tests/acpi-test-data/q35/SSDT.bridge Binary files differindex b3cac34d70..a778688617 100644 --- a/tests/acpi-test-data/q35/SSDT.bridge +++ b/tests/acpi-test-data/q35/SSDT.bridge diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 735ac610be..7e85dc45e3 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -17,7 +17,7 @@ #include "qemu-common.h" #include "libqtest.h" #include "qemu/compiler.h" -#include "hw/i386/acpi-defs.h" +#include "hw/acpi/acpi-defs.h" #include "hw/i386/smbios.h" #include "qemu/bitmap.h" diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 95497a037e..60e5b22a98 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -1,6 +1,6 @@ /* * Copyright IBM, Corp. 2009 - * Copyright (c) 2013 Red Hat Inc. + * Copyright (c) 2013, 2015 Red Hat Inc. * * Authors: * Anthony Liguori <aliguori@us.ibm.com> @@ -1005,6 +1005,7 @@ static void keyword_literal(void) { QObject *obj; QBool *qbool; + QObject *null; QString *str; obj = qobject_from_json("true"); @@ -1041,7 +1042,7 @@ static void keyword_literal(void) g_assert(qbool_get_int(qbool) == 0); QDECREF(qbool); - + obj = qobject_from_jsonf("%i", true); g_assert(obj != NULL); g_assert(qobject_type(obj) == QTYPE_QBOOL); @@ -1050,6 +1051,16 @@ static void keyword_literal(void) g_assert(qbool_get_int(qbool) != 0); QDECREF(qbool); + + obj = qobject_from_json("null"); + g_assert(obj != NULL); + g_assert(qobject_type(obj) == QTYPE_QNULL); + + null = qnull(); + g_assert(null == obj); + + qobject_decref(obj); + qobject_decref(null); } typedef struct LiteralQDictEntry LiteralQDictEntry; diff --git a/trace-events b/trace-events index 30eba926c4..11387c32b8 100644 --- a/trace-events +++ b/trace-events @@ -1562,6 +1562,7 @@ vfio_put_base_device(int fd) "close vdev->fd=%d" #hw/acpi/memory_hotplug.c mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32 +mhp_acpi_ejecting_invalid_slot(uint32_t slot) "0x%"PRIx32 mhp_acpi_read_addr_lo(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr lo: 0x%"PRIx32 mhp_acpi_read_addr_hi(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr hi: 0x%"PRIx32 mhp_acpi_read_size_lo(uint32_t slot, uint32_t size) "slot[0x%"PRIx32"] size lo: 0x%"PRIx32 @@ -1572,6 +1573,9 @@ mhp_acpi_write_slot(uint32_t slot) "set active slot: 0x%"PRIx32 mhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "slot[0x%"PRIx32"] OST EVENT: 0x%"PRIx32 mhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "slot[0x%"PRIx32"] OST STATUS: 0x%"PRIx32 mhp_acpi_clear_insert_evt(uint32_t slot) "slot[0x%"PRIx32"] clear insert event" +mhp_acpi_clear_remove_evt(uint32_t slot) "slot[0x%"PRIx32"] clear remove event" +mhp_acpi_pc_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm deleted" +mhp_acpi_pc_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm delete failed" # hw/i386/pc.c mhp_pc_dimm_assigned_slot(int slot) "0x%d" |