diff options
59 files changed, 449 insertions, 173 deletions
diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst index 911a98255b..0bd3f9399f 100644 --- a/docs/specs/acpi_hw_reduced_hotplug.rst +++ b/docs/specs/acpi_hw_reduced_hotplug.rst @@ -63,7 +63,8 @@ GED IO interface (4 byte access) bits: 0: Memory hotplug event 1: System power down event - 2-31: Reserved + 2: NVDIMM hotplug event + 3-31: Reserved **write_access:** diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index 777da07f4d..cab9bcd457 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -20,6 +20,6 @@ common-obj-$(CONFIG_TPM) += tpm.o common-obj-$(CONFIG_IPMI) += ipmi.o common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o else -common-obj-y += acpi-stub.o +common-obj-y += acpi-stub.o aml-build-stub.o endif -common-obj-$(CONFIG_ALL) += acpi-stub.o acpi-x86-stub.o ipmi-stub.o +common-obj-$(CONFIG_ALL) += acpi-stub.o aml-build-stub.o acpi-x86-stub.o ipmi-stub.o diff --git a/hw/acpi/aml-build-stub.c b/hw/acpi/aml-build-stub.c new file mode 100644 index 0000000000..58b2e16227 --- /dev/null +++ b/hw/acpi/aml-build-stub.c @@ -0,0 +1,79 @@ +/* + * ACPI aml builder stubs for platforms that don't support ACPI. + * + * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2016 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" + +void aml_append(Aml *parent_ctx, Aml *child) +{ +} + +Aml *aml_resource_template(void) +{ + return NULL; +} + +Aml *aml_device(const char *name_format, ...) +{ + return NULL; +} + +Aml *aml_eisaid(const char *str) +{ + return NULL; +} + +Aml *aml_name_decl(const char *name, Aml *val) +{ + return NULL; +} + +Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, + uint8_t aln, uint8_t len) +{ + return NULL; +} + +Aml *aml_irq_no_flags(uint8_t irq) +{ + return NULL; +} + +Aml *aml_int(const uint64_t val) +{ + return NULL; +} + +Aml *aml_package(uint8_t num_elements) +{ + return NULL; +} + +Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, + uint8_t channel) +{ + return NULL; +} + +Aml *aml_buffer(int buffer_size, uint8_t *byte_list) +{ + return NULL; +} diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index 021ed2bf23..5d17f78a1e 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -16,6 +16,7 @@ #include "hw/acpi/generic_event_device.h" #include "hw/irq.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/error-report.h" @@ -23,6 +24,7 @@ static const uint32_t ged_supported_events[] = { ACPI_GED_MEM_HOTPLUG_EVT, ACPI_GED_PWR_DOWN_EVT, + ACPI_GED_NVDIMM_HOTPLUG_EVT, }; /* @@ -110,6 +112,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), aml_int(0x80))); break; + case ACPI_GED_NVDIMM_HOTPLUG_EVT: + aml_append(if_ctx, + aml_notify(aml_name("\\_SB.NVDR"), + aml_int(0x80))); + break; default: /* * Please make sure all the events in ged_supported_events[] @@ -175,7 +182,11 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, AcpiGedState *s = ACPI_GED(hotplug_dev); if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); + if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) { + nvdimm_acpi_plug_cb(hotplug_dev, dev); + } else { + acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); + } } else { error_setg(errp, "virt: device plug request for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -192,6 +203,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) sel = ACPI_GED_MEM_HOTPLUG_EVT; } else if (ev & ACPI_POWER_DOWN_STATUS) { sel = ACPI_GED_PWR_DOWN_EVT; + } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { + sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; } else { /* Unknown event. Return without generating interrupt. */ warn_report("GED: Unsupported event %d. No irq injected", ev); diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index eb6a37b14e..fa7bf8b507 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -900,11 +900,13 @@ void nvdimm_acpi_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev) } void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, + struct AcpiGenericAddress dsm_io, FWCfgState *fw_cfg, Object *owner) { + state->dsm_io = dsm_io; memory_region_init_io(&state->io_mr, owner, &nvdimm_dsm_ops, state, - "nvdimm-acpi-io", NVDIMM_ACPI_IO_LEN); - memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, &state->io_mr); + "nvdimm-acpi-io", dsm_io.bit_width >> 3); + memory_region_add_subregion(io, dsm_io.address, &state->io_mr); state->dsm_mem = g_array_new(false, true /* clear */, 1); acpi_data_push(state->dsm_mem, sizeof(NvdimmDsmIn)); @@ -933,12 +935,15 @@ void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, #define NVDIMM_QEMU_RSVD_UUID "648B9CF2-CDA1-4312-8AD9-49C4AF32BD62" -static void nvdimm_build_common_dsm(Aml *dev) +static void nvdimm_build_common_dsm(Aml *dev, + NVDIMMState *nvdimm_state) { Aml *method, *ifctx, *function, *handle, *uuid, *dsm_mem, *elsectx2; Aml *elsectx, *unsupport, *unpatched, *expected_uuid, *uuid_invalid; Aml *pckg, *pckg_index, *pckg_buf, *field, *dsm_out_buf, *dsm_out_buf_size; + Aml *whilectx, *offset; uint8_t byte_list[1]; + AmlRegionSpace rs; method = aml_method(NVDIMM_COMMON_DSM, 5, AML_SERIALIZED); uuid = aml_arg(0); @@ -949,9 +954,16 @@ static void nvdimm_build_common_dsm(Aml *dev) aml_append(method, aml_store(aml_name(NVDIMM_ACPI_MEM_ADDR), dsm_mem)); + if (nvdimm_state->dsm_io.space_id == AML_AS_SYSTEM_IO) { + rs = AML_SYSTEM_IO; + } else { + rs = AML_SYSTEM_MEMORY; + } + /* map DSM memory and IO into ACPI namespace. */ - aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, AML_SYSTEM_IO, - aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN)); + aml_append(method, aml_operation_region(NVDIMM_DSM_IOPORT, rs, + aml_int(nvdimm_state->dsm_io.address), + nvdimm_state->dsm_io.bit_width >> 3)); aml_append(method, aml_operation_region(NVDIMM_DSM_MEMORY, AML_SYSTEM_MEMORY, dsm_mem, sizeof(NvdimmDsmIn))); @@ -966,7 +978,7 @@ static void nvdimm_build_common_dsm(Aml *dev) field = aml_field(NVDIMM_DSM_IOPORT, AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE); aml_append(field, aml_named_field(NVDIMM_DSM_NOTIFY, - NVDIMM_ACPI_IO_LEN * BITS_PER_BYTE)); + nvdimm_state->dsm_io.bit_width)); aml_append(method, field); /* @@ -1091,13 +1103,46 @@ static void nvdimm_build_common_dsm(Aml *dev) /* RLEN is not included in the payload returned to guest. */ aml_append(method, aml_subtract(aml_name(NVDIMM_DSM_OUT_BUF_SIZE), aml_int(4), dsm_out_buf_size)); + + /* + * As per ACPI spec 6.3, Table 19-419 Object Conversion Rules, if + * the Buffer Field <= to the size of an Integer (in bits), it will + * be treated as an integer. Moreover, the integer size depends on + * DSDT tables revision number. If revision number is < 2, integer + * size is 32 bits, otherwise it is 64 bits. + * Because of this CreateField() canot be used if RLEN < Integer Size. + * + * Also please note that APCI ASL operator SizeOf() doesn't support + * Integer and there isn't any other way to figure out the Integer + * size. Hence we assume 8 byte as Integer size and if RLEN < 8 bytes, + * build dsm_out_buf byte by byte. + */ + ifctx = aml_if(aml_lless(dsm_out_buf_size, aml_int(8))); + offset = aml_local(2); + aml_append(ifctx, aml_store(aml_int(0), offset)); + aml_append(ifctx, aml_name_decl("TBUF", aml_buffer(1, NULL))); + aml_append(ifctx, aml_store(aml_buffer(0, NULL), dsm_out_buf)); + + whilectx = aml_while(aml_lless(offset, dsm_out_buf_size)); + /* Copy 1 byte at offset from ODAT to temporary buffer(TBUF). */ + aml_append(whilectx, aml_store(aml_derefof(aml_index( + aml_name(NVDIMM_DSM_OUT_BUF), offset)), + aml_index(aml_name("TBUF"), aml_int(0)))); + aml_append(whilectx, aml_concatenate(dsm_out_buf, aml_name("TBUF"), + dsm_out_buf)); + aml_append(whilectx, aml_increment(offset)); + aml_append(ifctx, whilectx); + + aml_append(ifctx, aml_return(dsm_out_buf)); + aml_append(method, ifctx); + + /* If RLEN >= Integer size, just use CreateField() operator */ aml_append(method, aml_store(aml_shiftleft(dsm_out_buf_size, aml_int(3)), dsm_out_buf_size)); aml_append(method, aml_create_field(aml_name(NVDIMM_DSM_OUT_BUF), aml_int(0), dsm_out_buf_size, "OBUF")); - aml_append(method, aml_concatenate(aml_buffer(0, NULL), aml_name("OBUF"), - dsm_out_buf)); - aml_append(method, aml_return(dsm_out_buf)); + aml_append(method, aml_return(aml_name("OBUF"))); + aml_append(dev, method); } @@ -1234,7 +1279,8 @@ static void nvdimm_build_nvdimm_devices(Aml *root_dev, uint32_t ram_slots) } static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, - BIOSLinker *linker, GArray *dsm_dma_area, + BIOSLinker *linker, + NVDIMMState *nvdimm_state, uint32_t ram_slots) { Aml *ssdt, *sb_scope, *dev; @@ -1262,7 +1308,7 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, */ aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012"))); - nvdimm_build_common_dsm(dev); + nvdimm_build_common_dsm(dev, nvdimm_state); /* 0 is reserved for root device. */ nvdimm_build_device_dsm(dev, 0); @@ -1281,7 +1327,7 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data, NVDIMM_ACPI_MEM_ADDR); bios_linker_loader_alloc(linker, - NVDIMM_DSM_MEM_FILE, dsm_dma_area, + NVDIMM_DSM_MEM_FILE, nvdimm_state->dsm_mem, sizeof(NvdimmDsmIn), false /* high memory */); bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t), @@ -1303,7 +1349,7 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, return; } - nvdimm_build_ssdt(table_offsets, table_data, linker, state->dsm_mem, + nvdimm_build_ssdt(table_offsets, table_data, linker, state, ram_slots); device_list = nvdimm_get_device_list(); diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 188419dc1e..5364172537 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -25,6 +25,7 @@ config ARM_VIRT select DIMM select ACPI_MEMORY_HOTPLUG select ACPI_HW_REDUCED + select ACPI_NVDIMM config CHEETAH bool diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 81d41a3990..f22b1e6097 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -44,6 +44,7 @@ #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" #include "hw/arm/virt.h" +#include "hw/mem/nvdimm.h" #include "sysemu/numa.h" #include "sysemu/reset.h" #include "kvm_arm.h" @@ -826,6 +827,11 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) } } + if (ms->nvdimms_state->is_enabled) { + nvdimm_build_acpi(table_offsets, tables_blob, tables->linker, + ms->nvdimms_state, ms->ram_slots); + } + if (its_class_name() && !vmc->no_its) { acpi_add_table(table_offsets, tables_blob); build_iort(tables_blob, tables->linker, vms); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 626822554d..171e6908ec 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -150,6 +150,7 @@ static const MemMapEntry base_memmap[] = { [VIRT_SMMU] = { 0x09050000, 0x00020000 }, [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, + [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -567,6 +568,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) event |= ACPI_GED_MEM_HOTPLUG_EVT; } + if (ms->nvdimms_state->is_enabled) { + event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; + } + dev = qdev_create(NULL, TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", event); @@ -1884,6 +1889,18 @@ static void machvirt_init(MachineState *machine) create_platform_bus(vms); + if (machine->nvdimms_state->is_enabled) { + const struct AcpiGenericAddress arm_virt_nvdimm_acpi_dsmio = { + .space_id = AML_AS_SYSTEM_MEMORY, + .address = vms->memmap[VIRT_NVDIMM_ACPI].base, + .bit_width = NVDIMM_ACPI_IO_LEN << 3 + }; + + nvdimm_init_acpi_state(machine->nvdimms_state, sysmem, + arm_virt_nvdimm_acpi_dsmio, + vms->fw_cfg, OBJECT(vms)); + } + vms->bootinfo.ram_size = machine->ram_size; vms->bootinfo.nb_cpus = smp_cpus; vms->bootinfo.board_id = -1; @@ -2075,19 +2092,20 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + const MachineState *ms = MACHINE(hotplug_dev); const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); - if (is_nvdimm) { - error_setg(errp, "nvdimm is not yet supported"); - return; - } - if (!vms->acpi_dev) { error_setg(errp, "memory hotplug is not enabled: missing acpi-ged device"); return; } + if (is_nvdimm && !ms->nvdimms_state->is_enabled) { + error_setg(errp, "nvdimm is not enabled: add 'nvdimm=on' to '-M'"); + return; + } + pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); } @@ -2095,6 +2113,8 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + MachineState *ms = MACHINE(hotplug_dev); + bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); Error *local_err = NULL; pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); @@ -2102,6 +2122,10 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, goto out; } + if (is_nvdimm) { + nvdimm_plug(ms->nvdimms_state); + } + hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &error_abort); @@ -2226,6 +2250,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) hc->plug = virt_machine_device_plug_cb; hc->unplug_request = virt_machine_device_unplug_request_cb; mc->numa_mem_supported = true; + mc->nvdimm_supported = true; mc->auto_enable_numa_with_memhp = true; mc->default_ram_id = "mach-virt.ram"; diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 17df5338e7..6c485d1c9e 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -441,7 +441,9 @@ reconnect: virtio_err: g_free(s->vhost_vqs); + s->vhost_vqs = NULL; g_free(s->inflight); + s->inflight = NULL; for (i = 0; i < s->num_queues; i++) { virtio_delete_queue(s->virtqs[i]); } @@ -462,7 +464,9 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) vhost_dev_cleanup(&s->dev); vhost_dev_free_inflight(s->inflight); g_free(s->vhost_vqs); + s->vhost_vqs = NULL; g_free(s->inflight); + s->inflight = NULL; for (i = 0; i < s->num_queues; i++) { virtio_delete_queue(s->virtqs[i]); diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index 2b4c2aa126..95757a6619 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -114,6 +114,7 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) */ vpci_dev->modern_mem_bar_idx = 2; vpci_dev->msix_bar_idx = 4; + vpci_dev->modern_io_bar_idx = 5; if (!(vpci_dev->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ)) { /* diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 23c77eeb95..2e15f6848e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -128,6 +128,12 @@ typedef struct FwCfgTPMConfig { static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg); +const struct AcpiGenericAddress x86_nvdimm_acpi_dsmio = { + .space_id = AML_AS_SYSTEM_IO, + .address = NVDIMM_ACPI_IO_BASE, + .bit_width = NVDIMM_ACPI_IO_LEN << 3 +}; + static void init_common_fadt_data(MachineState *ms, Object *o, AcpiFadtData *data) { @@ -1151,14 +1157,11 @@ static Aml *build_kbd_device_aml(void) { Aml *dev; Aml *crs; - Aml *method; dev = aml_device("KBD"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0303"))); - method = aml_method("_STA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(0x0f))); - aml_append(dev, method); + aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); crs = aml_resource_template(); aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01)); @@ -1173,14 +1176,11 @@ static Aml *build_mouse_device_aml(void) { Aml *dev; Aml *crs; - Aml *method; dev = aml_device("MOU"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0F13"))); - method = aml_method("_STA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(0x0f))); - aml_append(dev, method); + aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); crs = aml_resource_template(); aml_append(crs, aml_irq_no_flags(12)); @@ -1294,6 +1294,7 @@ static void build_isa_devices_aml(Aml *table) error_report("No ISA bus, unable to define IPMI ACPI data"); } else { build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); + isa_build_aml(ISA_BUS(obj), scope); } aml_append(table, scope); @@ -2238,9 +2239,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, TPM_CRB_ADDR_SIZE, AML_READ_WRITE)); aml_append(dev, aml_name_decl("_CRS", crs)); - method = aml_method("_STA", 0, AML_NOTSERIALIZED); - aml_append(method, aml_return(aml_int(0x0f))); - aml_append(dev, method); + aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); tpm_build_ppi_acpi(tpm, dev); @@ -2513,6 +2512,34 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) build_header(linker, table_data, (void *)(table_data->data + dmar_start), "DMAR", table_data->len - dmar_start, 1, NULL, NULL); } + +/* + * Windows ACPI Emulated Devices Table + * (Version 1.0 - April 6, 2009) + * Spec: http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WAET.docx + * + * Helpful to speedup Windows guests and ignored by others. + */ +static void +build_waet(GArray *table_data, BIOSLinker *linker) +{ + int waet_start = table_data->len; + + /* WAET header */ + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + /* + * Set "ACPI PM timer good" flag. + * + * Tells Windows guests that our ACPI PM timer is reliable in the + * sense that guest can read it only once to obtain a reliable value. + * Which avoids costly VMExits caused by guest re-reading it unnecessarily. + */ + build_append_int_noprefix(table_data, 1 << 1 /* ACPI PM timer good */, 4); + + build_header(linker, table_data, (void *)(table_data->data + waet_start), + "WAET", table_data->len - waet_start, 1, NULL, NULL); +} + /* * IVRS table as specified in AMD IOMMU Specification v2.62, Section 5.2 * accessible here http://support.amd.com/TechDocs/48882_IOMMU.pdf @@ -2860,6 +2887,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) machine->nvdimms_state, machine->ram_slots); } + acpi_add_table(table_offsets, tables_blob); + build_waet(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); diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h index 007332e51c..74df5fc612 100644 --- a/hw/i386/acpi-build.h +++ b/hw/i386/acpi-build.h @@ -1,6 +1,9 @@ #ifndef HW_I386_ACPI_BUILD_H #define HW_I386_ACPI_BUILD_H +#include "hw/acpi/acpi-defs.h" + +extern const struct AcpiGenericAddress x86_nvdimm_acpi_dsmio; void acpi_setup(void); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 5143c51653..f6b8431c8b 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -91,6 +91,7 @@ #include "qapi/qmp/qerror.h" #include "config-devices.h" #include "e820_memory_layout.h" +#include "vmport.h" #include "fw_cfg.h" #include "trace.h" @@ -1152,7 +1153,7 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) i8042 = isa_create_simple(isa_bus, "i8042"); if (!no_vmport) { - vmport_init(isa_bus); + isa_create_simple(isa_bus, TYPE_VMPORT); vmmouse = isa_try_create(isa_bus, "vmmouse"); } else { vmmouse = NULL; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 22dee0e76c..b75087d71b 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -61,6 +61,7 @@ #include "migration/misc.h" #include "sysemu/numa.h" #include "hw/mem/nvdimm.h" +#include "hw/i386/acpi-build.h" #define MAX_IDE_BUS 2 @@ -297,6 +298,7 @@ static void pc_init1(MachineState *machine, if (machine->nvdimms_state->is_enabled) { nvdimm_init_acpi_state(machine->nvdimms_state, system_io, + x86_nvdimm_acpi_dsmio, x86ms->fw_cfg, OBJECT(pcms)); } } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index d37c425e22..d2806c1b29 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -54,6 +54,7 @@ #include "qemu/error-report.h" #include "sysemu/numa.h" #include "hw/mem/nvdimm.h" +#include "hw/i386/acpi-build.h" /* ICH9 AHCI has 6 ports */ #define MAX_SATA_PORTS 6 @@ -315,6 +316,7 @@ static void pc_q35_init(MachineState *machine) if (machine->nvdimms_state->is_enabled) { nvdimm_init_acpi_state(machine->nvdimms_state, system_io, + x86_nvdimm_acpi_dsmio, x86ms->fw_cfg, OBJECT(pcms)); } } diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c index e8e62bd96b..b3aef41327 100644 --- a/hw/i386/vmmouse.c +++ b/hw/i386/vmmouse.c @@ -25,10 +25,11 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "ui/console.h" -#include "hw/i386/pc.h" #include "hw/input/i8042.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" +#include "vmport.h" +#include "cpu.h" /* debug only vmmouse */ //#define DEBUG_VMMOUSE @@ -70,6 +71,26 @@ typedef struct VMMouseState ISAKBDState *i8042; } VMMouseState; +static void vmmouse_get_data(uint32_t *data) +{ + X86CPU *cpu = X86_CPU(current_cpu); + CPUX86State *env = &cpu->env; + + data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; + data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; + data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI]; +} + +static void vmmouse_set_data(const uint32_t *data) +{ + X86CPU *cpu = X86_CPU(current_cpu); + CPUX86State *env = &cpu->env; + + env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; + env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; + env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; +} + static uint32_t vmmouse_get_status(VMMouseState *s) { DPRINTF("vmmouse_get_status()\n"); diff --git a/hw/i386/vmport.c b/hw/i386/vmport.c index 1f31e27c8a..1aaaab691a 100644 --- a/hw/i386/vmport.c +++ b/hw/i386/vmport.c @@ -23,10 +23,10 @@ */ #include "qemu/osdep.h" #include "hw/isa/isa.h" -#include "hw/i386/pc.h" -#include "hw/input/i8042.h" #include "sysemu/hw_accel.h" #include "qemu/log.h" +#include "vmport.h" +#include "cpu.h" #include "trace.h" #define VMPORT_CMD_GETVERSION 0x0a @@ -109,27 +109,6 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) return ram_size; } -/* vmmouse helpers */ -void vmmouse_get_data(uint32_t *data) -{ - X86CPU *cpu = X86_CPU(current_cpu); - CPUX86State *env = &cpu->env; - - data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; - data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; - data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI]; -} - -void vmmouse_set_data(const uint32_t *data) -{ - X86CPU *cpu = X86_CPU(current_cpu); - CPUX86State *env = &cpu->env; - - env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; - env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; - env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; -} - static const MemoryRegionOps vmport_ops = { .read = vmport_ioport_read, .write = vmport_ioport_write, diff --git a/hw/i386/vmport.h b/hw/i386/vmport.h new file mode 100644 index 0000000000..47eda7a22b --- /dev/null +++ b/hw/i386/vmport.h @@ -0,0 +1,34 @@ +/* + * QEMU VMPort emulation + * + * Copyright (C) 2007 Hervé Poussineau + * + * 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. + */ + +#ifndef HW_I386_VMPORT_H +#define HW_I386_VMPORT_H + +#define TYPE_VMPORT "vmport" + +typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); + +void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); + +#endif diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 798dd9194e..1f2189f4d5 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -207,6 +207,21 @@ ISADevice *isa_vga_init(ISABus *bus) } } +void isa_build_aml(ISABus *bus, Aml *scope) +{ + BusChild *kid; + ISADevice *dev; + ISADeviceClass *dc; + + QTAILQ_FOREACH(kid, &bus->parent_obj.children, sibling) { + dev = ISA_DEVICE(kid->child); + dc = ISA_DEVICE_GET_CLASS(dev); + if (dc->build_aml) { + dc->build_aml(dev, scope); + } + } +} + static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent) { ISADevice *d = ISA_DEVICE(dev); diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig index 2ad052a536..c27844900d 100644 --- a/hw/mem/Kconfig +++ b/hw/mem/Kconfig @@ -8,4 +8,4 @@ config MEM_DEVICE config NVDIMM bool default y - depends on (PC || PSERIES) + depends on (PC || PSERIES || ARM_VIRT) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 0eb3a2a5d2..abc99b6eff 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -415,6 +415,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, { PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; + uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); PCIDevice *pci_dev = PCI_DEVICE(dev); /* Don't send event when device is enabled during qemu machine creation: @@ -430,6 +431,13 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, return; } + /* Check if hot-plug is disabled on the slot */ + if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { + error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", + DEVICE(hotplug_pdev)->id); + return; + } + /* To enable multifunction hot-plug, we just ensure the function * 0 added last. When function 0 is added, we set the sltsta and * inform OS via event notification. @@ -441,7 +449,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_DLLLA); } - pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), + pcie_cap_slot_event(hotplug_pdev, PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); } } @@ -470,8 +478,19 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, Error *local_err = NULL; PCIDevice *pci_dev = PCI_DEVICE(dev); PCIBus *bus = pci_get_bus(pci_dev); + PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; + uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + + /* Check if hot-unplug is disabled on the slot */ + if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { + error_setg(errp, "Hot-unplug failed: " + "unsupported by the port device '%s'", + DEVICE(hotplug_pdev)->id); + return; + } - pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err); + pcie_cap_slot_plug_common(hotplug_pdev, dev, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -490,7 +509,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, return; } - pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev)); + pcie_cap_slot_push_attention_button(hotplug_pdev); } /* pci express slot for pci express root/downstream port diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index dc4269cc55..d18c09911b 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -908,7 +908,6 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) { ISADevice *isadev = ISA_DEVICE(dev); RTCState *s = MC146818_RTC(dev); - int base = 0x70; s->cmos_data[RTC_REG_A] = 0x26; s->cmos_data[RTC_REG_B] = 0x02; @@ -951,7 +950,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) qemu_register_suspend_notifier(&s->suspend_notifier); memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2); - isa_register_ioport(isadev, &s->io, base); + isa_register_ioport(isadev, &s->io, RTC_ISA_BASE); /* register rtc 0x70 port for coalesced_pio */ memory_region_set_flush_coalesced(&s->io); @@ -960,7 +959,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->io, 0, &s->coalesced_io); memory_region_add_coalescing(&s->coalesced_io, 0, 1); - qdev_set_legacy_instance_id(dev, base, 3); + qdev_set_legacy_instance_id(dev, RTC_ISA_BASE, 3); qemu_register_reset(rtc_reset, s); object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL); diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 08e7e63790..ec21e8fbe8 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -407,18 +407,79 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, return 0; } +static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, + struct vhost_dev *dev, + VhostUserMsg *msg, + int *fds, size_t *fd_num, + bool track_ramblocks) +{ + int i, fd; + ram_addr_t offset; + MemoryRegion *mr; + struct vhost_memory_region *reg; + + msg->hdr.request = VHOST_USER_SET_MEM_TABLE; + + for (i = 0; i < dev->mem->nregions; ++i) { + reg = dev->mem->regions + i; + + assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); + mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, + &offset); + fd = memory_region_get_fd(mr); + if (fd > 0) { + if (track_ramblocks) { + assert(*fd_num < VHOST_MEMORY_MAX_NREGIONS); + trace_vhost_user_set_mem_table_withfd(*fd_num, mr->name, + reg->memory_size, + reg->guest_phys_addr, + reg->userspace_addr, + offset); + u->region_rb_offset[i] = offset; + u->region_rb[i] = mr->ram_block; + } else if (*fd_num == VHOST_MEMORY_MAX_NREGIONS) { + error_report("Failed preparing vhost-user memory table msg"); + return -1; + } + msg->payload.memory.regions[*fd_num].userspace_addr = + reg->userspace_addr; + msg->payload.memory.regions[*fd_num].memory_size = + reg->memory_size; + msg->payload.memory.regions[*fd_num].guest_phys_addr = + reg->guest_phys_addr; + msg->payload.memory.regions[*fd_num].mmap_offset = offset; + fds[(*fd_num)++] = fd; + } else if (track_ramblocks) { + u->region_rb_offset[i] = 0; + u->region_rb[i] = NULL; + } + } + + msg->payload.memory.nregions = *fd_num; + + if (!*fd_num) { + error_report("Failed initializing vhost-user memory map, " + "consider using -object memory-backend-file share=on"); + return -1; + } + + msg->hdr.size = sizeof(msg->payload.memory.nregions); + msg->hdr.size += sizeof(msg->payload.memory.padding); + msg->hdr.size += *fd_num * sizeof(VhostUserMemoryRegion); + + return 1; +} + static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, struct vhost_memory *mem) { struct vhost_user *u = dev->opaque; int fds[VHOST_MEMORY_MAX_NREGIONS]; - int i, fd; size_t fd_num = 0; VhostUserMsg msg_reply; int region_i, msg_i; VhostUserMsg msg = { - .hdr.request = VHOST_USER_SET_MEM_TABLE, .hdr.flags = VHOST_USER_VERSION, }; @@ -433,48 +494,11 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, u->region_rb_len = dev->mem->nregions; } - for (i = 0; i < dev->mem->nregions; ++i) { - struct vhost_memory_region *reg = dev->mem->regions + i; - ram_addr_t offset; - MemoryRegion *mr; - - assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); - mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, - &offset); - fd = memory_region_get_fd(mr); - if (fd > 0) { - assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); - trace_vhost_user_set_mem_table_withfd(fd_num, mr->name, - reg->memory_size, - reg->guest_phys_addr, - reg->userspace_addr, offset); - u->region_rb_offset[i] = offset; - u->region_rb[i] = mr->ram_block; - msg.payload.memory.regions[fd_num].userspace_addr = - reg->userspace_addr; - msg.payload.memory.regions[fd_num].memory_size = reg->memory_size; - msg.payload.memory.regions[fd_num].guest_phys_addr = - reg->guest_phys_addr; - msg.payload.memory.regions[fd_num].mmap_offset = offset; - fds[fd_num++] = fd; - } else { - u->region_rb_offset[i] = 0; - u->region_rb[i] = NULL; - } - } - - msg.payload.memory.nregions = fd_num; - - if (!fd_num) { - error_report("Failed initializing vhost-user memory map, " - "consider using -object memory-backend-file share=on"); + if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + true) < 0) { return -1; } - msg.hdr.size = sizeof(msg.payload.memory.nregions); - msg.hdr.size += sizeof(msg.payload.memory.padding); - msg.hdr.size += fd_num * sizeof(VhostUserMemoryRegion); - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { return -1; } @@ -545,7 +569,6 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, { struct vhost_user *u = dev->opaque; int fds[VHOST_MEMORY_MAX_NREGIONS]; - int i, fd; size_t fd_num = 0; bool do_postcopy = u->postcopy_listen && u->postcopy_fd.handler; bool reply_supported = virtio_has_feature(dev->protocol_features, @@ -559,7 +582,6 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, } VhostUserMsg msg = { - .hdr.request = VHOST_USER_SET_MEM_TABLE, .hdr.flags = VHOST_USER_VERSION, }; @@ -567,42 +589,11 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; } - for (i = 0; i < dev->mem->nregions; ++i) { - struct vhost_memory_region *reg = dev->mem->regions + i; - ram_addr_t offset; - MemoryRegion *mr; - - assert((uintptr_t)reg->userspace_addr == reg->userspace_addr); - mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, - &offset); - fd = memory_region_get_fd(mr); - if (fd > 0) { - if (fd_num == VHOST_MEMORY_MAX_NREGIONS) { - error_report("Failed preparing vhost-user memory table msg"); - return -1; - } - msg.payload.memory.regions[fd_num].userspace_addr = - reg->userspace_addr; - msg.payload.memory.regions[fd_num].memory_size = reg->memory_size; - msg.payload.memory.regions[fd_num].guest_phys_addr = - reg->guest_phys_addr; - msg.payload.memory.regions[fd_num].mmap_offset = offset; - fds[fd_num++] = fd; - } - } - - msg.payload.memory.nregions = fd_num; - - if (!fd_num) { - error_report("Failed initializing vhost-user memory map, " - "consider using -object memory-backend-file share=on"); + if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + false) < 0) { return -1; } - msg.hdr.size = sizeof(msg.payload.memory.nregions); - msg.hdr.size += sizeof(msg.payload.memory.padding); - msg.hdr.size += fd_num * sizeof(VhostUserMemoryRegion); - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { return -1; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 01ebe12f28..aff98a0ede 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1514,7 +1514,7 @@ void vhost_dev_set_config_notifier(struct vhost_dev *hdev, void vhost_dev_free_inflight(struct vhost_inflight *inflight) { - if (inflight->addr) { + if (inflight && inflight->addr) { qemu_memfd_free(inflight->addr, inflight->size, inflight->fd); inflight->addr = NULL; inflight->fd = -1; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 4cb784389c..d028c17c24 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1705,6 +1705,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) * * region 0 -- virtio legacy io bar * region 1 -- msi-x bar + * region 2 -- virtio modern io bar (off by default) * region 4+5 -- virtio modern memory (64bit) bar * */ diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 0f4ed53d7f..1539fe0667 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -33,7 +33,6 @@ struct Aml { uint8_t op; AmlBlockFlags block_flags; }; -typedef struct Aml Aml; typedef enum { AML_COMPATIBILITY = 0, diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index d157eac088..9eb86ca4fd 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -82,6 +82,7 @@ */ #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 #define ACPI_GED_PWR_DOWN_EVT 0x2 +#define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 typedef struct GEDState { MemoryRegion io; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 60b2f521eb..6d67ace76e 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -79,6 +79,7 @@ enum { VIRT_SECURE_MEM, VIRT_PCDIMM_ACPI, VIRT_ACPI_GED, + VIRT_NVDIMM_ACPI, VIRT_LOWMEMMAP_LAST, }; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 6ab6eda046..05e19455bb 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -129,19 +129,6 @@ typedef struct PCMachineClass { GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); -/* vmport.c */ -#define TYPE_VMPORT "vmport" -typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); - -static inline void vmport_init(ISABus *bus) -{ - isa_create_simple(bus, TYPE_VMPORT); -} - -void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); -void vmmouse_get_data(uint32_t *data); -void vmmouse_set_data(const uint32_t *data); - /* pc.c */ extern int fd_bootchk; diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index 59a4d4b50a..02c2350274 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -69,6 +69,7 @@ typedef struct IsaDmaClass { typedef struct ISADeviceClass { DeviceClass parent_class; + void (*build_aml)(ISADevice *dev, Aml *scope); } ISADeviceClass; struct ISABus { @@ -107,6 +108,7 @@ ISADevice *isa_try_create(ISABus *bus, const char *name); ISADevice *isa_create_simple(ISABus *bus, const char *name); ISADevice *isa_vga_init(ISABus *bus); +void isa_build_aml(ISABus *bus, Aml *scope); /** * isa_register_ioport: Install an I/O port region on the ISA bus. diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index 4807ca615b..a3c08955e8 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -26,6 +26,7 @@ #include "hw/mem/pc-dimm.h" #include "hw/acpi/bios-linker-loader.h" #include "qemu/uuid.h" +#include "hw/acpi/aml-build.h" #define NVDIMM_DEBUG 0 #define nvdimm_debug(fmt, ...) \ @@ -147,10 +148,12 @@ struct NVDIMMState { */ int32_t persistence; char *persistence_string; + struct AcpiGenericAddress dsm_io; }; typedef struct NVDIMMState NVDIMMState; void nvdimm_init_acpi_state(NVDIMMState *state, MemoryRegion *io, + struct AcpiGenericAddress dsm_io, FWCfgState *fw_cfg, Object *owner); void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, NVDIMMState *state, diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h index 10c93a096a..3713181b56 100644 --- a/include/hw/rtc/mc146818rtc.h +++ b/include/hw/rtc/mc146818rtc.h @@ -47,6 +47,7 @@ typedef struct RTCState { } RTCState; #define RTC_ISA_IRQ 8 +#define RTC_ISA_BASE 0x70 ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq); diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 375770a80f..ecf3cde26c 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -24,6 +24,7 @@ typedef struct AdapterInfo AdapterInfo; typedef struct AddressSpace AddressSpace; typedef struct AioContext AioContext; +typedef struct Aml Aml; typedef struct AnnounceTimer AnnounceTimer; typedef struct BdrvDirtyBitmap BdrvDirtyBitmap; typedef struct BdrvDirtyBitmapIter BdrvDirtyBitmapIter; diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e658e6546f..0ba213e9f2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -35,8 +35,6 @@ my $summary_file = 0; my $root; my %debug; my $help = 0; -my $acpi_testexpected; -my $acpi_nontestexpected; sub help { my ($exitcode) = @_; @@ -1261,21 +1259,23 @@ sub WARN { # According to tests/qtest/bios-tables-test.c: do not # change expected file in the same commit with adding test sub checkfilename { - my ($name) = @_; - if ($name =~ m#^tests/data/acpi/# and - # make exception for a shell script that rebuilds the files - not $name =~ m#^\.sh$# or - $name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { - $acpi_testexpected = $name; - } else { - $acpi_nontestexpected = $name; + my ($name, $acpi_testexpected, $acpi_nontestexpected) = @_; + + # Note: shell script that rebuilds the expected files is in the same + # directory as files themselves. + # Note: allowed diff list can be changed both when changing expected + # files and when changing tests. + if ($name =~ m#^tests/data/acpi/# and not $name =~ m#^\.sh$#) { + $$acpi_testexpected = $name; + } elsif ($name =~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) { + $$acpi_nontestexpected = $name; } - if (defined $acpi_testexpected and defined $acpi_nontestexpected) { + if (defined $$acpi_testexpected and defined $$acpi_nontestexpected) { ERROR("Do not add expected files together with tests, " . "follow instructions in " . "tests/qtest/bios-tables-test.c: both " . - $acpi_testexpected . " and " . - $acpi_nontestexpected . " found\n"); + $$acpi_testexpected . " and " . + $$acpi_nontestexpected . " found\n"); } } @@ -1325,6 +1325,9 @@ sub process { my %suppress_whiletrailers; my %suppress_export; + my $acpi_testexpected; + my $acpi_nontestexpected; + # Pre-scan the patch sanitizing the lines. sanitise_line_reset(); @@ -1454,11 +1457,11 @@ sub process { if ($line =~ /^diff --git.*?(\S+)$/) { $realfile = $1; $realfile =~ s@^([^/]*)/@@ if (!$file); - checkfilename($realfile); + checkfilename($realfile, \$acpi_testexpected, \$acpi_nontestexpected); } elsif ($line =~ /^\+\+\+\s+(\S+)/) { $realfile = $1; $realfile =~ s@^([^/]*)/@@ if (!$file); - checkfilename($realfile); + checkfilename($realfile, \$acpi_testexpected, \$acpi_nontestexpected); $p1_prefix = $1; if (!$file && $tree && $p1_prefix ne '' && diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT Binary files differindex c6adfe32d5..ad4b2d46cc 100644 --- a/tests/data/acpi/pc/DSDT +++ b/tests/data/acpi/pc/DSDT diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat Binary files differindex ad890e09aa..eff7aadfab 100644 --- a/tests/data/acpi/pc/DSDT.acpihmat +++ b/tests/data/acpi/pc/DSDT.acpihmat diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge Binary files differindex f01fa3ad4e..92ae808e2e 100644 --- a/tests/data/acpi/pc/DSDT.bridge +++ b/tests/data/acpi/pc/DSDT.bridge diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp Binary files differindex 3295d81c7f..f357235851 100644 --- a/tests/data/acpi/pc/DSDT.cphp +++ b/tests/data/acpi/pc/DSDT.cphp diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm Binary files differindex ad2800de67..7fa09463c1 100644 --- a/tests/data/acpi/pc/DSDT.dimmpxm +++ b/tests/data/acpi/pc/DSDT.dimmpxm diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs Binary files differindex 2633a8cecf..469d13e1f6 100644 --- a/tests/data/acpi/pc/DSDT.ipmikcs +++ b/tests/data/acpi/pc/DSDT.ipmikcs diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp Binary files differindex 9e75ac96e1..aee75bea27 100644 --- a/tests/data/acpi/pc/DSDT.memhp +++ b/tests/data/acpi/pc/DSDT.memhp diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem Binary files differindex 71a975b3e2..9a747f6f08 100644 --- a/tests/data/acpi/pc/DSDT.numamem +++ b/tests/data/acpi/pc/DSDT.numamem diff --git a/tests/data/acpi/pc/SSDT.dimmpxm b/tests/data/acpi/pc/SSDT.dimmpxm Binary files differindex 8ba0e67cb7..ac55387d57 100644 --- a/tests/data/acpi/pc/SSDT.dimmpxm +++ b/tests/data/acpi/pc/SSDT.dimmpxm diff --git a/tests/data/acpi/pc/WAET b/tests/data/acpi/pc/WAET Binary files differnew file mode 100644 index 0000000000..c2240f58df --- /dev/null +++ b/tests/data/acpi/pc/WAET diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT Binary files differindex 1f91888d7a..9fa4d5a405 100644 --- a/tests/data/acpi/q35/DSDT +++ b/tests/data/acpi/q35/DSDT diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat Binary files differindex 3586f6368a..2d834a854c 100644 --- a/tests/data/acpi/q35/DSDT.acpihmat +++ b/tests/data/acpi/q35/DSDT.acpihmat diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge Binary files differindex eae3a2a865..b75122b24a 100644 --- a/tests/data/acpi/q35/DSDT.bridge +++ b/tests/data/acpi/q35/DSDT.bridge diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp Binary files differindex 53d735a4de..c59c19ff46 100644 --- a/tests/data/acpi/q35/DSDT.cphp +++ b/tests/data/acpi/q35/DSDT.cphp diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm Binary files differindex 02ccdd5f38..9edc104ee6 100644 --- a/tests/data/acpi/q35/DSDT.dimmpxm +++ b/tests/data/acpi/q35/DSDT.dimmpxm diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt Binary files differindex 9e2d4f785c..3910e9b767 100644 --- a/tests/data/acpi/q35/DSDT.ipmibt +++ b/tests/data/acpi/q35/DSDT.ipmibt diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp Binary files differindex baefa611ac..8461e984c9 100644 --- a/tests/data/acpi/q35/DSDT.memhp +++ b/tests/data/acpi/q35/DSDT.memhp diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64 Binary files differindex aae0ea2110..fc0cc096ba 100644 --- a/tests/data/acpi/q35/DSDT.mmio64 +++ b/tests/data/acpi/q35/DSDT.mmio64 diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem Binary files differindex 859a2e0871..498c843be1 100644 --- a/tests/data/acpi/q35/DSDT.numamem +++ b/tests/data/acpi/q35/DSDT.numamem diff --git a/tests/data/acpi/q35/SSDT.dimmpxm b/tests/data/acpi/q35/SSDT.dimmpxm Binary files differindex 2d5b721bcf..98e6f0e3f3 100644 --- a/tests/data/acpi/q35/SSDT.dimmpxm +++ b/tests/data/acpi/q35/SSDT.dimmpxm diff --git a/tests/data/acpi/q35/WAET b/tests/data/acpi/q35/WAET Binary files differnew file mode 100644 index 0000000000..c2240f58df --- /dev/null +++ b/tests/data/acpi/q35/WAET diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp Binary files differindex c527ac4739..730e95a46d 100644 --- a/tests/data/acpi/virt/DSDT.memhp +++ b/tests/data/acpi/virt/DSDT.memhp diff --git a/tests/data/acpi/virt/NFIT.memhp b/tests/data/acpi/virt/NFIT.memhp Binary files differnew file mode 100644 index 0000000000..738c6f74c0 --- /dev/null +++ b/tests/data/acpi/virt/NFIT.memhp diff --git a/tests/data/acpi/virt/SSDT.memhp b/tests/data/acpi/virt/SSDT.memhp Binary files differnew file mode 100644 index 0000000000..db61d67332 --- /dev/null +++ b/tests/data/acpi/virt/SSDT.memhp diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 0a597bbacf..c9843829b3 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -927,12 +927,17 @@ static void test_acpi_virt_tcg_memhp(void) }; data.variant = ".memhp"; - test_acpi_one(" -cpu cortex-a57" + test_acpi_one(" -machine nvdimm=on" + " -cpu cortex-a57" " -m 256M,slots=3,maxmem=1G" " -object memory-backend-ram,id=ram0,size=128M" " -object memory-backend-ram,id=ram1,size=128M" " -numa node,memdev=ram0 -numa node,memdev=ram1" - " -numa dist,src=0,dst=1,val=21", + " -numa dist,src=0,dst=1,val=21" + " -object memory-backend-ram,id=ram2,size=128M" + " -object memory-backend-ram,id=nvm0,size=128M" + " -device pc-dimm,id=dimm0,memdev=ram2,node=0" + " -device nvdimm,id=dimm1,memdev=nvm0,node=1", &data); free_test_data(&data); |