From f404220e279cec435dae3ea6c4093b43b984c76a Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:08:55 +0100 Subject: [PATCH 01/18] q35: implement 128K SMRAM at default SMBASE address It's not what real HW does, implementing which would be overkill [**] and would require complex cross stack changes (QEMU+firmware) to make it work. So considering that SMRAM is owned by MCH, for simplicity (ab)use reserved Q35 register, which allows QEMU and firmware easily init and make RAM at SMBASE available only from SMM context. Patch uses commit (2f295167e0 q35/mch: implement extended TSEG sizes) for inspiration and uses reserved register in config space at 0x9c offset [*] to extend q35 pci-host with ability to use 128K at 0x30000 as SMRAM and hide it (like TSEG) from non-SMM context. Usage: 1: write 0xff in the register 2: if the feature is supported, follow up read from the register should return 0x01. At this point RAM at 0x30000 is still available for SMI handler configuration from non-SMM context 3: writing 0x02 in the register, locks SMBASE area, making its contents available only from SMM context. In non-SMM context, reads return 0xff and writes are ignored. Further writes into the register are ignored until the system reset. *) https://www.mail-archive.com/qemu-devel@nongnu.org/msg455991.html **) https://www.mail-archive.com/qemu-devel@nongnu.org/msg646965.html Signed-off-by: Igor Mammedov Message-Id: <1575896942-331151-3-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Tested-by: Laszlo Ersek --- hw/i386/pc.c | 4 +- hw/pci-host/q35.c | 84 +++++++++++++++++++++++++++++++++++---- include/hw/pci-host/q35.h | 10 +++++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 8054bc414754..a6302a772d19 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -93,7 +93,9 @@ #include "fw_cfg.h" #include "trace.h" -GlobalProperty pc_compat_4_2[] = {}; +GlobalProperty pc_compat_4_2[] = { + { "mch", "smbase-smram", "off" }, +}; const size_t pc_compat_4_2_len = G_N_ELEMENTS(pc_compat_4_2); GlobalProperty pc_compat_4_1[] = {}; diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 158d270b9f0c..6342f73b9fe1 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -275,20 +275,20 @@ static const TypeInfo q35_host_info = { * MCH D0:F0 */ -static uint64_t tseg_blackhole_read(void *ptr, hwaddr reg, unsigned size) +static uint64_t blackhole_read(void *ptr, hwaddr reg, unsigned size) { return 0xffffffff; } -static void tseg_blackhole_write(void *opaque, hwaddr addr, uint64_t val, - unsigned width) +static void blackhole_write(void *opaque, hwaddr addr, uint64_t val, + unsigned width) { /* nothing */ } -static const MemoryRegionOps tseg_blackhole_ops = { - .read = tseg_blackhole_read, - .write = tseg_blackhole_write, +static const MemoryRegionOps blackhole_ops = { + .read = blackhole_read, + .write = blackhole_write, .endianness = DEVICE_NATIVE_ENDIAN, .valid.min_access_size = 1, .valid.max_access_size = 4, @@ -430,6 +430,46 @@ static void mch_update_ext_tseg_mbytes(MCHPCIState *mch) } } +static void mch_update_smbase_smram(MCHPCIState *mch) +{ + PCIDevice *pd = PCI_DEVICE(mch); + uint8_t *reg = pd->config + MCH_HOST_BRIDGE_F_SMBASE; + bool lck; + + if (!mch->has_smram_at_smbase) { + return; + } + + if (*reg == MCH_HOST_BRIDGE_F_SMBASE_QUERY) { + pd->wmask[MCH_HOST_BRIDGE_F_SMBASE] = + MCH_HOST_BRIDGE_F_SMBASE_LCK; + *reg = MCH_HOST_BRIDGE_F_SMBASE_IN_RAM; + return; + } + + /* + * default/reset state, discard written value + * which will disable SMRAM balackhole at SMBASE + */ + if (pd->wmask[MCH_HOST_BRIDGE_F_SMBASE] == 0xff) { + *reg = 0x00; + } + + memory_region_transaction_begin(); + if (*reg & MCH_HOST_BRIDGE_F_SMBASE_LCK) { + /* disable all writes */ + pd->wmask[MCH_HOST_BRIDGE_F_SMBASE] &= + ~MCH_HOST_BRIDGE_F_SMBASE_LCK; + *reg = MCH_HOST_BRIDGE_F_SMBASE_LCK; + lck = true; + } else { + lck = false; + } + memory_region_set_enabled(&mch->smbase_blackhole, lck); + memory_region_set_enabled(&mch->smbase_window, lck); + memory_region_transaction_commit(); +} + static void mch_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len) { @@ -456,6 +496,10 @@ static void mch_write_config(PCIDevice *d, MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_SIZE)) { mch_update_ext_tseg_mbytes(mch); } + + if (ranges_overlap(address, len, MCH_HOST_BRIDGE_F_SMBASE, 1)) { + mch_update_smbase_smram(mch); + } } static void mch_update(MCHPCIState *mch) @@ -464,6 +508,7 @@ static void mch_update(MCHPCIState *mch) mch_update_pam(mch); mch_update_smram(mch); mch_update_ext_tseg_mbytes(mch); + mch_update_smbase_smram(mch); /* * pci hole goes from end-of-low-ram to io-apic. @@ -514,6 +559,9 @@ static void mch_reset(DeviceState *qdev) MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY); } + d->config[MCH_HOST_BRIDGE_F_SMBASE] = 0; + d->wmask[MCH_HOST_BRIDGE_F_SMBASE] = 0xff; + mch_update(mch); } @@ -563,7 +611,7 @@ static void mch_realize(PCIDevice *d, Error **errp) memory_region_add_subregion(&mch->smram, 0xfeda0000, &mch->high_smram); memory_region_init_io(&mch->tseg_blackhole, OBJECT(mch), - &tseg_blackhole_ops, NULL, + &blackhole_ops, NULL, "tseg-blackhole", 0); memory_region_set_enabled(&mch->tseg_blackhole, false); memory_region_add_subregion_overlap(mch->system_memory, @@ -575,6 +623,27 @@ static void mch_realize(PCIDevice *d, Error **errp) memory_region_set_enabled(&mch->tseg_window, false); memory_region_add_subregion(&mch->smram, mch->below_4g_mem_size, &mch->tseg_window); + + /* + * This is not what hardware does, so it's QEMU specific hack. + * See commit message for details. + */ + memory_region_init_io(&mch->smbase_blackhole, OBJECT(mch), &blackhole_ops, + NULL, "smbase-blackhole", + MCH_HOST_BRIDGE_SMBASE_SIZE); + memory_region_set_enabled(&mch->smbase_blackhole, false); + memory_region_add_subregion_overlap(mch->system_memory, + MCH_HOST_BRIDGE_SMBASE_ADDR, + &mch->smbase_blackhole, 1); + + memory_region_init_alias(&mch->smbase_window, OBJECT(mch), + "smbase-window", mch->ram_memory, + MCH_HOST_BRIDGE_SMBASE_ADDR, + MCH_HOST_BRIDGE_SMBASE_SIZE); + memory_region_set_enabled(&mch->smbase_window, false); + memory_region_add_subregion(&mch->smram, MCH_HOST_BRIDGE_SMBASE_ADDR, + &mch->smbase_window); + object_property_add_const_link(qdev_get_machine(), "smram", OBJECT(&mch->smram), &error_abort); @@ -601,6 +670,7 @@ uint64_t mch_mcfg_base(void) static Property mch_props[] = { DEFINE_PROP_UINT16("extended-tseg-mbytes", MCHPCIState, ext_tseg_mbytes, 16), + DEFINE_PROP_BOOL("smbase-smram", MCHPCIState, has_smram_at_smbase, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index b3bcf2e63278..976fbae5996b 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -32,6 +32,7 @@ #include "hw/acpi/ich9.h" #include "hw/pci-host/pam.h" #include "hw/i386/intel_iommu.h" +#include "qemu/units.h" #define TYPE_Q35_HOST_DEVICE "q35-pcihost" #define Q35_HOST_DEVICE(obj) \ @@ -54,6 +55,8 @@ typedef struct MCHPCIState { MemoryRegion smram_region, open_high_smram; MemoryRegion smram, low_smram, high_smram; MemoryRegion tseg_blackhole, tseg_window; + MemoryRegion smbase_blackhole, smbase_window; + bool has_smram_at_smbase; Range pci_hole; uint64_t below_4g_mem_size; uint64_t above_4g_mem_size; @@ -97,6 +100,13 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_QUERY 0xffff #define MCH_HOST_BRIDGE_EXT_TSEG_MBYTES_MAX 0xfff +#define MCH_HOST_BRIDGE_SMBASE_SIZE (128 * KiB) +#define MCH_HOST_BRIDGE_SMBASE_ADDR 0x30000 +#define MCH_HOST_BRIDGE_F_SMBASE 0x9c +#define MCH_HOST_BRIDGE_F_SMBASE_QUERY 0xff +#define MCH_HOST_BRIDGE_F_SMBASE_IN_RAM 0x01 +#define MCH_HOST_BRIDGE_F_SMBASE_LCK 0x02 + #define MCH_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */ #define MCH_HOST_BRIDGE_PCIEXBAR_SIZE 8 /* 64bit register */ #define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000 From 0cdd3eae15964ab589977a09a9765d5a5ca5b9cd Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:46:57 +0100 Subject: [PATCH 02/18] tests: q35: MCH: add default SMBASE SMRAM lock test test lockable SMRAM at default SMBASE feature, introduced by patch "q35: implement 128K SMRAM at default SMBASE address" Signed-off-by: Igor Mammedov Message-Id: <1575899217-333105-1-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/q35-test.c | 105 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/tests/qtest/q35-test.c b/tests/qtest/q35-test.c index a68183d513ac..c922d81bc020 100644 --- a/tests/qtest/q35-test.c +++ b/tests/qtest/q35-test.c @@ -186,6 +186,109 @@ static void test_tseg_size(const void *data) qtest_quit(qts); } +#define SMBASE 0x30000 +#define SMRAM_TEST_PATTERN 0x32 +#define SMRAM_TEST_RESET_PATTERN 0x23 + +static void test_smram_smbase_lock(void) +{ + QPCIBus *pcibus; + QPCIDevice *pcidev; + QDict *response; + QTestState *qts; + int i; + + qts = qtest_init("-M q35"); + + pcibus = qpci_new_pc(qts, NULL); + g_assert(pcibus != NULL); + + pcidev = qpci_device_find(pcibus, 0); + g_assert(pcidev != NULL); + + /* check that SMRAM is not enabled by default */ + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == 0); + qtest_writeb(qts, SMBASE, SMRAM_TEST_PATTERN); + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, SMRAM_TEST_PATTERN); + + /* check that writing junk to 0x9c before before negotiating is ignored */ + for (i = 0; i < 0xff; i++) { + qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_F_SMBASE, i); + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == 0); + } + + /* enable SMRAM at SMBASE */ + qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_F_SMBASE, 0xff); + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == 0x01); + /* lock SMRAM at SMBASE */ + qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_F_SMBASE, 0x02); + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == 0x02); + + /* check that SMRAM at SMBASE is locked and can't be unlocked */ + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, 0xff); + for (i = 0; i <= 0xff; i++) { + /* make sure register is immutable */ + qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_F_SMBASE, i); + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == 0x02); + + /* RAM access should go into black hole */ + qtest_writeb(qts, SMBASE, SMRAM_TEST_PATTERN); + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, 0xff); + } + + /* reset */ + response = qtest_qmp(qts, "{'execute': 'system_reset', 'arguments': {} }"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + qobject_unref(response); + + /* check RAM at SMBASE is available after reset */ + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, SMRAM_TEST_PATTERN); + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == 0); + qtest_writeb(qts, SMBASE, SMRAM_TEST_RESET_PATTERN); + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, SMRAM_TEST_RESET_PATTERN); + + g_free(pcidev); + qpci_free_pc(pcibus); + + qtest_quit(qts); +} + +static void test_without_smram_base(void) +{ + QPCIBus *pcibus; + QPCIDevice *pcidev; + QTestState *qts; + int i; + + qts = qtest_init("-M pc-q35-4.1"); + + pcibus = qpci_new_pc(qts, NULL); + g_assert(pcibus != NULL); + + pcidev = qpci_device_find(pcibus, 0); + g_assert(pcidev != NULL); + + /* check that RAM is accessible */ + qtest_writeb(qts, SMBASE, SMRAM_TEST_PATTERN); + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, SMRAM_TEST_PATTERN); + + /* check that writing to 0x9c succeeds */ + for (i = 0; i <= 0xff; i++) { + qpci_config_writeb(pcidev, MCH_HOST_BRIDGE_F_SMBASE, i); + g_assert(qpci_config_readb(pcidev, MCH_HOST_BRIDGE_F_SMBASE) == i); + } + + /* check that RAM is still accessible */ + qtest_writeb(qts, SMBASE, SMRAM_TEST_PATTERN + 1); + g_assert_cmpint(qtest_readb(qts, SMBASE), ==, (SMRAM_TEST_PATTERN + 1)); + + g_free(pcidev); + qpci_free_pc(pcibus); + + qtest_quit(qts); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -197,5 +300,7 @@ int main(int argc, char **argv) qtest_add_data_func("/q35/tseg-size/8mb", &tseg_8mb, test_tseg_size); qtest_add_data_func("/q35/tseg-size/ext/16mb", &tseg_ext_16mb, test_tseg_size); + qtest_add_func("/q35/smram/smbase_lock", test_smram_smbase_lock); + qtest_add_func("/q35/smram/legacy_smbase", test_without_smram_base); return g_test_run(); } From 1d7a52835dc6bf5d641a0d29ad35c881b8d0ba5a Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:08:57 +0100 Subject: [PATCH 03/18] acpi: cpuhp: spec: clarify 'CPU selector' register usage and endianness * Move reserved registers to the top of the section, so reader would be aware of effects when reading registers description. * State registers endianness explicitly at the beginning of the section * Describe registers behavior in case of 'CPU selector' register contains value that doesn't point to a possible CPU. Signed-off-by: Igor Mammedov Reviewed-by: Laszlo Ersek Message-Id: <1575896942-331151-5-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/specs/acpi_cpu_hotplug.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt index ee219c835808..4e65286ff5b1 100644 --- a/docs/specs/acpi_cpu_hotplug.txt +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -30,6 +30,18 @@ Register block base address: Register block size: ACPI_CPU_HOTPLUG_REG_LEN = 12 +All accesses to registers described below, imply little-endian byte order. + +Reserved resisters behavior: + - write accesses are ignored + - read accesses return all bits set to 0. + +The last stored value in 'CPU selector' must refer to a possible CPU, otherwise + - reads from any register return 0 + - writes to any other register are ignored until valid value is stored into it +On QEMU start, 'CPU selector' is initialized to a valid value, on reset it +keeps the current value. + read access: offset: [0x0-0x3] reserved @@ -86,9 +98,3 @@ write access: ACPI_DEVICE_OST QMP event from QEMU to external applications with current values of OST event and status registers. other values: reserved - -Selecting CPU device beyond possible range has no effect on platform: - - write accesses to CPU hot-plug registers not documented above are - ignored - - read accesses to CPU hot-plug registers not documented above return - all bits set to 0. From 1c1d43bf015df2768bf832ea76752dd95286fc8f Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:08:58 +0100 Subject: [PATCH 04/18] acpi: cpuhp: spec: fix 'Command data' description Correct returned value description in case 'Command field' == 0x0, it's not PXM but CPU selector value with pending event In addition describe 0 blanket value in case of not supported 'Command field' value. Signed-off-by: Igor Mammedov Reviewed-by: Laszlo Ersek Message-Id: <1575896942-331151-6-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/specs/acpi_cpu_hotplug.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt index 4e65286ff5b1..d5108720bfce 100644 --- a/docs/specs/acpi_cpu_hotplug.txt +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -56,9 +56,8 @@ read access: 3-7: reserved and should be ignored by OSPM [0x5-0x7] reserved [0x8] Command data: (DWORD access) - in case of error or unsupported command reads is 0xFFFFFFFF - current 'Command field' value: - 0: returns PXM value corresponding to device + contains 0 unless value last stored in 'Command field' is one of: + 0: contains 'CPU selector' value of a CPU with pending event[s] write access: offset: @@ -81,9 +80,9 @@ write access: value: 0: selects a CPU device with inserting/removing events and following reads from 'Command data' register return - selected CPU (CPU selector value). If no CPU with events - found, the current CPU selector doesn't change and - corresponding insert/remove event flags are not set. + selected CPU ('CPU selector' value). + If no CPU with events found, the current 'CPU selector' doesn't + change and corresponding insert/remove event flags are not modified. 1: following writes to 'Command data' register set OST event register in QEMU 2: following writes to 'Command data' register set OST status From 5b8e5363faa19f6f5064df7f3830c7b56d80f28d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:08:59 +0100 Subject: [PATCH 05/18] acpi: cpuhp: spec: clarify store into 'Command data' when 'Command field' == 0 Write section of 'Command data' register should describe what happens when it's written into. Correct description in case the last stored 'Command field' value is equal to 0, to reflect that currently it's not supported. Signed-off-by: Igor Mammedov Reviewed-by: Laszlo Ersek Message-Id: <1575896942-331151-7-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/specs/acpi_cpu_hotplug.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt index d5108720bfce..8fb9ad22e6eb 100644 --- a/docs/specs/acpi_cpu_hotplug.txt +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -90,8 +90,7 @@ write access: other values: reserved [0x6-0x7] reserved [0x8] Command data: (DWORD access) - current 'Command field' value: - 0: OSPM reads value of CPU selector + if last stored 'Command field' value: 1: stores value into OST event register 2: stores value into OST status register, triggers ACPI_DEVICE_OST QMP event from QEMU to external applications From e6d0c3ce689585ad8f38c826e69ee04fb2c2257c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:09:00 +0100 Subject: [PATCH 06/18] acpi: cpuhp: introduce 'Command data 2' field No functional change in practice, patch only aims to properly document (in spec and code) intended usage of the reserved space. The new field is to be used for 2 purposes: - detection of modern CPU hotplug interface using CPHP_GET_NEXT_CPU_WITH_EVENT_CMD command. procedure will be described in follow up patch: "acpi: cpuhp: spec: add typical usecases" - for returning upper 32 bits of architecture specific CPU ID, for new CPHP_GET_CPU_ID_CMD command added by follow up patch: "acpi: cpuhp: add CPHP_GET_CPU_ID_CMD command" Change is backward compatible with 4.2 and older machines, as field was unconditionally reserved and always returned 0x0 if modern CPU hotplug interface was enabled. Signed-off-by: Igor Mammedov Message-Id: <1575896942-331151-8-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Laszlo Ersek --- docs/specs/acpi_cpu_hotplug.txt | 5 ++++- hw/acpi/cpu.c | 11 +++++++++++ hw/acpi/trace-events | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt index 8fb9ad22e6eb..9879f9ef7e22 100644 --- a/docs/specs/acpi_cpu_hotplug.txt +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -44,7 +44,10 @@ keeps the current value. read access: offset: - [0x0-0x3] reserved + [0x0-0x3] Command data 2: (DWORD access) + if value last stored in 'Command field': + 0: reads as 0x0 + other values: reserved [0x4] CPU device status fields: (1 byte access) bits: 0: Device is enabled and may be used by guest diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 87f30a31d77b..d475c06953c0 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -12,6 +12,7 @@ #define ACPI_CPU_FLAGS_OFFSET_RW 4 #define ACPI_CPU_CMD_OFFSET_WR 5 #define ACPI_CPU_CMD_DATA_OFFSET_RW 8 +#define ACPI_CPU_CMD_DATA2_OFFSET_R 0 enum { CPHP_GET_NEXT_CPU_WITH_EVENT_CMD = 0, @@ -79,6 +80,16 @@ static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, unsigned size) } trace_cpuhp_acpi_read_cmd_data(cpu_st->selector, val); break; + case ACPI_CPU_CMD_DATA2_OFFSET_R: + switch (cpu_st->command) { + case CPHP_GET_NEXT_CPU_WITH_EVENT_CMD: + val = 0; + break; + default: + break; + } + trace_cpuhp_acpi_read_cmd_data2(cpu_st->selector, val); + break; default: break; } diff --git a/hw/acpi/trace-events b/hw/acpi/trace-events index 96b8273297a4..afbc77de1c71 100644 --- a/hw/acpi/trace-events +++ b/hw/acpi/trace-events @@ -23,6 +23,7 @@ cpuhp_acpi_read_flags(uint32_t idx, uint8_t flags) "idx[0x%"PRIx32"] flags: 0x%" cpuhp_acpi_write_idx(uint32_t idx) "set active cpu idx: 0x%"PRIx32 cpuhp_acpi_write_cmd(uint32_t idx, uint8_t cmd) "idx[0x%"PRIx32"] cmd: 0x%"PRIx8 cpuhp_acpi_read_cmd_data(uint32_t idx, uint32_t data) "idx[0x%"PRIx32"] data: 0x%"PRIx32 +cpuhp_acpi_read_cmd_data2(uint32_t idx, uint32_t data) "idx[0x%"PRIx32"] data: 0x%"PRIx32 cpuhp_acpi_cpu_has_events(uint32_t idx, bool ins, bool rm) "idx[0x%"PRIx32"] inserting: %d, removing: %d" cpuhp_acpi_clear_inserting_evt(uint32_t idx) "idx[0x%"PRIx32"]" cpuhp_acpi_clear_remove_evt(uint32_t idx) "idx[0x%"PRIx32"]" From ae340aa3d2567694c48737939496c1e699cad7e2 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:09:01 +0100 Subject: [PATCH 07/18] acpi: cpuhp: spec: add typical usecases Document work-flows for * enabling/detecting modern CPU hotplug interface * finding a CPU with pending 'insert/remove' event * enumerating present and possible CPUs Signed-off-by: Igor Mammedov Message-Id: <1575896942-331151-9-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Laszlo Ersek --- docs/specs/acpi_cpu_hotplug.txt | 51 +++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt index 9879f9ef7e22..cb99cf3c8e7d 100644 --- a/docs/specs/acpi_cpu_hotplug.txt +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -15,14 +15,14 @@ CPU present bitmap for: PIIX-PM (IO port 0xaf00-0xaf1f, 1-byte access) One bit per CPU. Bit position reflects corresponding CPU APIC ID. Read-only. The first DWORD in bitmap is used in write mode to switch from legacy - to new CPU hotplug interface, write 0 into it to do switch. + to modern CPU hotplug interface, write 0 into it to do switch. --------------------------------------------------------------- QEMU sets corresponding CPU bit on hot-add event and issues SCI with GPE.2 event set. CPU present map is read by ACPI BIOS GPE.2 handler to notify OS about CPU hot-add events. CPU hot-remove isn't supported. ===================================== -ACPI CPU hotplug interface registers: +Modern ACPI CPU hotplug interface registers: ------------------------------------- Register block base address: ICH9-LPC IO port 0x0cd8 @@ -67,6 +67,7 @@ write access: [0x0-0x3] CPU selector: (DWORD access) selects active CPU device. All following accesses to other registers will read/store data from/to selected CPU. + Valid values: [0 .. max_cpus) [0x4] CPU device control fields: (1 byte access) bits: 0: reserved, OSPM must clear it before writing to register. @@ -98,4 +99,48 @@ write access: 2: stores value into OST status register, triggers ACPI_DEVICE_OST QMP event from QEMU to external applications with current values of OST event and status registers. - other values: reserved + other values: reserved + +Typical usecases: + - (x86) Detecting and enabling modern CPU hotplug interface. + QEMU starts with legacy CPU hotplug interface enabled. Detecting and + switching to modern interface is based on the 2 legacy CPU hotplug features: + 1. Writes into CPU bitmap are ignored. + 2. CPU bitmap always has bit#0 set, corresponding to boot CPU. + + Use following steps to detect and enable modern CPU hotplug interface: + 1. Store 0x0 to the 'CPU selector' register, + attempting to switch to modern mode + 2. Store 0x0 to the 'CPU selector' register, + to ensure valid selector value + 3. Store 0x0 to the 'Command field' register, + 4. Read the 'Command data 2' register. + If read value is 0x0, the modern interface is enabled. + Otherwise legacy or no CPU hotplug interface available + + - Get a cpu with pending event + 1. Store 0x0 to the 'CPU selector' register. + 2. Store 0x0 to the 'Command field' register. + 3. Read the 'CPU device status fields' register. + 4. If both bit#1 and bit#2 are clear in the value read, there is no CPU + with a pending event and selected CPU remains unchanged. + 5. Otherwise, read the 'Command data' register. The value read is the + selector of the CPU with the pending event (which is already + selected). + + - Enumerate CPUs present/non present CPUs + 01. Set the present CPU count to 0. + 02. Set the iterator to 0. + 03. Store 0x0 to the 'CPU selector' register, to ensure that it's in + a valid state and that access to other registers won't be ignored. + 04. Store 0x0 to the 'Command field' register to make 'Command data' + register return 'CPU selector' value of selected CPU + 05. Read the 'CPU device status fields' register. + 06. If bit#0 is set, increment the present CPU count. + 07. Increment the iterator. + 08. Store the iterator to the 'CPU selector' register. + 09. Read the 'Command data' register. + 10. If the value read is not zero, goto 05. + 11. Otherwise store 0x0 to the 'CPU selector' register, to put it + into a valid state and exit. + The iterator at this point equals "max_cpus". From 3a61c8db9d25ff8ed08c5f96acecd63707187904 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 9 Dec 2019 14:09:02 +0100 Subject: [PATCH 08/18] acpi: cpuhp: add CPHP_GET_CPU_ID_CMD command Firmware can enumerate present at boot APs by broadcasting wakeup IPI, so that woken up secondary CPUs could register them-selves. However in CPU hotplug case, it would need to know architecture specific CPU IDs for possible and hotplugged CPUs so it could prepare environment for and wake hotplugged AP. Reuse and extend existing CPU hotplug interface to return architecture specific ID for currently selected CPU in 2 registers: - lower 32 bits in ACPI_CPU_CMD_DATA_OFFSET_RW - upper 32 bits in ACPI_CPU_CMD_DATA2_OFFSET_R On x86, firmware will use CPHP_GET_CPU_ID_CMD for fetching the APIC ID when handling hotplug SMI. Later, CPHP_GET_CPU_ID_CMD will be used on ARM to retrieve MPIDR, which serves the similar to APIC ID purpose. Signed-off-by: Igor Mammedov Message-Id: <1575896942-331151-10-git-send-email-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Laszlo Ersek --- docs/specs/acpi_cpu_hotplug.txt | 3 +++ hw/acpi/cpu.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/docs/specs/acpi_cpu_hotplug.txt b/docs/specs/acpi_cpu_hotplug.txt index cb99cf3c8e7d..a8ce5e74028f 100644 --- a/docs/specs/acpi_cpu_hotplug.txt +++ b/docs/specs/acpi_cpu_hotplug.txt @@ -47,6 +47,7 @@ read access: [0x0-0x3] Command data 2: (DWORD access) if value last stored in 'Command field': 0: reads as 0x0 + 3: upper 32 bits of architecture specific CPU ID value other values: reserved [0x4] CPU device status fields: (1 byte access) bits: @@ -61,6 +62,8 @@ read access: [0x8] Command data: (DWORD access) contains 0 unless value last stored in 'Command field' is one of: 0: contains 'CPU selector' value of a CPU with pending event[s] + 3: lower 32 bits of architecture specific CPU ID value + (in x86 case: APIC ID) write access: offset: diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index d475c06953c0..e2c957ce008e 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -18,6 +18,7 @@ enum { CPHP_GET_NEXT_CPU_WITH_EVENT_CMD = 0, CPHP_OST_EVENT_CMD = 1, CPHP_OST_STATUS_CMD = 2, + CPHP_GET_CPU_ID_CMD = 3, CPHP_CMD_MAX }; @@ -75,6 +76,9 @@ static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, unsigned size) case CPHP_GET_NEXT_CPU_WITH_EVENT_CMD: val = cpu_st->selector; break; + case CPHP_GET_CPU_ID_CMD: + val = cdev->arch_id & 0xFFFFFFFF; + break; default: break; } @@ -85,6 +89,9 @@ static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, unsigned size) case CPHP_GET_NEXT_CPU_WITH_EVENT_CMD: val = 0; break; + case CPHP_GET_CPU_ID_CMD: + val = cdev->arch_id >> 32; + break; default: break; } From 3c2ab5593bd3b75e0a13f6e9826606a640b46fe0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 17 Jan 2020 07:18:18 -0500 Subject: [PATCH 09/18] bios-tables-test: document expected file update Document the flow for the case where contributor updates the expected files. Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index f1ac2d7e9654..3ab4872bd74b 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -16,7 +16,10 @@ * 1. add empty files for new tables, if any, under tests/data/acpi * 2. list any changed files in tests/bios-tables-test-allowed-diff.h * 3. commit the above *before* making changes that affect the tables - * Maintainer: + * + * Contributor or ACPI Maintainer (steps 4-7 need to be redone to resolve conflicts + * in binary commit created in step 6): + * * After 1-3 above tests will pass but ignore differences with the expected files. * You will also notice that tests/bios-tables-test-allowed-diff.h lists * a bunch of files. This is your hint that you need to do the below: @@ -28,13 +31,23 @@ * output. If not - disassemble them yourself in any way you like. * Look at the differences - make sure they make sense and match what the * changes you are merging are supposed to do. + * Save the changes, preferably in form of ASL diff for the commit log in + * step 6. * * 5. From build directory, run: * $(SRC_PATH)/tests/data/acpi/rebuild-expected-aml.sh - * 6. Now commit any changes. - * 7. Before doing a pull request, make sure tests/bios-tables-test-allowed-diff.h - * is empty - this will ensure following changes to ACPI tables will - * be noticed. + * 6. Now commit any changes to the expected binary, include diff from step 4 + * in commit log. + * 7. Before sending patches to the list (Contributor) + * or before doing a pull request (Maintainer), make sure + * tests/bios-tables-test-allowed-diff.h is empty - this will ensure + * following changes to ACPI tables will be noticed. + * + * The resulting patchset/pull request then looks like this: + * - patch 1: list changed files in tests/bios-tables-test-allowed-diff.h. + * - patches 2 - n: real changes, may contain multiple patches. + * - patch n + 1: update golden master binaries and empty + * tests/bios-tables-test-allowed-diff.h */ #include "qemu/osdep.h" From 9580d60e66d1543a0d79265c0085ee09b8782987 Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Fri, 17 Jan 2020 14:09:26 +0800 Subject: [PATCH 10/18] virtio-9p-device: fix memleak in virtio_9p_device_unrealize v->vq forgot to cleanup in virtio_9p_device_unrealize, the memory leak stack is as follow: Direct leak of 14336 byte(s) in 2 object(s) allocated from: #0 0x7f819ae43970 (/lib64/libasan.so.5+0xef970) ??:? #1 0x7f819872f49d (/lib64/libglib-2.0.so.0+0x5249d) ??:? #2 0x55a3a58da624 (./x86_64-softmmu/qemu-system-x86_64+0x2c14624) /mnt/sdb/qemu/hw/virtio/virtio.c:2327 #3 0x55a3a571bac7 (./x86_64-softmmu/qemu-system-x86_64+0x2a55ac7) /mnt/sdb/qemu/hw/9pfs/virtio-9p-device.c:209 #4 0x55a3a58e7bc6 (./x86_64-softmmu/qemu-system-x86_64+0x2c21bc6) /mnt/sdb/qemu/hw/virtio/virtio.c:3504 #5 0x55a3a5ebfb37 (./x86_64-softmmu/qemu-system-x86_64+0x31f9b37) /mnt/sdb/qemu/hw/core/qdev.c:876 Reported-by: Euler Robot Signed-off-by: Pan Nengyuan Message-Id: <20200117060927.51996-2-pannengyuan@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Christian Schoenebeck Acked-by: Greg Kurz --- hw/9pfs/virtio-9p-device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 991e175c826f..ba35892940c2 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -218,6 +218,7 @@ static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) V9fsVirtioState *v = VIRTIO_9P(dev); V9fsState *s = &v->state; + virtio_del_queue(vdev, 0); virtio_cleanup(vdev); v9fs_device_unrealize_common(s, errp); } From ad30a9e9043ac6ca386d5baca71e6c3d33bfcb9c Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Fri, 17 Jan 2020 14:09:27 +0800 Subject: [PATCH 11/18] virtio-9p-device: convert to new virtio_delete_queue Use virtio_delete_queue to make it more clear. Signed-off-by: Pan Nengyuan Message-Id: <20200117060927.51996-3-pannengyuan@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: Christian Schoenebeck --- hw/9pfs/virtio-9p-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index ba35892940c2..1d1c50409c83 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -218,7 +218,7 @@ static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) V9fsVirtioState *v = VIRTIO_9P(dev); V9fsState *s = &v->state; - virtio_del_queue(vdev, 0); + virtio_delete_queue(v->vq); virtio_cleanup(vdev); v9fs_device_unrealize_common(s, errp); } From dd958f9ef44e2639a384fb9f764ff0bc8181abcd Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Fri, 17 Jan 2020 15:55:46 +0800 Subject: [PATCH 12/18] virtio-scsi: delete vqs in unrealize to avoid memleaks This patch fix memleaks when attaching/detaching virtio-scsi device, the memory leak stack is as follow: Direct leak of 21504 byte(s) in 3 object(s) allocated from: #0 0x7f491f2f2970 (/lib64/libasan.so.5+0xef970) ??:? #1 0x7f491e94649d (/lib64/libglib-2.0.so.0+0x5249d) ??:? #2 0x564d0f3919fa (./x86_64-softmmu/qemu-system-x86_64+0x2c3e9fa) /mnt/sdb/qemu/hw/virtio/virtio.c:2333 #3 0x564d0f2eca55 (./x86_64-softmmu/qemu-system-x86_64+0x2b99a55) /mnt/sdb/qemu/hw/scsi/virtio-scsi.c:912 #4 0x564d0f2ece7b (./x86_64-softmmu/qemu-system-x86_64+0x2b99e7b) /mnt/sdb/qemu/hw/scsi/virtio-scsi.c:924 #5 0x564d0f39ee47 (./x86_64-softmmu/qemu-system-x86_64+0x2c4be47) /mnt/sdb/qemu/hw/virtio/virtio.c:3531 #6 0x564d0f980224 (./x86_64-softmmu/qemu-system-x86_64+0x322d224) /mnt/sdb/qemu/hw/core/qdev.c:865 Reported-by: Euler Robot Signed-off-by: Pan Nengyuan Message-Id: <20200117075547.60864-2-pannengyuan@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi --- hw/scsi/virtio-scsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 4bc73a370efe..858b3aaccb03 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -943,7 +943,13 @@ void virtio_scsi_common_unrealize(DeviceState *dev) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); + int i; + virtio_del_queue(vdev, 0); + virtio_del_queue(vdev, 1); + for (i = 0; i < vs->conf.num_queues; i++) { + virtio_del_queue(vdev, i + 2); + } g_free(vs->cmd_vqs); virtio_cleanup(vdev); } From 2feff67c4e10823604ca2ce8ae933868b558d255 Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Fri, 17 Jan 2020 15:55:47 +0800 Subject: [PATCH 13/18] virtio-scsi: convert to new virtio_delete_queue Use virtio_delete_queue to make it more clear. Signed-off-by: Pan Nengyuan Message-Id: <20200117075547.60864-3-pannengyuan@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefan Hajnoczi --- hw/scsi/virtio-scsi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 858b3aaccb03..d3af42ef9257 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -945,10 +945,10 @@ void virtio_scsi_common_unrealize(DeviceState *dev) VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); int i; - virtio_del_queue(vdev, 0); - virtio_del_queue(vdev, 1); + virtio_delete_queue(vs->ctrl_vq); + virtio_delete_queue(vs->event_vq); for (i = 0; i < vs->conf.num_queues; i++) { - virtio_del_queue(vdev, i + 2); + virtio_delete_queue(vs->cmd_vqs[i]); } g_free(vs->cmd_vqs); virtio_cleanup(vdev); From e1932cf9144a008d85b28c6ff348495cf26e771d Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Wed, 15 Jan 2020 14:25:35 +0800 Subject: [PATCH 14/18] vhost-vsock: delete vqs in vhost_vsock_unrealize to avoid memleaks Receive/transmit/event vqs forgot to cleanup in vhost_vsock_unrealize. This patch save receive/transmit vq pointer in realize() and cleanup vqs through those vq pointers in unrealize(). The leak stack is as follow: Direct leak of 21504 byte(s) in 3 object(s) allocated from: #0 0x7f86a1356970 (/lib64/libasan.so.5+0xef970) ??:? #1 0x7f86a09aa49d (/lib64/libglib-2.0.so.0+0x5249d) ??:? #2 0x5604852f85ca (./x86_64-softmmu/qemu-system-x86_64+0x2c3e5ca) /mnt/sdb/qemu/hw/virtio/virtio.c:2333 #3 0x560485356208 (./x86_64-softmmu/qemu-system-x86_64+0x2c9c208) /mnt/sdb/qemu/hw/virtio/vhost-vsock.c:339 #4 0x560485305a17 (./x86_64-softmmu/qemu-system-x86_64+0x2c4ba17) /mnt/sdb/qemu/hw/virtio/virtio.c:3531 #5 0x5604858e6b65 (./x86_64-softmmu/qemu-system-x86_64+0x322cb65) /mnt/sdb/qemu/hw/core/qdev.c:865 #6 0x5604861e6c41 (./x86_64-softmmu/qemu-system-x86_64+0x3b2cc41) /mnt/sdb/qemu/qom/object.c:2102 Reported-by: Euler Robot Signed-off-by: Pan Nengyuan Message-Id: <20200115062535.50644-1-pannengyuan@huawei.com> Reviewed-by: Stefano Garzarella Reviewed-by: Stefan Hajnoczi Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-vsock.c | 12 ++++++++++-- include/hw/virtio/vhost-vsock.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index f5744363a8a9..b6cee479bbbd 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -335,8 +335,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) sizeof(struct virtio_vsock_config)); /* Receive and transmit queues belong to vhost */ - virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, vhost_vsock_handle_output); - virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, vhost_vsock_handle_output); + vsock->recv_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, + vhost_vsock_handle_output); + vsock->trans_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, + vhost_vsock_handle_output); /* The event queue belongs to QEMU */ vsock->event_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, @@ -363,6 +365,9 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) err_vhost_dev: vhost_dev_cleanup(&vsock->vhost_dev); err_virtio: + virtio_delete_queue(vsock->recv_vq); + virtio_delete_queue(vsock->trans_vq); + virtio_delete_queue(vsock->event_vq); virtio_cleanup(vdev); close(vhostfd); return; @@ -379,6 +384,9 @@ static void vhost_vsock_device_unrealize(DeviceState *dev, Error **errp) vhost_vsock_set_status(vdev, 0); vhost_dev_cleanup(&vsock->vhost_dev); + virtio_delete_queue(vsock->recv_vq); + virtio_delete_queue(vsock->trans_vq); + virtio_delete_queue(vsock->event_vq); virtio_cleanup(vdev); } diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h index d509d67c4a04..bc5a988ee556 100644 --- a/include/hw/virtio/vhost-vsock.h +++ b/include/hw/virtio/vhost-vsock.h @@ -33,6 +33,8 @@ typedef struct { struct vhost_virtqueue vhost_vqs[2]; struct vhost_dev vhost_dev; VirtQueue *event_vq; + VirtQueue *recv_vq; + VirtQueue *trans_vq; QEMUTimer *post_load_timer; /*< public >*/ From ff4776147e960b128ee68f94c728659f662f4378 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 16 Jan 2020 20:24:13 +0000 Subject: [PATCH 15/18] vhost: Add names to section rounded warning Add the memory region names to section rounding/alignment warnings. Signed-off-by: Dr. David Alan Gilbert Message-Id: <20200116202414.157959-2-dgilbert@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 4da0d5a6c586..774d87d98e73 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -590,9 +590,10 @@ static void vhost_region_add_section(struct vhost_dev *dev, * match up in the same RAMBlock if they do. */ if (mrs_gpa < prev_gpa_start) { - error_report("%s:Section rounded to %"PRIx64 - " prior to previous %"PRIx64, - __func__, mrs_gpa, prev_gpa_start); + error_report("%s:Section '%s' rounded to %"PRIx64 + " prior to previous '%s' %"PRIx64, + __func__, section->mr->name, mrs_gpa, + prev_sec->mr->name, prev_gpa_start); /* A way to cleanly fail here would be better */ return; } From 76525114736e8f669766e69b715fa59ce8648aae Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 16 Jan 2020 20:24:14 +0000 Subject: [PATCH 16/18] vhost: Only align sections for vhost-user I added hugepage alignment code in c1ece84e7c9 to deal with vhost-user + postcopy which needs aligned pages when using userfault. However, on x86 the lower 2MB of address space tends to be shotgun'd with small fragments around the 512-640k range - e.g. video RAM, and with HyperV synic pages tend to sit around there - again splitting it up. The alignment code complains with a 'Section rounded to ...' error and gives up. Since vhost-user already filters out devices without an fd (see vhost-user.c vhost_user_mem_section_filter) it shouldn't be affected by those overlaps. Turn the alignment off on vhost-kernel so that it doesn't try and align, and thus won't hit the rounding issues. Signed-off-by: Dr. David Alan Gilbert Message-Id: <20200116202414.157959-3-dgilbert@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Paolo Bonzini --- hw/virtio/vhost.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 774d87d98e73..25fd46917903 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -547,26 +547,28 @@ static void vhost_region_add_section(struct vhost_dev *dev, uintptr_t mrs_host = (uintptr_t)memory_region_get_ram_ptr(section->mr) + section->offset_within_region; RAMBlock *mrs_rb = section->mr->ram_block; - size_t mrs_page = qemu_ram_pagesize(mrs_rb); trace_vhost_region_add_section(section->mr->name, mrs_gpa, mrs_size, mrs_host); - /* Round the section to it's page size */ - /* First align the start down to a page boundary */ - uint64_t alignage = mrs_host & (mrs_page - 1); - if (alignage) { - mrs_host -= alignage; - mrs_size += alignage; - mrs_gpa -= alignage; - } - /* Now align the size up to a page boundary */ - alignage = mrs_size & (mrs_page - 1); - if (alignage) { - mrs_size += mrs_page - alignage; - } - trace_vhost_region_add_section_aligned(section->mr->name, mrs_gpa, mrs_size, - mrs_host); + if (dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER) { + /* Round the section to it's page size */ + /* First align the start down to a page boundary */ + size_t mrs_page = qemu_ram_pagesize(mrs_rb); + uint64_t alignage = mrs_host & (mrs_page - 1); + if (alignage) { + mrs_host -= alignage; + mrs_size += alignage; + mrs_gpa -= alignage; + } + /* Now align the size up to a page boundary */ + alignage = mrs_size & (mrs_page - 1); + if (alignage) { + mrs_size += mrs_page - alignage; + } + trace_vhost_region_add_section_aligned(section->mr->name, mrs_gpa, mrs_size, + mrs_host); + } if (dev->n_tmp_sections) { /* Since we already have at least one section, lets see if From aefcaf9d1b3ebb30981627bd08f595211a648a62 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 20 Jan 2020 11:07:25 -0600 Subject: [PATCH 17/18] i386:acpi: Remove _HID from the SMBus ACPI entry Per the ACPI spec (version 6.1, section 6.1.5 _HID) it is not required on enumerated buses (like PCI in this case), _ADR is required (and is already there). And the _HID value is wrong. Linux appears to ignore the _HID entry, but Windows 10 detects it as 'Unknown Device' and there is no driver available. See https://bugs.launchpad.net/qemu/+bug/1856724 Signed-off-by: Corey Minyard Cc: Michael S. Tsirkin Cc: Igor Mammedov Reviewed-by: Igor Mammedov Message-Id: <20200120170725.24935-6-minyard@acm.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 1 - tests/data/acpi/q35/DSDT | Bin 7879 -> 7869 bytes tests/data/acpi/q35/DSDT.acpihmat | Bin 9203 -> 9193 bytes tests/data/acpi/q35/DSDT.bridge | Bin 7896 -> 7886 bytes tests/data/acpi/q35/DSDT.cphp | Bin 8342 -> 8332 bytes tests/data/acpi/q35/DSDT.dimmpxm | Bin 9532 -> 9522 bytes tests/data/acpi/q35/DSDT.ipmibt | Bin 7954 -> 7944 bytes tests/data/acpi/q35/DSDT.memhp | Bin 9238 -> 9228 bytes tests/data/acpi/q35/DSDT.mmio64 | Bin 9009 -> 8999 bytes tests/data/acpi/q35/DSDT.numamem | Bin 7885 -> 7875 bytes 10 files changed, 1 deletion(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index e25df838f040..9c4e46fa7466 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1816,7 +1816,6 @@ static void build_smb0(Aml *table, I2CBus *smbus, int devnr, int func) Aml *scope = aml_scope("_SB.PCI0"); Aml *dev = aml_device("SMB0"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("APP0005"))); aml_append(dev, aml_name_decl("_ADR", aml_int(devnr << 16 | func))); build_acpi_ipmi_devices(dev, BUS(smbus), "\\_SB.PCI0.SMB0"); aml_append(scope, dev); diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT index 77ea60ffed421c566138fe6341421f579129a582..1f91888d7a485850cf27f152e247a90b208003dc 100644 GIT binary patch delta 42 xcmX?ZyVsV>CDe&h`+ diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm index 23fdf5e60a5069f60d6c680ac9c68c4a8a81318e..02ccdd5f38d5b2356dcca89398c41dcf2595dfff 100644 GIT binary patch delta 42 xcmdnvwaJUiCDv8151UVN}qe1Nm3L39&;u&FFx2QKET=2Ai9Y^*w@Km^J2+-Rsi7S3kU!J delta 52 zcmeCMn`Fo366_KpB+tOWxOgL1ouss?UVN}qe1Nm3L3ER3u&>&QD-BUv81%BUVN}qe1Nm3L3ER3u& Date: Wed, 22 Jan 2020 03:06:47 -0500 Subject: [PATCH 18/18] vhost: coding style fix Drop a trailing whitespace. Make line shorter. Fixes: 76525114736e8 ("vhost: Only align sections for vhost-user") Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 25fd46917903..9edfadc81de6 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -551,7 +551,7 @@ static void vhost_region_add_section(struct vhost_dev *dev, trace_vhost_region_add_section(section->mr->name, mrs_gpa, mrs_size, mrs_host); - if (dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER) { + if (dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER) { /* Round the section to it's page size */ /* First align the start down to a page boundary */ size_t mrs_page = qemu_ram_pagesize(mrs_rb); @@ -566,8 +566,8 @@ static void vhost_region_add_section(struct vhost_dev *dev, if (alignage) { mrs_size += mrs_page - alignage; } - trace_vhost_region_add_section_aligned(section->mr->name, mrs_gpa, mrs_size, - mrs_host); + trace_vhost_region_add_section_aligned(section->mr->name, mrs_gpa, + mrs_size, mrs_host); } if (dev->n_tmp_sections) {