aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-05-04 15:51:09 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-05-04 15:51:09 +0100
commit5375af3cd7b8adcc10c18d8083b7be63976c9645 (patch)
treec7f489dfdbc83f4dc215dc184a9325eed5fdca3a /hw
parent9af638cc1f665712522608c5d6b8c03d8fa67666 (diff)
parentd8a05995bd64117bf5219d3ba7956277e608e3ca (diff)
downloadqemu-5375af3cd7b8adcc10c18d8083b7be63976c9645.zip
qemu-5375af3cd7b8adcc10c18d8083b7be63976c9645.tar.gz
qemu-5375af3cd7b8adcc10c18d8083b7be63976c9645.tar.bz2
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio,acpi,pci,pc: backlog from pre-5.0 Mostly fixes, cleanups, but also new features for arm/virt and pc acpi. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Mon 04 May 2020 15:27:06 BST # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: (29 commits) hw/i386: Make vmmouse helpers static hw/i386: Add 'vmport.h' local header hw/i386/vmport: Remove unused 'hw/input/i8042.h' include hw/i386/pc: Create 'vmport' device in place acpi: unit-test: Update WAET ACPI Table expected binaries acpi: Add Windows ACPI Emulated Device Table (WAET) acpi: unit-test: Ignore diff in WAET ACPI table Refactor vhost_user_set_mem_table functions tests/acpi: add expected tables for bios-tables-test bios-tables-test: test pc-dimm and nvdimm coldplug for arm/virt tests: Update ACPI tables list for upcoming arm/virt test changes hw/arm/virt: Add nvdimm hotplug support hw/arm/virt: Add nvdimm hot-plug infrastructure nvdimm: Use configurable ACPI IO base and size hw/acpi/nvdimm: Fix for NVDIMM incorrect DSM output buffer length acpi: DSDT without _STA checkpatch: ignore allowed diff list checkpatch: fix acpi check with multiple file name vhost-user-blk: fix invalid memory access virtio-pci: update virtio pci bar layout documentation ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/Makefile.objs4
-rw-r--r--hw/acpi/aml-build-stub.c79
-rw-r--r--hw/acpi/generic_event_device.c15
-rw-r--r--hw/acpi/nvdimm.c72
-rw-r--r--hw/arm/Kconfig1
-rw-r--r--hw/arm/virt-acpi-build.c6
-rw-r--r--hw/arm/virt.c35
-rw-r--r--hw/block/vhost-user-blk.c4
-rw-r--r--hw/display/virtio-vga.c1
-rw-r--r--hw/i386/acpi-build.c52
-rw-r--r--hw/i386/acpi-build.h3
-rw-r--r--hw/i386/pc.c3
-rw-r--r--hw/i386/pc_piix.c2
-rw-r--r--hw/i386/pc_q35.c2
-rw-r--r--hw/i386/vmmouse.c23
-rw-r--r--hw/i386/vmport.c25
-rw-r--r--hw/i386/vmport.h34
-rw-r--r--hw/isa/isa-bus.c15
-rw-r--r--hw/mem/Kconfig2
-rw-r--r--hw/pci/pcie.c25
-rw-r--r--hw/rtc/mc146818rtc.c5
-rw-r--r--hw/virtio/vhost-user.c143
-rw-r--r--hw/virtio/vhost.c2
-rw-r--r--hw/virtio/virtio-pci.c1
24 files changed, 413 insertions, 141 deletions
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 777da07..cab9bcd 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 0000000..58b2e16
--- /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 021ed2b..5d17f78 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 eb6a37b..fa7bf8b 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 188419d..5364172 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 81d41a3..f22b1e6 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 6268225..171e690 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 17df533..6c485d1 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 2b4c2aa..95757a6 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 23c77ee..2e15f68 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 007332e..74df5fc 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 5143c51..f6b8431 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 22dee0e..b75087d 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 d37c425..d2806c1 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 e8e62bd..b3aef41 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 1f31e27..1aaaab6 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 0000000..47eda7a
--- /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 798dd91..1f2189f 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 2ad052a..c278449 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 0eb3a2a..abc99b6 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 dc4269c..d18c099 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 08e7e63..ec21e8f 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 01ebe12..aff98a0 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 4cb7843..d028c17 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
*
*/