From c6beefd674fff8d41b90365dfccad32e53a5abcb Mon Sep 17 00:00:00 2001 From: Adrian Moreno Date: Tue, 24 Sep 2019 18:20:44 +0200 Subject: [PATCH 01/19] vhost-user: save features if the char dev is closed That way the state can be correctly restored when the device is opened again. This might happen if the backend is restarted. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1738768 Reported-by: Pei Zhang Fixes: 6ab79a20af3a ("do not call vhost_net_cleanup() on running net from char user event") Cc: ddstreet@canonical.com Cc: Michael S. Tsirkin Cc: qemu-stable@nongnu.org Signed-off-by: Adrian Moreno Message-Id: <20190924162044.11414-1-amorenoz@redhat.com> Acked-by: Jason Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- net/vhost-user.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/vhost-user.c b/net/vhost-user.c index 51921de443..014199d600 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -235,6 +235,10 @@ static void chr_closed_bh(void *opaque) s = DO_UPCAST(NetVhostUserState, nc, ncs[0]); + if (s->vhost_net) { + s->acked_features = vhost_net_get_acked_features(s->vhost_net); + } + qmp_set_link(name, false, &err); qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, From 091c466e26867656d3d650a3a5a40169b97648a1 Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:23 +0100 Subject: [PATCH 02/19] hw/acpi: Make ACPI IO address space configurable This is in preparation for adding support for ARM64 platforms where it doesn't use port mapped IO for ACPI IO space. We are making changes so that MMIO region can be accommodated and board can pass the base address into the aml build function. Also move few MEMORY_* definitions to header so that other memory hotplug event signalling mechanisms (eg. Generic Event Device on HW-reduced acpi platforms) can use the same from their respective event handler code. Signed-off-by: Shameer Kolothum Reviewed-by: Eric Auger Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-2-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/memory_hotplug.c | 33 ++++++++++++++------------------ hw/i386/acpi-build.c | 7 ++++++- hw/i386/pc.c | 3 +++ include/hw/acpi/memory_hotplug.h | 9 +++++++-- include/hw/i386/pc.h | 3 +++ 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 9483d66e86..9b0b150f4f 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -30,12 +30,7 @@ #define MEMORY_SLOT_PROXIMITY_METHOD "MPXM" #define MEMORY_SLOT_EJECT_METHOD "MEJ0" #define MEMORY_SLOT_NOTIFY_METHOD "MTFY" -#define MEMORY_SLOT_SCAN_METHOD "MSCN" #define MEMORY_HOTPLUG_DEVICE "MHPD" -#define MEMORY_HOTPLUG_IO_LEN 24 -#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" - -static uint16_t memhp_io_base; static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev) { @@ -210,7 +205,7 @@ static const MemoryRegionOps acpi_memory_hotplug_ops = { }; void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, - MemHotplugState *state, uint16_t io_base) + MemHotplugState *state, hwaddr io_base) { MachineState *machine = MACHINE(qdev_get_machine()); @@ -219,12 +214,10 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, return; } - assert(!memhp_io_base); - memhp_io_base = io_base; state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count); memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state, "acpi-mem-hotplug", MEMORY_HOTPLUG_IO_LEN); - memory_region_add_subregion(as, memhp_io_base, &state->io); + memory_region_add_subregion(as, io_base, &state->io); } /** @@ -343,7 +336,8 @@ const VMStateDescription vmstate_memory_hotplug = { void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, const char *res_root, - const char *event_handler_method) + const char *event_handler_method, + AmlRegionSpace rs, hwaddr memhp_io_base) { int i; Aml *ifctx; @@ -352,10 +346,6 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, Aml *mem_ctrl_dev; char *mhp_res_path; - if (!memhp_io_base) { - return; - } - mhp_res_path = g_strdup_printf("%s." MEMORY_HOTPLUG_DEVICE, res_root); mem_ctrl_dev = aml_device("%s", mhp_res_path); { @@ -366,14 +356,19 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, aml_name_decl("_UID", aml_string("Memory hotplug resources"))); crs = aml_resource_template(); - aml_append(crs, - aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, - MEMORY_HOTPLUG_IO_LEN) - ); + if (rs == AML_SYSTEM_IO) { + aml_append(crs, + aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, + MEMORY_HOTPLUG_IO_LEN) + ); + } else { + aml_append(crs, aml_memory32_fixed(memhp_io_base, + MEMORY_HOTPLUG_IO_LEN, AML_READ_WRITE)); + } aml_append(mem_ctrl_dev, aml_name_decl("_CRS", crs)); aml_append(mem_ctrl_dev, aml_operation_region( - MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO, + MEMORY_HOTPLUG_IO_REGION, rs, aml_int(memhp_io_base), MEMORY_HOTPLUG_IO_LEN) ); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 4e0f9f425a..1d077a7cb7 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1888,7 +1888,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02"); } - build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", "\\_GPE._E03"); + + if (pcms->memhp_io_base && nr_mem) { + build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", + "\\_GPE._E03", AML_SYSTEM_IO, + pcms->memhp_io_base); + } scope = aml_scope("_GPE"); { diff --git a/hw/i386/pc.c b/hw/i386/pc.c index bcda50efcc..4b1904237e 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1766,6 +1766,9 @@ void pc_memory_init(PCMachineState *pcms, /* Init default IOAPIC address space */ pcms->ioapic_as = &address_space_memory; + + /* Init ACPI memory hotplug IO base address */ + pcms->memhp_io_base = ACPI_MEMORY_HOTPLUG_BASE; } /* diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h index 77c65765d6..dfe9cf3fde 100644 --- a/include/hw/acpi/memory_hotplug.h +++ b/include/hw/acpi/memory_hotplug.h @@ -5,6 +5,10 @@ #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" +#define MEMORY_SLOT_SCAN_METHOD "MSCN" +#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" +#define MEMORY_HOTPLUG_IO_LEN 24 + /** * MemStatus: * @is_removing: the memory device in slot has been requested to be ejected. @@ -29,7 +33,7 @@ typedef struct MemHotplugState { } MemHotplugState; void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, - MemHotplugState *state, uint16_t io_base); + MemHotplugState *state, hwaddr io_base); void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, DeviceState *dev, Error **errp); @@ -48,5 +52,6 @@ void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list); void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, const char *res_root, - const char *event_handler_method); + const char *event_handler_method, + AmlRegionSpace rs, hwaddr memhp_io_base); #endif diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 6df4f4b6fb..37bfd95113 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -70,6 +70,9 @@ struct PCMachineState { /* Address space used by IOAPIC device. All IOAPIC interrupts * will be translated to MSI messages in the address space. */ AddressSpace *ioapic_as; + + /* ACPI Memory hotplug IO base address */ + hwaddr memhp_io_base; }; #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" From 22338fea781cd26618b775afec068bc7238ff5c6 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 18 Sep 2019 14:06:24 +0100 Subject: [PATCH 03/19] hw/acpi: Do not create memory hotplug method when handler is not defined With Hardware-reduced ACPI, the GED device will manage ACPI hotplug entirely. As a consequence, make the memory specific events AML generation optional. The code will only be added when the method name is not NULL. Signed-off-by: Samuel Ortiz Signed-off-by: Shameer Kolothum Reviewed-by: Eric Auger Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-3-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/memory_hotplug.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 9b0b150f4f..8d2e82240f 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -712,10 +712,12 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, } aml_append(table, dev_container); - method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); - aml_append(method, - aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD)); - aml_append(table, method); + if (event_handler_method) { + method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); + aml_append(method, aml_call0(MEMORY_DEVICES_CONTAINER "." + MEMORY_SLOT_SCAN_METHOD)); + aml_append(table, method); + } g_free(mhp_res_path); } From ebb62075021a93847682ce67986b9373cbcdc34f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 18 Sep 2019 14:06:25 +0100 Subject: [PATCH 04/19] hw/acpi: Add ACPI Generic Event Device Support The ACPI Generic Event Device (GED) is a hardware-reduced specific device[ACPI v6.1 Section 5.6.9] that handles all platform events, including the hotplug ones. This patch generates the AML code that defines GEDs. Platforms need to specify their own GED Event bitmap to describe what kind of events they want to support through GED. Also this uses a a single interrupt for the GED device, relying on IO memory region to communicate the type of device affected by the interrupt. This way, we can support up to 32 events with a unique interrupt. This supports only memory hotplug for now. Signed-off-by: Samuel Ortiz Signed-off-by: Sebastien Boeuf Signed-off-by: Shameer Kolothum Reviewed-by: Eric Auger Message-Id: <20190918130633.4872-4-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- hw/acpi/Kconfig | 4 + hw/acpi/Makefile.objs | 1 + hw/acpi/generic_event_device.c | 303 +++++++++++++++++++++++++ include/hw/acpi/generic_event_device.h | 100 ++++++++ 4 files changed, 408 insertions(+) create mode 100644 hw/acpi/generic_event_device.c create mode 100644 include/hw/acpi/generic_event_device.h diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig index 7c59cf900b..12e3f1e86e 100644 --- a/hw/acpi/Kconfig +++ b/hw/acpi/Kconfig @@ -31,3 +31,7 @@ config ACPI_VMGENID bool default y depends on PC + +config ACPI_HW_REDUCED + bool + depends on ACPI diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index 9bb2101e3b..655a9c1973 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o +common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o common-obj-y += acpi_interface.o diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c new file mode 100644 index 0000000000..b94500b08d --- /dev/null +++ b/hw/acpi/generic_event_device.c @@ -0,0 +1,303 @@ +/* + * + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd + * Written by Samuel Ortiz, Shameer Kolothum + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "exec/address-spaces.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/generic_event_device.h" +#include "hw/irq.h" +#include "hw/mem/pc-dimm.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" + +static const uint32_t ged_supported_events[] = { + ACPI_GED_MEM_HOTPLUG_EVT, +}; + +/* + * The ACPI Generic Event Device (GED) is a hardware-reduced specific + * device[ACPI v6.1 Section 5.6.9] that handles all platform events, + * including the hotplug ones. Platforms need to specify their own + * GED Event bitmap to describe what kind of events they want to support + * through GED. This routine uses a single interrupt for the GED device, + * relying on IO memory region to communicate the type of device + * affected by the interrupt. This way, we can support up to 32 events + * with a unique interrupt. + */ +void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base) +{ + AcpiGedState *s = ACPI_GED(hotplug_dev); + Aml *crs = aml_resource_template(); + Aml *evt, *field; + Aml *dev = aml_device("%s", name); + Aml *evt_sel = aml_local(0); + Aml *esel = aml_name(AML_GED_EVT_SEL); + + /* _CRS interrupt */ + aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &ged_irq, 1)); + + aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0013"))); + aml_append(dev, aml_name_decl("_UID", aml_string(GED_DEVICE))); + aml_append(dev, aml_name_decl("_CRS", crs)); + + /* Append IO region */ + aml_append(dev, aml_operation_region(AML_GED_EVT_REG, rs, + aml_int(ged_base + ACPI_GED_EVT_SEL_OFFSET), + ACPI_GED_EVT_SEL_LEN)); + field = aml_field(AML_GED_EVT_REG, AML_DWORD_ACC, AML_NOLOCK, + AML_WRITE_AS_ZEROS); + aml_append(field, aml_named_field(AML_GED_EVT_SEL, + ACPI_GED_EVT_SEL_LEN * BITS_PER_BYTE)); + aml_append(dev, field); + + /* + * For each GED event we: + * - Add a conditional block for each event, inside a loop. + * - Call a method for each supported GED event type. + * + * The resulting ASL code looks like: + * + * Local0 = ESEL + * If ((Local0 & One) == One) + * { + * MethodEvent0() + * } + * + * If ((Local0 & 0x2) == 0x2) + * { + * MethodEvent1() + * } + * ... + */ + evt = aml_method("_EVT", 1, AML_SERIALIZED); + { + Aml *if_ctx; + uint32_t i; + uint32_t ged_events = ctpop32(s->ged_event_bitmap); + + /* Local0 = ESEL */ + aml_append(evt, aml_store(esel, evt_sel)); + + for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { + uint32_t event = s->ged_event_bitmap & ged_supported_events[i]; + + if (!event) { + continue; + } + + if_ctx = aml_if(aml_equal(aml_and(evt_sel, aml_int(event), NULL), + aml_int(event))); + switch (event) { + case ACPI_GED_MEM_HOTPLUG_EVT: + aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." + MEMORY_SLOT_SCAN_METHOD)); + break; + default: + /* + * Please make sure all the events in ged_supported_events[] + * are handled above. + */ + g_assert_not_reached(); + } + + aml_append(evt, if_ctx); + ged_events--; + } + + if (ged_events) { + error_report("Unsupported events specified"); + abort(); + } + } + + /* Append _EVT method */ + aml_append(dev, evt); + + aml_append(table, dev); +} + +/* Memory read by the GED _EVT AML dynamic method */ +static uint64_t ged_read(void *opaque, hwaddr addr, unsigned size) +{ + uint64_t val = 0; + GEDState *ged_st = opaque; + + switch (addr) { + case ACPI_GED_EVT_SEL_OFFSET: + /* Read the selector value and reset it */ + val = ged_st->sel; + ged_st->sel = 0; + break; + default: + break; + } + + return val; +} + +/* Nothing is expected to be written to the GED memory region */ +static void ged_write(void *opaque, hwaddr addr, uint64_t data, + unsigned int size) +{ +} + +static const MemoryRegionOps ged_ops = { + .read = ged_read, + .write = ged_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + 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); + } else { + error_setg(errp, "virt: device plug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); + } +} + +static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) +{ + AcpiGedState *s = ACPI_GED(adev); + GEDState *ged_st = &s->ged_state; + uint32_t sel; + + if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { + sel = ACPI_GED_MEM_HOTPLUG_EVT; + } else { + /* Unknown event. Return without generating interrupt. */ + warn_report("GED: Unsupported event %d. No irq injected", ev); + return; + } + + /* + * Set the GED selector field to communicate the event type. + * This will be read by GED aml code to select the appropriate + * event method. + */ + ged_st->sel |= sel; + + /* Trigger the event by sending an interrupt to the guest. */ + qemu_irq_pulse(s->irq); +} + +static Property acpi_ged_properties[] = { + DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription vmstate_memhp_state = { + .name = "acpi-ged/memhp", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_MEMORY_HOTPLUG(memhp_state, AcpiGedState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_ged_state = { + .name = "acpi-ged-state", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(sel, GEDState), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_acpi_ged = { + .name = "acpi-ged", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(ged_state, AcpiGedState, 1, vmstate_ged_state, GEDState), + VMSTATE_END_OF_LIST(), + }, + .subsections = (const VMStateDescription * []) { + &vmstate_memhp_state, + NULL + } +}; + +static void acpi_ged_initfn(Object *obj) +{ + DeviceState *dev = DEVICE(obj); + AcpiGedState *s = ACPI_GED(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + GEDState *ged_st = &s->ged_state; + + memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, + TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); + sysbus_init_mmio(sbd, &ged_st->io); + + sysbus_init_irq(sbd, &s->irq); + + s->memhp_state.is_enabled = true; + /* + * GED handles memory hotplug event and acpi-mem-hotplug + * memory region gets initialized here. Create an exclusive + * container for memory hotplug IO and expose it as GED sysbus + * MMIO so that boards can map it separately. + */ + memory_region_init(&s->container_memhp, OBJECT(dev), "memhp container", + MEMORY_HOTPLUG_IO_LEN); + sysbus_init_mmio(sbd, &s->container_memhp); + acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), + &s->memhp_state, 0); +} + +static void acpi_ged_class_init(ObjectClass *class, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(class); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class); + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); + + dc->desc = "ACPI Generic Event Device"; + dc->props = acpi_ged_properties; + dc->vmsd = &vmstate_acpi_ged; + + hc->plug = acpi_ged_device_plug_cb; + + adevc->send_event = acpi_ged_send_event; +} + +static const TypeInfo acpi_ged_info = { + .name = TYPE_ACPI_GED, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AcpiGedState), + .instance_init = acpi_ged_initfn, + .class_init = acpi_ged_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { TYPE_ACPI_DEVICE_IF }, + { } + } +}; + +static void acpi_ged_register_types(void) +{ + type_register_static(&acpi_ged_info); +} + +type_init(acpi_ged_register_types) diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h new file mode 100644 index 0000000000..2049e8d873 --- /dev/null +++ b/include/hw/acpi/generic_event_device.h @@ -0,0 +1,100 @@ +/* + * + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd + * Written by Samuel Ortiz, Shameer Kolothum + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * The ACPI Generic Event Device (GED) is a hardware-reduced specific + * device[ACPI v6.1 Section 5.6.9] that handles all platform events, + * including the hotplug ones. Generic Event Device allows platforms + * to handle interrupts in ACPI ASL statements. It follows a very + * similar approach like the _EVT method from GPIO events. All + * interrupts are listed in _CRS and the handler is written in _EVT + * method. Here, we use a single interrupt for the GED device, relying + * on IO memory region to communicate the type of device affected by + * the interrupt. This way, we can support up to 32 events with a + * unique interrupt. + * + * Here is an example. + * + * Device (\_SB.GED) + * { + * Name (_HID, "ACPI0013") + * Name (_UID, Zero) + * Name (_CRS, ResourceTemplate () + * { + * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) + * { + * 0x00000029, + * } + * }) + * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) + * Field (EREG, DWordAcc, NoLock, WriteAsZeros) + * { + * ESEL, 32 + * } + * + * Method (_EVT, 1, Serialized) // _EVT: Event + * { + * Local0 = ESEL // ESEL = IO memory region which specifies the + * // device type. + * If (((Local0 & One) == One)) + * { + * MethodEvent1() + * } + * If ((Local0 & 0x2) == 0x2) + * { + * MethodEvent2() + * } + * ... + * } + * } + * + */ + +#ifndef HW_ACPI_GED_H +#define HW_ACPI_GED_H + +#include "hw/sysbus.h" +#include "hw/acpi/memory_hotplug.h" + +#define TYPE_ACPI_GED "acpi-ged" +#define ACPI_GED(obj) \ + OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) + +#define ACPI_GED_EVT_SEL_OFFSET 0x0 +#define ACPI_GED_EVT_SEL_LEN 0x4 + +#define GED_DEVICE "GED" +#define AML_GED_EVT_REG "EREG" +#define AML_GED_EVT_SEL "ESEL" + +/* + * Platforms need to specify the GED event bitmap + * to describe what kind of events they want to support + * through GED. + */ +#define ACPI_GED_MEM_HOTPLUG_EVT 0x1 + +typedef struct GEDState { + MemoryRegion io; + uint32_t sel; +} GEDState; + +typedef struct AcpiGedState { + SysBusDevice parent_obj; + MemHotplugState memhp_state; + MemoryRegion container_memhp; + GEDState ged_state; + uint32_t ged_event_bitmap; + qemu_irq irq; +} AcpiGedState; + +void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, + uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); + +#endif From 1f283ae1245ec79b84c161f8cf17c0518421e2ad Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Wed, 18 Sep 2019 14:06:26 +0100 Subject: [PATCH 05/19] hw/arm/virt: Add memory hotplug framework This patch adds the memory hot-plug/hot-unplug infrastructure in machvirt. The device memory is not yet exposed to the Guest either through DT or ACPI and hence both cold/hot plug of memory is explicitly disabled for now. Signed-off-by: Eric Auger Signed-off-by: Kwangwoo Lee Signed-off-by: Shameer Kolothum Reviewed-by: Peter Maydell Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-5-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/Kconfig | 2 ++ hw/arm/virt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 76a2a6bcbf..39d285ad3d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -20,6 +20,8 @@ config ARM_VIRT select SMBIOS select VIRTIO_MMIO select ACPI_PCI + select MEM_DEVICE + select DIMM config CHEETAH bool diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d74538b021..1c967e3fee 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -68,6 +68,8 @@ #include "hw/arm/smmuv3.h" #include "hw/acpi/acpi.h" #include "target/arm/internals.h" +#include "hw/mem/pc-dimm.h" +#include "hw/mem/nvdimm.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -1876,6 +1878,42 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) return ms->possible_cpus; } +static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + + /* + * The device memory is not yet exposed to the Guest either through + * DT or ACPI and hence both cold/hot plug of memory is explicitly + * disabled for now. + */ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + error_setg(errp, "memory cold/hot plug is not yet supported"); + return; + } + + pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); +} + +static void virt_memory_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + Error *local_err = NULL; + + pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); + + error_propagate(errp, local_err); +} + +static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_memory_pre_plug(hotplug_dev, dev, errp); + } +} + static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1887,12 +1925,23 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, SYS_BUS_DEVICE(dev)); } } + if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { + virt_memory_plug(hotplug_dev, dev, errp); + } +} + +static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + error_setg(errp, "device unplug request for unsupported device" + " type: %s", object_get_typename(OBJECT(dev))); } static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, DeviceState *dev) { - if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) { + if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) || + (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { return HOTPLUG_HANDLER(machine); } @@ -1956,7 +2005,9 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->kvm_type = virt_kvm_type; assert(!mc->get_hotplug_handler); mc->get_hotplug_handler = virt_machine_get_hotplug_handler; + hc->pre_plug = virt_machine_device_pre_plug_cb; hc->plug = virt_machine_device_plug_cb; + hc->unplug_request = virt_machine_device_unplug_request_cb; mc->numa_mem_supported = true; } From cff51ac978c4fa0b3d0de0fd62d772d9003f123e Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:27 +0100 Subject: [PATCH 06/19] hw/arm/virt: Enable device memory cold/hot plug with ACPI boot This initializes the GED device with base memory and irq, configures ged memory hotplug event and builds the corresponding aml code. With this, both hot and cold plug of device memory is enabled now for Guest with ACPI boot. Memory cold plug support with Guest DT boot is not yet supported. As DSDT table gets changed by this, update bios-tables-test-allowed-diff.h to avoid "make check" failure. Signed-off-by: Shameer Kolothum Message-Id: <20190918130633.4872-6-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- hw/arm/Kconfig | 2 + hw/arm/virt-acpi-build.c | 21 ++++++++++ hw/arm/virt.c | 59 +++++++++++++++++++++++---- include/hw/arm/virt.h | 4 ++ tests/bios-tables-test-allowed-diff.h | 1 + 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 39d285ad3d..c6e7782580 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -22,6 +22,8 @@ config ARM_VIRT select ACPI_PCI select MEM_DEVICE select DIMM + select ACPI_MEMORY_HOTPLUG + select ACPI_HW_REDUCED config CHEETAH bool diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 6cdf156cf5..cadeea0f41 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -39,6 +39,8 @@ #include "hw/acpi/aml-build.h" #include "hw/acpi/utils.h" #include "hw/acpi/pci.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/acpi/generic_event_device.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" #include "hw/arm/virt.h" @@ -708,6 +710,7 @@ static void build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { Aml *scope, *dsdt; + MachineState *ms = MACHINE(vms); const MemMapEntry *memmap = vms->memmap; const int *irqmap = vms->irqmap; @@ -732,6 +735,24 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) vms->highmem, vms->highmem_ecam); acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); + if (vms->acpi_dev) { + build_ged_aml(scope, "\\_SB."GED_DEVICE, + HOTPLUG_HANDLER(vms->acpi_dev), + irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, + memmap[VIRT_ACPI_GED].base); + } + + if (vms->acpi_dev) { + uint32_t event = object_property_get_uint(OBJECT(vms->acpi_dev), + "ged-event", &error_abort); + + if (event & ACPI_GED_MEM_HOTPLUG_EVT) { + build_memory_hotplug_aml(scope, ms->ram_slots, "\\_SB", NULL, + AML_SYSTEM_MEMORY, + memmap[VIRT_PCDIMM_ACPI].base); + } + } + acpi_dsdt_add_power_button(scope); aml_append(dsdt, scope); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 1c967e3fee..f926477ba5 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -70,6 +70,7 @@ #include "target/arm/internals.h" #include "hw/mem/pc-dimm.h" #include "hw/mem/nvdimm.h" +#include "hw/acpi/generic_event_device.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -140,6 +141,8 @@ static const MemMapEntry base_memmap[] = { [VIRT_GPIO] = { 0x09030000, 0x00001000 }, [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, [VIRT_SMMU] = { 0x09050000, 0x00020000 }, + [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, + [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -175,6 +178,7 @@ static const int a15irqmap[] = { [VIRT_PCIE] = 3, /* ... to 6 */ [VIRT_GPIO] = 7, [VIRT_SECURE_UART] = 8, + [VIRT_ACPI_GED] = 9, [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ @@ -527,6 +531,29 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) } } +static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) +{ + DeviceState *dev; + MachineState *ms = MACHINE(vms); + int irq = vms->irqmap[VIRT_ACPI_GED]; + uint32_t event = 0; + + if (ms->ram_slots) { + event = ACPI_GED_MEM_HOTPLUG_EVT; + } + + dev = qdev_create(NULL, TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); + + qdev_init_nofail(dev); + + return dev; +} + static void create_its(VirtMachineState *vms, DeviceState *gicdev) { const char *itsclass = its_class_name(); @@ -1491,6 +1518,7 @@ static void machvirt_init(MachineState *machine) MemoryRegion *ram = g_new(MemoryRegion, 1); bool firmware_loaded; bool aarch64 = true; + bool has_ged = !vmc->no_ged; unsigned int smp_cpus = machine->smp.cpus; unsigned int max_cpus = machine->smp.max_cpus; @@ -1705,6 +1733,10 @@ static void machvirt_init(MachineState *machine) create_gpio(vms, pic); + if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { + vms->acpi_dev = create_acpi_ged(vms, pic); + } + /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. @@ -1881,14 +1913,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); - /* - * The device memory is not yet exposed to the Guest either through - * DT or ACPI and hence both cold/hot plug of memory is explicitly - * disabled for now. - */ - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - error_setg(errp, "memory cold/hot plug is not yet supported"); + 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; } @@ -1898,11 +1933,18 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, static void virt_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { + HotplugHandlerClass *hhc; VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); Error *local_err = NULL; pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); + if (local_err) { + goto out; + } + hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); + hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &error_abort); +out: error_propagate(errp, local_err); } @@ -2109,8 +2151,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(4, 2) static void virt_machine_4_1_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_4_2_options(mc); compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); + vmc->no_ged = true; } DEFINE_VIRT_MACHINE(4, 1) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index a72094204e..577ee49b4b 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -77,6 +77,8 @@ enum { VIRT_GPIO, VIRT_SECURE_UART, VIRT_SECURE_MEM, + VIRT_PCDIMM_ACPI, + VIRT_ACPI_GED, VIRT_LOWMEMMAP_LAST, }; @@ -106,6 +108,7 @@ typedef struct { bool claim_edge_triggered_timers; bool smbios_old_sys_ver; bool no_highmem_ecam; + bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */ } VirtMachineClass; typedef struct { @@ -133,6 +136,7 @@ typedef struct { uint32_t iommu_phandle; int psci_conduit; hwaddr highest_gpa; + DeviceState *acpi_dev; } VirtMachineState; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h index dfb8523c8b..7b4adbc822 100644 --- a/tests/bios-tables-test-allowed-diff.h +++ b/tests/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/virt/DSDT", From 442da7dc77af171b800f4f082d245dadd3c6ed75 Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:28 +0100 Subject: [PATCH 07/19] hw/arm/virt-acpi-build: Add PC-DIMM in SRAT Generate Memory Affinity Structures for PC-DIMM ranges. Also, Linux and Windows need ACPI SRAT table to make memory hotplug work properly, however currently QEMU doesn't create SRAT table if numa options aren't present on CLI. Hence add support(>=4.2) to create numa node automatically (auto_enable_numa_with_memhp) when QEMU is started with memory hotplug enabled but without '-numa' options on CLI. Signed-off-by: Shameer Kolothum Signed-off-by: Eric Auger Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-7-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 8 ++++++++ hw/arm/virt.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index cadeea0f41..c97661ad68 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -546,6 +546,14 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } } + if (ms->device_memory) { + numamem = acpi_data_push(table_data, sizeof *numamem); + build_srat_memory(numamem, ms->device_memory->base, + memory_region_size(&ms->device_memory->mr), + ms->numa_state->num_nodes - 1, + MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); + } + build_header(linker, table_data, (void *)(table_data->data + srat_start), "SRAT", table_data->len - srat_start, 3, NULL, NULL); } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f926477ba5..d221841c42 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2051,6 +2051,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->auto_enable_numa_with_memhp = true; } static void virt_instance_init(Object *obj) @@ -2156,6 +2157,7 @@ static void virt_machine_4_1_options(MachineClass *mc) virt_machine_4_2_options(mc); compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); vmc->no_ged = true; + mc->auto_enable_numa_with_memhp = false; } DEFINE_VIRT_MACHINE(4, 1) From c345680cb46f240f62cf2356503d8783033c8180 Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:29 +0100 Subject: [PATCH 08/19] hw/arm: Factor out powerdown notifier from GPIO This is in preparation of using GED device for system_powerdown event. Make the powerdown notifier registration independent of create_gpio() fn. Signed-off-by: Shameer Kolothum Reviewed-by: Eric Auger Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-8-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt.c | 12 ++++-------- include/hw/arm/virt.h | 1 + 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index d221841c42..dbd8c18f36 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -797,10 +797,6 @@ static void virt_powerdown_req(Notifier *n, void *opaque) qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); } -static Notifier virt_system_powerdown_notifier = { - .notify = virt_powerdown_req -}; - static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) { char *nodename; @@ -841,10 +837,6 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) KEY_POWER); qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff", "gpios", phandle, 3, 0); - - /* connect powerdown request */ - qemu_register_powerdown_notifier(&virt_system_powerdown_notifier); - g_free(nodename); } @@ -1737,6 +1729,10 @@ static void machvirt_init(MachineState *machine) vms->acpi_dev = create_acpi_ged(vms, pic); } + /* connect powerdown request */ + vms->powerdown_notifier.notify = virt_powerdown_req; + qemu_register_powerdown_notifier(&vms->powerdown_notifier); + /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 577ee49b4b..0b41083e9d 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -137,6 +137,7 @@ typedef struct { int psci_conduit; hwaddr highest_gpa; DeviceState *acpi_dev; + Notifier powerdown_notifier; } VirtMachineState; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) From 1962f31b86b6fbba41a87a667ef3f58cdac14f3b Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:30 +0100 Subject: [PATCH 09/19] hw/arm: Use GED for system_powerdown event For machines 4.2 or higher with ACPI boot use GED for system_powerdown event instead of GPIO. Guest boot with DT still uses GPIO. Signed-off-by: Shameer Kolothum Reviewed-by: Eric Auger Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-9-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/generic_event_device.c | 8 ++++++++ hw/arm/virt-acpi-build.c | 6 +++--- hw/arm/virt.c | 18 ++++++++++++------ include/hw/acpi/acpi_dev_interface.h | 1 + include/hw/acpi/generic_event_device.h | 3 +++ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index b94500b08d..9cee90cc70 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -22,6 +22,7 @@ static const uint32_t ged_supported_events[] = { ACPI_GED_MEM_HOTPLUG_EVT, + ACPI_GED_PWR_DOWN_EVT, }; /* @@ -104,6 +105,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD)); break; + case ACPI_GED_PWR_DOWN_EVT: + aml_append(if_ctx, + aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), + aml_int(0x80))); + break; default: /* * Please make sure all the events in ged_supported_events[] @@ -184,6 +190,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { sel = ACPI_GED_MEM_HOTPLUG_EVT; + } else if (ev & ACPI_POWER_DOWN_STATUS) { + sel = ACPI_GED_PWR_DOWN_EVT; } else { /* Unknown event. Return without generating interrupt. */ warn_report("GED: Unsupported event %d. No irq injected", ev); diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index c97661ad68..4cd50175e0 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -50,7 +50,6 @@ #include "migration/vmstate.h" #define ARM_SPI_BASE 32 -#define ACPI_POWER_BUTTON_DEVICE "PWRB" static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) { @@ -741,13 +740,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), vms->highmem, vms->highmem_ecam); - acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], - (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); if (vms->acpi_dev) { build_ged_aml(scope, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(vms->acpi_dev), irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, memmap[VIRT_ACPI_GED].base); + } else { + acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], + (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); } if (vms->acpi_dev) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index dbd8c18f36..d4bedc2607 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -536,10 +536,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) DeviceState *dev; MachineState *ms = MACHINE(vms); int irq = vms->irqmap[VIRT_ACPI_GED]; - uint32_t event = 0; + uint32_t event = ACPI_GED_PWR_DOWN_EVT; if (ms->ram_slots) { - event = ACPI_GED_MEM_HOTPLUG_EVT; + event |= ACPI_GED_MEM_HOTPLUG_EVT; } dev = qdev_create(NULL, TYPE_ACPI_GED); @@ -793,8 +793,14 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) static DeviceState *gpio_key_dev; static void virt_powerdown_req(Notifier *n, void *opaque) { - /* use gpio Pin 3 for power button event */ - qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); + VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier); + + if (s->acpi_dev) { + acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS); + } else { + /* use gpio Pin 3 for power button event */ + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); + } } static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) @@ -1723,10 +1729,10 @@ static void machvirt_init(MachineState *machine) create_pcie(vms, pic); - create_gpio(vms, pic); - if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { vms->acpi_dev = create_acpi_ged(vms, pic); + } else { + create_gpio(vms, pic); } /* connect powerdown request */ diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h index 0ba90effd2..a2a12af9b9 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h @@ -13,6 +13,7 @@ typedef enum { ACPI_MEMORY_HOTPLUG_STATUS = 8, ACPI_NVDIMM_HOTPLUG_STATUS = 16, ACPI_VMGENID_CHANGE_STATUS = 32, + ACPI_POWER_DOWN_STATUS = 64, } AcpiEventStatusBits; #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index 2049e8d873..d157eac088 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -62,6 +62,8 @@ #include "hw/sysbus.h" #include "hw/acpi/memory_hotplug.h" +#define ACPI_POWER_BUTTON_DEVICE "PWRB" + #define TYPE_ACPI_GED "acpi-ged" #define ACPI_GED(obj) \ OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) @@ -79,6 +81,7 @@ * through GED. */ #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 +#define ACPI_GED_PWR_DOWN_EVT 0x2 typedef struct GEDState { MemoryRegion io; From e86fba5009055e52ae651c5581a4bb083a43ff41 Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:31 +0100 Subject: [PATCH 10/19] docs/specs: Add ACPI GED documentation Documents basic concepts of ACPI Generic Event device(GED) and interface between QEMU and the ACPI BIOS. Signed-off-by: Shameer Kolothum Reviewed-by: Eric Auger Message-Id: <20190918130633.4872-10-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/specs/acpi_hw_reduced_hotplug.rst | 70 ++++++++++++++++++++++++++ docs/specs/index.rst | 1 + 2 files changed, 71 insertions(+) create mode 100644 docs/specs/acpi_hw_reduced_hotplug.rst diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst new file mode 100644 index 0000000000..911a98255b --- /dev/null +++ b/docs/specs/acpi_hw_reduced_hotplug.rst @@ -0,0 +1,70 @@ +================================================== +QEMU and ACPI BIOS Generic Event Device interface +================================================== + +The ACPI *Generic Event Device* (GED) is a HW reduced platform +specific device introduced in ACPI v6.1 that handles all platform +events, including the hotplug ones. GED is modelled as a device +in the namespace with a _HID defined to be ACPI0013. This document +describes the interface between QEMU and the ACPI BIOS. + +GED allows HW reduced platforms to handle interrupts in ACPI ASL +statements. It follows a very similar approach to the _EVT method +from GPIO events. All interrupts are listed in _CRS and the handler +is written in _EVT method. However, the QEMU implementation uses a +single interrupt for the GED device, relying on an IO memory region +to communicate the type of device affected by the interrupt. This way, +we can support up to 32 events with a unique interrupt. + +**Here is an example,** + +:: + + Device (\_SB.GED) + { + Name (_HID, "ACPI0013") + Name (_UID, Zero) + Name (_CRS, ResourceTemplate () + { + Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) + { + 0x00000029, + } + }) + OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) + Field (EREG, DWordAcc, NoLock, WriteAsZeros) + { + ESEL, 32 + } + Method (_EVT, 1, Serialized) + { + Local0 = ESEL // ESEL = IO memory region which specifies the + // device type. + If (((Local0 & One) == One)) + { + MethodEvent1() + } + If ((Local0 & 0x2) == 0x2) + { + MethodEvent2() + } + ... + } + } + +GED IO interface (4 byte access) +-------------------------------- +**read access:** + +:: + + [0x0-0x3] Event selector bit field (32 bit) set by QEMU. + + bits: + 0: Memory hotplug event + 1: System power down event + 2-31: Reserved + +**write_access:** + +Nothing is expected to be written into GED IO memory diff --git a/docs/specs/index.rst b/docs/specs/index.rst index 40adb97c5e..984ba44029 100644 --- a/docs/specs/index.rst +++ b/docs/specs/index.rst @@ -12,3 +12,4 @@ Contents: ppc-xive ppc-spapr-xive + acpi_hw_reduced_hotplug From cd0f061c78d333f46bd1dab6fdf61d2400256eac Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:32 +0100 Subject: [PATCH 11/19] tests: Update ACPI tables list for upcoming arm/virt tests This is in preparation to add numamem and memhp tests to arm/virt platform. The bios-tables-test-allowed-diff.h is updated with a list of expected ACPI tables that needs to be present in tests/data/acpi/virt folder. Signed-off-by: Shameer Kolothum Message-Id: <20190918130633.4872-11-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- tests/bios-tables-test-allowed-diff.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h index 7b4adbc822..3776dd2f3d 100644 --- a/tests/bios-tables-test-allowed-diff.h +++ b/tests/bios-tables-test-allowed-diff.h @@ -1,2 +1,17 @@ /* List of comma-separated changed AML files to ignore */ "tests/data/acpi/virt/DSDT", +"tests/data/acpi/virt/APIC.memhp", +"tests/data/acpi/virt/APIC.numamem", +"tests/data/acpi/virt/DSDT.memhp", +"tests/data/acpi/virt/DSDT.numamem", +"tests/data/acpi/virt/FACP.memhp", +"tests/data/acpi/virt/FACP.numamem", +"tests/data/acpi/virt/GTDT.memhp", +"tests/data/acpi/virt/GTDT.numamem", +"tests/data/acpi/virt/MCFG.memhp", +"tests/data/acpi/virt/MCFG.numamem", +"tests/data/acpi/virt/SLIT.memhp", +"tests/data/acpi/virt/SPCR.memhp", +"tests/data/acpi/virt/SPCR.numamem", +"tests/data/acpi/virt/SRAT.memhp", +"tests/data/acpi/virt/SRAT.numamem", From 6c35ed68c651f644b6c364190ce7b7019d8b7627 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 29 Sep 2019 10:54:12 -0400 Subject: [PATCH 12/19] tests/acpi: add empty files Needed to make tests pass. Will replace with actual files. Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/virt/APIC.memhp | 0 tests/data/acpi/virt/APIC.numamem | 0 tests/data/acpi/virt/DSDT.memhp | 0 tests/data/acpi/virt/DSDT.numamem | 0 tests/data/acpi/virt/FACP.memhp | 0 tests/data/acpi/virt/FACP.numamem | 0 tests/data/acpi/virt/GTDT.memhp | 0 tests/data/acpi/virt/GTDT.numamem | 0 tests/data/acpi/virt/MCFG.memhp | 0 tests/data/acpi/virt/MCFG.numamem | 0 tests/data/acpi/virt/SLIT.memhp | 0 tests/data/acpi/virt/SPCR.memhp | 0 tests/data/acpi/virt/SPCR.numamem | 0 tests/data/acpi/virt/SRAT.memhp | 0 tests/data/acpi/virt/SRAT.numamem | 0 15 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/acpi/virt/APIC.memhp create mode 100644 tests/data/acpi/virt/APIC.numamem create mode 100644 tests/data/acpi/virt/DSDT.memhp create mode 100644 tests/data/acpi/virt/DSDT.numamem create mode 100644 tests/data/acpi/virt/FACP.memhp create mode 100644 tests/data/acpi/virt/FACP.numamem create mode 100644 tests/data/acpi/virt/GTDT.memhp create mode 100644 tests/data/acpi/virt/GTDT.numamem create mode 100644 tests/data/acpi/virt/MCFG.memhp create mode 100644 tests/data/acpi/virt/MCFG.numamem create mode 100644 tests/data/acpi/virt/SLIT.memhp create mode 100644 tests/data/acpi/virt/SPCR.memhp create mode 100644 tests/data/acpi/virt/SPCR.numamem create mode 100644 tests/data/acpi/virt/SRAT.memhp create mode 100644 tests/data/acpi/virt/SRAT.numamem diff --git a/tests/data/acpi/virt/APIC.memhp b/tests/data/acpi/virt/APIC.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/APIC.numamem b/tests/data/acpi/virt/APIC.numamem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/FACP.memhp b/tests/data/acpi/virt/FACP.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/FACP.numamem b/tests/data/acpi/virt/FACP.numamem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/GTDT.memhp b/tests/data/acpi/virt/GTDT.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/GTDT.numamem b/tests/data/acpi/virt/GTDT.numamem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/MCFG.memhp b/tests/data/acpi/virt/MCFG.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/MCFG.numamem b/tests/data/acpi/virt/MCFG.numamem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/SLIT.memhp b/tests/data/acpi/virt/SLIT.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/SPCR.memhp b/tests/data/acpi/virt/SPCR.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/SPCR.numamem b/tests/data/acpi/virt/SPCR.numamem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/data/acpi/virt/SRAT.numamem b/tests/data/acpi/virt/SRAT.numamem new file mode 100644 index 0000000000..e69de29bb2 From 4eb74c4f4300f754060888924e8eec1339d26bf6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sat, 5 Oct 2019 17:09:17 -0400 Subject: [PATCH 13/19] tests: allow empty expected files An empty expected file is a handy way to seed the files without creating merge conflicts. Signed-off-by: Michael S. Tsirkin --- tests/bios-tables-test.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 9b3d8b0d1b..8b066cc8f9 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -334,7 +334,10 @@ try_again: g_assert(ret); g_assert_no_error(error); g_assert(exp_sdt.aml); - g_assert(exp_sdt.aml_len); + if (!exp_sdt.aml_len) { + fprintf(stderr, "Warning! zero length expected file '%s'\n", + aml_file); + } g_array_append_val(exp_tables, exp_sdt); } From 669c77433b17613b67bacaf6f52a29ea7c5077bb Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Wed, 18 Sep 2019 14:06:33 +0100 Subject: [PATCH 14/19] tests: Add bios tests to arm/virt This adds numamem and memhp tests for arm/virt platform. Signed-off-by: Shameer Kolothum Reviewed-by: Igor Mammedov Message-Id: <20190918130633.4872-12-shameerali.kolothum.thodi@huawei.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/bios-tables-test.c | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 8b066cc8f9..652a78773f 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -873,6 +873,53 @@ static void test_acpi_piix4_tcg_dimm_pxm(void) test_acpi_tcg_dimm_pxm(MACHINE_PC); } +static void test_acpi_virt_tcg_memhp(void) +{ + test_data data = { + .machine = "virt", + .accel = "tcg", + .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", + .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", + .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", + .ram_start = 0x40000000ULL, + .scan_len = 256ULL * 1024 * 1024, + }; + + data.variant = ".memhp"; + test_acpi_one(" -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", + &data); + + free_test_data(&data); + +} + +static void test_acpi_virt_tcg_numamem(void) +{ + test_data data = { + .machine = "virt", + .accel = "tcg", + .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", + .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", + .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", + .ram_start = 0x40000000ULL, + .scan_len = 128ULL * 1024 * 1024, + }; + + data.variant = ".numamem"; + test_acpi_one(" -cpu cortex-a57" + " -object memory-backend-ram,id=ram0,size=128M" + " -numa node,memdev=ram0", + &data); + + free_test_data(&data); + +} + static void test_acpi_virt_tcg(void) { test_data data = { @@ -919,6 +966,8 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); } else if (strcmp(arch, "aarch64") == 0) { qtest_add_func("acpi/virt", test_acpi_virt_tcg); + qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); + qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); } ret = g_test_run(); boot_sector_cleanup(disk); From 30c63d4fbd69acdc3744cbcd277cb5c1dd16f0fc Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sat, 5 Oct 2019 17:25:55 -0400 Subject: [PATCH 15/19] tests: document how to update acpi tables Looks like no one understands how to do it. Document the process. Signed-off-by: Michael S. Tsirkin --- tests/bios-tables-test.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c index 652a78773f..0b33fb265f 100644 --- a/tests/bios-tables-test.c +++ b/tests/bios-tables-test.c @@ -10,6 +10,33 @@ * See the COPYING file in the top-level directory. */ +/* + * How to add or update the tests: + * Contributor: + * 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: + * 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: + * 4. Run + * make check V=1 + * this will produce a bunch of warnings about differences + * beween actual and expected ACPI tables. If you have IASL installed, + * they will also be disassembled so you can look at the disassembled + * 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. + * + * 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. + */ + #include "qemu/osdep.h" #include #include "qemu-common.h" From 2e2b56285e5c82df8d2b320e69ab62a13c8ae3c3 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sat, 5 Oct 2019 17:27:43 -0400 Subject: [PATCH 16/19] tests/acpi: add expected tables for arm/virt Signed-off-by: Michael S. Tsirkin --- tests/bios-tables-test-allowed-diff.h | 16 ---------------- tests/data/acpi/virt/APIC.memhp | Bin 0 -> 168 bytes tests/data/acpi/virt/APIC.numamem | Bin 0 -> 168 bytes tests/data/acpi/virt/DSDT | Bin 18476 -> 18470 bytes tests/data/acpi/virt/DSDT.memhp | Bin 0 -> 19807 bytes tests/data/acpi/virt/DSDT.numamem | Bin 0 -> 18470 bytes tests/data/acpi/virt/FACP.memhp | Bin 0 -> 268 bytes tests/data/acpi/virt/FACP.numamem | Bin 0 -> 268 bytes tests/data/acpi/virt/GTDT.memhp | Bin 0 -> 96 bytes tests/data/acpi/virt/GTDT.numamem | Bin 0 -> 96 bytes tests/data/acpi/virt/MCFG.memhp | Bin 0 -> 60 bytes tests/data/acpi/virt/MCFG.numamem | Bin 0 -> 60 bytes tests/data/acpi/virt/SLIT.memhp | Bin 0 -> 48 bytes tests/data/acpi/virt/SPCR.memhp | Bin 0 -> 80 bytes tests/data/acpi/virt/SPCR.numamem | Bin 0 -> 80 bytes tests/data/acpi/virt/SRAT.memhp | Bin 0 -> 186 bytes tests/data/acpi/virt/SRAT.numamem | Bin 0 -> 106 bytes 17 files changed, 16 deletions(-) diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h index 3776dd2f3d..dfb8523c8b 100644 --- a/tests/bios-tables-test-allowed-diff.h +++ b/tests/bios-tables-test-allowed-diff.h @@ -1,17 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/virt/DSDT", -"tests/data/acpi/virt/APIC.memhp", -"tests/data/acpi/virt/APIC.numamem", -"tests/data/acpi/virt/DSDT.memhp", -"tests/data/acpi/virt/DSDT.numamem", -"tests/data/acpi/virt/FACP.memhp", -"tests/data/acpi/virt/FACP.numamem", -"tests/data/acpi/virt/GTDT.memhp", -"tests/data/acpi/virt/GTDT.numamem", -"tests/data/acpi/virt/MCFG.memhp", -"tests/data/acpi/virt/MCFG.numamem", -"tests/data/acpi/virt/SLIT.memhp", -"tests/data/acpi/virt/SPCR.memhp", -"tests/data/acpi/virt/SPCR.numamem", -"tests/data/acpi/virt/SRAT.memhp", -"tests/data/acpi/virt/SRAT.numamem", diff --git a/tests/data/acpi/virt/APIC.memhp b/tests/data/acpi/virt/APIC.memhp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..797dfde2841c51b7e72065602e99ce1714347f0d 100644 GIT binary patch literal 168 zcmZ<^@N{0mz`($~*~#D8BUr&HBEZ=ZD8>jB1F=Cg4Dd+6SPUF6788)c?E~X6Fu>G{ hBZPn~MyPrgD9sGlkD?67;f3451Xcqw&w(L;0RYV=2>}2A literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/APIC.numamem b/tests/data/acpi/virt/APIC.numamem index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..797dfde2841c51b7e72065602e99ce1714347f0d 100644 GIT binary patch literal 168 zcmZ<^@N{0mz`($~*~#D8BUr&HBEZ=ZD8>jB1F=Cg4Dd+6SPUF6788)c?E~X6Fu>G{ hBZPn~MyPrgD9sGlkD?67;f3451Xcqw&w(L;0RYV=2>}2A literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT index 20e85c7f89f645c69935c615c07084e221419960..bce76e3d23e99e6c5ef64c94c770282dd30ecdd0 100644 GIT binary patch delta 158 zcmZ28fpOUcMlP3Nmk>1%1_q`n6S<@r8#k)uy4O3g$LPfeJH@-Zy2NwDdw9C=Iywh< z8W%@Sdfp4yOWK9nNgF0fuWKiy1_Nb)t!Ndfq{dQizT{|8^m>X w4R-ZW5Rr{{4GZBc0C5r)2u!X{;9_FnVrmNr4|3vah;EVxF(8&rmhcb(0N5-gnE(I) delta 126 zcmZ2BfpN_QMlP3Nmk=Ef1_q{ziCof*?Hko{-K9L(-2?m$IO07#U3eXXd_4>d%nTVg z;vHRrCdP|7GIKHrFfeqoF)%W!GcYhzf@EAh1(mrJdZZZ`p%5q`&cGnaAO~bHGk}Z( RDiq<3cQr6(nEcOO0|1l~7c~F? diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b4b153fcdc30d211237fced6be1e99d3500bd276 100644 GIT binary patch literal 19807 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 B2mt^9 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/GTDT.numamem b/tests/data/acpi/virt/GTDT.numamem index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..10107a65e958ff6495bb8c17d63d0539690f59f6 100644 GIT binary patch literal 96 zcmZ<{aS2IaU|?Xn>E!S15v<@85#a0&6k`O6f!H7#8OTC8azL5|h^3)?DJYFj0RVOU B2mt^9 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/MCFG.memhp b/tests/data/acpi/virt/MCFG.memhp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e8987e1af0ec3829770bf4fe11fab02b06160dd2 100644 GIT binary patch literal 60 scmeZuc5}C3U|?YMck*}k2v%^42ypfViZKGkKx`0=1Oyx)oc|yS05YNo0RR91 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/MCFG.numamem b/tests/data/acpi/virt/MCFG.numamem index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e8987e1af0ec3829770bf4fe11fab02b06160dd2 100644 GIT binary patch literal 60 scmeZuc5}C3U|?YMck*}k2v%^42ypfViZKGkKx`0=1Oyx)oc|yS05YNo0RR91 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/SLIT.memhp b/tests/data/acpi/virt/SLIT.memhp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..74ec3b4b461ffecca36d8537975c202a5f011185 100644 GIT binary patch literal 48 scmWIc@eDCwU|?X>aq@Te2v%^42yhMtiZKGkKx`1r1jHb~B`V4V0NaKK0RR91 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/SPCR.memhp b/tests/data/acpi/virt/SPCR.memhp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..377271a0e7817cc21a28c02123a89facad63604f 100644 GIT binary patch literal 80 zcmWFza1IJ!U|?VpcJg=j2v%^42yhMtiZKGkKx`1r48#l^3?L>agsBLmm>C$E7#RKo I0Z0r60QF4^0RR91 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/SPCR.numamem b/tests/data/acpi/virt/SPCR.numamem index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..377271a0e7817cc21a28c02123a89facad63604f 100644 GIT binary patch literal 80 zcmWFza1IJ!U|?VpcJg=j2v%^42yhMtiZKGkKx`1r48#l^3?L>agsBLmm>C$E7#RKo I0Z0r60QF4^0RR91 literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1b57db2072e7f7e2085c4a427aa31c7383851b71 100644 GIT binary patch literal 186 zcmWFzatztUz`(%l?Bwt45v<@85#SsQ6k`O6f!H7#gkgYL2*!emGHSp?7#yH14wwi` Z4T#UE0q1!TsjdO4?gNx&V1_Y(Gyr))3IPBB literal 0 HcmV?d00001 diff --git a/tests/data/acpi/virt/SRAT.numamem b/tests/data/acpi/virt/SRAT.numamem index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9526e5a28eb2a315d3bc9d9b11852319d5a8898e 100644 GIT binary patch literal 106 zcmWFzatz60U|?Wg?d0$55v<@85#SsQ6k`O6f!H7#gkgYL2*!emGHSp?7#yH14wwi` H4Tui_yqE|9 literal 0 HcmV?d00001 From ddc7757d298b112cd245e537998263943d456472 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 30 Sep 2019 11:51:33 +0100 Subject: [PATCH 17/19] virtio: Add virtio_fs linux headers Pull in the virtio_fs.h linux header and the constant for the virtiofs ID; by running scripts/update-linux-headers.sh against Linus's tree 97f9a3c4eee55b0178b518ae7114a6a53372913d. Signed-off-by: Stefan Hajnoczi Signed-off-by: Vivek Goyal Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Miklos Szeredi Message-Id: <20190930105135.27244-2-dgilbert@redhat.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/standard-headers/linux/virtio_fs.h | 19 +++++++++++++++++++ include/standard-headers/linux/virtio_ids.h | 2 ++ 2 files changed, 21 insertions(+) create mode 100644 include/standard-headers/linux/virtio_fs.h diff --git a/include/standard-headers/linux/virtio_fs.h b/include/standard-headers/linux/virtio_fs.h new file mode 100644 index 0000000000..9d88817a6b --- /dev/null +++ b/include/standard-headers/linux/virtio_fs.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ + +#ifndef _LINUX_VIRTIO_FS_H +#define _LINUX_VIRTIO_FS_H + +#include "standard-headers/linux/types.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_config.h" +#include "standard-headers/linux/virtio_types.h" + +struct virtio_fs_config { + /* Filesystem name (UTF-8, not NUL-terminated, padded with NULs) */ + uint8_t tag[36]; + + /* Number of request queues */ + uint32_t num_request_queues; +} QEMU_PACKED; + +#endif /* _LINUX_VIRTIO_FS_H */ diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h index 32b2f94d1f..585e07b273 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -43,6 +43,8 @@ #define VIRTIO_ID_INPUT 18 /* virtio input */ #define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */ #define VIRTIO_ID_CRYPTO 20 /* virtio crypto */ +#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */ +#define VIRTIO_ID_FS 26 /* virtio filesystem */ #define VIRTIO_ID_PMEM 27 /* virtio pmem */ #endif /* _LINUX_VIRTIO_IDS_H */ From 98fc1ada4cf70af0f1df1a2d7183cf786fc7da05 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 30 Sep 2019 11:51:34 +0100 Subject: [PATCH 18/19] virtio: add vhost-user-fs base device The virtio-fs virtio device provides shared file system access using the FUSE protocol carried over virtio. The actual file server is implemented in an external vhost-user-fs device backend process. Signed-off-by: Stefan Hajnoczi Signed-off-by: Sebastien Boeuf Signed-off-by: Dr. David Alan Gilbert Message-Id: <20190930105135.27244-3-dgilbert@redhat.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- configure | 13 ++ hw/virtio/Makefile.objs | 1 + hw/virtio/vhost-user-fs.c | 299 ++++++++++++++++++++++++++++++ include/hw/virtio/vhost-user-fs.h | 45 +++++ 4 files changed, 358 insertions(+) create mode 100644 hw/virtio/vhost-user-fs.c create mode 100644 include/hw/virtio/vhost-user-fs.h diff --git a/configure b/configure index 8f8446f52b..7bd01b201c 100755 --- a/configure +++ b/configure @@ -381,6 +381,7 @@ vhost_crypto="" vhost_scsi="" vhost_vsock="" vhost_user="" +vhost_user_fs="" kvm="no" hax="no" hvf="no" @@ -1293,6 +1294,10 @@ for opt do ;; --enable-vhost-vsock) vhost_vsock="yes" ;; + --disable-vhost-user-fs) vhost_user_fs="no" + ;; + --enable-vhost-user-fs) vhost_user_fs="yes" + ;; --disable-opengl) opengl="no" ;; --enable-opengl) opengl="yes" @@ -2236,6 +2241,10 @@ test "$vhost_crypto" = "" && vhost_crypto=$vhost_user if test "$vhost_crypto" = "yes" && test "$vhost_user" = "no"; then error_exit "--enable-vhost-crypto requires --enable-vhost-user" fi +test "$vhost_user_fs" = "" && vhost_user_fs=$vhost_user +if test "$vhost_user_fs" = "yes" && test "$vhost_user" = "no"; then + error_exit "--enable-vhost-user-fs requires --enable-vhost-user" +fi # OR the vhost-kernel and vhost-user values for simplicity if test "$vhost_net" = ""; then @@ -6377,6 +6386,7 @@ echo "vhost-crypto support $vhost_crypto" echo "vhost-scsi support $vhost_scsi" echo "vhost-vsock support $vhost_vsock" echo "vhost-user support $vhost_user" +echo "vhost-user-fs support $vhost_user_fs" echo "Trace backends $trace_backends" if have_backend "simple"; then echo "Trace output file $trace_file-" @@ -6873,6 +6883,9 @@ fi if test "$vhost_user" = "yes" ; then echo "CONFIG_VHOST_USER=y" >> $config_host_mak fi +if test "$vhost_user_fs" = "yes" ; then + echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak +fi if test "$blobs" = "yes" ; then echo "INSTALL_BLOBS=yes" >> $config_host_mak fi diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index 964ce78607..47ffbf22c4 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -11,6 +11,7 @@ common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o common-obj-$(CONFIG_VIRTIO_MMIO) += virtio-mmio.o obj-$(CONFIG_VIRTIO_BALLOON) += virtio-balloon.o obj-$(CONFIG_VIRTIO_CRYPTO) += virtio-crypto.o +obj-$(CONFIG_VHOST_USER_FS) += vhost-user-fs.o obj-$(call land,$(CONFIG_VIRTIO_CRYPTO),$(CONFIG_VIRTIO_PCI)) += virtio-crypto-pci.o obj-$(CONFIG_VIRTIO_PMEM) += virtio-pmem.o common-obj-$(call land,$(CONFIG_VIRTIO_PMEM),$(CONFIG_VIRTIO_PCI)) += virtio-pmem-pci.o diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c new file mode 100644 index 0000000000..f0df7f4746 --- /dev/null +++ b/hw/virtio/vhost-user-fs.c @@ -0,0 +1,299 @@ +/* + * Vhost-user filesystem virtio device + * + * Copyright 2018-2019 Red Hat, Inc. + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" +#include +#include "standard-headers/linux/virtio_fs.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/virtio-bus.h" +#include "hw/virtio/virtio-access.h" +#include "qemu/error-report.h" +#include "hw/virtio/vhost-user-fs.h" +#include "monitor/monitor.h" + +static void vuf_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VHostUserFS *fs = VHOST_USER_FS(vdev); + struct virtio_fs_config fscfg = {}; + + memcpy((char *)fscfg.tag, fs->conf.tag, + MIN(strlen(fs->conf.tag) + 1, sizeof(fscfg.tag))); + + virtio_stl_p(vdev, &fscfg.num_request_queues, fs->conf.num_request_queues); + + memcpy(config, &fscfg, sizeof(fscfg)); +} + +static void vuf_start(VirtIODevice *vdev) +{ + VHostUserFS *fs = VHOST_USER_FS(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + int i; + + if (!k->set_guest_notifiers) { + error_report("binding does not support guest notifiers"); + return; + } + + ret = vhost_dev_enable_notifiers(&fs->vhost_dev, vdev); + if (ret < 0) { + error_report("Error enabling host notifiers: %d", -ret); + return; + } + + ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, true); + if (ret < 0) { + error_report("Error binding guest notifier: %d", -ret); + goto err_host_notifiers; + } + + fs->vhost_dev.acked_features = vdev->guest_features; + ret = vhost_dev_start(&fs->vhost_dev, vdev); + if (ret < 0) { + error_report("Error starting vhost: %d", -ret); + goto err_guest_notifiers; + } + + /* + * guest_notifier_mask/pending not used yet, so just unmask + * everything here. virtio-pci will do the right thing by + * enabling/disabling irqfd. + */ + for (i = 0; i < fs->vhost_dev.nvqs; i++) { + vhost_virtqueue_mask(&fs->vhost_dev, vdev, i, false); + } + + return; + +err_guest_notifiers: + k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false); +err_host_notifiers: + vhost_dev_disable_notifiers(&fs->vhost_dev, vdev); +} + +static void vuf_stop(VirtIODevice *vdev) +{ + VHostUserFS *fs = VHOST_USER_FS(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + int ret; + + if (!k->set_guest_notifiers) { + return; + } + + vhost_dev_stop(&fs->vhost_dev, vdev); + + ret = k->set_guest_notifiers(qbus->parent, fs->vhost_dev.nvqs, false); + if (ret < 0) { + error_report("vhost guest notifier cleanup failed: %d", ret); + return; + } + + vhost_dev_disable_notifiers(&fs->vhost_dev, vdev); +} + +static void vuf_set_status(VirtIODevice *vdev, uint8_t status) +{ + VHostUserFS *fs = VHOST_USER_FS(vdev); + bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; + + if (!vdev->vm_running) { + should_start = false; + } + + if (fs->vhost_dev.started == should_start) { + return; + } + + if (should_start) { + vuf_start(vdev); + } else { + vuf_stop(vdev); + } +} + +static uint64_t vuf_get_features(VirtIODevice *vdev, + uint64_t requested_features, + Error **errp) +{ + /* No feature bits used yet */ + return requested_features; +} + +static void vuf_handle_output(VirtIODevice *vdev, VirtQueue *vq) +{ + /* + * Not normally called; it's the daemon that handles the queue; + * however virtio's cleanup path can call this. + */ +} + +static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, + bool mask) +{ + VHostUserFS *fs = VHOST_USER_FS(vdev); + + vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask); +} + +static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) +{ + VHostUserFS *fs = VHOST_USER_FS(vdev); + + return vhost_virtqueue_pending(&fs->vhost_dev, idx); +} + +static void vuf_device_realize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserFS *fs = VHOST_USER_FS(dev); + unsigned int i; + size_t len; + int ret; + + if (!fs->conf.chardev.chr) { + error_setg(errp, "missing chardev"); + return; + } + + if (!fs->conf.tag) { + error_setg(errp, "missing tag property"); + return; + } + len = strlen(fs->conf.tag); + if (len == 0) { + error_setg(errp, "tag property cannot be empty"); + return; + } + if (len > sizeof_field(struct virtio_fs_config, tag)) { + error_setg(errp, "tag property must be %zu bytes or less", + sizeof_field(struct virtio_fs_config, tag)); + return; + } + + if (fs->conf.num_request_queues == 0) { + error_setg(errp, "num-request-queues property must be larger than 0"); + return; + } + + if (!is_power_of_2(fs->conf.queue_size)) { + error_setg(errp, "queue-size property must be a power of 2"); + return; + } + + if (fs->conf.queue_size > VIRTQUEUE_MAX_SIZE) { + error_setg(errp, "queue-size property must be %u or smaller", + VIRTQUEUE_MAX_SIZE); + return; + } + + if (!vhost_user_init(&fs->vhost_user, &fs->conf.chardev, errp)) { + return; + } + + virtio_init(vdev, "vhost-user-fs", VIRTIO_ID_FS, + sizeof(struct virtio_fs_config)); + + /* Hiprio queue */ + virtio_add_queue(vdev, fs->conf.queue_size, vuf_handle_output); + + /* Request queues */ + for (i = 0; i < fs->conf.num_request_queues; i++) { + virtio_add_queue(vdev, fs->conf.queue_size, vuf_handle_output); + } + + /* 1 high prio queue, plus the number configured */ + fs->vhost_dev.nvqs = 1 + fs->conf.num_request_queues; + fs->vhost_dev.vqs = g_new0(struct vhost_virtqueue, fs->vhost_dev.nvqs); + ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user, + VHOST_BACKEND_TYPE_USER, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "vhost_dev_init failed"); + goto err_virtio; + } + + return; + +err_virtio: + vhost_user_cleanup(&fs->vhost_user); + virtio_cleanup(vdev); + g_free(fs->vhost_dev.vqs); + return; +} + +static void vuf_device_unrealize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserFS *fs = VHOST_USER_FS(dev); + + /* This will stop vhost backend if appropriate. */ + vuf_set_status(vdev, 0); + + vhost_dev_cleanup(&fs->vhost_dev); + + vhost_user_cleanup(&fs->vhost_user); + + virtio_cleanup(vdev); + g_free(fs->vhost_dev.vqs); + fs->vhost_dev.vqs = NULL; +} + +static const VMStateDescription vuf_vmstate = { + .name = "vhost-user-fs", + .unmigratable = 1, +}; + +static Property vuf_properties[] = { + DEFINE_PROP_CHR("chardev", VHostUserFS, conf.chardev), + DEFINE_PROP_STRING("tag", VHostUserFS, conf.tag), + DEFINE_PROP_UINT16("num-request-queues", VHostUserFS, + conf.num_request_queues, 1), + DEFINE_PROP_UINT16("queue-size", VHostUserFS, conf.queue_size, 128), + DEFINE_PROP_STRING("vhostfd", VHostUserFS, conf.vhostfd), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vuf_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + dc->props = vuf_properties; + dc->vmsd = &vuf_vmstate; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + vdc->realize = vuf_device_realize; + vdc->unrealize = vuf_device_unrealize; + vdc->get_features = vuf_get_features; + vdc->get_config = vuf_get_config; + vdc->set_status = vuf_set_status; + vdc->guest_notifier_mask = vuf_guest_notifier_mask; + vdc->guest_notifier_pending = vuf_guest_notifier_pending; +} + +static const TypeInfo vuf_info = { + .name = TYPE_VHOST_USER_FS, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VHostUserFS), + .class_init = vuf_class_init, +}; + +static void vuf_register_types(void) +{ + type_register_static(&vuf_info); +} + +type_init(vuf_register_types) diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h new file mode 100644 index 0000000000..539885b458 --- /dev/null +++ b/include/hw/virtio/vhost-user-fs.h @@ -0,0 +1,45 @@ +/* + * Vhost-user filesystem virtio device + * + * Copyright 2018-2019 Red Hat, Inc. + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#ifndef _QEMU_VHOST_USER_FS_H +#define _QEMU_VHOST_USER_FS_H + +#include "hw/virtio/virtio.h" +#include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" +#include "chardev/char-fe.h" + +#define TYPE_VHOST_USER_FS "vhost-user-fs-device" +#define VHOST_USER_FS(obj) \ + OBJECT_CHECK(VHostUserFS, (obj), TYPE_VHOST_USER_FS) + +typedef struct { + CharBackend chardev; + char *tag; + uint16_t num_request_queues; + uint16_t queue_size; + char *vhostfd; +} VHostUserFSConf; + +typedef struct { + /*< private >*/ + VirtIODevice parent; + VHostUserFSConf conf; + struct vhost_virtqueue *vhost_vqs; + struct vhost_dev vhost_dev; + VhostUserState vhost_user; + + /*< public >*/ +} VHostUserFS; + +#endif /* _QEMU_VHOST_USER_FS_H */ From 9d59bed1da5e5815987879346cf708344060ea63 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Mon, 30 Sep 2019 11:51:35 +0100 Subject: [PATCH 19/19] virtio: add vhost-user-fs-pci device Add the PCI version of vhost-user-fs. Launch QEMU like this: qemu -chardev socket,path=/tmp/vhost-fs.sock,id=chr0 -device vhost-user-fs-pci,tag=myfs,chardev=chr0 Signed-off-by: Stefan Hajnoczi Signed-off-by: Sebastien Boeuf Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Cornelia Huck Message-Id: <20190930105135.27244-4-dgilbert@redhat.com> Acked-by: Peter Maydell Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/Makefile.objs | 1 + hw/virtio/vhost-user-fs-pci.c | 85 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 hw/virtio/vhost-user-fs-pci.c diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs index 47ffbf22c4..e2f70fbb89 100644 --- a/hw/virtio/Makefile.objs +++ b/hw/virtio/Makefile.objs @@ -15,6 +15,7 @@ obj-$(CONFIG_VHOST_USER_FS) += vhost-user-fs.o obj-$(call land,$(CONFIG_VIRTIO_CRYPTO),$(CONFIG_VIRTIO_PCI)) += virtio-crypto-pci.o obj-$(CONFIG_VIRTIO_PMEM) += virtio-pmem.o common-obj-$(call land,$(CONFIG_VIRTIO_PMEM),$(CONFIG_VIRTIO_PCI)) += virtio-pmem-pci.o +obj-$(call land,$(CONFIG_VHOST_USER_FS),$(CONFIG_VIRTIO_PCI)) += vhost-user-fs-pci.o obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o ifeq ($(CONFIG_VIRTIO_PCI),y) diff --git a/hw/virtio/vhost-user-fs-pci.c b/hw/virtio/vhost-user-fs-pci.c new file mode 100644 index 0000000000..933a3f265b --- /dev/null +++ b/hw/virtio/vhost-user-fs-pci.c @@ -0,0 +1,85 @@ +/* + * Vhost-user filesystem virtio device PCI glue + * + * Copyright 2018-2019 Red Hat, Inc. + * + * Authors: + * Dr. David Alan Gilbert + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/vhost-user-fs.h" +#include "virtio-pci.h" + +struct VHostUserFSPCI { + VirtIOPCIProxy parent_obj; + VHostUserFS vdev; +}; + +typedef struct VHostUserFSPCI VHostUserFSPCI; + +#define TYPE_VHOST_USER_FS_PCI "vhost-user-fs-pci-base" + +#define VHOST_USER_FS_PCI(obj) \ + OBJECT_CHECK(VHostUserFSPCI, (obj), TYPE_VHOST_USER_FS_PCI) + +static Property vhost_user_fs_pci_properties[] = { + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, + DEV_NVECTORS_UNSPECIFIED), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vhost_user_fs_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VHostUserFSPCI *dev = VHOST_USER_FS_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { + vpci_dev->nvectors = dev->vdev.conf.num_request_queues + 1; + } + + qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); + object_property_set_bool(OBJECT(vdev), true, "realized", errp); +} + +static void vhost_user_fs_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->realize = vhost_user_fs_pci_realize; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->props = vhost_user_fs_pci_properties; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */ + pcidev_k->revision = 0x00; + pcidev_k->class_id = PCI_CLASS_STORAGE_OTHER; +} + +static void vhost_user_fs_pci_instance_init(Object *obj) +{ + VHostUserFSPCI *dev = VHOST_USER_FS_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_FS); +} + +static const VirtioPCIDeviceTypeInfo vhost_user_fs_pci_info = { + .base_name = TYPE_VHOST_USER_FS_PCI, + .non_transitional_name = "vhost-user-fs-pci", + .instance_size = sizeof(VHostUserFSPCI), + .instance_init = vhost_user_fs_pci_instance_init, + .class_init = vhost_user_fs_pci_class_init, +}; + +static void vhost_user_fs_pci_register(void) +{ + virtio_pci_types_register(&vhost_user_fs_pci_info); +} + +type_init(vhost_user_fs_pci_register);