From 23609e47c0f62b537ba9803cb15e69993fd0c266 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:06 -0400 Subject: [PATCH 001/180] acpi: add interface to build device specific AML There is already ISADeviceClass::build_aml() callback which builds device specific AML blob for some ISA devices. To extend the same idea to other devices, add TYPE_ACPI_DEV_AML_IF Interface that will provide a more generic callback which will be used not only for ISA but other devices. It will allow get rid of some data-mining and ad-hoc AML building, by asking device(s) to generate its own AML blob like it's done for ISA devices. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-2-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/acpi_interface.c | 8 ++++++ hw/acpi/meson.build | 2 +- include/hw/acpi/acpi_aml_interface.h | 40 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 include/hw/acpi/acpi_aml_interface.h diff --git a/hw/acpi/acpi_interface.c b/hw/acpi/acpi_interface.c index 6583917b8e..c668d361f6 100644 --- a/hw/acpi/acpi_interface.c +++ b/hw/acpi/acpi_interface.c @@ -1,5 +1,6 @@ #include "qemu/osdep.h" #include "hw/acpi/acpi_dev_interface.h" +#include "hw/acpi/acpi_aml_interface.h" #include "qemu/module.h" void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event) @@ -18,8 +19,15 @@ static void register_types(void) .parent = TYPE_INTERFACE, .class_size = sizeof(AcpiDeviceIfClass), }; + static const TypeInfo acpi_dev_aml_if_info = { + .name = TYPE_ACPI_DEV_AML_IF, + .parent = TYPE_INTERFACE, + .class_size = sizeof(AcpiDevAmlIfClass), + }; + type_register_static(&acpi_dev_if_info); + type_register_static(&acpi_dev_aml_if_info); } type_init(register_types) diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index cea2f5f93a..f8c820ca94 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -29,7 +29,7 @@ acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c')) if have_tpm acpi_ss.add(files('tpm.c')) endif -softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c')) +softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c')) softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c', 'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c', diff --git a/include/hw/acpi/acpi_aml_interface.h b/include/hw/acpi/acpi_aml_interface.h new file mode 100644 index 0000000000..ab76f0e55d --- /dev/null +++ b/include/hw/acpi/acpi_aml_interface.h @@ -0,0 +1,40 @@ +#ifndef ACPI_AML_INTERFACE_H +#define ACPI_AML_INTERFACE_H + +#include "qom/object.h" +#include "hw/acpi/aml-build.h" + +#define TYPE_ACPI_DEV_AML_IF "acpi-dev-aml-interface" +typedef struct AcpiDevAmlIfClass AcpiDevAmlIfClass; +DECLARE_CLASS_CHECKERS(AcpiDevAmlIfClass, ACPI_DEV_AML_IF, TYPE_ACPI_DEV_AML_IF) +#define ACPI_DEV_AML_IF(obj) \ + INTERFACE_CHECK(AcpiDevAmlIf, (obj), TYPE_ACPI_DEV_AML_IF) + +typedef struct AcpiDevAmlIf AcpiDevAmlIf; +typedef void (*dev_aml_fn)(AcpiDevAmlIf *adev, Aml *scope); + +/** + * AcpiDevAmlIfClass: + * + * build_dev_aml: adds device specific AML blob to provided scope + * + * Interface is designed for providing generic callback that builds device + * specific AML blob. + */ +struct AcpiDevAmlIfClass { + /* */ + InterfaceClass parent_class; + + /* */ + dev_aml_fn build_dev_aml; +}; + +static inline void call_dev_aml_func(DeviceState *dev, Aml *scope) +{ + if (object_dynamic_cast(OBJECT(dev), TYPE_ACPI_DEV_AML_IF)) { + AcpiDevAmlIfClass *klass = ACPI_DEV_AML_IF_GET_CLASS(dev); + klass->build_dev_aml(ACPI_DEV_AML_IF(dev), scope); + } +} + +#endif From f974e0b75b42e50e6f3d529603e316df3e571ca1 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:07 -0400 Subject: [PATCH 002/180] acpi: make isa_build_aml() support AcpiDevAmlIf interface To allow incremental conversion from ISADeviceClass::build_aml to AcpiDevAmlIf, add support for the later without removing the former. Once conversion is complete, another commit will drop ISADeviceClass::build_aml related code. Signed-off-by: Igor Mammedov Reviewed-by: Ani Sinha Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-3-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/isa/isa-bus.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index cd5ad3687d..237e2cee12 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -24,6 +24,7 @@ #include "hw/sysbus.h" #include "sysemu/sysemu.h" #include "hw/isa/isa.h" +#include "hw/acpi/acpi_aml_interface.h" static ISABus *isabus; @@ -196,8 +197,12 @@ void isa_build_aml(ISABus *bus, Aml *scope) QTAILQ_FOREACH(kid, &bus->parent_obj.children, sibling) { dev = ISA_DEVICE(kid->child); dc = ISA_DEVICE_GET_CLASS(dev); + bool has_build_dev_aml = !!object_dynamic_cast(OBJECT(dev), + TYPE_ACPI_DEV_AML_IF); if (dc->build_aml) { dc->build_aml(dev, scope); + } else if (has_build_dev_aml) { + call_dev_aml_func(DEVICE(dev), scope); } } } From e7c72a678ab707e1c76c5cdf9befb410cb25e72c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:08 -0400 Subject: [PATCH 003/180] acpi: fdc-isa: replace ISADeviceClass::build_aml with AcpiDevAmlIfClass:build_dev_aml Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-4-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/fdc-isa.c | 16 ++++++++++------ hw/i386/acpi-build.c | 1 - 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/hw/block/fdc-isa.c b/hw/block/fdc-isa.c index fa20450747..fee1ca68a8 100644 --- a/hw/block/fdc-isa.c +++ b/hw/block/fdc-isa.c @@ -32,7 +32,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/timer.h" -#include "hw/acpi/aml-build.h" +#include "hw/acpi/acpi_aml_interface.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -214,9 +214,9 @@ int cmos_get_fd_drive_type(FloppyDriveType fd0) return val; } -static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope) +static void build_fdc_aml(AcpiDevAmlIf *adev, Aml *scope) { - FDCtrlISABus *isa = ISA_FDC(isadev); + FDCtrlISABus *isa = ISA_FDC(adev); Aml *dev; Aml *crs; int i; @@ -241,7 +241,7 @@ static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope) aml_append(dev, aml_name_decl("_CRS", crs)); for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) { - FloppyDriveType type = isa_fdc_get_drive_type(isadev, i); + FloppyDriveType type = isa_fdc_get_drive_type(ISA_DEVICE(adev), i); if (type < FLOPPY_DRIVE_TYPE_NONE) { fde_buf[i] = cpu_to_le32(1); /* drive present */ @@ -283,14 +283,14 @@ static Property isa_fdc_properties[] = { static void isabus_fdc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->desc = "virtual floppy controller"; dc->realize = isabus_fdc_realize; dc->fw_name = "fdc"; dc->reset = fdctrl_external_reset_isa; dc->vmsd = &vmstate_isa_fdc; - isa->build_aml = fdc_isa_build_aml; + adevc->build_dev_aml = build_fdc_aml; device_class_set_props(dc, isa_fdc_properties); set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } @@ -313,6 +313,10 @@ static const TypeInfo isa_fdc_info = { .instance_size = sizeof(FDCtrlISABus), .class_init = isabus_fdc_class_init, .instance_init = isabus_fdc_instance_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void isa_fdc_register_types(void) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index c125939ed6..1449832aa9 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -40,7 +40,6 @@ #include "hw/acpi/bios-linker-loader.h" #include "hw/isa/isa.h" #include "hw/input/i8042.h" -#include "hw/block/fdc.h" #include "hw/acpi/memory_hotplug.h" #include "sysemu/tpm.h" #include "hw/acpi/tpm.h" From ef26fc47baf57be482e5d32bfe9b4769906f5eb7 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:09 -0400 Subject: [PATCH 004/180] acpi: parallel port: replace ISADeviceClass::build_aml with AcpiDevAmlIfClass:build_dev_aml Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-5-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/char/parallel.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/char/parallel.c b/hw/char/parallel.c index f735a6cd7f..1c9ca47820 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -28,7 +28,7 @@ #include "qemu/module.h" #include "chardev/char-parallel.h" #include "chardev/char-fe.h" -#include "hw/acpi/aml-build.h" +#include "hw/acpi/acpi_aml_interface.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -570,9 +570,9 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp) s, "parallel"); } -static void parallel_isa_build_aml(ISADevice *isadev, Aml *scope) +static void parallel_isa_build_aml(AcpiDevAmlIf *adev, Aml *scope) { - ISAParallelState *isa = ISA_PARALLEL(isadev); + ISAParallelState *isa = ISA_PARALLEL(adev); Aml *dev; Aml *crs; @@ -645,11 +645,11 @@ static Property parallel_isa_properties[] = { static void parallel_isa_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->realize = parallel_isa_realizefn; dc->vmsd = &vmstate_parallel_isa; - isa->build_aml = parallel_isa_build_aml; + adevc->build_dev_aml = parallel_isa_build_aml; device_class_set_props(dc, parallel_isa_properties); set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -659,6 +659,10 @@ static const TypeInfo parallel_isa_info = { .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(ISAParallelState), .class_init = parallel_isa_class_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void parallel_register_types(void) From 0d170dc13c54d46566fb1717f9342826b8c0c7de Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:10 -0400 Subject: [PATCH 005/180] acpi: serial-is: replace ISADeviceClass::build_aml with AcpiDevAmlIfClass:build_dev_aml Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-6-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/char/serial-isa.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index 7a7ed239cd..141a6cb168 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -27,7 +27,7 @@ #include "qapi/error.h" #include "qemu/module.h" #include "sysemu/sysemu.h" -#include "hw/acpi/aml-build.h" +#include "hw/acpi/acpi_aml_interface.h" #include "hw/char/serial.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -83,9 +83,9 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(isadev, &s->io, isa->iobase); } -static void serial_isa_build_aml(ISADevice *isadev, Aml *scope) +static void serial_isa_build_aml(AcpiDevAmlIf *adev, Aml *scope) { - ISASerialState *isa = ISA_SERIAL(isadev); + ISASerialState *isa = ISA_SERIAL(adev); Aml *dev; Aml *crs; @@ -122,11 +122,11 @@ static Property serial_isa_properties[] = { static void serial_isa_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->realize = serial_isa_realizefn; dc->vmsd = &vmstate_isa_serial; - isa->build_aml = serial_isa_build_aml; + adevc->build_dev_aml = serial_isa_build_aml; device_class_set_props(dc, serial_isa_properties); set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -146,6 +146,10 @@ static const TypeInfo serial_isa_info = { .instance_size = sizeof(ISASerialState), .instance_init = serial_isa_initfn, .class_init = serial_isa_class_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void serial_register_types(void) From d9cf178cc0bcad20fb2c6f1a08bb24a2b45c1c77 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:11 -0400 Subject: [PATCH 006/180] acpi: mc146818rtc: replace ISADeviceClass::build_aml with AcpiDevAmlIfClass:build_dev_aml Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-7-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/rtc/mc146818rtc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index f235c2ddbe..ef9765bb8f 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -26,7 +26,7 @@ #include "qemu/cutils.h" #include "qemu/module.h" #include "qemu/bcd.h" -#include "hw/acpi/aml-build.h" +#include "hw/acpi/acpi_aml_interface.h" #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" @@ -1017,9 +1017,9 @@ static void rtc_reset_hold(Object *obj) qemu_irq_lower(s->irq); } -static void rtc_build_aml(ISADevice *isadev, Aml *scope) +static void rtc_build_aml(AcpiDevAmlIf *adev, Aml *scope) { - RTCState *s = MC146818_RTC(isadev); + RTCState *s = MC146818_RTC(adev); Aml *dev; Aml *crs; @@ -1043,13 +1043,13 @@ static void rtc_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass); - ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->realize = rtc_realizefn; dc->vmsd = &vmstate_rtc; rc->phases.enter = rtc_reset_enter; rc->phases.hold = rtc_reset_hold; - isa->build_aml = rtc_build_aml; + adevc->build_dev_aml = rtc_build_aml; device_class_set_props(dc, mc146818rtc_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); } @@ -1059,6 +1059,10 @@ static const TypeInfo mc146818rtc_info = { .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(RTCState), .class_init = rtc_class_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void mc146818rtc_register_types(void) From 68f01317b4e43ef67ef9cffd646773a4db857fbf Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:12 -0400 Subject: [PATCH 007/180] acpi: pckbd: replace ISADeviceClass::build_aml with AcpiDevAmlIfClass:build_dev_aml Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-8-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/input/pckbd.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index 4efdf75620..45c40fe3f3 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -29,7 +29,7 @@ #include "qapi/error.h" #include "hw/isa/isa.h" #include "migration/vmstate.h" -#include "hw/acpi/aml-build.h" +#include "hw/acpi/acpi_aml_interface.h" #include "hw/input/ps2.h" #include "hw/irq.h" #include "hw/input/i8042.h" @@ -767,9 +767,9 @@ static void i8042_realizefn(DeviceState *dev, Error **errp) qemu_register_reset(kbd_reset, s); } -static void i8042_build_aml(ISADevice *isadev, Aml *scope) +static void i8042_build_aml(AcpiDevAmlIf *adev, Aml *scope) { - ISAKBDState *isa_s = I8042(isadev); + ISAKBDState *isa_s = I8042(adev); Aml *kbd; Aml *mou; Aml *crs; @@ -807,12 +807,12 @@ static Property i8042_properties[] = { static void i8042_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); device_class_set_props(dc, i8042_properties); dc->realize = i8042_realizefn; dc->vmsd = &vmstate_kbd_isa; - isa->build_aml = i8042_build_aml; + adevc->build_dev_aml = i8042_build_aml; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -822,6 +822,10 @@ static const TypeInfo i8042_info = { .instance_size = sizeof(ISAKBDState), .instance_init = i8042_initfn, .class_init = i8042_class_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void i8042_register_types(void) From a576158ee9e68d3237bb5a2b0ff0280b291e7972 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:13 -0400 Subject: [PATCH 008/180] isa-bus: drop no longer used ISADeviceClass::build_aml Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-9-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/isa/isa-bus.c | 12 +----------- include/hw/isa/isa.h | 1 - 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 237e2cee12..1bee1a47f1 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -191,19 +191,9 @@ ISADevice *isa_vga_init(ISABus *bus) void isa_build_aml(ISABus *bus, Aml *scope) { BusChild *kid; - ISADevice *dev; - ISADeviceClass *dc; QTAILQ_FOREACH(kid, &bus->parent_obj.children, sibling) { - dev = ISA_DEVICE(kid->child); - dc = ISA_DEVICE_GET_CLASS(dev); - bool has_build_dev_aml = !!object_dynamic_cast(OBJECT(dev), - TYPE_ACPI_DEV_AML_IF); - if (dc->build_aml) { - dc->build_aml(dev, scope); - } else if (has_build_dev_aml) { - call_dev_aml_func(DEVICE(dev), scope); - } + call_dev_aml_func(DEVICE(kid->child), scope); } } diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index 034d706ba1..5c5a3d43a7 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -64,7 +64,6 @@ struct IsaDmaClass { struct ISADeviceClass { DeviceClass parent_class; - void (*build_aml)(ISADevice *dev, Aml *scope); }; struct ISABus { From dc35bfb6e0be460b05193af87c89a7a3cd0dae54 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:14 -0400 Subject: [PATCH 009/180] tests: acpi: add and whitelist DSDT.ipmismbus expected blob .. which will be used by follow up smbus-ipmi test-case Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-10-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.ipmismbus | 0 tests/qtest/bios-tables-test-allowed-diff.h | 1 + 2 files changed, 1 insertion(+) create mode 100644 tests/data/acpi/q35/DSDT.ipmismbus diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/q35/DSDT.ipmismbus new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..b4687d1cc8 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/DSDT.ipmismbus", From ac70b4a3f158152f8a60aa882eb8d98b2f041729 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:15 -0400 Subject: [PATCH 010/180] tests: acpi: q35: add test for smbus-ipmi device expected new device node: Device (MI1) { Name (_HID, EisaId ("IPI0001")) // _HID: Hardware ID Name (_STR, "ipmi_smbus") // _STR: Description String Name (_UID, One) // _UID: Unique ID Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x000186A0, AddressingMode7Bit, "\\_SB.PCI0.SMB0", 0x00, ResourceProducer, , Exclusive, ) }) Name (_IFT, 0x04) // _IFT: IPMI Interface Type Name (_SRV, 0x0200) // _SRV: IPMI Spec Revision } Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-11-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index a4a46e97f0..d896840270 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -955,6 +955,21 @@ static void test_acpi_q35_tcg_ipmi(void) free_test_data(&data); } +static void test_acpi_q35_tcg_smbus_ipmi(void) +{ + test_data data; + + memset(&data, 0, sizeof(data)); + data.machine = MACHINE_Q35; + data.variant = ".ipmismbus"; + data.required_struct_types = ipmi_required_struct_types; + data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); + test_acpi_one("-device ipmi-bmc-sim,id=bmc0" + " -device smbus-ipmi,bmc=bmc0", + &data); + free_test_data(&data); +} + static void test_acpi_piix4_tcg_ipmi(void) { test_data data; @@ -1743,6 +1758,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi); qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); + qtest_add_func("acpi/q35/smbus/ipmi", test_acpi_q35_tcg_smbus_ipmi); qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp); qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp); From f4e2fb67bc40b06bf7544536c03e5e234ab5320b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:16 -0400 Subject: [PATCH 011/180] tests: acpi: update expected blob DSDT.ipmismbus basic q35 DSDT with an extra device node: Device (MI1) { Name (_HID, EisaId ("IPI0001")) // _HID: Hardware ID Name (_STR, "ipmi_smbus") // _STR: Description String Name (_UID, One) // _UID: Unique ID Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x000186A0, AddressingMode7Bit, "\\_SB.PCI0.SMB0", 0x00, ResourceProducer, , Exclusive, ) }) Name (_IFT, 0x04) // _IFT: IPMI Interface Type Name (_SRV, 0x0200) // _SRV: IPMI Spec Revision } Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-12-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.ipmismbus | Bin 0 -> 8391 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/q35/DSDT.ipmismbus index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..07ba873b79caadd73ed9721fcbeee84c57676e2a 100644 GIT binary patch literal 8391 zcmb7JOKcm*8J^`!tL0K!Qk3OaY{E{`M+%3s^JhY z_y6rLX27<-bna|z1|Qz)Z7~AvZ3UJ^2Tp0O>leG7zH2qz zTHfqdYo1-WZ<%J-6-QCCTku-U>~7RNmR+6cuK8~4_G`@bt}G85@xe}d!E!qFe_s0b z?CD>Aapmp8y%I{g>CR>9?cOf?(LyqjM}zucCeK5L!+c!@Ea28TX>9F0bQ7KhAv zmpOG)s4SV)W~nVz8qh|nI{VdTyUuLJ?thnLvCd70;)Rz=4KLShdEH$0xvt+Xuz*^6 z0X1#D*R!17(Ee=DV}o9DG&*3zxz7fh?6;dX`}hCi2kgL_7kx`xb05u8U+#a$VvM0T zPhOzj(0F(HCu@G8%ZC`{&!Q{MT5COG^(@<2nSVMefrRSxpIIq-0E=rBMeoroS?0L4 zSTTC6#|)!lTw~YpdoF@%o&MwXwT(m8{DQ_Zt@t?_p-%teYO}p8bH~K>HZ-hbr7Ffd z(RZSzd2XL)zUZ#i4>@t5F`832526pE%sl6C&J(S+d)S*~c>Q?lfCbDj&oKi-)JQ)Z zqy47qw~gdI+cI%!C~z@$8##P=xz4^{x{O)yH`~I6OH$w#^QFr;QEb#(M)JO(QQ#IE z8}(eX=DnQj7{yh0g=L>;x~0pJ&UuPPqhN;+!MnyTqa2+dQ1b!HK2-o`8j5lS^wkTo zy{wmLdVYOwxEfB4`_KRVKmN1t)jwPMrheitZatt}ufNe7o*!Ii!xMvDD}ovD0l$xI z+_ocjkd7KR>5JW68ZHj5TQfl>9$_iA8T4*#GIp?OHfwH~W$iA0jbMi&=hIgVx>+3e z8$OYnt#&iBa$`S}jN$HNtBsWs6UPRQ%PeD4yA?rDkwFwem1R;f^aC?V;KGPl0M3bX zoCl~3iHZCi8{te~!-$v?8eyCXC}$!hCVIoMQO=Y-h%#bIXjCu(5OxxgvJF^b{?UsGok5BaHfPNbe#xQoim!w8BOPmt`niE)6{gD znod*KiBQ#vCy+AIvzpFXT_-|Sr={t%G@X{N6QQazsp(8=I+MCigsM(F3zh3>YdURR zCqh+cO4FIrbf$Ej2vwbPn$9^*=bWw+p{jFU(>br{oY!?CRCPLqMyP%xF3@n$C=_6QQbeLDRXQ>0HotB2;x|HJw>aXI9sVP}RAp>0H!wF6ufF zsydHpI*(~OkLfxQsygu|fxAyWhn6&*OS(>ks?Ot@&f}WSO(lj!`%? zPy{F|f+zx66b34A+>#7NEZIK;MFsTGKoLr5Fi?S&2C6{GKn3*BKoO!h(m(|^jHsq+ zpaObmpa{_;j)j2=Y#4`0?L_Wpa`W-7^uKV$y` zEN8+%6(|{~fN~}oC_Az;Y%GRDqI#3Mglifg+ST zVW0xbnJ`cVN(L&RoJj_XQ0jz%3M^;BKouw%sDN@N87M-j69y``0?L_Wpa`W-7^uKf}LawZulLa7r5ibyd~M5=)zR1FlNVxS5W2C6X0Kouq# zsKSJSDohxt!XyJ#m}H;|69%d)R`Lm~^^j|8iYS4Oz(QK_3;JE8W`f};ZGa1%i)=P9;rmqTpRn6=|Z5^ut!`b(( z{T(c_%pO?D>@&4>w>1kuE1#aTlAk2lEMEzFm))i|D~|74@cxc9&*%u9XkqDPbq4PU z1-ay5W4VSFgG_YWPam@uKAB^)QMen!^PAyGjMa{g>1U()qM5=9b5an zWuDff7!YoY$4gzmo>Jc9<-M`;-Vx=!uzYE}eC!d* zmz44)UcNL|zH~(SQdqt`UOxT^<;zO>GA~~qD_=gMd^s#%884rBgz^=oe1(^7MBCJK6Z0~or^5@#L^{znHQmHK!xAvfGbs#jB@^jH+thRu^CqjO z!>h_fI?*;Y-NZat)YIYpWg?wuo0@LozCNa>!%NLXI?*;Y-Nb#mq^HB1&O|!Vrl)fX z=EDW;zBl97i`ZSsp9@-eZ>4sFH+H)>-q_l^akw5&yB$wj z=Rbvg;}6?J2{!zQ4z6PL_X3&f1c_Sd#yWA6aY zM+@{{+m_wA`9lf{Eax^$4a2Q9e8X+kUox=Fo~N&}!J@8P_pp?oA!O9`ORG7+y+S*O z742H1W(JHJF}E&V<%5O}iB6^pZnKupFXyQnVtXo{O}p*#E0Li!*kK>J`FwsiTTNh( zpfKAxfA#5@+(03rB!CwA$D2_sV7=kV!T1T15LokA+@CnJx^mFV*5f4W(Fz&ksgPl6 z{%rY}>$?r}2pOi^C|$`!MgiLnjB8(dnZY$9VAlep7qHDQSMA>ndd8h?H1&e*@seEd zcq1;#aOuu?D=y3SSHs!CrZqyDuYzgkhmTK;99{Qd`xf6^`~1Y7QsRUJ|p_VzT^Y@fo+&*H}KrU=Ube9U?0XQ z>{K!KU%r*g&(q8IXhbjH^ocNSlh?#%*&oCi_IvHjJ?#E|C(hh^@%B^L7!I?EHX1G3 zX~V#2ABt%!)Qw?q#9lbxXD(oH#G{egm1m;Z9!-k(1pZ9SC2|Ra@26glHLJ~*7-HJ2 zewYMsYPjROaBMa#| Date: Wed, 8 Jun 2022 09:53:17 -0400 Subject: [PATCH 012/180] tests: acpi: whitelist DSDT.ipmismbus expected blob Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-13-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..b4687d1cc8 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/DSDT.ipmismbus", From ea01c52291ffb7b571e21bb137470abd9e1c3175 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:18 -0400 Subject: [PATCH 013/180] ipmi: acpi: use relative path to resource source smbus-ipmi AML description needs to specify a path to its parent node in _CRS. The rest of IPMI inplementations (ISA based) do not need path at all. Instead of passing through a full path use relative path to point to smbus-ipmi's parent node, it will let follow up patches to create IPMI device AML in a generic way instead of current ad-hoc way. (i.e. AML will be generated the same way it's done for other ISA device, and smbus will be converted to generate AML for its slave devices the same way as ISA) expected AML change: Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x000186A0, - AddressingMode7Bit, "\\_SB.PCI0.SMB0", + AddressingMode7Bit, "^", 0x00, ResourceProducer, , Exclusive, ) }) Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-14-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/ipmi-stub.c | 2 +- hw/acpi/ipmi.c | 12 ++++++------ hw/i386/acpi-build.c | 4 ++-- include/hw/acpi/ipmi.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/acpi/ipmi-stub.c b/hw/acpi/ipmi-stub.c index 8634fb325c..f525f71c2d 100644 --- a/hw/acpi/ipmi-stub.c +++ b/hw/acpi/ipmi-stub.c @@ -10,6 +10,6 @@ #include "qemu/osdep.h" #include "hw/acpi/ipmi.h" -void build_acpi_ipmi_devices(Aml *table, BusState *bus, const char *resource) +void build_acpi_ipmi_devices(Aml *table, BusState *bus) { } diff --git a/hw/acpi/ipmi.c b/hw/acpi/ipmi.c index 96e48eba15..c30b44fcf5 100644 --- a/hw/acpi/ipmi.c +++ b/hw/acpi/ipmi.c @@ -13,7 +13,7 @@ #include "hw/acpi/acpi.h" #include "hw/acpi/ipmi.h" -static Aml *aml_ipmi_crs(IPMIFwInfo *info, const char *resource) +static Aml *aml_ipmi_crs(IPMIFwInfo *info) { Aml *crs = aml_resource_template(); @@ -49,7 +49,7 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info, const char *resource) break; case IPMI_MEMSPACE_SMBUS: aml_append(crs, aml_i2c_serial_bus_device(info->base_address, - resource)); + "^")); break; default: abort(); @@ -62,7 +62,7 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info, const char *resource) return crs; } -static Aml *aml_ipmi_device(IPMIFwInfo *info, const char *resource) +static Aml *aml_ipmi_device(IPMIFwInfo *info) { Aml *dev; uint16_t version = ((info->ipmi_spec_major_revision << 8) @@ -75,14 +75,14 @@ static Aml *aml_ipmi_device(IPMIFwInfo *info, const char *resource) aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s", info->interface_name))); aml_append(dev, aml_name_decl("_UID", aml_int(info->uuid))); - aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info, resource))); + aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info))); aml_append(dev, aml_name_decl("_IFT", aml_int(info->interface_type))); aml_append(dev, aml_name_decl("_SRV", aml_int(version))); return dev; } -void build_acpi_ipmi_devices(Aml *scope, BusState *bus, const char *resource) +void build_acpi_ipmi_devices(Aml *scope, BusState *bus) { BusChild *kid; @@ -102,6 +102,6 @@ void build_acpi_ipmi_devices(Aml *scope, BusState *bus, const char *resource) iic = IPMI_INTERFACE_GET_CLASS(obj); memset(&info, 0, sizeof(info)); iic->get_fwinfo(ii, &info); - aml_append(scope, aml_ipmi_device(&info, resource)); + aml_append(scope, aml_ipmi_device(&info)); } } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 1449832aa9..88506d563f 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -873,7 +873,7 @@ static void build_isa_devices_aml(Aml *table) assert(obj && !ambiguous); scope = aml_scope("_SB.PCI0.ISA"); - build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA"); + build_acpi_ipmi_devices(scope, BUS(obj)); isa_build_aml(ISA_BUS(obj), scope); aml_append(table, scope); @@ -1406,7 +1406,7 @@ static void build_smb0(Aml *table, I2CBus *smbus, int devnr, int func) Aml *dev = aml_device("SMB0"); aml_append(dev, aml_name_decl("_ADR", aml_int(devnr << 16 | func))); - build_acpi_ipmi_devices(dev, BUS(smbus), "\\_SB.PCI0.SMB0"); + build_acpi_ipmi_devices(dev, BUS(smbus)); aml_append(scope, dev); aml_append(table, scope); } diff --git a/include/hw/acpi/ipmi.h b/include/hw/acpi/ipmi.h index c14ad682ac..c38483565c 100644 --- a/include/hw/acpi/ipmi.h +++ b/include/hw/acpi/ipmi.h @@ -16,6 +16,6 @@ * bus matches the given bus. The resource is the ACPI resource that * contains the IPMI device, this is required for the I2C CRS. */ -void build_acpi_ipmi_devices(Aml *table, BusState *bus, const char *resource); +void build_acpi_ipmi_devices(Aml *table, BusState *bus); #endif /* HW_ACPI_IPMI_H */ From 0f5b3fd7483e3fe8f0c8fc28346a1b0cd91de106 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:19 -0400 Subject: [PATCH 014/180] tests: acpi: update expected DSDT.ipmismbus blob expected AML change: Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { I2cSerialBusV2 (0x0000, ControllerInitiated, 0x000186A0, - AddressingMode7Bit, "\\_SB.PCI0.SMB0", + AddressingMode7Bit, "^", 0x00, ResourceProducer, , Exclusive, ) }) Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-15-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.ipmismbus | Bin 8391 -> 8378 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/q35/DSDT.ipmismbus index 07ba873b79caadd73ed9721fcbeee84c57676e2a..415fe08a407690c0e118743d872de79d22f01a4c 100644 GIT binary patch delta 85 zcmX@^xXY2tCD80n^Yqk0Lq6G-v9sr delta 98 zcmdnxc-)c8CD$MJ|5 sqMMx9CjXGsR#xLu?vrC+1VW%jHiiXlAVv&OqaH}39!S?_OQ}XS01jdo-v9sr diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index b4687d1cc8..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,2 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/q35/DSDT.ipmismbus", From 4b66ddcc4d2d690f11152aeed1097f44ecff1aa4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:20 -0400 Subject: [PATCH 015/180] acpi: ich9-smb: add support for AcpiDevAmlIf interface wire AcpiDevAmlIf interface to build ich9-smb and its slave devices AML. It will be used by followup patches to switch from creating AML in ad-hoc way to a more systematic one that will scan present devices and ask them to provide their AML code like it's done with ISA devices. This patch is a partial conversion, as it only fetches AML from slave devices attached to its I2C bus. The conversion will be completed when PCI bus is switched to use AcpiDevAmlIf and build_smb0() could be dropped. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-16-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i2c/smbus_ich9.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c index 44dd5653b7..ee50ba1f2c 100644 --- a/hw/i2c/smbus_ich9.c +++ b/hw/i2c/smbus_ich9.c @@ -29,6 +29,7 @@ #include "hw/i386/ich9.h" #include "qom/object.h" +#include "hw/acpi/acpi_aml_interface.h" OBJECT_DECLARE_SIMPLE_TYPE(ICH9SMBState, ICH9_SMB_DEVICE) @@ -94,10 +95,22 @@ static void ich9_smbus_realize(PCIDevice *d, Error **errp) &s->smb.io); } +static void build_ich9_smb_aml(AcpiDevAmlIf *adev, Aml *scope) +{ + BusChild *kid; + ICH9SMBState *s = ICH9_SMB_DEVICE(adev); + BusState *bus = BUS(s->smb.smbus); + + QTAILQ_FOREACH(kid, &bus->children, sibling) { + call_dev_aml_func(DEVICE(kid->child), scope); + } +} + static void ich9_smb_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); k->vendor_id = PCI_VENDOR_ID_INTEL; k->device_id = PCI_DEVICE_ID_INTEL_ICH9_6; @@ -112,6 +125,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) * pc_q35_init() */ dc->user_creatable = false; + adevc->build_dev_aml = build_ich9_smb_aml; } static void ich9_smb_set_irq(PMSMBus *pmsmb, bool enabled) @@ -143,6 +157,7 @@ static const TypeInfo ich9_smb_info = { .class_init = ich9_smb_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { TYPE_ACPI_DEV_AML_IF }, { }, }, }; From 5876d9b53fee5fc5a341fad1618cf3a9731206da Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:21 -0400 Subject: [PATCH 016/180] acpi: ipmi: use AcpiDevAmlIf interface to build IPMI device descriptors convert ad-hoc way we use to generate AML for ISA/SMB IPMI devices to a generic approach (i.e. make devices provide its own AML blobs like it is done with other ISA devices (ex. KBD)) Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-17-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/ipmi-stub.c | 2 +- hw/acpi/ipmi.c | 49 +++++++++++++----------------------------- hw/i386/acpi-build.c | 17 ++++++++++----- hw/ipmi/isa_ipmi_bt.c | 4 ++++ hw/ipmi/isa_ipmi_kcs.c | 4 ++++ hw/ipmi/smbus_ipmi.c | 4 ++++ include/hw/acpi/ipmi.h | 9 ++------ 7 files changed, 42 insertions(+), 47 deletions(-) diff --git a/hw/acpi/ipmi-stub.c b/hw/acpi/ipmi-stub.c index f525f71c2d..befaf0a882 100644 --- a/hw/acpi/ipmi-stub.c +++ b/hw/acpi/ipmi-stub.c @@ -10,6 +10,6 @@ #include "qemu/osdep.h" #include "hw/acpi/ipmi.h" -void build_acpi_ipmi_devices(Aml *table, BusState *bus) +void build_ipmi_dev_aml(AcpiDevAmlIf *adev, Aml *scope) { } diff --git a/hw/acpi/ipmi.c b/hw/acpi/ipmi.c index c30b44fcf5..a20e57d465 100644 --- a/hw/acpi/ipmi.c +++ b/hw/acpi/ipmi.c @@ -62,46 +62,27 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info) return crs; } -static Aml *aml_ipmi_device(IPMIFwInfo *info) +void build_ipmi_dev_aml(AcpiDevAmlIf *adev, Aml *scope) { Aml *dev; - uint16_t version = ((info->ipmi_spec_major_revision << 8) - | (info->ipmi_spec_minor_revision << 4)); + IPMIFwInfo info = {}; + IPMIInterface *ii = IPMI_INTERFACE(adev); + IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii); + uint16_t version; - assert(info->ipmi_spec_minor_revision <= 15); + iic->get_fwinfo(ii, &info); + assert(info.ipmi_spec_minor_revision <= 15); + version = ((info.ipmi_spec_major_revision << 8) + | (info.ipmi_spec_minor_revision << 4)); - dev = aml_device("MI%d", info->uuid); + dev = aml_device("MI%d", info.uuid); aml_append(dev, aml_name_decl("_HID", aml_eisaid("IPI0001"))); aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s", - info->interface_name))); - aml_append(dev, aml_name_decl("_UID", aml_int(info->uuid))); - aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info))); - aml_append(dev, aml_name_decl("_IFT", aml_int(info->interface_type))); + info.interface_name))); + aml_append(dev, aml_name_decl("_UID", aml_int(info.uuid))); + aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(&info))); + aml_append(dev, aml_name_decl("_IFT", aml_int(info.interface_type))); aml_append(dev, aml_name_decl("_SRV", aml_int(version))); - return dev; -} - -void build_acpi_ipmi_devices(Aml *scope, BusState *bus) -{ - - BusChild *kid; - - QTAILQ_FOREACH(kid, &bus->children, sibling) { - IPMIInterface *ii; - IPMIInterfaceClass *iic; - IPMIFwInfo info; - Object *obj = object_dynamic_cast(OBJECT(kid->child), - TYPE_IPMI_INTERFACE); - - if (!obj) { - continue; - } - - ii = IPMI_INTERFACE(obj); - iic = IPMI_INTERFACE_GET_CLASS(obj); - memset(&info, 0, sizeof(info)); - iic->get_fwinfo(ii, &info); - aml_append(scope, aml_ipmi_device(&info)); - } + aml_append(scope, dev); } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 88506d563f..5b963cca32 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -39,6 +39,7 @@ #include "hw/nvram/fw_cfg.h" #include "hw/acpi/bios-linker-loader.h" #include "hw/isa/isa.h" +#include "hw/acpi/acpi_aml_interface.h" #include "hw/input/i8042.h" #include "hw/acpi/memory_hotplug.h" #include "sysemu/tpm.h" @@ -73,7 +74,6 @@ #include "hw/i386/intel_iommu.h" #include "hw/virtio/virtio-iommu.h" -#include "hw/acpi/ipmi.h" #include "hw/acpi/hmat.h" #include "hw/acpi/viot.h" #include "hw/acpi/cxl.h" @@ -873,7 +873,6 @@ static void build_isa_devices_aml(Aml *table) assert(obj && !ambiguous); scope = aml_scope("_SB.PCI0.ISA"); - build_acpi_ipmi_devices(scope, BUS(obj)); isa_build_aml(ISA_BUS(obj), scope); aml_append(table, scope); @@ -1400,13 +1399,21 @@ static Aml *build_q35_osc_method(bool enable_native_pcie_hotplug) return method; } -static void build_smb0(Aml *table, I2CBus *smbus, int devnr, int func) +static void build_smb0(Aml *table, int devnr, int func) { Aml *scope = aml_scope("_SB.PCI0"); Aml *dev = aml_device("SMB0"); + bool ambiguous; + Object *obj; + /* + * temporarily fish out device hosting SMBUS, build_smb0 will be gone once + * PCI enumeration will be switched to call_dev_aml_func() + */ + obj = object_resolve_path_type("", TYPE_ICH9_SMB_DEVICE, &ambiguous); + assert(obj && !ambiguous); aml_append(dev, aml_name_decl("_ADR", aml_int(devnr << 16 | func))); - build_acpi_ipmi_devices(dev, BUS(smbus)); + call_dev_aml_func(DEVICE(obj), dev); aml_append(scope, dev); aml_append(table, scope); } @@ -1524,7 +1531,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, } build_q35_pci0_int(dsdt); if (pcms->smbus && !pcmc->do_not_add_smb_acpi) { - build_smb0(dsdt, pcms->smbus, ICH9_SMB_DEV, ICH9_SMB_FUNC); + build_smb0(dsdt, ICH9_SMB_DEV, ICH9_SMB_FUNC); } } diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c index 88aa734e9e..a83e7243d6 100644 --- a/hw/ipmi/isa_ipmi_bt.c +++ b/hw/ipmi/isa_ipmi_bt.c @@ -31,6 +31,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qom/object.h" +#include "hw/acpi/ipmi.h" #define TYPE_ISA_IPMI_BT "isa-ipmi-bt" OBJECT_DECLARE_SIMPLE_TYPE(ISAIPMIBTDevice, ISA_IPMI_BT) @@ -144,6 +145,7 @@ static void isa_ipmi_bt_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc); dc->realize = isa_ipmi_bt_realize; device_class_set_props(dc, ipmi_isa_properties); @@ -151,6 +153,7 @@ static void isa_ipmi_bt_class_init(ObjectClass *oc, void *data) iic->get_backend_data = isa_ipmi_bt_get_backend_data; ipmi_bt_class_init(iic); iic->get_fwinfo = isa_ipmi_bt_get_fwinfo; + adevc->build_dev_aml = build_ipmi_dev_aml; } static const TypeInfo isa_ipmi_bt_info = { @@ -161,6 +164,7 @@ static const TypeInfo isa_ipmi_bt_info = { .class_init = isa_ipmi_bt_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_IPMI_INTERFACE }, + { TYPE_ACPI_DEV_AML_IF }, { } } }; diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c index afabb95ebe..b2ed70b9da 100644 --- a/hw/ipmi/isa_ipmi_kcs.c +++ b/hw/ipmi/isa_ipmi_kcs.c @@ -31,6 +31,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qom/object.h" +#include "hw/acpi/ipmi.h" #define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs" OBJECT_DECLARE_SIMPLE_TYPE(ISAIPMIKCSDevice, ISA_IPMI_KCS) @@ -151,6 +152,7 @@ static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc); dc->realize = ipmi_isa_realize; device_class_set_props(dc, ipmi_isa_properties); @@ -158,6 +160,7 @@ static void isa_ipmi_kcs_class_init(ObjectClass *oc, void *data) iic->get_backend_data = isa_ipmi_kcs_get_backend_data; ipmi_kcs_class_init(iic); iic->get_fwinfo = isa_ipmi_kcs_get_fwinfo; + adevc->build_dev_aml = build_ipmi_dev_aml; } static const TypeInfo isa_ipmi_kcs_info = { @@ -168,6 +171,7 @@ static const TypeInfo isa_ipmi_kcs_info = { .class_init = isa_ipmi_kcs_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_IPMI_INTERFACE }, + { TYPE_ACPI_DEV_AML_IF }, { } } }; diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c index 1fdf0a66b6..9ef9112dd5 100644 --- a/hw/ipmi/smbus_ipmi.c +++ b/hw/ipmi/smbus_ipmi.c @@ -28,6 +28,7 @@ #include "qemu/error-report.h" #include "hw/ipmi/ipmi.h" #include "qom/object.h" +#include "hw/acpi/ipmi.h" #define TYPE_SMBUS_IPMI "smbus-ipmi" OBJECT_DECLARE_SIMPLE_TYPE(SMBusIPMIDevice, SMBUS_IPMI) @@ -353,6 +354,7 @@ static void smbus_ipmi_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); IPMIInterfaceClass *iic = IPMI_INTERFACE_CLASS(oc); SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(oc); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(oc); sc->receive_byte = ipmi_receive_byte; sc->write_data = ipmi_write_data; @@ -363,6 +365,7 @@ static void smbus_ipmi_class_init(ObjectClass *oc, void *data) iic->handle_if_event = smbus_ipmi_handle_event; iic->set_irq_enable = smbus_ipmi_set_irq_enable; iic->get_fwinfo = smbus_ipmi_get_fwinfo; + adevc->build_dev_aml = build_ipmi_dev_aml; } static const TypeInfo smbus_ipmi_info = { @@ -373,6 +376,7 @@ static const TypeInfo smbus_ipmi_info = { .class_init = smbus_ipmi_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_IPMI_INTERFACE }, + { TYPE_ACPI_DEV_AML_IF }, { } } }; diff --git a/include/hw/acpi/ipmi.h b/include/hw/acpi/ipmi.h index c38483565c..6c8079c97a 100644 --- a/include/hw/acpi/ipmi.h +++ b/include/hw/acpi/ipmi.h @@ -9,13 +9,8 @@ #ifndef HW_ACPI_IPMI_H #define HW_ACPI_IPMI_H -#include "hw/acpi/aml-build.h" +#include "hw/acpi/acpi_aml_interface.h" -/* - * Add ACPI IPMI entries for all registered IPMI devices whose parent - * bus matches the given bus. The resource is the ACPI resource that - * contains the IPMI device, this is required for the I2C CRS. - */ -void build_acpi_ipmi_devices(Aml *table, BusState *bus); +void build_ipmi_dev_aml(AcpiDevAmlIf *adev, Aml *scope); #endif /* HW_ACPI_IPMI_H */ From 38003951b5948865f0a6be3e43b3658ae54d6e97 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:22 -0400 Subject: [PATCH 017/180] q35: acpi: drop not needed PCMachineClass::do_not_add_smb_acpi by default we do not version ACPI AML as it's considered a part of firmware. Drop do_not_add_smb_acpi that blocked SMBUS AML description on 3.1 and older machine types without providing justification. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-18-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 2 +- hw/i386/pc_piix.c | 1 - hw/i386/pc_q35.c | 1 - include/hw/i386/pc.h | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 5b963cca32..d943354999 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1530,7 +1530,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_x86_acpi_pci_hotplug(dsdt, pm->pcihp_io_base); } build_q35_pci0_int(dsdt); - if (pcms->smbus && !pcmc->do_not_add_smb_acpi) { + if (pcms->smbus) { build_smb0(dsdt, ICH9_SMB_DEV, ICH9_SMB_FUNC); } } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 578e537b35..7f777f7aed 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -564,7 +564,6 @@ static void pc_i440fx_3_1_machine_options(MachineClass *m) pc_i440fx_4_0_machine_options(m); m->is_default = false; - pcmc->do_not_add_smb_acpi = true; m->smbus_no_migration_support = true; m->alias = NULL; pcmc->pvh_enabled = false; diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 42eb8b9707..f96cbd04e2 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -514,7 +514,6 @@ static void pc_q35_3_1_machine_options(MachineClass *m) pc_q35_4_0_machine_options(m); m->default_kernel_irqchip_split = false; - pcmc->do_not_add_smb_acpi = true; m->smbus_no_migration_support = true; m->alias = NULL; pcmc->pvh_enabled = false; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index ffcac5121e..dee38cfac4 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -104,7 +104,6 @@ struct PCMachineClass { bool rsdp_in_ram; int legacy_acpi_table_size; unsigned acpi_data_size; - bool do_not_add_smb_acpi; int pci_root_uid; /* SMBIOS compat: */ From 6a4b286ced99377652f1ae0963e69ccac8c3df3b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 9 Jun 2022 07:48:55 -0400 Subject: [PATCH 018/180] tests: acpi: white-list to be re-factored pc/q35 DSDT Signed-off-by: Igor Mammedov Message-Id: <20220609114855.3477822-1-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..666e257bf9 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,33 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/pc/DSDT", +"tests/data/acpi/pc/DSDT.acpierst", +"tests/data/acpi/pc/DSDT.acpihmat", +"tests/data/acpi/pc/DSDT.bridge", +"tests/data/acpi/pc/DSDT.cphp", +"tests/data/acpi/pc/DSDT.dimmpxm", +"tests/data/acpi/pc/DSDT.hpbridge", +"tests/data/acpi/pc/DSDT.ipmikcs", +"tests/data/acpi/pc/DSDT.memhp", +"tests/data/acpi/pc/DSDT.nohpet", +"tests/data/acpi/pc/DSDT.numamem", +"tests/data/acpi/pc/DSDT.roothp", +"tests/data/acpi/pc/DSDT.hpbrroot", +"tests/data/acpi/q35/DSDT", +"tests/data/acpi/q35/DSDT.acpierst", +"tests/data/acpi/q35/DSDT.acpihmat", +"tests/data/acpi/q35/DSDT.bridge", +"tests/data/acpi/q35/DSDT.cphp", +"tests/data/acpi/q35/DSDT.dimmpxm", +"tests/data/acpi/q35/DSDT.ipmibt", +"tests/data/acpi/q35/DSDT.ivrs", +"tests/data/acpi/q35/DSDT.memhp", +"tests/data/acpi/q35/DSDT.mmio64", +"tests/data/acpi/q35/DSDT.multi-bridge", +"tests/data/acpi/q35/DSDT.nohpet", +"tests/data/acpi/q35/DSDT.numamem", +"tests/data/acpi/q35/DSDT.tis.tpm12", +"tests/data/acpi/q35/DSDT.tis.tpm2", +"tests/data/acpi/q35/DSDT.viot", +"tests/data/acpi/q35/DSDT.xapic", +"tests/data/acpi/q35/DSDT.ipmismbus", +"tests/data/acpi/q35/DSDT.cxl", From 92ea7fb3fe311d30905e12a962b22a38251c1a79 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:24 -0400 Subject: [PATCH 019/180] acpi: pc: isa bridge: use AcpiDevAmlIf interface to build ISA device descriptors replaces ad-hoc build_isa_devices_aml() with generic AcpiDevAmlIf way to build bridge AML including all devices that are attached to its ISA bus. Later when PCI is converted to AcpiDevAmlIf, build_piix4_isa_bridge() will also be dropped since PCI parts itself will take care of building device prologue/epilogue AML for each enumerated PCI device. Expected AML change is contextual, where ISA devices are moved from separately declared _SB.PCI0.ISA scope , directly under Device(ISA) node. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-20-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 16 +++++++++++----- hw/isa/piix3.c | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index d943354999..f903f30b7e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1280,15 +1280,22 @@ static void build_piix4_isa_bridge(Aml *table) { Aml *dev; Aml *scope; + Object *obj; + bool ambiguous; + + /* + * temporarily fish out isa bridge, build_piix4_isa_bridge() will be dropped + * once PCI is converted to AcpiDevAmlIf and would be ble to generate + * AML for bridge itself + */ + obj = object_resolve_path_type("", TYPE_PIIX3_PCI_DEVICE, &ambiguous); + assert(obj && !ambiguous); scope = aml_scope("_SB.PCI0"); dev = aml_device("ISA"); aml_append(dev, aml_name_decl("_ADR", aml_int(0x00010000))); - /* PIIX PCI to ISA irq remapping */ - aml_append(dev, aml_operation_region("P40C", AML_PCI_CONFIG, - aml_int(0x60), 0x04)); - + call_dev_aml_func(DEVICE(obj), dev); aml_append(scope, dev); aml_append(table, scope); } @@ -1476,7 +1483,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_hpet_aml(dsdt); } build_piix4_isa_bridge(dsdt); - build_isa_devices_aml(dsdt); if (pm->pcihp_bridge_en || pm->pcihp_root_en) { build_x86_acpi_pci_hotplug(dsdt, pm->pcihp_io_base); } diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index dab901c9ad..bfccd666d4 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -32,6 +32,7 @@ #include "sysemu/reset.h" #include "sysemu/runstate.h" #include "migration/vmstate.h" +#include "hw/acpi/acpi_aml_interface.h" #define XEN_PIIX_NUM_PIRQS 128ULL @@ -286,10 +287,24 @@ static void piix3_realize(PCIDevice *dev, Error **errp) qemu_register_reset(piix3_reset, d); } +static void build_pci_isa_aml(AcpiDevAmlIf *adev, Aml *scope) +{ + BusChild *kid; + BusState *bus = qdev_get_child_bus(DEVICE(adev), "isa.0"); + + /* PIIX PCI to ISA irq remapping */ + aml_append(scope, aml_operation_region("P40C", AML_PCI_CONFIG, + aml_int(0x60), 0x04)); + QTAILQ_FOREACH(kid, &bus->children, sibling) { + call_dev_aml_func(DEVICE(kid->child), scope); + } +} + static void pci_piix3_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; @@ -304,6 +319,7 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data) * pc_piix.c's pc_init1() */ dc->user_creatable = false; + adevc->build_dev_aml = build_pci_isa_aml; } static const TypeInfo piix3_pci_type_info = { @@ -314,6 +330,7 @@ static const TypeInfo piix3_pci_type_info = { .class_init = pci_piix3_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { TYPE_ACPI_DEV_AML_IF }, { }, }, }; From 887e8e9d3a4578059bd0a213e9b3cae81943dc18 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:25 -0400 Subject: [PATCH 020/180] acpi: q35: isa bridge: use AcpiDevAmlIf interface to build ISA device descriptors replaces adhoc build_isa_devices_aml() with generic AcpiDevAmlIf way to build bridge AML including all devices that are attached to its ISA bus. Later when PCI is converted to AcpiDevAmlIf, build_q35_isa_bridge() will also be dropped since PCI parts itself will take care of building device prologue/epilogue AML for each enumerated PCI device. Expected AML change is contextual, where ISA devices are moved from separately declared _SB.PCI0.ISA scope, directly under Device(ISA) node. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-21-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 30 +++++++++++------------------- hw/isa/lpc_ich9.c | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index f903f30b7e..f7f1671407 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -864,20 +864,6 @@ static Aml *build_vmbus_device_aml(VMBusBridge *vmbus_bridge) return dev; } -static void build_isa_devices_aml(Aml *table) -{ - bool ambiguous; - Object *obj = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous); - Aml *scope; - - assert(obj && !ambiguous); - - scope = aml_scope("_SB.PCI0.ISA"); - isa_build_aml(ISA_BUS(obj), scope); - - aml_append(table, scope); -} - static void build_dbg_aml(Aml *table) { Aml *field; @@ -1263,15 +1249,22 @@ static void build_q35_isa_bridge(Aml *table) { Aml *dev; Aml *scope; + Object *obj; + bool ambiguous; + + /* + * temporarily fish out isa bridge, build_q35_isa_bridge() will be dropped + * once PCI is converted to AcpiDevAmlIf and would be ble to generate + * AML for bridge itself + */ + obj = object_resolve_path_type("", TYPE_ICH9_LPC_DEVICE, &ambiguous); + assert(obj && !ambiguous); scope = aml_scope("_SB.PCI0"); dev = aml_device("ISA"); aml_append(dev, aml_name_decl("_ADR", aml_int(0x001F0000))); - /* ICH9 PCI to ISA irq remapping */ - aml_append(dev, aml_operation_region("PIRQ", AML_PCI_CONFIG, - aml_int(0x60), 0x0C)); - + call_dev_aml_func(DEVICE(obj), dev); aml_append(scope, dev); aml_append(table, scope); } @@ -1531,7 +1524,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_hpet_aml(dsdt); } build_q35_isa_bridge(dsdt); - build_isa_devices_aml(dsdt); if (pm->pcihp_bridge_en) { build_x86_acpi_pci_hotplug(dsdt, pm->pcihp_io_base); } diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 5f143dca17..4553b5925b 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -50,6 +50,7 @@ #include "hw/core/cpu.h" #include "hw/nvram/fw_cfg.h" #include "qemu/cutils.h" +#include "hw/acpi/acpi_aml_interface.h" /*****************************************************************************/ /* ICH9 LPC PCI to ISA bridge */ @@ -803,12 +804,28 @@ static void ich9_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev) acpi_send_gpe_event(&s->pm.acpi_regs, s->pm.irq, ev); } +static void build_ich9_isa_aml(AcpiDevAmlIf *adev, Aml *scope) +{ + BusChild *kid; + ICH9LPCState *s = ICH9_LPC_DEVICE(adev); + BusState *bus = BUS(s->isa_bus); + + /* ICH9 PCI to ISA irq remapping */ + aml_append(scope, aml_operation_region("PIRQ", AML_PCI_CONFIG, + aml_int(0x60), 0x0C)); + + QTAILQ_FOREACH(kid, &bus->children, sibling) { + call_dev_aml_func(DEVICE(kid->child), scope); + } +} + static void ich9_lpc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(klass); + AcpiDevAmlIfClass *amldevc = ACPI_DEV_AML_IF_CLASS(klass); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->reset = ich9_lpc_reset; @@ -833,6 +850,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) adevc->ospm_status = ich9_pm_ospm_status; adevc->send_event = ich9_send_gpe; adevc->madt_cpu = pc_madt_cpu_entry; + amldevc->build_dev_aml = build_ich9_isa_aml; } static const TypeInfo ich9_lpc_info = { @@ -845,6 +863,7 @@ static const TypeInfo ich9_lpc_info = { { TYPE_HOTPLUG_HANDLER }, { TYPE_ACPI_DEVICE_IF }, { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { TYPE_ACPI_DEV_AML_IF }, { } } }; From 8796f60fbfa15cf392c5892311ccec5f4ec805b5 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 9 Jun 2022 07:51:13 -0400 Subject: [PATCH 021/180] tests: acpi: update expected blobs Expected AML change: ISA devices under separate _SB.PCI0.ISA scope are moved directly under Device(ISA) node. Example from PC machine, and q35 have similar changes: { Name (_ADR, 0x00010000) // _ADR: Address OperationRegion (P40C, PCI_Config, 0x60, 0x04) - } - } - - Scope (_SB.PCI0.ISA) - { - Device (KBD) - { - Name (_HID, EisaId ("PNP0303") /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */) // _HID: Hardware ID - Name (_STA, 0x0F) // _STA: Status - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + Device (KBD) { - IO (Decode16, - 0x0060, // Range Minimum - 0x0060, // Range Maximum - 0x01, // Alignment - 0x01, // Length - ) - IO (Decode16, - 0x0064, // Range Minimum - 0x0064, // Range Maximum - 0x01, // Alignment - 0x01, // Length - ) - IRQNoFlags () - {1} - }) - } - - Device (MOU) - { - Name (_HID, EisaId ("PNP0F13") /* PS/2 Mouse */) // _HID: Hardware ID - Name (_STA, 0x0F) // _STA: Status - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings - { - IRQNoFlags () - {12} - }) - } + Name (_HID, EisaId ("PNP0303") /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */) // _HID: Hardware ID + Name (_STA, 0x0F) // _STA: Status + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x0060, // Range Minimum + 0x0060, // Range Maximum + 0x01, // Alignment + 0x01, // Length + ) + IO (Decode16, + 0x0064, // Range Minimum + 0x0064, // Range Maximum + 0x01, // Alignment + 0x01, // Length + ) + IRQNoFlags () + {1} + }) + } - Device (FDC0) - { - Name (_HID, EisaId ("PNP0700")) // _HID: Hardware ID - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings - { - IO (Decode16, - 0x03F2, // Range Minimum - 0x03F2, // Range Maximum - 0x00, // Alignment - 0x04, // Length - ) - IO (Decode16, - 0x03F7, // Range Minimum - 0x03F7, // Range Maximum - 0x00, // Alignment - 0x01, // Length - ) - IRQNoFlags () - {6} - DMA (Compatibility, NotBusMaster, Transfer8, ) - {2} - }) - Device (FLPA) + Device (MOU) { - Name (_ADR, Zero) // _ADR: Address - Name (_FDI, Package (0x10) // _FDI: Floppy Drive Information + Name (_HID, EisaId ("PNP0F13") /* PS/2 Mouse */) // _HID: Hardware ID + Name (_STA, 0x0F) // _STA: Status + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { - Zero, - 0x05, - 0x4F, - 0x30, - One, - 0xAF, - 0x02, - 0x25, - 0x02, - 0x12, - 0x1B, - 0xFF, - 0x6C, - 0xF6, - 0x0F, - 0x08 + IRQNoFlags () + {12} }) } - Name (_FDE, Buffer (0x14) // _FDE: Floppy Disk Enumerate + Device (FDC0) { - /* 0000 */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ - /* 0008 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ - /* 0010 */ 0x02, 0x00, 0x00, 0x00 // .... - }) - } + Name (_HID, EisaId ("PNP0700")) // _HID: Hardware ID + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x03F2, // Range Minimum + 0x03F2, // Range Maximum + 0x00, // Alignment + 0x04, // Length + ) + IO (Decode16, + 0x03F7, // Range Minimum + 0x03F7, // Range Maximum + 0x00, // Alignment + 0x01, // Length + ) + IRQNoFlags () + {6} + DMA (Compatibility, NotBusMaster, Transfer8, ) + {2} + }) + Device (FLPA) + { + Name (_ADR, Zero) // _ADR: Address + Name (_FDI, Package (0x10) // _FDI: Floppy Drive Information + { + Zero, + 0x05, + 0x4F, + 0x30, + One, + 0xAF, + 0x02, + 0x25, + 0x02, + 0x12, + 0x1B, + 0xFF, + 0x6C, + 0xF6, + 0x0F, + 0x08 + }) + } - Device (LPT1) - { - Name (_HID, EisaId ("PNP0400") /* Standard LPT Parallel Port */) // _HID: Hardware ID - Name (_UID, One) // _UID: Unique ID - Name (_STA, 0x0F) // _STA: Status - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + Name (_FDE, Buffer (0x14) // _FDE: Floppy Disk Enumerate + { + /* 0000 */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ + /* 0008 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ + /* 0010 */ 0x02, 0x00, 0x00, 0x00 // .... + }) + } + + Device (LPT1) { - IO (Decode16, - 0x0378, // Range Minimum - 0x0378, // Range Maximum - 0x08, // Alignment - 0x08, // Length - ) - IRQNoFlags () - {7} - }) - } + Name (_HID, EisaId ("PNP0400") /* Standard LPT Parallel Port */) // _HID: Hardware ID + Name (_UID, One) // _UID: Unique ID + Name (_STA, 0x0F) // _STA: Status + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x0378, // Range Minimum + 0x0378, // Range Maximum + 0x08, // Alignment + 0x08, // Length + ) + IRQNoFlags () + {7} + }) + } - Device (COM1) - { - Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */) // _HID: Hardware ID - Name (_UID, One) // _UID: Unique ID - Name (_STA, 0x0F) // _STA: Status - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + Device (COM1) { - IO (Decode16, - 0x03F8, // Range Minimum - 0x03F8, // Range Maximum - 0x00, // Alignment - 0x08, // Length - ) - IRQNoFlags () - {4} - }) - } + Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */) // _HID: Hardware ID + Name (_UID, One) // _UID: Unique ID + Name (_STA, 0x0F) // _STA: Status + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x03F8, // Range Minimum + 0x03F8, // Range Maximum + 0x00, // Alignment + 0x08, // Length + ) + IRQNoFlags () + {4} + }) + } - Device (RTC) - { - Name (_HID, EisaId ("PNP0B00") /* AT Real-Time Clock */) // _HID: Hardware ID - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + Device (RTC) { - IO (Decode16, - 0x0070, // Range Minimum - 0x0070, // Range Maximum - 0x01, // Alignment - 0x08, // Length - ) - IRQNoFlags () - {8} - }) + Name (_HID, EisaId ("PNP0B00") /* AT Real-Time Clock */) // _HID: Hardware ID + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x0070, // Range Minimum + 0x0070, // Range Maximum + 0x01, // Alignment + 0x08, // Length + ) + IRQNoFlags () + {8} + }) + } } } Signed-off-by: Igor Mammedov Message-Id: <20220609115113.3478093-1-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/pc/DSDT | Bin 6002 -> 5987 bytes tests/data/acpi/pc/DSDT.acpierst | Bin 5969 -> 5954 bytes tests/data/acpi/pc/DSDT.acpihmat | Bin 7327 -> 7312 bytes tests/data/acpi/pc/DSDT.bridge | Bin 8668 -> 8653 bytes tests/data/acpi/pc/DSDT.cphp | Bin 6466 -> 6451 bytes tests/data/acpi/pc/DSDT.dimmpxm | Bin 7656 -> 7641 bytes tests/data/acpi/pc/DSDT.hpbridge | Bin 5969 -> 5954 bytes tests/data/acpi/pc/DSDT.hpbrroot | Bin 3084 -> 3069 bytes tests/data/acpi/pc/DSDT.ipmikcs | Bin 6074 -> 6059 bytes tests/data/acpi/pc/DSDT.memhp | Bin 7361 -> 7346 bytes tests/data/acpi/pc/DSDT.nohpet | Bin 5860 -> 5845 bytes tests/data/acpi/pc/DSDT.numamem | Bin 6008 -> 5993 bytes tests/data/acpi/pc/DSDT.roothp | Bin 6210 -> 6195 bytes tests/data/acpi/q35/DSDT | Bin 8289 -> 8274 bytes tests/data/acpi/q35/DSDT.acpierst | Bin 8306 -> 8291 bytes tests/data/acpi/q35/DSDT.acpihmat | Bin 9614 -> 9599 bytes tests/data/acpi/q35/DSDT.bridge | Bin 11003 -> 10988 bytes tests/data/acpi/q35/DSDT.cphp | Bin 8753 -> 8738 bytes tests/data/acpi/q35/DSDT.cxl | Bin 9615 -> 9600 bytes tests/data/acpi/q35/DSDT.dimmpxm | Bin 9943 -> 9928 bytes tests/data/acpi/q35/DSDT.ipmibt | Bin 8364 -> 8349 bytes tests/data/acpi/q35/DSDT.ipmismbus | Bin 8378 -> 8363 bytes tests/data/acpi/q35/DSDT.ivrs | Bin 8306 -> 8291 bytes tests/data/acpi/q35/DSDT.memhp | Bin 9648 -> 9633 bytes tests/data/acpi/q35/DSDT.mmio64 | Bin 9419 -> 9404 bytes tests/data/acpi/q35/DSDT.multi-bridge | Bin 8583 -> 8568 bytes tests/data/acpi/q35/DSDT.nohpet | Bin 8147 -> 8132 bytes tests/data/acpi/q35/DSDT.numamem | Bin 8295 -> 8280 bytes tests/data/acpi/q35/DSDT.tis.tpm12 | Bin 8900 -> 8885 bytes tests/data/acpi/q35/DSDT.tis.tpm2 | Bin 8921 -> 8906 bytes tests/data/acpi/q35/DSDT.viot | Bin 9398 -> 9383 bytes tests/data/acpi/q35/DSDT.xapic | Bin 35652 -> 35637 bytes tests/qtest/bios-tables-test-allowed-diff.h | 32 -------------------- 33 files changed, 32 deletions(-) diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index cc1223773e9c459a8d2f20666c051a74338d40b7..e80bef30317b5ef3bf0d2fb7aaabd6def109adb6 100644 GIT binary patch delta 44 zcmeyQ_gIh1CDVgT_=4|o6o diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst index bb0593eeb8730d51a6f0fe51a00a00df9c83c419..d5a2ca51652dfc3637a817bac4a02d6ff6dc8ac2 100644 GIT binary patch delta 44 zcmcbpcSw)RCDNE47$d)%q+WcmQ+$B4r$Ka+r^IAkM#;_LjK4$y1_}%4 delta 60 zcmX@4cTtbaCD5O59$B_ diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat index 2d0678eb83277088b156d386067429b0f29f9338..f86c743c4d64041c7fbd9999cc700e88416770b7 100644 GIT binary patch delta 44 zcmbPlIl+?4CDe8-u~CD(^b delta 60 zcmdmNbjXOyCD`pO$^ZZwMi9gR diff --git a/tests/data/acpi/pc/DSDT.hpbridge b/tests/data/acpi/pc/DSDT.hpbridge index bb0593eeb8730d51a6f0fe51a00a00df9c83c419..d5a2ca51652dfc3637a817bac4a02d6ff6dc8ac2 100644 GIT binary patch delta 44 zcmcbpcSw)RCDNE47$d)%q+WcmQ+$B4r$Ka+r^IAkM#;_LjK4$y1_}%4 delta 60 zcmX@4cTtbaCD5O59$B_ diff --git a/tests/data/acpi/pc/DSDT.hpbrroot b/tests/data/acpi/pc/DSDT.hpbrroot index 6ff6f198c7caf445d25c01117a6357b398358cbf..ec99b1622934a0fd8bc316291c33231e4c57dce0 100644 GIT binary patch delta 44 zcmeB?_$$uk66_N4mz#lsk!d5B7$d)%q+WcmQ+$B4r$Ka+r^IAkM#;_Lj9a+?2qz1y delta 60 zcmew>-Xp=~66_Mf!^6P9Xt0q>jFDGOFFx2QKET=2Ai7CvvOc4vpn#vaJ~K?vGuSbH Jvj^i=E�n4z2(I diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs index 2e618e49d357ae1d0ac20d822f71d676ea90f2fc..f0d9e75841ea3d69fed9384e439bc4e94c7a4c4e 100644 GIT binary patch delta 44 zcmdm`zgnNmCD5sPVoWGo(9oPj`q_qyg@S55@oh diff --git a/tests/data/acpi/pc/DSDT.nohpet b/tests/data/acpi/pc/DSDT.nohpet index 623f06a900d12500d2197d101f76f6875e92ed64..cb7bf7d850f340e12a7237c987f570300fd9c92b 100644 GIT binary patch delta 41 xcmaE&dsUaqCD|w< diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/pc/DSDT.roothp index cee3b4d80b51ad30153953ace46127923ce8b271..46e03d39e00ea70e55d6a12333ca2b98c5e5bb53 100644 GIT binary patch delta 44 zcmX?Pu-SmiCDk-8M! diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat index f24d4874bff8d327a165ed7c36de507aea114edd..af10345e8806c78a0074b3a8819b5cfca4d70c01 100644 GIT binary patch delta 44 zcmeD4{_n-*66_LEugbu{IC&%2O-6oaLB053r}zM8PlM*Co#F$WJq@Cp+yo|nV3gb}#q>}E0AVT) A?*IS* delta 80 zcmaD8`a6`%CD@~ diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp index f1275606f68eeba54bfb11e63d818420385a62b9..ac8456a43d54209d77917163b282954d7429b331 100644 GIT binary patch delta 44 zcmdn!vdD$YCDF$oF>WK*O-6Gyz4&0K_yA{5gXktH&tS)Rj(A6xARYz=d4}kQ b0MDR6Cawf79szHDeP) diff --git a/tests/data/acpi/q35/DSDT.cxl b/tests/data/acpi/q35/DSDT.cxl index c1206defed0154e9024702bba88453b2790a306d..369ae90196113ec666a4acec7bb7a93be5b60e75 100644 GIT binary patch delta 44 zcmeD8Zt&)E33dr-P-S3Xytk3-CL_PIpk92iQ+$B4r$Ka+o517`jFOwBm`araDH9DJ delta 80 zcmZqh?)T<$33dtTS7l&eWZKAelhIsFFFx2QKET=2Ai7D)GuSbnBi_*^h=+keo*}v+ bz%wY2i7SDNN5Gq3pBbhQq-rxaQ>iilJo#F$WJq@Cp97QL8V3gb}#WYC{05{ML Ap#T5? delta 80 zcmbR1xWv04cW( ABme*a delta 80 zcmZ4OxXY2tCDk-8M! diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp index 4e9cb3dc6896bb79ccac0fe342a404549f6610e8..663456fc0d3c71a51b541f5ab952e05c9dac01e6 100644 GIT binary patch delta 44 zcmdnsz0jM>CDCo#F$WJq@Cp+yo|nV3gb}#WYPB05)0; AjQ{`u delta 80 zcmZ4Jy}_HyCD<^x}h^;scyL4WgT*JcAwMIpQ5%f_NAh-$Gfh(l0GH<#M*si- diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64 index eb5a1c7171c02d153487bfcecfb7019b7c1bf406..91afd01d598c7c2c733387dfb5140d0fcad54adb 100644 GIT binary patch delta 44 zcmX@@xyO^sCD<^x}h^;scyL4WgT*JcAwMIpQ5%f_NAh-$Gi_7?0G&M*X#fBK diff --git a/tests/data/acpi/q35/DSDT.multi-bridge b/tests/data/acpi/q35/DSDT.multi-bridge index 45808eb03b78d07ebbe853f674abfed589d35e26..afde339a181628ae9153251eee026b437ab685bc 100644 GIT binary patch delta 44 zcmZp7{^7*s66_LEp~%3%n6;7XCL_PIpk92iQ+$B4r$Ka+o517`jFOwBm~!O-DNYRX delta 80 zcmez2)b7mX66_MvuE@Z^*te1ECZoBUUVN}qe1Nm3L3ERpXRu>DN4%p;5Dx=`JVSIt bfM-x36ITKkkAOG7J~K=qNY!R;rd)Xdd|?!< diff --git a/tests/data/acpi/q35/DSDT.nohpet b/tests/data/acpi/q35/DSDT.nohpet index 83d1aa00ac5686df479673fb0d7830f946e25dea..0fb09121cf8f6ad8810587c8b77df9552dd31f42 100644 GIT binary patch delta 65 zcmca?f5e{4CDCo#F$WJq@Cp+yo|nV3gb}#k5KR06d2c A!T8>CD<^x}h^;scyL4WgT*JcAwMIpQ5%f_NAh-$Gp$kp0HY)od;kCd diff --git a/tests/data/acpi/q35/DSDT.tis.tpm2 b/tests/data/acpi/q35/DSDT.tis.tpm2 index 00d732e46f5d9d056e557bd026fa30f9db3b8c30..4e16b126cc1c32f2346078fa69c5261c245d15e8 100644 GIT binary patch delta 44 zcmccVddii{CDCo#F$WJq@Cp+yo|nV3gb}#k5}m07~=@ AI{*Lx delta 80 zcmX@*defE5CD diff --git a/tests/data/acpi/q35/DSDT.viot b/tests/data/acpi/q35/DSDT.viot index 1c3b4da5cbe81ecab5e1ef50d383b561c5e0f55f..e20e4ee5e92e11ccf890a18fbdd78181c43f3b5c 100644 GIT binary patch delta 44 zcmdnyx!jY>CD<^x}h^;scyL4WgT*JcAwMIpQ5%f_NAh-$GtE%~0E!3|6aWAK diff --git a/tests/data/acpi/q35/DSDT.xapic b/tests/data/acpi/q35/DSDT.xapic index 17552ce363ae81985f69f9ae85837a1540b79ae0..3cab5956eee60363251a6fab0cc981bbbda64443 100644 GIT binary patch delta 46 zcmX>yjcMyNCN7s?mk`r#1_s8Sja)Yw`JDyz;)9*y1Drh#qMO_VCVya*+$_bU)d>Jm Crw#`I delta 82 zcmdlwjp@iVCN7s?mk^h31_s6r8@X;Wnycx>2Rp?FIC~mIH%WO0JH~UwJGun%Ffhn7 eL^lL@1_d&4C2;Wwc=PKs!xVy4ZRTdu>I4AAB^AK{ diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 666e257bf9..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,33 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/pc/DSDT", -"tests/data/acpi/pc/DSDT.acpierst", -"tests/data/acpi/pc/DSDT.acpihmat", -"tests/data/acpi/pc/DSDT.bridge", -"tests/data/acpi/pc/DSDT.cphp", -"tests/data/acpi/pc/DSDT.dimmpxm", -"tests/data/acpi/pc/DSDT.hpbridge", -"tests/data/acpi/pc/DSDT.ipmikcs", -"tests/data/acpi/pc/DSDT.memhp", -"tests/data/acpi/pc/DSDT.nohpet", -"tests/data/acpi/pc/DSDT.numamem", -"tests/data/acpi/pc/DSDT.roothp", -"tests/data/acpi/pc/DSDT.hpbrroot", -"tests/data/acpi/q35/DSDT", -"tests/data/acpi/q35/DSDT.acpierst", -"tests/data/acpi/q35/DSDT.acpihmat", -"tests/data/acpi/q35/DSDT.bridge", -"tests/data/acpi/q35/DSDT.cphp", -"tests/data/acpi/q35/DSDT.dimmpxm", -"tests/data/acpi/q35/DSDT.ipmibt", -"tests/data/acpi/q35/DSDT.ivrs", -"tests/data/acpi/q35/DSDT.memhp", -"tests/data/acpi/q35/DSDT.mmio64", -"tests/data/acpi/q35/DSDT.multi-bridge", -"tests/data/acpi/q35/DSDT.nohpet", -"tests/data/acpi/q35/DSDT.numamem", -"tests/data/acpi/q35/DSDT.tis.tpm12", -"tests/data/acpi/q35/DSDT.tis.tpm2", -"tests/data/acpi/q35/DSDT.viot", -"tests/data/acpi/q35/DSDT.xapic", -"tests/data/acpi/q35/DSDT.ipmismbus", -"tests/data/acpi/q35/DSDT.cxl", From 39728badab1aadd3a269614da2d42b4f7f09cb0a Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:27 -0400 Subject: [PATCH 022/180] tests: acpi: add and white-list DSDT.applesmc expected blob Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-23-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.applesmc | 0 tests/qtest/bios-tables-test-allowed-diff.h | 1 + 2 files changed, 1 insertion(+) create mode 100644 tests/data/acpi/q35/DSDT.applesmc diff --git a/tests/data/acpi/q35/DSDT.applesmc b/tests/data/acpi/q35/DSDT.applesmc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..e893029d87 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/DSDT.applesmc", From cde55744e9bcaefe1fbce6194a21bb3b7b9c2ae7 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:28 -0400 Subject: [PATCH 023/180] tests: acpi: add applesmc testcase Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-24-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index d896840270..7d238218ca 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1625,6 +1625,17 @@ static void test_acpi_q35_slic(void) free_test_data(&data); } +static void test_acpi_q35_applesmc(void) +{ + test_data data = { + .machine = MACHINE_Q35, + .variant = ".applesmc", + }; + + test_acpi_one("-device isa-applesmc", &data); + free_test_data(&data); +} + static void test_oem_fields(test_data *data) { int i; @@ -1783,6 +1794,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); + qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); From 1d7ea915003a2064dc542ffee8d02104a2dee728 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:29 -0400 Subject: [PATCH 024/180] acpi: applesmc: use AcpiDevAmlIfClass:build_dev_aml to provide device's AML .. and clean up not longer needed conditionals in DSTD build code. applesmc AML will be fetched and included when ISA bridge will build its own AML code (incl. attached devices). Expected AML change: the device under separate _SB.PCI0.ISA scope is moved directly under Device(ISA) node. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-25-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 22 ---------------------- hw/misc/applesmc.c | 29 +++++++++++++++++++++++++++++ include/hw/isa/isa.h | 14 -------------- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index f7f1671407..b96705c688 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -121,7 +121,6 @@ typedef struct AcpiMiscInfo { const unsigned char *dsdt_code; unsigned dsdt_size; uint16_t pvpanic_port; - uint16_t applesmc_io_base; } AcpiMiscInfo; typedef struct AcpiBuildPciBusHotplugState { @@ -307,7 +306,6 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) info->tpm_version = tpm_get_version(tpm_find()); #endif info->pvpanic_port = pvpanic_port(); - info->applesmc_io_base = applesmc_port(); } /* @@ -1800,26 +1798,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dsdt, scope); } - if (misc->applesmc_io_base) { - scope = aml_scope("\\_SB.PCI0.ISA"); - dev = aml_device("SMC"); - - aml_append(dev, aml_name_decl("_HID", aml_eisaid("APP0001"))); - /* device present, functioning, decoding, not shown in UI */ - aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); - - crs = aml_resource_template(); - aml_append(crs, - aml_io(AML_DECODE16, misc->applesmc_io_base, misc->applesmc_io_base, - 0x01, APPLESMC_MAX_DATA_LENGTH) - ); - aml_append(crs, aml_irq_no_flags(6)); - aml_append(dev, aml_name_decl("_CRS", crs)); - - aml_append(scope, dev); - aml_append(dsdt, scope); - } - if (misc->pvpanic_port) { scope = aml_scope("\\_SB.PCI0.ISA"); diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c index 81cd6b6423..5f9c742e50 100644 --- a/hw/misc/applesmc.c +++ b/hw/misc/applesmc.c @@ -37,10 +37,14 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "qom/object.h" +#include "hw/acpi/acpi_aml_interface.h" /* #define DEBUG_SMC */ #define APPLESMC_DEFAULT_IOBASE 0x300 +#define TYPE_APPLE_SMC "isa-applesmc" +#define APPLESMC_MAX_DATA_LENGTH 32 +#define APPLESMC_PROP_IO_BASE "iobase" enum { APPLESMC_DATA_PORT = 0x00, @@ -347,14 +351,35 @@ static Property applesmc_isa_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void build_applesmc_aml(AcpiDevAmlIf *adev, Aml *scope) +{ + Aml *crs; + AppleSMCState *s = APPLE_SMC(adev); + uint32_t iobase = s->iobase; + Aml *dev = aml_device("SMC"); + + aml_append(dev, aml_name_decl("_HID", aml_eisaid("APP0001"))); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + crs = aml_resource_template(); + aml_append(crs, + aml_io(AML_DECODE16, iobase, iobase, 0x01, APPLESMC_MAX_DATA_LENGTH) + ); + aml_append(crs, aml_irq_no_flags(6)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + static void qdev_applesmc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->realize = applesmc_isa_realize; dc->reset = qdev_applesmc_isa_reset; device_class_set_props(dc, applesmc_isa_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); + adevc->build_dev_aml = build_applesmc_aml; } static const TypeInfo applesmc_isa_info = { @@ -362,6 +387,10 @@ static const TypeInfo applesmc_isa_info = { .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(AppleSMCState), .class_init = qdev_applesmc_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void applesmc_register_types(void) diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index 5c5a3d43a7..6f9380007d 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -16,20 +16,6 @@ OBJECT_DECLARE_TYPE(ISADevice, ISADeviceClass, ISA_DEVICE) #define TYPE_ISA_BUS "ISA" OBJECT_DECLARE_SIMPLE_TYPE(ISABus, ISA_BUS) -#define TYPE_APPLE_SMC "isa-applesmc" -#define APPLESMC_MAX_DATA_LENGTH 32 -#define APPLESMC_PROP_IO_BASE "iobase" - -static inline uint16_t applesmc_port(void) -{ - Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL); - - if (obj) { - return object_property_get_uint(obj, APPLESMC_PROP_IO_BASE, NULL); - } - return 0; -} - #define TYPE_ISADMA "isa-dma" typedef struct IsaDmaClass IsaDmaClass; From ec66dbc75381ad6c3ac62c907b014d847ece4580 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:30 -0400 Subject: [PATCH 025/180] tests: acpi: update expected blobs @@ -145,6 +145,23 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) { Name (_ADR, 0x001F0000) // _ADR: Address OperationRegion (PIRQ, PCI_Config, 0x60, 0x0C) + Device (SMC) + { + Name (_HID, EisaId ("APP0001")) // _HID: Hardware ID + Name (_STA, 0x0B) // _STA: Status + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x0300, // Range Minimum + 0x0300, // Range Maximum + 0x01, // Alignment + 0x20, // Length + ) + IRQNoFlags () + {6} + }) + } + Device (KBD) { Name (_HID, EisaId ("PNP0303") /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */) // _HID: Hardware ID @@ -3246,26 +3263,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) } } - Scope (\_SB.PCI0.ISA) - { - Device (SMC) - { - Name (_HID, EisaId ("APP0001")) // _HID: Hardware ID - Name (_STA, 0x0B) // _STA: Status - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings - { - IO (Decode16, - 0x0300, // Range Minimum - 0x0300, // Range Maximum - 0x01, // Alignment - 0x20, // Length - ) - IRQNoFlags () - {6} - }) - } - } - Scope (\_SB) { Scope (PCI0) Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-26-imammedo@redhat.com> --- tests/data/acpi/q35/DSDT.applesmc | Bin 0 -> 8320 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/q35/DSDT.applesmc b/tests/data/acpi/q35/DSDT.applesmc index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..00092aacc6ce44dd8792b00a0fa183e5b06d33c6 100644 GIT binary patch literal 8320 zcmb7JOKcm*8J^`!tL0K!Qk3OaY{E&)_r?xN%s)PQXYx!=g zYz~?&&#oL;ra5rMS<)O-ye=~bn=OwO*X9Q6ft$MXI&;0ttD{bOxRYP9oPPUX7rs4v z`lT-}zf-yQ^MC&0&g)hRfb;lk;_ros4&eu(btW7+za3sTJ|sH7wmMq+?T}vEV}%AEI@ z(>8_5n%VSgJ*m=wHd58!ZTh`7vl%=1F3VE=TMorbFV{L=$?tlDQt`P#(5tYBTEd8$ zw%!jdCmh+I4MR2zv*YnT8!db`++x4mvf01?m)>Xl)}rWJ-dgy0p89g|9ZNBW-c*WD zQFmy-`+MF}E2s?kAfp3k(HXzh-AGuWW%u`<4B9TP(M`!X%z%ns#mb7jj+JW|EXk5a z>D)_5+uwWUQq_ymm4hV25jyV0acj9@ge+u+(J-#DYxsLE!C8;B*EbJYi%S~Iw9@Bj z0Q-CA*Zkh99JrKt9OC}O6?lK%O}?8n&2zgv^Lcl@eaJ}zjlrJ5xu3kBWac@Ca~|*Z zq~gj!Hom<)b;Kf!z&U1M1UvZ$Be?6kLC?tEvn>;Mjsh1WyII1)EA@AS+C@x~zuOk> zYnB4HTCQEhg=(kWHL?eSMuA)HY_>~&%X_8NH>zvyC02agcWW0D{YNPpkE0zzMDH2b z8Rh8zfSUJN@repJvrv>PqC*&C!=jh*y`a4?T8n4S!Snz4Pw?#f?ax-eX`lG3+m0yL z8@~!ij}C9J(TU-8D}f2}A%DzlJk?{ipHCXM=)mr-jFyKtthuO=POu!?io)AljO}lk ze#@=1qCLQ0Bif#Sf?yOluD zkUC}$!hCVIoMNzRl# zNHStdXi_i%FS`?h={^XF>BZQS8uO&aJgGAgs?1Xw^OVLs zr85z#%+nh4w8lKGGZCuHM>OUm8uJmIiBM&p;Y{f=XE;;7G*E$!BdVzysDK_CC_?mzV_~2I8%ME54kZH>P#LN^VW1){ zXTm@gC>bb1>562a2&GOKsK9b23{-)VfeI+ENd}5g>V$y`EN8+%6(|{~fN~}oC_`0?L_Wpa`W-7^uKf}LawZulLa7r5DzKah16818paRO7WS|J8P8g`bawZH^ zfs%m=C})y^B9uB|paRR8Fi-_b1}dPONd}5g>V$y`EN8+%6(|{~fN~}oC_Az;Y%GRDqI#3Mglifg+STVW0xbnJ`cVN(L&RoJj_XQ0jz% zB2o+#k!qj_RRcw+7^uR8fhtTgP=!ebsxV=o3KIsZFv&m_CK;&0gn=qd7^uP|167!0 zpb8TPsxV=o3X=>}VUmF=Oc*F4d3Rx;h;YaFV3L6%#BGovG3D68KoQBYg@GcHV@n2# zP>wAbC_=0xogBbI*~lL9e^&SDAJV%S`cvuO`sve2`Y)9hMrbj_@VgroIPON34lW%$ zlVNFQqeka-IyC6eG>c2E4Xg%?=0C7@cd!OCzi(xW&$Kq&?mPh9a(=_a-Yc6rMpEmtuh+%At-20=G4?(D>Upz_onSFcV~$KuKN zu3lBDS9$d+`lnW}7H3zl_V?PPU97ZWH89q0B_5)@tCV+nd3U0`dqjCRF7HieC8p_HH%LAVknC@a3R&Oh2_>{*Vn%8l<$!Tom^>p~wm`W$wW~Q5(mjyi?K0v0@iME;P zrsf%zfN7pdVfZSUN+;T8rkk2KMLiupRi@I3wwdXs=E1U_4&N_R=|tPibW_juF+CkV zYNpbOwwdXsp3@aQ9lms?(up=bopb8JdiLI8(5_-92D>hH5*q@}`io-oqG?@uIw>~} z{BA9fPpO5;32(}|{${E9<~z|FH-A}r>$SJvy!qDlYj3l@;reTr;-@udSqp2$^()+FA*4 zuhJ`Ft+~}{nGvH#JoOi@a6Rad=wz2drF*k5K<`FVXw^O@ZNQ@)49U0fY^a{gkM#Qc~Mi{ZJFW2nf3`67dZ8U|^_GC#e zc(M^UWwi47WGimV_E)3%;g&T{jU3(gX!|zxaf{vDLa**VKYDfw#-9w_ zzHKWRO$`h#f_HP9_8n^}vGGU=ud;2r<U!5&(Di`{5^XlwjZqK{xLC-#7m}fsN zQ~5D?(e)W)6IqGLR)XG`Y{W3n>|Ot(7wDPB{KpT|1JAX&Pfs^yK)ce*XDyRqwSm4v ziwoFO?PW;}+qr(DcnXuJ;nxPW@_81|c$!G`OgZZ*y2K}bJg3UfvEomFU1c;7hwlfm zW2H3sZin|&LpbeaF;n@b5Z_9@n6>_VJI4}OBEWA<2kaQ$x9{7AiFO0;B>cX`<@@$w zoWmXxWB=uQu>3lG7LUjDSxmnK({^V~Y-9aVTw#CEuH3`6?RVnJy%+C1fgRmAn`ooa zqCGGSoc5!bHYwc{21jgS^9|w(21mRasa<&|Y8$Eiomk40G6vu2yqNNvepd`J?J_?| zf Date: Wed, 8 Jun 2022 09:53:31 -0400 Subject: [PATCH 026/180] tests: acpi: white-lists expected DSDT.pvpanic-isa blob Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-27-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.pvpanic-isa | 0 tests/qtest/bios-tables-test-allowed-diff.h | 1 + 2 files changed, 1 insertion(+) create mode 100644 tests/data/acpi/q35/DSDT.pvpanic-isa diff --git a/tests/data/acpi/q35/DSDT.pvpanic-isa b/tests/data/acpi/q35/DSDT.pvpanic-isa new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..d5cd7aa4f5 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/DSDT.pvpanic-isa", From fd7bcffe5988d799f37e4ad92cfd1480ce7a9ce6 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:32 -0400 Subject: [PATCH 027/180] tests: acpi: add pvpanic-isa: testcase Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-28-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 7d238218ca..56498bbcc8 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1636,6 +1636,17 @@ static void test_acpi_q35_applesmc(void) free_test_data(&data); } +static void test_acpi_q35_pvpanic_isa(void) +{ + test_data data = { + .machine = MACHINE_Q35, + .variant = ".pvpanic-isa", + }; + + test_acpi_one("-device pvpanic", &data); + free_test_data(&data); +} + static void test_oem_fields(test_data *data) { int i; @@ -1795,6 +1806,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); + qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); From ff36e90e7c12c0bfdb43737614f8ef7c3bc35bd1 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:33 -0400 Subject: [PATCH 028/180] acpi: pvpanic-isa: use AcpiDevAmlIfClass:build_dev_aml to provide device's AML .. and clean up not longer needed conditionals in DSTD build code pvpanic-isa AML will be fetched and included when ISA bridge will build its own AML code (including attached devices). Expected AML change: the device under separate _SB.PCI0.ISA scope is moved directly under Device(ISA) node. Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-29-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 37 ---------------------------------- hw/misc/pvpanic-isa.c | 42 +++++++++++++++++++++++++++++++++++++++ include/hw/misc/pvpanic.h | 9 --------- 3 files changed, 42 insertions(+), 46 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index b96705c688..bbe02b068e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -31,7 +31,6 @@ #include "hw/cxl/cxl.h" #include "hw/core/cpu.h" #include "target/i386/cpu.h" -#include "hw/misc/pvpanic.h" #include "hw/timer/hpet.h" #include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" @@ -120,7 +119,6 @@ typedef struct AcpiMiscInfo { #endif const unsigned char *dsdt_code; unsigned dsdt_size; - uint16_t pvpanic_port; } AcpiMiscInfo; typedef struct AcpiBuildPciBusHotplugState { @@ -305,7 +303,6 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) #ifdef CONFIG_TPM info->tpm_version = tpm_get_version(tpm_find()); #endif - info->pvpanic_port = pvpanic_port(); } /* @@ -1798,40 +1795,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dsdt, scope); } - if (misc->pvpanic_port) { - scope = aml_scope("\\_SB.PCI0.ISA"); - - dev = aml_device("PEVT"); - aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001"))); - - crs = aml_resource_template(); - aml_append(crs, - aml_io(AML_DECODE16, misc->pvpanic_port, misc->pvpanic_port, 1, 1) - ); - aml_append(dev, aml_name_decl("_CRS", crs)); - - aml_append(dev, aml_operation_region("PEOR", AML_SYSTEM_IO, - aml_int(misc->pvpanic_port), 1)); - field = aml_field("PEOR", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); - aml_append(field, aml_named_field("PEPT", 8)); - aml_append(dev, field); - - /* device present, functioning, decoding, shown in UI */ - aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); - - method = aml_method("RDPT", 0, AML_NOTSERIALIZED); - aml_append(method, aml_store(aml_name("PEPT"), aml_local(0))); - aml_append(method, aml_return(aml_local(0))); - aml_append(dev, method); - - method = aml_method("WRPT", 1, AML_NOTSERIALIZED); - aml_append(method, aml_store(aml_arg(0), aml_name("PEPT"))); - aml_append(dev, method); - - aml_append(scope, dev); - aml_append(dsdt, scope); - } - sb_scope = aml_scope("\\_SB"); { Object *pci_host; diff --git a/hw/misc/pvpanic-isa.c b/hw/misc/pvpanic-isa.c index b84d4d458d..ccec50f61b 100644 --- a/hw/misc/pvpanic-isa.c +++ b/hw/misc/pvpanic-isa.c @@ -22,6 +22,7 @@ #include "qom/object.h" #include "hw/isa/isa.h" #include "standard-headers/linux/pvpanic.h" +#include "hw/acpi/acpi_aml_interface.h" OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE) @@ -63,6 +64,41 @@ static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(d, &ps->mr, s->ioport); } +static void build_pvpanic_isa_aml(AcpiDevAmlIf *adev, Aml *scope) +{ + Aml *crs, *field, *method; + PVPanicISAState *s = PVPANIC_ISA_DEVICE(adev); + Aml *dev = aml_device("PEVT"); + + aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0001"))); + + crs = aml_resource_template(); + aml_append(crs, + aml_io(AML_DECODE16, s->ioport, s->ioport, 1, 1) + ); + aml_append(dev, aml_name_decl("_CRS", crs)); + + aml_append(dev, aml_operation_region("PEOR", AML_SYSTEM_IO, + aml_int(s->ioport), 1)); + field = aml_field("PEOR", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); + aml_append(field, aml_named_field("PEPT", 8)); + aml_append(dev, field); + + /* device present, functioning, decoding, shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); + + method = aml_method("RDPT", 0, AML_NOTSERIALIZED); + aml_append(method, aml_store(aml_name("PEPT"), aml_local(0))); + aml_append(method, aml_return(aml_local(0))); + aml_append(dev, method); + + method = aml_method("WRPT", 1, AML_NOTSERIALIZED); + aml_append(method, aml_store(aml_arg(0), aml_name("PEPT"))); + aml_append(dev, method); + + aml_append(scope, dev); +} + static Property pvpanic_isa_properties[] = { DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505), DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, @@ -73,10 +109,12 @@ static Property pvpanic_isa_properties[] = { static void pvpanic_isa_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); dc->realize = pvpanic_isa_realizefn; device_class_set_props(dc, pvpanic_isa_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); + adevc->build_dev_aml = build_pvpanic_isa_aml; } static const TypeInfo pvpanic_isa_info = { @@ -85,6 +123,10 @@ static const TypeInfo pvpanic_isa_info = { .instance_size = sizeof(PVPanicISAState), .instance_init = pvpanic_isa_initfn, .class_init = pvpanic_isa_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_ACPI_DEV_AML_IF }, + { }, + }, }; static void pvpanic_register_types(void) diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h index 7f16cc9b16..e520566ab0 100644 --- a/include/hw/misc/pvpanic.h +++ b/include/hw/misc/pvpanic.h @@ -33,13 +33,4 @@ struct PVPanicState { void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size); -static inline uint16_t pvpanic_port(void) -{ - Object *o = object_resolve_path_type("", TYPE_PVPANIC_ISA_DEVICE, NULL); - if (!o) { - return 0; - } - return object_property_get_uint(o, PVPANIC_IOPORT_PROP, NULL); -} - #endif From d09ac1167ef05519fcf94ea98734614d8aade7a4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:34 -0400 Subject: [PATCH 029/180] tests: acpi: update expected DSDT.pvpanic-isa blob @@ -145,6 +145,37 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) { Name (_ADR, 0x001F0000) // _ADR: Address OperationRegion (PIRQ, PCI_Config, 0x60, 0x0C) + Device (PEVT) + { + Name (_HID, "QEMU0001") // _HID: Hardware ID + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + IO (Decode16, + 0x0505, // Range Minimum + 0x0505, // Range Maximum + 0x01, // Alignment + 0x01, // Length + ) + }) + OperationRegion (PEOR, SystemIO, 0x0505, One) + Field (PEOR, ByteAcc, NoLock, Preserve) + { + PEPT, 8 + } + + Name (_STA, 0x0F) // _STA: Status + Method (RDPT, 0, NotSerialized) + { + Local0 = PEPT /* \_SB_.PCI0.ISA_.PEVT.PEPT */ + Return (Local0) + } + + Method (WRPT, 1, NotSerialized) + { + PEPT = Arg0 + } + } + Device (KBD) { Name (_HID, EisaId ("PNP0303") /* IBM Enhanced Keyboard (101/102-key, PS/2 Mouse) */) // _HID: Hardware ID @@ -3246,40 +3277,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) } } - Scope (\_SB.PCI0.ISA) - { - Device (PEVT) - { - Name (_HID, "QEMU0001") // _HID: Hardware ID - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings - { - IO (Decode16, - 0x0505, // Range Minimum - 0x0505, // Range Maximum - 0x01, // Alignment - 0x01, // Length - ) - }) - OperationRegion (PEOR, SystemIO, 0x0505, One) - Field (PEOR, ByteAcc, NoLock, Preserve) - { - PEPT, 8 - } - - Name (_STA, 0x0F) // _STA: Status - Method (RDPT, 0, NotSerialized) - { - Local0 = PEPT /* \_SB_.PCI0.ISA_.PEVT.PEPT */ - Return (Local0) - } - - Method (WRPT, 1, NotSerialized) - { - PEPT = Arg0 - } - } - } - Scope (\_SB) { Scope (PCI0) Signed-off-by: Igor Mammedov Message-Id: <20220608135340.3304695-30-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.pvpanic-isa | Bin 0 -> 8375 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/q35/DSDT.pvpanic-isa b/tests/data/acpi/q35/DSDT.pvpanic-isa index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cc545b5d2505246d33f83d2482273968aa1be032 100644 GIT binary patch literal 8375 zcmb7JOKcm*8J^`!tK~{sQk3LZY{E&?~(R|lb;iIo;;J&VO^} z)XzV^_)huW&;I#~+pk+G0M6mBiNEJ#xAeAd5ed_Z*mY;~~sS)V@^Wez=w zBPzLTiz2FO_2BjH{)=9_?D96w1+AdumR8X&w;krrSf@T-Va%q^q2Hf|!{J}WEpu)# zr)dh6zF80aj#Ozt8>#B<)q_rx*^J%)Hp^1on-0Z`FZ(U87__}!vG9B^?37tdB~eU8 z+wVn|6AkQ7`w{C$+2Qbj4dy@XZ?oTR+w9-}OCPWUYeBRvXU%^!OKrLTElV+m*3?&? zrshzGclXzp8)3P}I~ff)gT@4n_GZG0EE}Ve3H+Bud*?R&=2oe6D0$AZYDOAA!?-~t zf1_<=5n(Ry`@j!67)7+(S}4r7y`aNlDvJ)Hf_9f@D-TiaxL1$Igof5Oi(6Ej* zS2NyCzMC}7vwOVebM8j-kdp=)V>E^HAo(E4%(D*XJlXEJhpowuW(BW0W-&9&vkblD zv~mwSelKvtj*-1*TP6ma0v7|aRm8A&BB-L`V_cPL@WU3 z#WT(WREESv{T!R%OkhV5F(ov?I1^CLL`Y1uhGUbQDO-?a#FWsaU;@gS2#G1PV6_S? zuP4Qs5}FcB*?5Gi&a|d8&6yIK7EIZAgsRSrrZdBt5}MI9&fI%jpA2vwbyrqj}NTDnezs?MyYGpp&$>N*jsI`Mv0#?#hx z+PY4Js?Ir0=bWZD>pBstIu|sZ3!2UaT_-|Sr=#g~G@XvF6QQaz zr|HaTI&->CgsRTGrZcbU%u8LB#AprTsNgn=qhGEjul70EymN}VuJf#pmX zr~)Me6;Pg&3>2Z%2?G^a&V+#~P%=;fAz;Y%GRDqI#3Mglifg+ST zVW0xbnJ`cVN(L&RoJj_XQ0jz%3M^;BKouw%sDN@N87M-j69y``0?L_Wpa`W-7^uKf}LawZulLa7r5DzKah16818paRO7WS|J8P8g`bawZH^ zfs%m=C})y^B9uB|paRR8Fi-_b1}dPONd}5g>V$zJQVbN4YM=;J14XD9sKSJSDoip^ zg-HggFkzqy69%d<$v_n*8K}a9fhtTGsKO)zRhVR;3KIsZFkzqylMGa0l7T8r7$_n+ zx-d{g7%|?NWS|H!3^F99>{}QpBH6bvP(-qC$v_dxz9j=ihz+O{Jy<9k*nR%b>H+;j zdN)IV%H5kkc_vB!rP6*1?V%V!d$SD3-K@~XrHf}W?C5OzbYG=QjV^Vwu-MqdZopvn zeQR$QTQ{=@R<`hLW7BQV0?;ny=B?}}88*xJmu|4zRA!}dZN%^IS__Qs(1y_R3gxY@U4Q>=h+@g=epzeQNefVS4sTcfU#6 z#ReTV5l7ms#3Q74mGmx8?~bK+k4W#1(tBg#Eo^9gXZ4%>Ag{Ue>{Ea z5z_lgdY`BF$I|;pr1wYZtK;d@kC48qq_6Vy)v@%|Bhpt#>1*TZGmntIrlha&^tG|{ zwIkBkM(OM0>1Q4xeO*ak=jrQX>FY^|C^SFM0f- zbv>$Xd>LCgy*hkrOjIYzrdBtxF7tYI_yC!xPLxfpZepEb3z*iK6o#*oiRwhz)aoYI zO+l{?pDGj8iL$BHO{{|@y*hlqOjIYzrdBsGub1`e@KG~SohX}H-NZay(W}Fk&O~*h zOs~#4`EWmbe<5sEaDaou8as(|1ZU$VapqCCE@_!94Krp`h*^LB64!$U ziAK(q-JpRZj}kRQ97m-KIk!`NH8HUIyX+$u2O?Js^$d3J%d_3bFFlh|g^~c;ejhJJ zvY17K6aDcABq6pIu{ph^->Xg2Tt;BdKL9dM$qMN6- zuKVGOG^ert@x$`KyfzPLc4GxJ%bi@-G8uLo=sUD9kE7U5mc+2#tJexAv3P2M-}6i7 z*l5MmLZUh4Y^3NBU-+XnReGKkehlm?qmDRyKZp}6r66!yyrmk#X)cMC$`6J33G9We z_2*l2EP*Wo{DySFiQxnLfo+&5H}Fov?;AXRU?0YFI74FWzx?QyKc~;);gCLy>6c*I zp{|KztUrn;><`+LdpPa=Ry?`)((R{k5Im|)lu>Wd85lZF`%z4Xlx_;0BhJ40xpEnu zBVLVEuDlb)!DUuBIDaP=GsTR-PdYE8f_l&vT}+454=X_@O?kgg)^*RmXB)?GO! Date: Wed, 8 Jun 2022 09:53:35 -0400 Subject: [PATCH 030/180] tests: acpi: white-list DSDT.tis.tpm2/DSDT.tis.tpm12 expected blobs Signed-off-by: Igor Mammedov Acked-by: Ani Sinha Message-Id: <20220608135340.3304695-31-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..7b3bf9a207 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,3 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/DSDT.tis.tpm2", +"tests/data/acpi/q35/DSDT.tis.tpm12", From 5198d7939cc1b5076e0d673f93e6074f0235f2ff Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:36 -0400 Subject: [PATCH 031/180] acpi: pc/q35: tpm-tis: fix TPM device scope tpm-tis 2.0, is not a PCI device but ISA one, move it under ISA scope to fix incorrect placement. Fixes: 24cf5413aa0 (acpi: Make TPM 2.0 with TIS available as MSFT0101) Signed-off-by: Igor Mammedov Reviewed-by: Ani Sinha Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-32-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index bbe02b068e..6b496480d2 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1813,15 +1813,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, #ifdef CONFIG_TPM if (TPM_IS_TIS_ISA(tpm)) { + dev = aml_device("ISA.TPM"); if (misc->tpm_version == TPM_VERSION_2_0) { - dev = aml_device("TPM"); aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device"))); } else { - dev = aml_device("ISA.TPM"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31"))); } From d3ecb22c939ebbf92aa9d28b912a3b8a947a54f1 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:37 -0400 Subject: [PATCH 032/180] acpi: pc/q35: remove not needed 'if' condition on pci bus Signed-off-by: Igor Mammedov Reviewed-by: Ani Sinha Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-33-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6b496480d2..1204b6da05 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1797,16 +1797,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, sb_scope = aml_scope("\\_SB"); { - Object *pci_host; - PCIBus *bus = NULL; - - pci_host = acpi_get_i386_pci_host(); + Object *pci_host = acpi_get_i386_pci_host(); if (pci_host) { - bus = PCI_HOST_BRIDGE(pci_host)->bus; - } - - if (bus) { + PCIBus *bus = PCI_HOST_BRIDGE(pci_host)->bus; Aml *scope = aml_scope("PCI0"); /* Scan all PCI buses. Generate tables to support hotplug. */ build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); From 168e3aa7acdf128fb8176616dfe099d6ef3c2182 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:38 -0400 Subject: [PATCH 033/180] acpi: tpm-tis: use AcpiDevAmlIfClass:build_dev_aml to provide device's AML .. and clean up not longer needed conditionals in DSTD build code tpm-tis AML will be fetched and included when ISA bridge will build its own AML code (including attached devices). Expected AML change: the device under separate _SB.PCI0.ISA scope is moved directly under Device(ISA) node. Signed-off-by: Igor Mammedov Reviewed-by: Ani Sinha Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-34-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 34 ---------------------------------- hw/tpm/tpm_tis_isa.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 1204b6da05..0b65fc99cd 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1804,40 +1804,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, Aml *scope = aml_scope("PCI0"); /* Scan all PCI buses. Generate tables to support hotplug. */ build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); - -#ifdef CONFIG_TPM - if (TPM_IS_TIS_ISA(tpm)) { - dev = aml_device("ISA.TPM"); - if (misc->tpm_version == TPM_VERSION_2_0) { - aml_append(dev, aml_name_decl("_HID", - aml_string("MSFT0101"))); - aml_append(dev, - aml_name_decl("_STR", - aml_string("TPM 2.0 Device"))); - } else { - aml_append(dev, aml_name_decl("_HID", - aml_eisaid("PNP0C31"))); - } - aml_append(dev, aml_name_decl("_UID", aml_int(1))); - - aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); - crs = aml_resource_template(); - aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE, - TPM_TIS_ADDR_SIZE, AML_READ_WRITE)); - /* - FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs, - Rewrite to take IRQ from TPM device model and - fix default IRQ value there to use some unused IRQ - */ - /* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */ - aml_append(dev, aml_name_decl("_CRS", crs)); - - tpm_build_ppi_acpi(tpm, dev); - - aml_append(scope, dev); - } -#endif - aml_append(sb_scope, scope); } } diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c index 3477afd735..91e3792248 100644 --- a/hw/tpm/tpm_tis_isa.c +++ b/hw/tpm/tpm_tis_isa.c @@ -30,6 +30,7 @@ #include "tpm_prop.h" #include "tpm_tis.h" #include "qom/object.h" +#include "hw/acpi/acpi_aml_interface.h" struct TPMStateISA { /*< private >*/ @@ -138,10 +139,39 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp) } } +static void build_tpm_tis_isa_aml(AcpiDevAmlIf *adev, Aml *scope) +{ + Aml *dev, *crs; + TPMStateISA *isadev = TPM_TIS_ISA(adev); + TPMIf *ti = TPM_IF(isadev); + + dev = aml_device("TPM"); + if (tpm_tis_isa_get_tpm_version(ti) == TPM_VERSION_2_0) { + aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device"))); + } else { + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31"))); + } + aml_append(dev, aml_name_decl("_UID", aml_int(1))); + aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); + crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE, + AML_READ_WRITE)); + /* + * FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs, + * fix default TPM_TIS_IRQ value there to use some unused IRQ + */ + /* aml_append(crs, aml_irq_no_flags(isadev->state.irq_num)); */ + aml_append(dev, aml_name_decl("_CRS", crs)); + tpm_build_ppi_acpi(ti, dev); + aml_append(scope, dev); +} + static void tpm_tis_isa_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); TPMIfClass *tc = TPM_IF_CLASS(klass); + AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass); device_class_set_props(dc, tpm_tis_isa_properties); dc->vmsd = &vmstate_tpm_tis_isa; @@ -151,6 +181,7 @@ static void tpm_tis_isa_class_init(ObjectClass *klass, void *data) tc->request_completed = tpm_tis_isa_request_completed; tc->get_version = tpm_tis_isa_get_tpm_version; set_bit(DEVICE_CATEGORY_MISC, dc->categories); + adevc->build_dev_aml = build_tpm_tis_isa_aml; } static const TypeInfo tpm_tis_isa_info = { @@ -161,6 +192,7 @@ static const TypeInfo tpm_tis_isa_info = { .class_init = tpm_tis_isa_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_TPM_IF }, + { TYPE_ACPI_DEV_AML_IF }, { } } }; From f3115cdd9cb8cb6ffba5b9d3e37f096724c77099 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:39 -0400 Subject: [PATCH 034/180] tests: acpi: update expected DSDT.tis.tpm2/DSDT.tis.tpm12 blobs expected move of tmp-tis device description directly under Device(ISA) node. for tpm-tis 2.0: @@ -145,6 +145,189 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) { Name (_ADR, 0x001F0000) // _ADR: Address OperationRegion (PIRQ, PCI_Config, 0x60, 0x0C) + Device (TPM) + { + Name (_HID, "MSFT0101" /* TPM 2.0 Security Device */) // _HID: Hardware ID + Name (_STR, "TPM 2.0 Device") // _STR: Description String + Name (_UID, One) // _UID: Unique ID + Name (_STA, 0x0F) // _STA: Status ... + } @@ -3281,189 +3464,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) Method (PCNT, 0, NotSerialized) { } - - Device (TPM) - { - Name (_HID, "MSFT0101" /* TPM 2.0 Security Device */) // _HID: Hardware ID - Name (_STR, "TPM 2.0 Device") // _STR: Description String - Name (_UID, One) // _UID: Unique ID - Name (_STA, 0x0F) // _STA: Status ... - } for tpm-tis 1.2: @@ -145,6 +145,188 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) { Name (_ADR, 0x001F0000) // _ADR: Address OperationRegion (PIRQ, PCI_Config, 0x60, 0x0C) + Device (TPM) + { + Name (_HID, EisaId ("PNP0C31")) // _HID: Hardware ID + Name (_UID, One) // _UID: Unique ID + Name (_STA, 0x0F) // _STA: Status ... + } @@ -3281,188 +3463,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) Method (PCNT, 0, NotSerialized) { } - - Device (ISA.TPM) - { - Name (_HID, EisaId ("PNP0C31")) // _HID: Hardware ID - Name (_UID, One) // _UID: Unique ID - Name (_STA, 0x0F) // _STA: Status ... - } Signed-off-by: Igor Mammedov Acked-by: Ani Sinha Message-Id: <20220608135340.3304695-35-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.tis.tpm12 | Bin 8885 -> 8880 bytes tests/data/acpi/q35/DSDT.tis.tpm2 | Bin 8906 -> 8906 bytes tests/qtest/bios-tables-test-allowed-diff.h | 2 -- 3 files changed, 2 deletions(-) diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/q35/DSDT.tis.tpm12 index 0b5c97fdb5da8b7b55d6b5f2af498a447fda7bf8..a97d884c50485f848054c6ac95ecfa055ff59e5b 100644 GIT binary patch delta 89 zcmdn$y1|vpCDCo#F$WJq@Cp+yp#>9pgFT9bJNW7#QRk vq8kD{g94ej61aFa$Fi`>ak*;6fK&_kYEI5ka^Z|_a#hs>Y1z!rg5>c diff --git a/tests/data/acpi/q35/DSDT.tis.tpm2 b/tests/data/acpi/q35/DSDT.tis.tpm2 index 4e16b126cc1c32f2346078fa69c5261c245d15e8..1f5392919b5ea69696b49ff13aab5c37d0615919 100644 GIT binary patch delta 85 zcmX@*ddii{CDCo#F$WJq@Cp+yp#>9pgFT9bJNW7#QRk nq8kD{g94ej61aFam$R_Sad~OSfK&@OX-{rba@owyl*0r7A8!`n diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 7b3bf9a207..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,3 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/q35/DSDT.tis.tpm2", -"tests/data/acpi/q35/DSDT.tis.tpm12", From 92344e76b867883a023b2b51123a1ca58c5bb714 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 8 Jun 2022 09:53:40 -0400 Subject: [PATCH 035/180] x86: acpi-build: do not include hw/isa/isa.h directly the last remaining dependency on ISA in acpi-build.c is iapc_boot_arch_8042() which pulls in in isa.h in its own header hw/input/i8042.h. Clean up not longer needed direct inclusion of isa.h in acpi-build.c Signed-off-by: Igor Mammedov Acked-by: Gerd Hoffmann Message-Id: <20220608135340.3304695-36-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0b65fc99cd..f41e14a469 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -37,7 +37,6 @@ #include "hw/acpi/cpu.h" #include "hw/nvram/fw_cfg.h" #include "hw/acpi/bios-linker-loader.h" -#include "hw/isa/isa.h" #include "hw/acpi/acpi_aml_interface.h" #include "hw/input/i8042.h" #include "hw/acpi/memory_hotplug.h" From 03b39fcf64bc958e3223e1d696f9de06de904fc6 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:33 +0100 Subject: [PATCH 036/180] hw/cxl: Make the CXL fixed memory window setup a machine parameter. Paolo Bonzini requested this change to simplify the ongoing effort to allow machine setup entirely via RPC. Includes shortening the command line form cxl-fixed-memory-window to cxl-fmw as the command lines are extremely long even with this change. The json change is needed to ensure that there is a CXLFixedMemoryWindowOptionsList even though the actual element in the json is never used. Similar to existing SgxEpcProperties. Update qemu-options.hx to reflect that this is now a -machine parameter. The bulk of -M / -machine parameters are documented under machine, so use that in preference to M. Update cxl-test and bios-tables-test to reflect new parameters. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Reviewed-by: Davidlohr Bueso Message-Id: <20220608145440.26106-2-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- docs/system/devices/cxl.rst | 4 +- hw/core/machine.c | 22 --------- hw/cxl/cxl-host-stubs.c | 6 +-- hw/cxl/cxl-host.c | 72 ++++++++++++++++++++++++++-- hw/i386/pc.c | 3 ++ hw/pci-bridge/pci_expander_bridge.c | 2 +- include/hw/boards.h | 1 + include/hw/cxl/cxl.h | 7 +-- include/hw/cxl/cxl_host.h | 21 +++++++++ qapi/machine.json | 13 +++++ qemu-options.hx | 73 ++++++++++++++--------------- softmmu/vl.c | 44 ----------------- tests/qtest/bios-tables-test.c | 4 +- tests/qtest/cxl-test.c | 4 +- 14 files changed, 150 insertions(+), 126 deletions(-) create mode 100644 include/hw/cxl/cxl_host.h diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst index 9293cbf01a..bcbfe8c490 100644 --- a/docs/system/devices/cxl.rst +++ b/docs/system/devices/cxl.rst @@ -251,7 +251,7 @@ A very simple setup with just one directly attached CXL Type 3 device:: -device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1 \ -device cxl-rp,port=0,bus=cxl.1,id=root_port13,chassis=0,slot=2 \ -device cxl-type3,bus=root_port13,memdev=cxl-mem1,lsa=cxl-lsa1,id=cxl-pmem0 \ - -cxl-fixed-memory-window targets.0=cxl.1,size=4G + -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G A setup suitable for 4 way interleave. Only one fixed window provided, to enable 2 way interleave across 2 CXL host bridges. Each host bridge has 2 CXL Root Ports, with @@ -277,7 +277,7 @@ the CXL Type3 device directly attached (no switches).:: -device cxl-type3,bus=root_port15,memdev=cxl-mem3,lsa=cxl-lsa3,id=cxl-pmem2 \ -device cxl-rp,port=1,bus=cxl.2,id=root_port16,chassis=0,slot=6 \ -device cxl-type3,bus=root_port16,memdev=cxl-mem4,lsa=cxl-lsa4,id=cxl-pmem3 \ - -cxl-fixed-memory-window targets.0=cxl.1,targets.1=cxl.2,size=4G,interleave-granularity=8k + -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.targets.1=cxl.2,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=8k Kernel Configuration Options ---------------------------- diff --git a/hw/core/machine.c b/hw/core/machine.c index c53548d0b1..2e589d99e9 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -629,20 +629,6 @@ static void machine_set_nvdimm_persistence(Object *obj, const char *value, nvdimms_state->persistence_string = g_strdup(value); } -static bool machine_get_cxl(Object *obj, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - return ms->cxl_devices_state->is_enabled; -} - -static void machine_set_cxl(Object *obj, bool value, Error **errp) -{ - MachineState *ms = MACHINE(obj); - - ms->cxl_devices_state->is_enabled = value; -} - void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type) { QAPI_LIST_PREPEND(mc->allowed_dynamic_sysbus_devices, g_strdup(type)); @@ -929,8 +915,6 @@ static void machine_class_init(ObjectClass *oc, void *data) mc->default_ram_size = 128 * MiB; mc->rom_file_has_mr = true; - /* Few machines support CXL, so default to off */ - mc->cxl_supported = false; /* numa node memory size aligned on 8MB by default. * On Linux, each node's border has to be 8MB aligned */ @@ -1092,13 +1076,7 @@ static void machine_initfn(Object *obj) } if (mc->cxl_supported) { - Object *obj = OBJECT(ms); - ms->cxl_devices_state = g_new0(CXLState, 1); - object_property_add_bool(obj, "cxl", machine_get_cxl, machine_set_cxl); - object_property_set_description(obj, "cxl", - "Set on/off to enable/disable " - "CXL instantiation"); } if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { diff --git a/hw/cxl/cxl-host-stubs.c b/hw/cxl/cxl-host-stubs.c index 24465a52ab..de3e8894d5 100644 --- a/hw/cxl/cxl-host-stubs.c +++ b/hw/cxl/cxl-host-stubs.c @@ -6,11 +6,9 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/cxl/cxl.h" - -void cxl_fixed_memory_window_config(MachineState *ms, - CXLFixedMemoryWindowOptions *object, - Error **errp) {}; +#include "hw/cxl/cxl_host.h" void cxl_fixed_memory_window_link_targets(Error **errp) {}; +void cxl_machine_init(Object *obj, CXLState *state) {}; const MemoryRegionOps cfmws_ops; diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c index 469b3c4ced..3a79c32b42 100644 --- a/hw/cxl/cxl-host.c +++ b/hw/cxl/cxl-host.c @@ -15,14 +15,15 @@ #include "qapi/qapi-visit-machine.h" #include "hw/cxl/cxl.h" +#include "hw/cxl/cxl_host.h" #include "hw/pci/pci_bus.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_host.h" #include "hw/pci/pcie_port.h" -void cxl_fixed_memory_window_config(MachineState *ms, - CXLFixedMemoryWindowOptions *object, - Error **errp) +static void cxl_fixed_memory_window_config(CXLState *cxl_state, + CXLFixedMemoryWindowOptions *object, + Error **errp) { CXLFixedWindow *fw = g_malloc0(sizeof(*fw)); strList *target; @@ -62,8 +63,7 @@ void cxl_fixed_memory_window_config(MachineState *ms, fw->enc_int_gran = 0; } - ms->cxl_devices_state->fixed_windows = - g_list_append(ms->cxl_devices_state->fixed_windows, fw); + cxl_state->fixed_windows = g_list_append(cxl_state->fixed_windows, fw); return; } @@ -220,3 +220,65 @@ const MemoryRegionOps cfmws_ops = { .unaligned = true, }, }; + +static void machine_get_cxl(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + CXLState *cxl_state = opaque; + bool value = cxl_state->is_enabled; + + visit_type_bool(v, name, &value, errp); +} + +static void machine_set_cxl(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + CXLState *cxl_state = opaque; + bool value; + + if (!visit_type_bool(v, name, &value, errp)) { + return; + } + cxl_state->is_enabled = value; +} + +static void machine_get_cfmw(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + CXLFixedMemoryWindowOptionsList **list = opaque; + + visit_type_CXLFixedMemoryWindowOptionsList(v, name, list, errp); +} + +static void machine_set_cfmw(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + CXLState *state = opaque; + CXLFixedMemoryWindowOptionsList *cfmw_list = NULL; + CXLFixedMemoryWindowOptionsList *it; + + visit_type_CXLFixedMemoryWindowOptionsList(v, name, &cfmw_list, errp); + if (!cfmw_list) { + return; + } + + for (it = cfmw_list; it; it = it->next) { + cxl_fixed_memory_window_config(state, it->value, errp); + } + state->cfmw_list = cfmw_list; +} + +void cxl_machine_init(Object *obj, CXLState *state) +{ + object_property_add(obj, "cxl", "bool", machine_get_cxl, + machine_set_cxl, NULL, state); + object_property_set_description(obj, "cxl", + "Set on/off to enable/disable " + "CXL instantiation"); + + object_property_add(obj, "cxl-fmw", "CXLFixedMemoryWindow", + machine_get_cfmw, machine_set_cfmw, + NULL, state); + object_property_set_description(obj, "cxl-fmw", + "CXL Fixed Memory Windows (array)"); +} diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 7c39c91335..98e63347f2 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -76,6 +76,7 @@ #include "hw/mem/pc-dimm.h" #include "hw/mem/nvdimm.h" #include "hw/cxl/cxl.h" +#include "hw/cxl/cxl_host.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" #include "qapi/qapi-visit-machine.h" @@ -1682,6 +1683,7 @@ static void pc_machine_set_max_fw_size(Object *obj, Visitor *v, static void pc_machine_initfn(Object *obj) { PCMachineState *pcms = PC_MACHINE(obj); + MachineState *ms = MACHINE(obj); #ifdef CONFIG_VMPORT pcms->vmport = ON_OFF_AUTO_AUTO; @@ -1706,6 +1708,7 @@ static void pc_machine_initfn(Object *obj) pcms->pcspk = isa_new(TYPE_PC_SPEAKER); object_property_add_alias(OBJECT(pcms), "pcspk-audiodev", OBJECT(pcms->pcspk), "audiodev"); + cxl_machine_init(obj, ms->cxl_devices_state); } static void pc_machine_reset(MachineState *machine) diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c index 69244decdb..02032360f5 100644 --- a/hw/pci-bridge/pci_expander_bridge.c +++ b/hw/pci-bridge/pci_expander_bridge.c @@ -468,7 +468,7 @@ static void pxb_cxl_dev_realize(PCIDevice *dev, Error **errp) error_setg(errp, "pxb-cxl devices cannot reside on a PCI bus"); return; } - if (!ms->cxl_devices_state->is_enabled) { + if (!ms->cxl_devices_state || !ms->cxl_devices_state->is_enabled) { error_setg(errp, "Machine does not have cxl=on"); return; } diff --git a/include/hw/boards.h b/include/hw/boards.h index fa57bac4fb..dd9fc56df2 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -362,6 +362,7 @@ struct MachineState { struct NVDIMMState *nvdimms_state; struct CXLState *cxl_devices_state; struct NumaState *numa_state; + CXLFixedMemoryWindowOptionsList *cfmws_list; }; #define DEFINE_MACHINE(namestr, machine_initfn) \ diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h index 21d28ca110..84078a484d 100644 --- a/include/hw/cxl/cxl.h +++ b/include/hw/cxl/cxl.h @@ -12,6 +12,7 @@ #include "qapi/qapi-types-machine.h" +#include "qapi/qapi-visit-machine.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_host.h" #include "cxl_pci.h" @@ -40,6 +41,7 @@ typedef struct CXLState { MemoryRegion host_mr; unsigned int next_mr_idx; GList *fixed_windows; + CXLFixedMemoryWindowOptionsList *cfmw_list; } CXLState; struct CXLHost { @@ -51,11 +53,6 @@ struct CXLHost { #define TYPE_PXB_CXL_HOST "pxb-cxl-host" OBJECT_DECLARE_SIMPLE_TYPE(CXLHost, PXB_CXL_HOST) -void cxl_fixed_memory_window_config(MachineState *ms, - CXLFixedMemoryWindowOptions *object, - Error **errp); void cxl_fixed_memory_window_link_targets(Error **errp); -extern const MemoryRegionOps cfmws_ops; - #endif diff --git a/include/hw/cxl/cxl_host.h b/include/hw/cxl/cxl_host.h new file mode 100644 index 0000000000..87a6933de2 --- /dev/null +++ b/include/hw/cxl/cxl_host.h @@ -0,0 +1,21 @@ +/* + * QEMU CXL Host Setup + * + * Copyright (c) 2022 Huawei + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/cxl/cxl.h" +#include "hw/boards.h" + +#ifndef CXL_HOST_H +#define CXL_HOST_H + +void cxl_machine_init(Object *obj, CXLState *state); + +extern const MemoryRegionOps cfmws_ops; + +#endif diff --git a/qapi/machine.json b/qapi/machine.json index f750a16396..6afd1936b0 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -523,6 +523,19 @@ '*interleave-granularity': 'size', 'targets': ['str'] }} +## +# @CXLFMWProperties: +# +# List of CXL Fixed Memory Windows. +# +# @cxl-fmw: List of CXLFixedMemoryWindowOptions +# +# Since 7.1 +## +{ 'struct' : 'CXLFMWProperties', + 'data': { 'cxl-fmw': ['CXLFixedMemoryWindowOptions'] } +} + ## # @X86CPURegister32: # diff --git a/qemu-options.hx b/qemu-options.hx index 60cf188da4..377d22fbd8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -36,7 +36,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " nvdimm=on|off controls NVDIMM support (default=off)\n" " memory-encryption=@var{} memory encryption object to use (default=none)\n" " hmat=on|off controls ACPI HMAT support (default=off)\n" - " memory-backend='backend-id' specifies explicitly provided backend for main RAM (default=none)\n", + " memory-backend='backend-id' specifies explicitly provided backend for main RAM (default=none)\n" + " cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]\n", QEMU_ARCH_ALL) SRST ``-machine [type=]name[,prop=value[,...]]`` @@ -124,6 +125,38 @@ SRST -object memory-backend-ram,id=pc.ram,size=512M,x-use-canonical-path-for-ramblock-id=off -machine memory-backend=pc.ram -m 512M + + ``cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]`` + Define a CXL Fixed Memory Window (CFMW). + + Described in the CXL 2.0 ECN: CEDT CFMWS & QTG _DSM. + + They are regions of Host Physical Addresses (HPA) on a system which + may be interleaved across one or more CXL host bridges. The system + software will assign particular devices into these windows and + configure the downstream Host-managed Device Memory (HDM) decoders + in root ports, switch ports and devices appropriately to meet the + interleave requirements before enabling the memory devices. + + ``targets.X=target`` provides the mapping to CXL host bridges + which may be identified by the id provied in the -device entry. + Multiple entries are needed to specify all the targets when + the fixed memory window represents interleaved memory. X is the + target index from 0. + + ``size=size`` sets the size of the CFMW. This must be a multiple of + 256MiB. The region will be aligned to 256MiB but the location is + platform and configuration dependent. + + ``interleave-granularity=granularity`` sets the granularity of + interleave. Default 256KiB. Only 256KiB, 512KiB, 1024KiB, 2048KiB + 4096KiB, 8192KiB and 16384KiB granularities supported. + + Example: + + :: + + -machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512k ERST DEF("M", HAS_ARG, QEMU_OPTION_M, @@ -467,44 +500,6 @@ SRST -numa hmat-cache,node-id=1,size=10K,level=1,associativity=direct,policy=write-back,line=8 ERST -DEF("cxl-fixed-memory-window", HAS_ARG, QEMU_OPTION_cxl_fixed_memory_window, - "-cxl-fixed-memory-window targets.0=firsttarget,targets.1=secondtarget,size=size[,interleave-granularity=granularity]\n", - QEMU_ARCH_ALL) -SRST -``-cxl-fixed-memory-window targets.0=firsttarget,targets.1=secondtarget,size=size[,interleave-granularity=granularity]`` - Define a CXL Fixed Memory Window (CFMW). - - Described in the CXL 2.0 ECN: CEDT CFMWS & QTG _DSM. - - They are regions of Host Physical Addresses (HPA) on a system which - may be interleaved across one or more CXL host bridges. The system - software will assign particular devices into these windows and - configure the downstream Host-managed Device Memory (HDM) decoders - in root ports, switch ports and devices appropriately to meet the - interleave requirements before enabling the memory devices. - - ``targets.X=firsttarget`` provides the mapping to CXL host bridges - which may be identified by the id provied in the -device entry. - Multiple entries are needed to specify all the targets when - the fixed memory window represents interleaved memory. X is the - target index from 0. - - ``size=size`` sets the size of the CFMW. This must be a multiple of - 256MiB. The region will be aligned to 256MiB but the location is - platform and configuration dependent. - - ``interleave-granularity=granularity`` sets the granularity of - interleave. Default 256KiB. Only 256KiB, 512KiB, 1024KiB, 2048KiB - 4096KiB, 8192KiB and 16384KiB granularities supported. - - Example: - - :: - - -cxl-fixed-memory-window targets.0=cxl.0,targets.1=cxl.1,size=128G,interleave-granularity=512k - -ERST - DEF("add-fd", HAS_ARG, QEMU_OPTION_add_fd, "-add-fd fd=fd,set=set[,opaque=opaque]\n" " Add 'fd' to fd 'set'\n", QEMU_ARCH_ALL) diff --git a/softmmu/vl.c b/softmmu/vl.c index 4c1e94b00e..ff0ad9ab54 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -147,12 +147,6 @@ typedef struct BlockdevOptionsQueueEntry { typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; -typedef struct CXLFMWOptionQueueEntry { - CXLFixedMemoryWindowOptions *opts; - Location loc; - QSIMPLEQ_ENTRY(CXLFMWOptionQueueEntry) entry; -} CXLFMWOptionQueueEntry; - typedef struct ObjectOption { ObjectOptions *opts; QTAILQ_ENTRY(ObjectOption) next; @@ -179,8 +173,6 @@ static int snapshot; static bool preconfig_requested; static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); -static QSIMPLEQ_HEAD(, CXLFMWOptionQueueEntry) CXLFMW_opts = - QSIMPLEQ_HEAD_INITIALIZER(CXLFMW_opts); static bool nographic = false; static int mem_prealloc; /* force preallocation of physical target memory */ static const char *vga_model = NULL; @@ -1072,24 +1064,6 @@ static void parse_display(const char *p) } } -static void parse_cxl_fixed_memory_window(const char *optarg) -{ - CXLFMWOptionQueueEntry *cfmws_entry; - Visitor *v; - - v = qobject_input_visitor_new_str(optarg, "cxl-fixed-memory-window", - &error_fatal); - cfmws_entry = g_new(CXLFMWOptionQueueEntry, 1); - visit_type_CXLFixedMemoryWindowOptions(v, NULL, &cfmws_entry->opts, - &error_fatal); - if (!cfmws_entry->opts) { - exit(1); - } - visit_free(v); - loc_save(&cfmws_entry->loc); - QSIMPLEQ_INSERT_TAIL(&CXLFMW_opts, cfmws_entry, entry); -} - static inline bool nonempty_str(const char *str) { return str && *str; @@ -1948,20 +1922,6 @@ static void qemu_create_late_backends(void) qemu_semihosting_console_init(); } -static void cxl_set_opts(void) -{ - while (!QSIMPLEQ_EMPTY(&CXLFMW_opts)) { - CXLFMWOptionQueueEntry *cfmws_entry = QSIMPLEQ_FIRST(&CXLFMW_opts); - - loc_restore(&cfmws_entry->loc); - QSIMPLEQ_REMOVE_HEAD(&CXLFMW_opts, entry); - cxl_fixed_memory_window_config(current_machine, cfmws_entry->opts, - &error_fatal); - qapi_free_CXLFixedMemoryWindowOptions(cfmws_entry->opts); - g_free(cfmws_entry); - } -} - static void qemu_resolve_machine_memdev(void) { if (ram_memdev_id) { @@ -2789,9 +2749,6 @@ void qemu_init(int argc, char **argv, char **envp) exit(1); } break; - case QEMU_OPTION_cxl_fixed_memory_window: - parse_cxl_fixed_memory_window(optarg); - break; case QEMU_OPTION_display: parse_display(optarg); break; @@ -3598,7 +3555,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_resolve_machine_memdev(); parse_numa_opts(current_machine); - cxl_set_opts(); if (vmstate_dump_file) { /* dump and exit */ diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 56498bbcc8..359916c228 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1582,8 +1582,8 @@ static void test_acpi_q35_cxl(void) " -device cxl-type3,bus=rp3,memdev=cxl-mem3,lsa=lsa3" " -device cxl-rp,port=1,bus=cxl.2,id=rp4,chassis=0,slot=6" " -device cxl-type3,bus=rp4,memdev=cxl-mem4,lsa=lsa4" - " -cxl-fixed-memory-window targets.0=cxl.1,size=4G,interleave-granularity=8k" - " -cxl-fixed-memory-window targets.0=cxl.1,targets.1=cxl.2,size=4G,interleave-granularity=8k", + " -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=8k," + "cxl-fmw.1.targets.0=cxl.1,cxl-fmw.1.targets.1=cxl.2,cxl-fmw.1.size=4G,cxl-fmw.1.interleave-granularity=8k", tmp_path, tmp_path, tmp_path, tmp_path, tmp_path, tmp_path, tmp_path, tmp_path); test_acpi_one(params, &data); diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c index 079011af6a..2133e973f4 100644 --- a/tests/qtest/cxl-test.c +++ b/tests/qtest/cxl-test.c @@ -10,12 +10,12 @@ #define QEMU_PXB_CMD "-machine q35,cxl=on " \ "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 " \ - "-cxl-fixed-memory-window targets.0=cxl.0,size=4G " + "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.size=4G " #define QEMU_2PXB_CMD "-machine q35,cxl=on " \ "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 " \ "-device pxb-cxl,id=cxl.1,bus=pcie.0,bus_nr=53 " \ - "-cxl-fixed-memory-window targets.0=cxl.0,targets.1=cxl.1,size=4G " + "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=4G " #define QEMU_RP "-device cxl-rp,id=rp0,bus=cxl.0,chassis=0,slot=0 " From 513598050ad12641b2dde6cf27471faca65be48f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:34 +0100 Subject: [PATCH 037/180] hw/acpi/cxl: Pass in the CXLState directly rather than MachineState Refactoring step on path to moving all CXL state out of MachineState. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-3-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/cxl.c | 9 ++++----- hw/i386/acpi-build.c | 4 ++-- include/hw/acpi/cxl.h | 5 +++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c index 31d5235136..2bf8c07993 100644 --- a/hw/acpi/cxl.c +++ b/hw/acpi/cxl.c @@ -65,9 +65,8 @@ static void cedt_build_chbs(GArray *table_data, PXBDev *cxl) * Interleave ways encoding in CXL 2.0 ECN: 3, 6, 12 and 16-way memory * interleaving. */ -static void cedt_build_cfmws(GArray *table_data, MachineState *ms) +static void cedt_build_cfmws(GArray *table_data, CXLState *cxls) { - CXLState *cxls = ms->cxl_devices_state; GList *it; for (it = cxls->fixed_windows; it; it = it->next) { @@ -129,9 +128,9 @@ static int cxl_foreach_pxb_hb(Object *obj, void *opaque) return 0; } -void cxl_build_cedt(MachineState *ms, GArray *table_offsets, GArray *table_data, +void cxl_build_cedt(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, const char *oem_id, - const char *oem_table_id) + const char *oem_table_id, CXLState *cxl_state) { Aml *cedt; AcpiTable table = { .sig = "CEDT", .rev = 1, .oem_id = oem_id, @@ -144,7 +143,7 @@ void cxl_build_cedt(MachineState *ms, GArray *table_offsets, GArray *table_data, /* reserve space for CEDT header */ object_child_foreach_recursive(object_get_root(), cxl_foreach_pxb_hb, cedt); - cedt_build_cfmws(cedt->buf, ms); + cedt_build_cfmws(cedt->buf, cxl_state); /* copy AML table into ACPI tables blob and patch header there */ g_array_append_vals(table_data, cedt->buf->data, cedt->buf->len); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index f41e14a469..663c34b9d1 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2615,8 +2615,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) x86ms->oem_id, x86ms->oem_table_id); } if (machine->cxl_devices_state->is_enabled) { - cxl_build_cedt(machine, table_offsets, tables_blob, tables->linker, - x86ms->oem_id, x86ms->oem_table_id); + cxl_build_cedt(table_offsets, tables_blob, tables->linker, + x86ms->oem_id, x86ms->oem_table_id, machine->cxl_devices_state); } acpi_add_table(table_offsets, tables_blob); diff --git a/include/hw/acpi/cxl.h b/include/hw/acpi/cxl.h index 0c496538c0..acf4418886 100644 --- a/include/hw/acpi/cxl.h +++ b/include/hw/acpi/cxl.h @@ -19,10 +19,11 @@ #define HW_ACPI_CXL_H #include "hw/acpi/bios-linker-loader.h" +#include "hw/cxl/cxl.h" -void cxl_build_cedt(MachineState *ms, GArray *table_offsets, GArray *table_data, +void cxl_build_cedt(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, const char *oem_id, - const char *oem_table_id); + const char *oem_table_id, CXLState *cxl_state); void build_cxl_osc_method(Aml *dev); #endif From dab390ff2454134486c934c8f2677f3ed7c8463c Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:35 +0100 Subject: [PATCH 038/180] hw/cxl: Push linking of CXL targets into i386/pc rather than in machine.c Whilst here take the oportunity to shorten the function name. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-4-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-host-stubs.c | 2 +- hw/cxl/cxl-host.c | 8 +++----- hw/i386/pc.c | 5 +++++ include/hw/cxl/cxl.h | 2 -- include/hw/cxl/cxl_host.h | 1 + softmmu/vl.c | 2 -- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/cxl/cxl-host-stubs.c b/hw/cxl/cxl-host-stubs.c index de3e8894d5..e0d5ec8ad5 100644 --- a/hw/cxl/cxl-host-stubs.c +++ b/hw/cxl/cxl-host-stubs.c @@ -8,7 +8,7 @@ #include "hw/cxl/cxl.h" #include "hw/cxl/cxl_host.h" -void cxl_fixed_memory_window_link_targets(Error **errp) {}; +void cxl_fmws_link_targets(CXLState *stat, Error **errp) {}; void cxl_machine_init(Object *obj, CXLState *state) {}; const MemoryRegionOps cfmws_ops; diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c index 3a79c32b42..8e7738a65b 100644 --- a/hw/cxl/cxl-host.c +++ b/hw/cxl/cxl-host.c @@ -68,14 +68,12 @@ static void cxl_fixed_memory_window_config(CXLState *cxl_state, return; } -void cxl_fixed_memory_window_link_targets(Error **errp) +void cxl_fmws_link_targets(CXLState *cxl_state, Error **errp) { - MachineState *ms = MACHINE(qdev_get_machine()); - - if (ms->cxl_devices_state && ms->cxl_devices_state->fixed_windows) { + if (cxl_state && cxl_state->fixed_windows) { GList *it; - for (it = ms->cxl_devices_state->fixed_windows; it; it = it->next) { + for (it = cxl_state->fixed_windows; it; it = it->next) { CXLFixedWindow *fw = it->data; int i; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 98e63347f2..6cecd74d58 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -732,6 +732,11 @@ void pc_machine_done(Notifier *notifier, void *data) PCMachineState *pcms = container_of(notifier, PCMachineState, machine_done); X86MachineState *x86ms = X86_MACHINE(pcms); + MachineState *ms = MACHINE(pcms); + + if (ms->cxl_devices_state) { + cxl_fmws_link_targets(ms->cxl_devices_state, &error_fatal); + } /* set the number of CPUs */ x86_rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus); diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h index 84078a484d..134b295b40 100644 --- a/include/hw/cxl/cxl.h +++ b/include/hw/cxl/cxl.h @@ -53,6 +53,4 @@ struct CXLHost { #define TYPE_PXB_CXL_HOST "pxb-cxl-host" OBJECT_DECLARE_SIMPLE_TYPE(CXLHost, PXB_CXL_HOST) -void cxl_fixed_memory_window_link_targets(Error **errp); - #endif diff --git a/include/hw/cxl/cxl_host.h b/include/hw/cxl/cxl_host.h index 87a6933de2..4d642a81fa 100644 --- a/include/hw/cxl/cxl_host.h +++ b/include/hw/cxl/cxl_host.h @@ -15,6 +15,7 @@ #define CXL_HOST_H void cxl_machine_init(Object *obj, CXLState *state); +void cxl_fmws_link_targets(CXLState *stat, Error **errp); extern const MemoryRegionOps cfmws_ops; diff --git a/softmmu/vl.c b/softmmu/vl.c index ff0ad9ab54..54e920ada1 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -93,7 +93,6 @@ #include "qemu/config-file.h" #include "qemu/qemu-options.h" #include "qemu/main-loop.h" -#include "hw/cxl/cxl.h" #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif @@ -2568,7 +2567,6 @@ void qmp_x_exit_preconfig(Error **errp) qemu_init_board(); qemu_create_cli_devices(); - cxl_fixed_memory_window_link_targets(errp); qemu_machine_creation_done(); if (loadvm) { From 96f7da1711348758f9919ffdfe1e984012ef7acd Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:36 +0100 Subject: [PATCH 039/180] tests/acpi: Allow modification of q35 CXL CEDT table. Needed to allow memory address changes as a result of next patch. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-5-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..effa58b75b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/CEDT.cxl", From 7bd1900b365b5e7ae498cf9c915867fcaa5296fc Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:37 +0100 Subject: [PATCH 040/180] pci/pci_expander_bridge: For CXL HB delay the HB register memory region setup. As the CXLState will no long be accessible via MachineState at time of PXB_CXL realization, come back later from the machine specific code to fill in the missing memory region setup. Only at this stage is it possible to check if cxl=on, so that check is moved to this later point. Note that for multiple host bridges, the allocation order of the register spaces is changed. This will be reflected in ACPI CEDT. Stubs are added to handle case of CONFIG_PXB=n for machines that call these functions. The bus walking logic is common to all machines so add a utility function + stub to cxl-host*. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-6-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-host-stubs.c | 1 + hw/cxl/cxl-host.c | 20 +++++++++++++ hw/i386/pc.c | 3 ++ hw/pci-bridge/meson.build | 5 +++- hw/pci-bridge/pci_expander_bridge.c | 32 +++++++++++++-------- hw/pci-bridge/pci_expander_bridge_stubs.c | 14 +++++++++ include/hw/cxl/cxl_host.h | 1 + include/hw/pci-bridge/pci_expander_bridge.h | 12 ++++++++ 8 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 hw/pci-bridge/pci_expander_bridge_stubs.c create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h diff --git a/hw/cxl/cxl-host-stubs.c b/hw/cxl/cxl-host-stubs.c index e0d5ec8ad5..cae4afcdde 100644 --- a/hw/cxl/cxl-host-stubs.c +++ b/hw/cxl/cxl-host-stubs.c @@ -10,5 +10,6 @@ void cxl_fmws_link_targets(CXLState *stat, Error **errp) {}; void cxl_machine_init(Object *obj, CXLState *state) {}; +void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp) {}; const MemoryRegionOps cfmws_ops; diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c index 8e7738a65b..efa14908d8 100644 --- a/hw/cxl/cxl-host.c +++ b/hw/cxl/cxl-host.c @@ -20,6 +20,7 @@ #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_host.h" #include "hw/pci/pcie_port.h" +#include "hw/pci-bridge/pci_expander_bridge.h" static void cxl_fixed_memory_window_config(CXLState *cxl_state, CXLFixedMemoryWindowOptions *object, @@ -280,3 +281,22 @@ void cxl_machine_init(Object *obj, CXLState *state) object_property_set_description(obj, "cxl-fmw", "CXL Fixed Memory Windows (array)"); } + +void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp) +{ + /* Walk the pci busses looking for pxb busses to hook up */ + if (bus) { + QLIST_FOREACH(bus, &bus->child, sibling) { + if (!pci_bus_is_root(bus)) { + continue; + } + if (pci_bus_is_cxl(bus)) { + if (!state->is_enabled) { + error_setg(errp, "CXL host bridges present, but cxl=off"); + return; + } + pxb_cxl_hook_up_registers(state, bus, errp); + } + } + } +} diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 6cecd74d58..9f48d02739 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -37,6 +37,7 @@ #include "hw/ide.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" +#include "hw/pci-bridge/pci_expander_bridge.h" #include "hw/nvram/fw_cfg.h" #include "hw/timer/hpet.h" #include "hw/firmware/smbios.h" @@ -735,6 +736,8 @@ void pc_machine_done(Notifier *notifier, void *data) MachineState *ms = MACHINE(pcms); if (ms->cxl_devices_state) { + cxl_hook_up_pxb_registers(pcms->bus, ms->cxl_devices_state, + &error_fatal); cxl_fmws_link_targets(ms->cxl_devices_state, &error_fatal); } diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build index b6d26a03d5..fdbe2e07c5 100644 --- a/hw/pci-bridge/meson.build +++ b/hw/pci-bridge/meson.build @@ -3,7 +3,8 @@ pci_ss.add(files('pci_bridge_dev.c')) pci_ss.add(when: 'CONFIG_I82801B11', if_true: files('i82801b11.c')) pci_ss.add(when: 'CONFIG_IOH3420', if_true: files('ioh3420.c')) pci_ss.add(when: 'CONFIG_PCIE_PORT', if_true: files('pcie_root_port.c', 'gen_pcie_root_port.c', 'pcie_pci_bridge.c')) -pci_ss.add(when: 'CONFIG_PXB', if_true: files('pci_expander_bridge.c')) +pci_ss.add(when: 'CONFIG_PXB', if_true: files('pci_expander_bridge.c'), + if_false: files('pci_expander_bridge_stubs.c')) pci_ss.add(when: 'CONFIG_XIO3130', if_true: files('xio3130_upstream.c', 'xio3130_downstream.c')) pci_ss.add(when: 'CONFIG_CXL', if_true: files('cxl_root_port.c')) @@ -13,3 +14,5 @@ pci_ss.add(when: 'CONFIG_DEC_PCI', if_true: files('dec.c')) pci_ss.add(when: 'CONFIG_SIMBA', if_true: files('simba.c')) softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss) + +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('pci_expander_bridge_stubs.c')) diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c index 02032360f5..c9e817aa58 100644 --- a/hw/pci-bridge/pci_expander_bridge.c +++ b/hw/pci-bridge/pci_expander_bridge.c @@ -17,6 +17,7 @@ #include "hw/pci/pci_host.h" #include "hw/qdev-properties.h" #include "hw/pci/pci_bridge.h" +#include "hw/pci-bridge/pci_expander_bridge.h" #include "hw/cxl/cxl.h" #include "qemu/range.h" #include "qemu/error-report.h" @@ -186,25 +187,38 @@ static const TypeInfo pxb_host_info = { static void pxb_cxl_realize(DeviceState *dev, Error **errp) { - MachineState *ms = MACHINE(qdev_get_machine()); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); CXLHost *cxl = PXB_CXL_HOST(dev); CXLComponentState *cxl_cstate = &cxl->cxl_cstate; struct MemoryRegion *mr = &cxl_cstate->crb.component_registers; - hwaddr offset; cxl_component_register_block_init(OBJECT(dev), cxl_cstate, TYPE_PXB_CXL_HOST); sysbus_init_mmio(sbd, mr); +} - offset = memory_region_size(mr) * ms->cxl_devices_state->next_mr_idx; - if (offset > memory_region_size(&ms->cxl_devices_state->host_mr)) { +/* + * Host bridge realization has no means of knowning state associated + * with a particular machine. As such, it is nececssary to delay + * final setup of the host bridge register space until later in the + * machine bring up. + */ +void pxb_cxl_hook_up_registers(CXLState *cxl_state, PCIBus *bus, Error **errp) +{ + PXBDev *pxb = PXB_CXL_DEV(pci_bridge_get_device(bus)); + CXLHost *cxl = pxb->cxl.cxl_host_bridge; + CXLComponentState *cxl_cstate = &cxl->cxl_cstate; + struct MemoryRegion *mr = &cxl_cstate->crb.component_registers; + hwaddr offset; + + offset = memory_region_size(mr) * cxl_state->next_mr_idx; + if (offset > memory_region_size(&cxl_state->host_mr)) { error_setg(errp, "Insufficient space for pxb cxl host register space"); return; } - memory_region_add_subregion(&ms->cxl_devices_state->host_mr, offset, mr); - ms->cxl_devices_state->next_mr_idx++; + memory_region_add_subregion(&cxl_state->host_mr, offset, mr); + cxl_state->next_mr_idx++; } static void pxb_cxl_host_class_init(ObjectClass *class, void *data) @@ -461,17 +475,11 @@ static const TypeInfo pxb_pcie_dev_info = { static void pxb_cxl_dev_realize(PCIDevice *dev, Error **errp) { - MachineState *ms = MACHINE(qdev_get_machine()); - /* A CXL PXB's parent bus is still PCIe */ if (!pci_bus_is_express(pci_get_bus(dev))) { error_setg(errp, "pxb-cxl devices cannot reside on a PCI bus"); return; } - if (!ms->cxl_devices_state || !ms->cxl_devices_state->is_enabled) { - error_setg(errp, "Machine does not have cxl=on"); - return; - } pxb_dev_realize_common(dev, CXL, errp); pxb_dev_reset(DEVICE(dev)); diff --git a/hw/pci-bridge/pci_expander_bridge_stubs.c b/hw/pci-bridge/pci_expander_bridge_stubs.c new file mode 100644 index 0000000000..b35180311f --- /dev/null +++ b/hw/pci-bridge/pci_expander_bridge_stubs.c @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Stubs for calls made from machines to handle the case where CONFIG_PXB + * is not enabled. + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" +#include "hw/pci-bridge/pci_expander_bridge.h" +#include "hw/cxl/cxl.h" + +void pxb_cxl_hook_up_registers(CXLState *state, PCIBus *bus, Error **errp) {}; diff --git a/include/hw/cxl/cxl_host.h b/include/hw/cxl/cxl_host.h index 4d642a81fa..a1b662ce40 100644 --- a/include/hw/cxl/cxl_host.h +++ b/include/hw/cxl/cxl_host.h @@ -16,6 +16,7 @@ void cxl_machine_init(Object *obj, CXLState *state); void cxl_fmws_link_targets(CXLState *stat, Error **errp); +void cxl_hook_up_pxb_registers(PCIBus *bus, CXLState *state, Error **errp); extern const MemoryRegionOps cfmws_ops; diff --git a/include/hw/pci-bridge/pci_expander_bridge.h b/include/hw/pci-bridge/pci_expander_bridge.h new file mode 100644 index 0000000000..0b3856d615 --- /dev/null +++ b/include/hw/pci-bridge/pci_expander_bridge.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef PCI_EXPANDER_BRIDGE_H +#define PCI_EXPANDER_BRIDGE_H + +#include "hw/cxl/cxl.h" + +void pxb_cxl_hook_up_registers(CXLState *state, PCIBus *bus, Error **errp); + +#endif /* PCI_EXPANDER_BRIDGE_H */ From 3546b0529a5799d1a13397fa3586711b3da52190 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:38 +0100 Subject: [PATCH 041/180] tests/acpi: Update q35/CEDT.cxl for new memory addresses. The CEDT table includes addreses of host bridge registers. There are allocated in a different order due to the previous patch, so update to the table is needed. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-7-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/CEDT.cxl | Bin 184 -> 184 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/q35/CEDT.cxl b/tests/data/acpi/q35/CEDT.cxl index b8fa06b00e65712e91e0a5ea0d9277e0146d1c00..ff8203af070241bd23dd0eb8a51460692bb7d229 100644 GIT binary patch delta 18 acmdnNxPx(m*~Boui7rAD&G;s!ga80Nd Date: Wed, 8 Jun 2022 15:54:39 +0100 Subject: [PATCH 042/180] hw/cxl: Move the CXLState from MachineState to machine type specific state. This removes the last of the CXL code from the MachineState where it is visible to all Machines to only those that support CXL (currently i386/pc) As i386/pc always support CXL now, stop allocating the state independently. Note the pxb register hookup code runs even if cxl=off in order to detect pxb_cxl host bridges and fail to start if any are present as they won't have the control registers available. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-8-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/core/machine.c | 6 ------ hw/i386/acpi-build.c | 6 +++--- hw/i386/pc.c | 33 ++++++++++++++++----------------- include/hw/boards.h | 1 - include/hw/i386/pc.h | 2 ++ 5 files changed, 21 insertions(+), 27 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 2e589d99e9..a673302cce 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -33,7 +33,6 @@ #include "sysemu/qtest.h" #include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" -#include "hw/cxl/cxl.h" #include "migration/global_state.h" #include "migration/vmstate.h" #include "exec/confidential-guest-support.h" @@ -1075,10 +1074,6 @@ static void machine_initfn(Object *obj) "Valid values are cpu, mem-ctrl"); } - if (mc->cxl_supported) { - ms->cxl_devices_state = g_new0(CXLState, 1); - } - if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) { ms->numa_state = g_new0(NumaState, 1); object_property_add_bool(obj, "hmat", @@ -1116,7 +1111,6 @@ static void machine_finalize(Object *obj) g_free(ms->device_memory); g_free(ms->nvdimms_state); g_free(ms->numa_state); - g_free(ms->cxl_devices_state); } bool machine_usb(MachineState *machine) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 663c34b9d1..73d0bf5937 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1631,7 +1631,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, /* Handle the ranges for the PXB expanders */ if (pci_bus_is_cxl(bus)) { - MemoryRegion *mr = &machine->cxl_devices_state->host_mr; + MemoryRegion *mr = &pcms->cxl_devices_state.host_mr; uint64_t base = mr->addr; cxl_present = true; @@ -2614,9 +2614,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) machine->nvdimms_state, machine->ram_slots, x86ms->oem_id, x86ms->oem_table_id); } - if (machine->cxl_devices_state->is_enabled) { + if (pcms->cxl_devices_state.is_enabled) { cxl_build_cedt(table_offsets, tables_blob, tables->linker, - x86ms->oem_id, x86ms->oem_table_id, machine->cxl_devices_state); + x86ms->oem_id, x86ms->oem_table_id, &pcms->cxl_devices_state); } acpi_add_table(table_offsets, tables_blob); diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9f48d02739..a0c0d69698 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -733,12 +733,12 @@ void pc_machine_done(Notifier *notifier, void *data) PCMachineState *pcms = container_of(notifier, PCMachineState, machine_done); X86MachineState *x86ms = X86_MACHINE(pcms); - MachineState *ms = MACHINE(pcms); - if (ms->cxl_devices_state) { - cxl_hook_up_pxb_registers(pcms->bus, ms->cxl_devices_state, - &error_fatal); - cxl_fmws_link_targets(ms->cxl_devices_state, &error_fatal); + cxl_hook_up_pxb_registers(pcms->bus, &pcms->cxl_devices_state, + &error_fatal); + + if (pcms->cxl_devices_state.is_enabled) { + cxl_fmws_link_targets(&pcms->cxl_devices_state, &error_fatal); } /* set the number of CPUs */ @@ -908,8 +908,8 @@ void pc_memory_init(PCMachineState *pcms, &machine->device_memory->mr); } - if (machine->cxl_devices_state->is_enabled) { - MemoryRegion *mr = &machine->cxl_devices_state->host_mr; + if (pcms->cxl_devices_state.is_enabled) { + MemoryRegion *mr = &pcms->cxl_devices_state.host_mr; hwaddr cxl_size = MiB; if (pcmc->has_reserved_memory && machine->device_memory->base) { @@ -927,12 +927,12 @@ void pc_memory_init(PCMachineState *pcms, memory_region_init(mr, OBJECT(machine), "cxl_host_reg", cxl_size); memory_region_add_subregion(system_memory, cxl_base, mr); cxl_resv_end = cxl_base + cxl_size; - if (machine->cxl_devices_state->fixed_windows) { + if (pcms->cxl_devices_state.fixed_windows) { hwaddr cxl_fmw_base; GList *it; cxl_fmw_base = ROUND_UP(cxl_base + cxl_size, 256 * MiB); - for (it = machine->cxl_devices_state->fixed_windows; it; it = it->next) { + for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) { CXLFixedWindow *fw = it->data; fw->base = cxl_fmw_base; @@ -974,7 +974,7 @@ void pc_memory_init(PCMachineState *pcms, res_mem_end += memory_region_size(&machine->device_memory->mr); } - if (machine->cxl_devices_state->is_enabled) { + if (pcms->cxl_devices_state.is_enabled) { res_mem_end = cxl_resv_end; } *val = cpu_to_le64(ROUND_UP(res_mem_end, 1 * GiB)); @@ -1010,12 +1010,12 @@ uint64_t pc_pci_hole64_start(void) X86MachineState *x86ms = X86_MACHINE(pcms); uint64_t hole64_start = 0; - if (ms->cxl_devices_state->host_mr.addr) { - hole64_start = ms->cxl_devices_state->host_mr.addr + - memory_region_size(&ms->cxl_devices_state->host_mr); - if (ms->cxl_devices_state->fixed_windows) { + if (pcms->cxl_devices_state.host_mr.addr) { + hole64_start = pcms->cxl_devices_state.host_mr.addr + + memory_region_size(&pcms->cxl_devices_state.host_mr); + if (pcms->cxl_devices_state.fixed_windows) { GList *it; - for (it = ms->cxl_devices_state->fixed_windows; it; it = it->next) { + for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) { CXLFixedWindow *fw = it->data; hole64_start = fw->mr.addr + memory_region_size(&fw->mr); } @@ -1691,7 +1691,6 @@ static void pc_machine_set_max_fw_size(Object *obj, Visitor *v, static void pc_machine_initfn(Object *obj) { PCMachineState *pcms = PC_MACHINE(obj); - MachineState *ms = MACHINE(obj); #ifdef CONFIG_VMPORT pcms->vmport = ON_OFF_AUTO_AUTO; @@ -1716,7 +1715,7 @@ static void pc_machine_initfn(Object *obj) pcms->pcspk = isa_new(TYPE_PC_SPEAKER); object_property_add_alias(OBJECT(pcms), "pcspk-audiodev", OBJECT(pcms->pcspk), "audiodev"); - cxl_machine_init(obj, ms->cxl_devices_state); + cxl_machine_init(obj, &pcms->cxl_devices_state); } static void pc_machine_reset(MachineState *machine) diff --git a/include/hw/boards.h b/include/hw/boards.h index dd9fc56df2..031f5f884d 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -360,7 +360,6 @@ struct MachineState { CPUArchIdList *possible_cpus; CpuTopology smp; struct NVDIMMState *nvdimms_state; - struct CXLState *cxl_devices_state; struct NumaState *numa_state; CXLFixedMemoryWindowOptionsList *cfmws_list; }; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index dee38cfac4..003a86b721 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -14,6 +14,7 @@ #include "qom/object.h" #include "hw/i386/sgx-epc.h" #include "hw/firmware/smbios.h" +#include "hw/cxl/cxl.h" #define HPET_INTCAP "hpet-intcap" @@ -55,6 +56,7 @@ typedef struct PCMachineState { hwaddr memhp_io_base; SGXEPCState sgx_epc; + CXLState cxl_devices_state; } PCMachineState; #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" From 518f5f6ad6edfb17a35cc13368c4c5205fe75839 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 15:54:40 +0100 Subject: [PATCH 043/180] hw/machine: Drop cxl_supported flag as no longer useful As all the CXL elements have moved to boards that support CXL, there is no need to maintain a top level flag. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608145440.26106-9-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 1 - include/hw/boards.h | 1 - 2 files changed, 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index a0c0d69698..1b6067ff22 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1804,7 +1804,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE; mc->nvdimm_supported = true; mc->smp_props.dies_supported = true; - mc->cxl_supported = true; mc->default_ram_id = "pc.ram"; object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size", diff --git a/include/hw/boards.h b/include/hw/boards.h index 031f5f884d..d94edcef28 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -269,7 +269,6 @@ struct MachineClass { bool ignore_boot_device_suffixes; bool smbus_no_migration_support; bool nvdimm_supported; - bool cxl_supported; bool numa_mem_supported; bool auto_enable_numa; SMPCompatProps smp_props; From 36f18c6989a3d1ff1d7a0e50b0868ef3958299b4 Mon Sep 17 00:00:00 2001 From: Claudio Fontana Date: Tue, 31 May 2022 13:47:07 +0200 Subject: [PATCH 044/180] pci: fix overflow in snprintf string formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the code in pcibus_get_fw_dev_path contained the potential for a stack buffer overflow of 1 byte, potentially writing to the stack an extra NUL byte. This overflow could happen if the PCI slot is >= 0x10000000, and the PCI function is >= 0x10000000, due to the size parameter of snprintf being incorrectly calculated in the call: if (PCI_FUNC(d->devfn)) snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); since the off obtained from a previous call to snprintf is added instead of subtracted from the total available size of the buffer. Without the accurate size guard from snprintf, we end up writing in the worst case: name (32) + "@" (1) + SLOT (8) + "," (1) + FUNC (8) + term NUL (1) = 51 bytes In order to provide something more robust, replace all of the code in pcibus_get_fw_dev_path with a single call to g_strdup_printf, so there is no need to rely on manual calculations. Found by compiling QEMU with FORTIFY_SOURCE=3 as the error: *** buffer overflow detected ***: terminated Thread 1 "qemu-system-x86" received signal SIGABRT, Aborted. [Switching to Thread 0x7ffff642c380 (LWP 121307)] 0x00007ffff71ff55c in __pthread_kill_implementation () from /lib64/libc.so.6 (gdb) bt #0 0x00007ffff71ff55c in __pthread_kill_implementation () at /lib64/libc.so.6 #1 0x00007ffff71ac6f6 in raise () at /lib64/libc.so.6 #2 0x00007ffff7195814 in abort () at /lib64/libc.so.6 #3 0x00007ffff71f279e in __libc_message () at /lib64/libc.so.6 #4 0x00007ffff729767a in __fortify_fail () at /lib64/libc.so.6 #5 0x00007ffff7295c36 in () at /lib64/libc.so.6 #6 0x00007ffff72957f5 in __snprintf_chk () at /lib64/libc.so.6 #7 0x0000555555b1c1fd in pcibus_get_fw_dev_path () #8 0x0000555555f2bde4 in qdev_get_fw_dev_path_helper.constprop () #9 0x0000555555f2bd86 in qdev_get_fw_dev_path_helper.constprop () #10 0x00005555559a6e5d in get_boot_device_path () #11 0x00005555559a712c in get_boot_devices_list () #12 0x0000555555b1a3d0 in fw_cfg_machine_reset () #13 0x0000555555bf4c2d in pc_machine_reset () #14 0x0000555555c66988 in qemu_system_reset () #15 0x0000555555a6dff6 in qdev_machine_creation_done () #16 0x0000555555c79186 in qmp_x_exit_preconfig.part () #17 0x0000555555c7b459 in qemu_init () #18 0x0000555555960a29 in main () Found-by: Dario Faggioli Found-by: Martin Liška Cc: qemu-stable@nongnu.org Signed-off-by: Claudio Fontana Message-Id: <20220531114707.18830-1-cfontana@suse.de> Reviewed-by: Ani Sinha --- hw/pci/pci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index a9b37f8000..6e7015329c 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2640,15 +2640,15 @@ static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len) static char *pcibus_get_fw_dev_path(DeviceState *dev) { PCIDevice *d = (PCIDevice *)dev; - char path[50], name[33]; - int off; + char name[33]; + int has_func = !!PCI_FUNC(d->devfn); - off = snprintf(path, sizeof(path), "%s@%x", - pci_dev_fw_name(dev, name, sizeof name), - PCI_SLOT(d->devfn)); - if (PCI_FUNC(d->devfn)) - snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); - return g_strdup(path); + return g_strdup_printf("%s@%x%s%.*x", + pci_dev_fw_name(dev, name, sizeof(name)), + PCI_SLOT(d->devfn), + has_func ? "," : "", + has_func, + PCI_FUNC(d->devfn)); } static char *pcibus_get_dev_path(DeviceState *dev) From f824f5294711ffc17c642dff3d898043d420d336 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 8 Jun 2022 14:08:04 +0100 Subject: [PATCH 045/180] hw/cxl: Fix missing write mask for HDM decoder target list registers Without being able to write these registers, no interleaving is possible. More refined checks of HDM register state on commit to follow. Signed-off-by: Jonathan Cameron Reviewed-by: Ben Widawsky Message-Id: <20220608130804.25795-1-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-component-utils.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c index 7985c9bfca..3edd303a33 100644 --- a/hw/cxl/cxl-component-utils.c +++ b/hw/cxl/cxl-component-utils.c @@ -154,7 +154,8 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk) reg_state[R_CXL_RAS_ERR_CAP_CTRL] = 0x00; } -static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk) +static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk, + enum reg_type type) { int decoder_count = 1; int i; @@ -174,6 +175,14 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk) write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * 0x20] = 0xf0000000; write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * 0x20] = 0xffffffff; write_msk[R_CXL_HDM_DECODER0_CTRL + i * 0x20] = 0x13ff; + if (type == CXL2_DEVICE || + type == CXL2_TYPE3_DEVICE || + type == CXL2_LOGICAL_DEVICE) { + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xf0000000; + } else { + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_LO + i * 0x20] = 0xffffffff; + } + write_msk[R_CXL_HDM_DECODER0_TARGET_LIST_HI + i * 0x20] = 0xffffffff; } } @@ -239,7 +248,7 @@ void cxl_component_register_init_common(uint32_t *reg_state, uint32_t *write_msk } init_cap_reg(HDM, 5, 1); - hdm_init_common(reg_state, write_msk); + hdm_init_common(reg_state, write_msk, type); if (caps < 5) { return; From 6164a1110448d4e2e13963b69093950acdd2348c Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:27 +0100 Subject: [PATCH 046/180] hw/acpi/viot: rename build_pci_range_node() to enumerate_pci_host_bridges() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation for separating out the VIOT ACPI table build from the PCI host bridge numeration. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-2-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index c1af75206e..a41daded71 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -17,7 +17,7 @@ struct viot_pci_ranges { }; /* Build PCI range for a given PCI host bridge */ -static int build_pci_range_node(Object *obj, void *opaque) +static int enumerate_pci_host_bridges(Object *obj, void *opaque) { struct viot_pci_ranges *pci_ranges = opaque; GArray *blob = pci_ranges->blob; @@ -78,7 +78,7 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, }; /* Build the list of PCI ranges that this viommu manages */ - object_child_foreach_recursive(OBJECT(ms), build_pci_range_node, + object_child_foreach_recursive(OBJECT(ms), enumerate_pci_host_bridges, &pci_ranges); /* ACPI table header */ From 1b805ab560d3c020377680742ae2a49c7eb417d0 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:28 +0100 Subject: [PATCH 047/180] hw/acpi/viot: move the individual PCI host bridge entry generation to a new function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of generating each table entry inline, move the individual PCI host bridge table entry generation to a separate build_pci_host_range() function. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-3-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index a41daded71..5dafcbf5ef 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -16,6 +16,31 @@ struct viot_pci_ranges { uint16_t output_node; }; +static void build_pci_host_range(GArray *table_data, int min_bus, int max_bus, + uint16_t output_node) +{ + /* Type */ + build_append_int_noprefix(table_data, 1 /* PCI range */, 1); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 1); + /* Length */ + build_append_int_noprefix(table_data, 24, 2); + /* Endpoint start */ + build_append_int_noprefix(table_data, PCI_BUILD_BDF(min_bus, 0), 4); + /* PCI Segment start */ + build_append_int_noprefix(table_data, 0, 2); + /* PCI Segment end */ + build_append_int_noprefix(table_data, 0, 2); + /* PCI BDF start */ + build_append_int_noprefix(table_data, PCI_BUILD_BDF(min_bus, 0), 2); + /* PCI BDF end */ + build_append_int_noprefix(table_data, PCI_BUILD_BDF(max_bus, 0xff), 2); + /* Output node */ + build_append_int_noprefix(table_data, output_node, 2); + /* Reserved */ + build_append_int_noprefix(table_data, 0, 6); +} + /* Build PCI range for a given PCI host bridge */ static int enumerate_pci_host_bridges(Object *obj, void *opaque) { @@ -30,27 +55,8 @@ static int enumerate_pci_host_bridges(Object *obj, void *opaque) pci_bus_range(bus, &min_bus, &max_bus); - /* Type */ - build_append_int_noprefix(blob, 1 /* PCI range */, 1); - /* Reserved */ - build_append_int_noprefix(blob, 0, 1); - /* Length */ - build_append_int_noprefix(blob, 24, 2); - /* Endpoint start */ - build_append_int_noprefix(blob, PCI_BUILD_BDF(min_bus, 0), 4); - /* PCI Segment start */ - build_append_int_noprefix(blob, 0, 2); - /* PCI Segment end */ - build_append_int_noprefix(blob, 0, 2); - /* PCI BDF start */ - build_append_int_noprefix(blob, PCI_BUILD_BDF(min_bus, 0), 2); - /* PCI BDF end */ - build_append_int_noprefix(blob, PCI_BUILD_BDF(max_bus, 0xff), 2); - /* Output node */ - build_append_int_noprefix(blob, pci_ranges->output_node, 2); - /* Reserved */ - build_append_int_noprefix(blob, 0, 6); - + build_pci_host_range(blob, min_bus, max_bus, + pci_ranges->output_node); pci_ranges->count++; } } From e5f73c8397dddef8fc4b2fca76ffc153070a5db1 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:29 +0100 Subject: [PATCH 048/180] hw/acpi/viot: build array of PCI host bridges before generating VIOT ACPI table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Perform the generation of the VIOT ACPI table in 2 separate passes: the first pass enumerates all of the PCI host bridges and adds the min_bus and max_bus information to an array. Once this is done the VIOT table header is generated using the size of the array to calculate the node count, which means it is no longer necessary to use a sub-array to hold the PCI host bridge range information along with viommu_off. Finally the PCI host bridge array is iterated again to add the required entries to the final VIOT ACPI table. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-4-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index 5dafcbf5ef..c32bbdd180 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -10,10 +10,9 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" -struct viot_pci_ranges { - GArray *blob; - size_t count; - uint16_t output_node; +struct viot_pci_host_range { + int min_bus; + int max_bus; }; static void build_pci_host_range(GArray *table_data, int min_bus, int max_bus, @@ -44,8 +43,7 @@ static void build_pci_host_range(GArray *table_data, int min_bus, int max_bus, /* Build PCI range for a given PCI host bridge */ static int enumerate_pci_host_bridges(Object *obj, void *opaque) { - struct viot_pci_ranges *pci_ranges = opaque; - GArray *blob = pci_ranges->blob; + GArray *pci_host_ranges = opaque; if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) { PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus; @@ -55,9 +53,11 @@ static int enumerate_pci_host_bridges(Object *obj, void *opaque) pci_bus_range(bus, &min_bus, &max_bus); - build_pci_host_range(blob, min_bus, max_bus, - pci_ranges->output_node); - pci_ranges->count++; + const struct viot_pci_host_range pci_host_range = { + .min_bus = min_bus, + .max_bus = max_bus, + }; + g_array_append_val(pci_host_ranges, pci_host_range); } } @@ -78,19 +78,19 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, int viommu_off = 48; AcpiTable table = { .sig = "VIOT", .rev = 0, .oem_id = oem_id, .oem_table_id = oem_table_id }; - struct viot_pci_ranges pci_ranges = { - .output_node = viommu_off, - .blob = g_array_new(false, true /* clear */, 1), - }; + GArray *pci_host_ranges = g_array_new(false, true, + sizeof(struct viot_pci_host_range)); + struct viot_pci_host_range *pci_host_range; + int i; /* Build the list of PCI ranges that this viommu manages */ object_child_foreach_recursive(OBJECT(ms), enumerate_pci_host_bridges, - &pci_ranges); + pci_host_ranges); /* ACPI table header */ acpi_table_begin(&table, table_data); /* Node count */ - build_append_int_noprefix(table_data, pci_ranges.count + 1, 2); + build_append_int_noprefix(table_data, pci_host_ranges->len + 1, 2); /* Node offset */ build_append_int_noprefix(table_data, viommu_off, 2); /* Reserved */ @@ -111,9 +111,15 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, build_append_int_noprefix(table_data, 0, 8); /* PCI ranges found above */ - g_array_append_vals(table_data, pci_ranges.blob->data, - pci_ranges.blob->len); - g_array_free(pci_ranges.blob, true); + for (i = 0; i < pci_host_ranges->len; i++) { + pci_host_range = &g_array_index(pci_host_ranges, + struct viot_pci_host_range, i); + + build_pci_host_range(table_data, pci_host_range->min_bus, + pci_host_range->max_bus, viommu_off); + } + + g_array_free(pci_host_ranges, true); acpi_table_end(linker, &table); } From 4c8f2ffff1bffcf4649c5373a50f2475c598eb0e Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:30 +0100 Subject: [PATCH 049/180] tests/acpi: virt: allow VIOT acpi table changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mark Cave-Ayland Acked-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-5-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..8367ffe1d4 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/virt/VIOT", From 68f14a87291343bcec2bfcec7fdc0c8a3c01f66c Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:31 +0100 Subject: [PATCH 050/180] hw/acpi/viot: sort VIOT ACPI table entries by PCI host bridge min_bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures that the VIOT ACPI table output is always stable for a given PCI topology by ensuring that entries are ordered according to min_bus. Signed-off-by: Mark Cave-Ayland Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-6-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/viot.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hw/acpi/viot.c b/hw/acpi/viot.c index c32bbdd180..4e0bf69067 100644 --- a/hw/acpi/viot.c +++ b/hw/acpi/viot.c @@ -64,6 +64,20 @@ static int enumerate_pci_host_bridges(Object *obj, void *opaque) return 0; } +static gint pci_host_range_compare(gconstpointer a, gconstpointer b) +{ + struct viot_pci_host_range *range_a = (struct viot_pci_host_range *)a; + struct viot_pci_host_range *range_b = (struct viot_pci_host_range *)b; + + if (range_a->min_bus < range_b->min_bus) { + return -1; + } else if (range_a->min_bus > range_b->min_bus) { + return 1; + } else { + return 0; + } +} + /* * Generate a VIOT table with one PCI-based virtio-iommu that manages PCI * endpoints. @@ -87,6 +101,9 @@ void build_viot(MachineState *ms, GArray *table_data, BIOSLinker *linker, object_child_foreach_recursive(OBJECT(ms), enumerate_pci_host_bridges, pci_host_ranges); + /* Sort the pci host ranges by min_bus */ + g_array_sort(pci_host_ranges, pci_host_range_compare); + /* ACPI table header */ acpi_table_begin(&table, table_data); /* Node count */ From 5060004c303ce564e6ddb87d8255b7741870f9d6 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Wed, 25 May 2022 18:32:32 +0100 Subject: [PATCH 051/180] tests/acpi: virt: update golden masters for VIOT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Differences between disassembled ASL files for VIOT: +++ /tmp/asl-V69GM1.dsl 2022-05-18 10:22:27.239796759 +0100 @@ -36,11 +36,11 @@ [041h 0065 1] Reserved : 00 [042h 0066 2] Length : 0018 -[044h 0068 4] Endpoint start : 00003000 +[044h 0068 4] Endpoint start : 00001000 [048h 0072 2] PCI Segment start : 0000 [04Ah 0074 2] PCI Segment end : 0000 -[04Ch 0076 2] PCI BDF start : 3000 -[04Eh 0078 2] PCI BDF end : 30FF +[04Ch 0076 2] PCI BDF start : 1000 +[04Eh 0078 2] PCI BDF end : 10FF [050h 0080 2] Output node : 0030 [052h 0082 6] Reserved : 000000000000 @@ -48,11 +48,11 @@ [059h 0089 1] Reserved : 00 [05Ah 0090 2] Length : 0018 -[05Ch 0092 4] Endpoint start : 00001000 +[05Ch 0092 4] Endpoint start : 00003000 [060h 0096 2] PCI Segment start : 0000 [062h 0098 2] PCI Segment end : 0000 -[064h 0100 2] PCI BDF start : 1000 -[066h 0102 2] PCI BDF end : 10FF +[064h 0100 2] PCI BDF start : 3000 +[066h 0102 2] PCI BDF end : 30FF [068h 0104 2] Output node : 0030 [06Ah 0106 6] Reserved : 000000000000 @@ -62,6 +62,6 @@ 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC 0020: 01 00 00 00 03 00 30 00 00 00 00 00 00 00 00 00 // ......0......... 0030: 03 00 10 00 00 00 10 00 00 00 00 00 00 00 00 00 // ................ - 0040: 01 00 18 00 00 30 00 00 00 00 00 00 00 30 FF 30 // .....0.......0.0 - 0050: 30 00 00 00 00 00 00 00 01 00 18 00 00 10 00 00 // 0............... - 0060: 00 00 00 00 00 10 FF 10 30 00 00 00 00 00 00 00 // ........0....... + 0040: 01 00 18 00 00 10 00 00 00 00 00 00 00 10 FF 10 // ................ + 0050: 30 00 00 00 00 00 00 00 01 00 18 00 00 30 00 00 // 0............0.. + 0060: 00 00 00 00 00 30 FF 30 30 00 00 00 00 00 00 00 // .....0.00....... Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220525173232.31429-7-mark.cave-ayland@ilande.co.uk> Reviewed-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/VIOT.viot | Bin 112 -> 112 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/q35/VIOT.viot b/tests/data/acpi/q35/VIOT.viot index 9b179266ccbf84f1c250ee646812d17e27987764..275c78fbe8e93190321d957c91c3f17551f865d4 100644 GIT binary patch delta 10 RcmXRYnBY1wR(PU=1OOI`1E2r^ delta 10 RcmXRYnBY1wR(PU=1OOI`1E2r^ diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 8367ffe1d4..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,2 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/virt/VIOT", From fb38d0c97dd665f7e0c1cb8176090500ce2275e1 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Wed, 25 May 2022 20:55:39 +0800 Subject: [PATCH 052/180] hw/virtio/vhost-user: don't use uninitialized variable Variable `vdev` in `struct vhost_dev` will not be ready until start the device, so let's not use it for the error output here. Fixes: 5653493 ("hw/virtio/vhost-user: don't suppress F_CONFIG when supported") Signed-off-by: Changpeng Liu Message-Id: <20220525125540.50979-1-changpeng.liu@intel.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Fixes: 5653493 ("hw/virtio/vhost-user: don't suppress F_CONFIG when supported") Signed-off-by: Changpeng Liu Fixes: 5653493 ("hw/virtio/vhost-user: don't suppress F_CONFIG when supported") Signed-off-by: Changpeng Liu --- hw/virtio/vhost-user.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index b040c1ad2b..0594178224 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -2031,18 +2031,16 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, if (supports_f_config) { if (!virtio_has_feature(protocol_features, VHOST_USER_PROTOCOL_F_CONFIG)) { - error_setg(errp, "vhost-user device %s expecting " + error_setg(errp, "vhost-user device expecting " "VHOST_USER_PROTOCOL_F_CONFIG but the vhost-user backend does " - "not support it.", dev->vdev->name); + "not support it."); return -EPROTO; } } else { if (virtio_has_feature(protocol_features, VHOST_USER_PROTOCOL_F_CONFIG)) { warn_reportf_err(*errp, "vhost-user backend supports " - "VHOST_USER_PROTOCOL_F_CONFIG for " - "device %s but QEMU does not.", - dev->vdev->name); + "VHOST_USER_PROTOCOL_F_CONFIG but QEMU does not."); protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG); } } From 06cb5c82ebf5fd0f7b3c3de24d650e1259ca6ce4 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Wed, 25 May 2022 20:55:40 +0800 Subject: [PATCH 053/180] hw/vhost-user-scsi|blk: set `supports_config` flag correctly Currently vhost-user-scsi driver doesn't allow to change the configuration space of virtio_scsi, while vhost-user-blk support that, so here we set the flag in vhost-user-blk driver and unset it in vhost-user-scsi. Signed-off-by: Changpeng Liu Message-Id: <20220525125540.50979-2-changpeng.liu@intel.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Signed-off-by: Changpeng Liu Signed-off-by: Changpeng Liu --- hw/block/vhost-user-blk.c | 1 + hw/scsi/vhost-user-scsi.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 5dca4eab09..9117222456 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -337,6 +337,7 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp) vhost_dev_set_config_notifier(&s->dev, &blk_ops); + s->vhost_user.supports_config = true; ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0, errp); if (ret < 0) { diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index 9be21d07ee..1b2f7eed98 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -121,7 +121,6 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) vsc->dev.backend_features = 0; vqs = vsc->dev.vqs; - s->vhost_user.supports_config = true; ret = vhost_dev_init(&vsc->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0, errp); if (ret < 0) { From 7666a81d159e2ab76e8a1962e37615e8894552f5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: [PATCH 054/180] target/arm: Mark exception helpers as noreturn Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-2-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/helper.h b/target/arm/helper.h index b1334e0c42..5161cdf73d 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -44,9 +44,9 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) -DEF_HELPER_2(exception_internal, void, env, i32) -DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32) -DEF_HELPER_2(exception_bkpt_insn, void, env, i32) +DEF_HELPER_2(exception_internal, noreturn, env, i32) +DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32) +DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) From fa33eead8674c08fee3ac770c20fd64970fa0142 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: [PATCH 055/180] target/arm: Add coproc parameter to syn_fp_access_trap With ARMv8, this field is always RES0. With ARMv7, targeting EL2 and TA=0, it is always 0xA. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/syndrome.h | 7 ++++--- target/arm/translate-a64.c | 3 ++- target/arm/translate-vfp.c | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h index 0cb26dde7d..c105f9e6ba 100644 --- a/target/arm/syndrome.h +++ b/target/arm/syndrome.h @@ -185,12 +185,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm, | (rt2 << 10) | (rt << 5) | (crm << 1) | isread; } -static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit) +static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit, + int coproc) { - /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */ + /* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 */ return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT) | (is_16bit ? 0 : ARM_EL_IL) - | (cv << 24) | (cond << 20) | 0xa; + | (cv << 24) | (cond << 20) | coproc; } static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index d438fb89e7..e752589090 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1162,7 +1162,8 @@ static bool fp_access_check(DisasContext *s) s->fp_access_checked = true; gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false), s->fp_excp_el); + syn_fp_access_trap(1, 0xe, false, 0), + s->fp_excp_el); return false; } s->fp_access_checked = true; diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c index 40a513b822..0f797c56fd 100644 --- a/target/arm/translate-vfp.c +++ b/target/arm/translate-vfp.c @@ -219,8 +219,18 @@ static void gen_update_fp_context(DisasContext *s) static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled) { if (s->fp_excp_el) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false), s->fp_excp_el); + /* + * The full syndrome is only used for HSR when HCPTR traps: + * For v8, when TA==0, coproc is RES0. + * For v7, any use of a Floating-point instruction or access + * to a Floating-point Extension register that is trapped to + * Hyp mode because of a trap configured in the HCPTR sets + * this field to 0xA. + */ + int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa; + uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc); + + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el); return false; } From 57287a6e953f6e6f614c87296f8c44ea9c4907b6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: [PATCH 056/180] target/arm: Move exception_target_el out of line Move the function to op_helper.c, near raise_exception. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/internals.h | 16 +--------------- target/arm/op_helper.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index a1bae4588a..af9de2dbe5 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1098,21 +1098,6 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx); -static inline int exception_target_el(CPUARMState *env) -{ - int target_el = MAX(1, arm_current_el(env)); - - /* - * No such thing as secure EL1 if EL3 is aarch32, - * so update the target EL to EL3 in this case. - */ - if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) { - target_el = 3; - } - - return target_el; -} - /* Determine if allocation tags are available. */ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el, uint64_t sctlr) @@ -1339,6 +1324,7 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu); bool el_is_in_host(CPUARMState *env, int el); void aa32_max_features(ARMCPU *cpu); +int exception_target_el(CPUARMState *env); /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index c4bd668870..97c8c9ec77 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -28,6 +28,21 @@ #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) +int exception_target_el(CPUARMState *env) +{ + int target_el = MAX(1, arm_current_el(env)); + + /* + * No such thing as secure EL1 if EL3 is aarch32, + * so update the target EL to EL3 in this case. + */ + if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) { + target_el = 3; + } + + return target_el; +} + void raise_exception(CPUARMState *env, uint32_t excp, uint32_t syndrome, uint32_t target_el) { From 55ba15b73734e09fc8a14c88c34cad4c0e61abb2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:30 +0100 Subject: [PATCH 057/180] target/arm: Move arm_singlestep_active out of line Move the function to debug_helper.c, and the declaration to internals.h. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-5-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 10 ---------- target/arm/debug_helper.c | 12 ++++++++++++ target/arm/internals.h | 1 + 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 78dbcb5592..bb1dc3289a 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3106,16 +3106,6 @@ static inline bool arm_generate_debug_exceptions(CPUARMState *env) } } -/* Is single-stepping active? (Note that the "is EL_D AArch64?" check - * implicitly means this always returns false in pre-v8 CPUs.) - */ -static inline bool arm_singlestep_active(CPUARMState *env) -{ - return extract32(env->cp15.mdscr_el1, 0, 1) - && arm_el_is_aa64(env, arm_debug_target_el(env)) - && arm_generate_debug_exceptions(env); -} - static inline bool arm_sctlr_b(CPUARMState *env) { return diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 46893697cc..1abf41c5f8 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -11,6 +11,18 @@ #include "exec/exec-all.h" #include "exec/helper-proto.h" + +/* + * Is single-stepping active? (Note that the "is EL_D AArch64?" check + * implicitly means this always returns false in pre-v8 CPUs.) + */ +bool arm_singlestep_active(CPUARMState *env) +{ + return extract32(env->cp15.mdscr_el1, 0, 1) + && arm_el_is_aa64(env, arm_debug_target_el(env)) + && arm_generate_debug_exceptions(env); +} + /* Return true if the linked breakpoint entry lbn passes its checks */ static bool linked_bp_matches(ARMCPU *cpu, int lbn) { diff --git a/target/arm/internals.h b/target/arm/internals.h index af9de2dbe5..64e2c1dfad 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1325,6 +1325,7 @@ bool el_is_in_host(CPUARMState *env, int el); void aa32_max_features(ARMCPU *cpu); int exception_target_el(CPUARMState *env); +bool arm_singlestep_active(CPUARMState *env); /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ From 31c8df53ee2c1bed06ea80644399d6998b887ad1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: [PATCH 058/180] target/arm: Move arm_generate_debug_exceptions out of line Move arm_generate_debug_exceptions and its two subroutines, {aa32,aa64}_generate_debug_exceptions into debug_helper.c, and the one interface declaration to internals.h. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-6-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 91 ------------------------------------- target/arm/debug_helper.c | 94 +++++++++++++++++++++++++++++++++++++++ target/arm/internals.h | 1 + 3 files changed, 95 insertions(+), 91 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index bb1dc3289a..50b5a9c9fd 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3015,97 +3015,6 @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu) return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0; } -/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ -static inline bool aa64_generate_debug_exceptions(CPUARMState *env) -{ - int cur_el = arm_current_el(env); - int debug_el; - - if (cur_el == 3) { - return false; - } - - /* MDCR_EL3.SDD disables debug events from Secure state */ - if (arm_is_secure_below_el3(env) - && extract32(env->cp15.mdcr_el3, 16, 1)) { - return false; - } - - /* - * Same EL to same EL debug exceptions need MDSCR_KDE enabled - * while not masking the (D)ebug bit in DAIF. - */ - debug_el = arm_debug_target_el(env); - - if (cur_el == debug_el) { - return extract32(env->cp15.mdscr_el1, 13, 1) - && !(env->daif & PSTATE_D); - } - - /* Otherwise the debug target needs to be a higher EL */ - return debug_el > cur_el; -} - -static inline bool aa32_generate_debug_exceptions(CPUARMState *env) -{ - int el = arm_current_el(env); - - if (el == 0 && arm_el_is_aa64(env, 1)) { - return aa64_generate_debug_exceptions(env); - } - - if (arm_is_secure(env)) { - int spd; - - if (el == 0 && (env->cp15.sder & 1)) { - /* SDER.SUIDEN means debug exceptions from Secure EL0 - * are always enabled. Otherwise they are controlled by - * SDCR.SPD like those from other Secure ELs. - */ - return true; - } - - spd = extract32(env->cp15.mdcr_el3, 14, 2); - switch (spd) { - case 1: - /* SPD == 0b01 is reserved, but behaves as 0b00. */ - case 0: - /* For 0b00 we return true if external secure invasive debug - * is enabled. On real hardware this is controlled by external - * signals to the core. QEMU always permits debug, and behaves - * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high. - */ - return true; - case 2: - return false; - case 3: - return true; - } - } - - return el != 2; -} - -/* Return true if debugging exceptions are currently enabled. - * This corresponds to what in ARM ARM pseudocode would be - * if UsingAArch32() then - * return AArch32.GenerateDebugExceptions() - * else - * return AArch64.GenerateDebugExceptions() - * We choose to push the if() down into this function for clarity, - * since the pseudocode has it at all callsites except for the one in - * CheckSoftwareStep(), where it is elided because both branches would - * always return the same value. - */ -static inline bool arm_generate_debug_exceptions(CPUARMState *env) -{ - if (env->aarch64) { - return aa64_generate_debug_exceptions(env); - } else { - return aa32_generate_debug_exceptions(env); - } -} - static inline bool arm_sctlr_b(CPUARMState *env) { return diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 1abf41c5f8..20a0e4261a 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,6 +12,100 @@ #include "exec/helper-proto.h" +/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ +static bool aa64_generate_debug_exceptions(CPUARMState *env) +{ + int cur_el = arm_current_el(env); + int debug_el; + + if (cur_el == 3) { + return false; + } + + /* MDCR_EL3.SDD disables debug events from Secure state */ + if (arm_is_secure_below_el3(env) + && extract32(env->cp15.mdcr_el3, 16, 1)) { + return false; + } + + /* + * Same EL to same EL debug exceptions need MDSCR_KDE enabled + * while not masking the (D)ebug bit in DAIF. + */ + debug_el = arm_debug_target_el(env); + + if (cur_el == debug_el) { + return extract32(env->cp15.mdscr_el1, 13, 1) + && !(env->daif & PSTATE_D); + } + + /* Otherwise the debug target needs to be a higher EL */ + return debug_el > cur_el; +} + +static bool aa32_generate_debug_exceptions(CPUARMState *env) +{ + int el = arm_current_el(env); + + if (el == 0 && arm_el_is_aa64(env, 1)) { + return aa64_generate_debug_exceptions(env); + } + + if (arm_is_secure(env)) { + int spd; + + if (el == 0 && (env->cp15.sder & 1)) { + /* + * SDER.SUIDEN means debug exceptions from Secure EL0 + * are always enabled. Otherwise they are controlled by + * SDCR.SPD like those from other Secure ELs. + */ + return true; + } + + spd = extract32(env->cp15.mdcr_el3, 14, 2); + switch (spd) { + case 1: + /* SPD == 0b01 is reserved, but behaves as 0b00. */ + case 0: + /* + * For 0b00 we return true if external secure invasive debug + * is enabled. On real hardware this is controlled by external + * signals to the core. QEMU always permits debug, and behaves + * as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high. + */ + return true; + case 2: + return false; + case 3: + return true; + } + } + + return el != 2; +} + +/* + * Return true if debugging exceptions are currently enabled. + * This corresponds to what in ARM ARM pseudocode would be + * if UsingAArch32() then + * return AArch32.GenerateDebugExceptions() + * else + * return AArch64.GenerateDebugExceptions() + * We choose to push the if() down into this function for clarity, + * since the pseudocode has it at all callsites except for the one in + * CheckSoftwareStep(), where it is elided because both branches would + * always return the same value. + */ +bool arm_generate_debug_exceptions(CPUARMState *env) +{ + if (env->aarch64) { + return aa64_generate_debug_exceptions(env); + } else { + return aa32_generate_debug_exceptions(env); + } +} + /* * Is single-stepping active? (Note that the "is EL_D AArch64?" check * implicitly means this always returns false in pre-v8 CPUs.) diff --git a/target/arm/internals.h b/target/arm/internals.h index 64e2c1dfad..02fa70f75a 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1326,6 +1326,7 @@ bool el_is_in_host(CPUARMState *env, int el); void aa32_max_features(ARMCPU *cpu); int exception_target_el(CPUARMState *env); bool arm_singlestep_active(CPUARMState *env); +bool arm_generate_debug_exceptions(CPUARMState *env); /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ From 831c1b1087c3aace40a8de36c3780ead81ebbb73 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: [PATCH 059/180] target/arm: Use is_a64 in arm_generate_debug_exceptions Use the accessor rather than the raw structure member. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-7-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 20a0e4261a..a18a09a0c3 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -99,7 +99,7 @@ static bool aa32_generate_debug_exceptions(CPUARMState *env) */ bool arm_generate_debug_exceptions(CPUARMState *env) { - if (env->aarch64) { + if (is_a64(env)) { return aa64_generate_debug_exceptions(env); } else { return aa32_generate_debug_exceptions(env); From 16f9d5f6937d26f73a9694ba6bac0e113e3015e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: [PATCH 060/180] target/arm: Move exception_bkpt_insn to debug_helper.c Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 31 +++++++++++++++++++++++++++++++ target/arm/op_helper.c | 29 ----------------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index a18a09a0c3..80dff0788b 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -430,6 +430,37 @@ void arm_debug_excp_handler(CPUState *cs) } } +/* + * Raise an EXCP_BKPT with the specified syndrome register value, + * targeting the correct exception level for debug exceptions. + */ +void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) +{ + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + + /* FSR will only be used if the debug target EL is AArch32. */ + env->exception.fsr = arm_debug_exception_fsr(env); + /* + * FAR is UNKNOWN: clear vaddress to avoid potentially exposing + * values to the guest that it shouldn't be able to see at its + * exception/security level. + */ + env->exception.vaddress = 0; + /* + * Other kinds of architectural debug exception are ignored if + * they target an exception level below the current one (in QEMU + * this is checked by arm_generate_debug_exceptions()). Breakpoint + * instructions are special because they always generate an exception + * to somewhere: if they can't go to the configured debug exception + * level they are taken to the current exception level. + */ + if (debug_el < cur_el) { + debug_el = cur_el; + } + raise_exception(env, EXCP_BKPT, syndrome, debug_el); +} + #if !defined(CONFIG_USER_ONLY) vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 97c8c9ec77..2a8bdc2cbf 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -399,35 +399,6 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, raise_exception(env, excp, syndrome, target_el); } -/* Raise an EXCP_BKPT with the specified syndrome register value, - * targeting the correct exception level for debug exceptions. - */ -void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) -{ - int debug_el = arm_debug_target_el(env); - int cur_el = arm_current_el(env); - - /* FSR will only be used if the debug target EL is AArch32. */ - env->exception.fsr = arm_debug_exception_fsr(env); - /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing - * values to the guest that it shouldn't be able to see at its - * exception/security level. - */ - env->exception.vaddress = 0; - /* - * Other kinds of architectural debug exception are ignored if - * they target an exception level below the current one (in QEMU - * this is checked by arm_generate_debug_exceptions()). Breakpoint - * instructions are special because they always generate an exception - * to somewhere: if they can't go to the configured debug exception - * level they are taken to the current exception level. - */ - if (debug_el < cur_el) { - debug_el = cur_el; - } - raise_exception(env, EXCP_BKPT, syndrome, debug_el); -} - uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~CPSR_EXEC; From a853e3ae559ddd6020012ee0e6475dfab65d1eb1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: [PATCH 061/180] target/arm: Move arm_debug_exception_fsr to debug_helper.c This function now now only used in debug_helper.c, so there is no reason to have a declaration in a header. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 26 ++++++++++++++++++++++++++ target/arm/internals.h | 25 ------------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 80dff0788b..a743061e89 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -379,6 +379,32 @@ bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) return check_watchpoints(cpu); } +/* + * Return the FSR value for a debug exception (watchpoint, hardware + * breakpoint or BKPT insn) targeting the specified exception level. + */ +static uint32_t arm_debug_exception_fsr(CPUARMState *env) +{ + ARMMMUFaultInfo fi = { .type = ARMFault_Debug }; + int target_el = arm_debug_target_el(env); + bool using_lpae = false; + + if (target_el == 2 || arm_el_is_aa64(env, target_el)) { + using_lpae = true; + } else { + if (arm_feature(env, ARM_FEATURE_LPAE) && + (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) { + using_lpae = true; + } + } + + if (using_lpae) { + return arm_fi_to_lfsc(&fi); + } else { + return arm_fi_to_sfsc(&fi); + } +} + void arm_debug_excp_handler(CPUState *cs) { /* diff --git a/target/arm/internals.h b/target/arm/internals.h index 02fa70f75a..6f94f3019d 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -793,31 +793,6 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; } -/* Return the FSR value for a debug exception (watchpoint, hardware - * breakpoint or BKPT insn) targeting the specified exception level. - */ -static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) -{ - ARMMMUFaultInfo fi = { .type = ARMFault_Debug }; - int target_el = arm_debug_target_el(env); - bool using_lpae = false; - - if (target_el == 2 || arm_el_is_aa64(env, target_el)) { - using_lpae = true; - } else { - if (arm_feature(env, ARM_FEATURE_LPAE) && - (env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) { - using_lpae = true; - } - } - - if (using_lpae) { - return arm_fi_to_lfsc(&fi); - } else { - return arm_fi_to_sfsc(&fi); - } -} - /** * arm_num_brps: Return number of implemented breakpoints. * Note that the ID register BRPS field is "number of bps - 1", From d3c5d50a5c498e3c32c59db210d501a980091ad6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:31 +0100 Subject: [PATCH 062/180] target/arm: Rename helper_exception_with_syndrome Rename to helper_exception_with_syndrome_el, to emphasize that the target el is a parameter. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-10-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.h | 2 +- target/arm/op_helper.c | 6 +++--- target/arm/translate.c | 6 +++--- target/arm/translate.h | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/target/arm/helper.h b/target/arm/helper.h index 5161cdf73d..5a6802e3fa 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -45,7 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception_internal, noreturn, env, i32) -DEF_HELPER_4(exception_with_syndrome, noreturn, env, i32, i32, i32) +DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 2a8bdc2cbf..8a6a3b8551 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -381,7 +381,7 @@ void HELPER(yield)(CPUARMState *env) * those EXCP values which are special cases for QEMU to interrupt * execution and not to be used for exceptions which are passed to * the guest (those must all have syndrome information and thus should - * use exception_with_syndrome). + * use exception_with_syndrome*). */ void HELPER(exception_internal)(CPUARMState *env, uint32_t excp) { @@ -393,8 +393,8 @@ void HELPER(exception_internal)(CPUARMState *env, uint32_t excp) } /* Raise an exception with the specified syndrome register value */ -void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, - uint32_t syndrome, uint32_t target_el) +void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp, + uint32_t syndrome, uint32_t target_el) { raise_exception(env, excp, syndrome, target_el); } diff --git a/target/arm/translate.c b/target/arm/translate.c index 87a899d638..dc033600c0 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1119,9 +1119,9 @@ static void gen_exception_el(DisasContext *s, int excp, uint32_t syn, { gen_set_condexec(s); gen_set_pc_im(s, s->pc_curr); - gen_helper_exception_with_syndrome(cpu_env, - tcg_constant_i32(excp), - tcg_constant_i32(syn), tcg_el); + gen_helper_exception_with_syndrome_el(cpu_env, + tcg_constant_i32(excp), + tcg_constant_i32(syn), tcg_el); s->base.is_jmp = DISAS_NORETURN; } diff --git a/target/arm/translate.h b/target/arm/translate.h index f473a21ed4..c57830126b 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -332,9 +332,9 @@ static inline void gen_ss_advance(DisasContext *s) static inline void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) { - gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syndrome), - tcg_constant_i32(target_el)); + gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome), + tcg_constant_i32(target_el)); } /* Generate an architectural singlestep exception */ From 9c9d03f0c556fb72be840773f0e8024a9a72d5e4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: [PATCH 063/180] target/arm: Introduce gen_exception_insn_el_v Create a function below gen_exception_insn that takes the target_el as a TCGv_i32, replacing gen_exception_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index dc033600c0..9cb31663dd 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,8 +1086,8 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } -void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, - uint32_t syn, uint32_t target_el) +static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, TCGv_i32 tcg_el) { if (s->aarch64) { gen_a64_set_pc_im(pc); @@ -1095,10 +1095,17 @@ void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, gen_set_condexec(s); gen_set_pc_im(s, pc); } - gen_exception(excp, syn, target_el); + gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syn), tcg_el); s->base.is_jmp = DISAS_NORETURN; } +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, uint32_t target_el) +{ + gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el)); +} + static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) { gen_set_condexec(s); @@ -1114,17 +1121,6 @@ void unallocated_encoding(DisasContext *s) default_exception_el(s)); } -static void gen_exception_el(DisasContext *s, int excp, uint32_t syn, - TCGv_i32 tcg_el) -{ - gen_set_condexec(s); - gen_set_pc_im(s, s->pc_curr); - gen_helper_exception_with_syndrome_el(cpu_env, - tcg_constant_i32(excp), - tcg_constant_i32(syn), tcg_el); - s->base.is_jmp = DISAS_NORETURN; -} - /* Force a TB lookup after an instruction that changes the CPU state. */ void gen_lookup_tb(DisasContext *s) { @@ -2847,7 +2843,8 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, tcg_el = tcg_constant_i32(3); } - gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el); + gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF, + syn_uncategorized(), tcg_el); tcg_temp_free_i32(tcg_el); return false; } From 8c5d24dc7dace7aeb9d3d1f9eebd679c3b22e3ff Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: [PATCH 064/180] target/arm: Rename gen_exception_insn to gen_exception_insn_el Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 36 ++++++++++++++++---------------- target/arm/translate-m-nocp.c | 16 +++++++------- target/arm/translate-mve.c | 4 ++-- target/arm/translate-vfp.c | 6 +++--- target/arm/translate.c | 39 ++++++++++++++++++----------------- target/arm/translate.h | 4 ++-- 6 files changed, 53 insertions(+), 52 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index e752589090..14bc80dba0 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1161,9 +1161,9 @@ static bool fp_access_check(DisasContext *s) assert(!s->fp_access_checked); s->fp_access_checked = true; - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_fp_access_trap(1, 0xe, false, 0), - s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, false, 0), + s->fp_excp_el); return false; } s->fp_access_checked = true; @@ -1179,8 +1179,8 @@ bool sve_access_check(DisasContext *s) assert(!s->sve_access_checked); s->sve_access_checked = true; - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_sve_access_trap(), s->sve_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_sve_access_trap(), s->sve_excp_el); return false; } s->sve_access_checked = true; @@ -1816,8 +1816,8 @@ static void gen_sysreg_undef(DisasContext *s, bool isread, } else { syndrome = syn_uncategorized(); } - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome, - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome, + default_exception_el(s)); } /* MRS - move from system register @@ -2069,8 +2069,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) switch (op2_ll) { case 1: /* SVC */ gen_ss_advance(s); - gen_exception_insn(s, s->base.pc_next, EXCP_SWI, - syn_aa64_svc(imm16), default_exception_el(s)); + gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI, + syn_aa64_svc(imm16), default_exception_el(s)); break; case 2: /* HVC */ if (s->current_el == 0) { @@ -2083,8 +2083,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) gen_a64_set_pc_im(s->pc_curr); gen_helper_pre_hvc(cpu_env); gen_ss_advance(s); - gen_exception_insn(s, s->base.pc_next, EXCP_HVC, - syn_aa64_hvc(imm16), 2); + gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC, + syn_aa64_hvc(imm16), 2); break; case 3: /* SMC */ if (s->current_el == 0) { @@ -2094,8 +2094,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) gen_a64_set_pc_im(s->pc_curr); gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16))); gen_ss_advance(s); - gen_exception_insn(s, s->base.pc_next, EXCP_SMC, - syn_aa64_smc(imm16), 3); + gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC, + syn_aa64_smc(imm16), 3); break; default: unallocated_encoding(s); @@ -14725,8 +14725,8 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_illegalstate(), default_exception_el(s)); return; } @@ -14757,9 +14757,9 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) if (s->btype != 0 && s->guarded_page && !btype_destination_ok(insn, s->bt, s->btype)) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_btitrap(s->btype), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_btitrap(s->btype), + default_exception_el(s)); return; } } else { diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c index 27363a7b4e..636bfb1788 100644 --- a/target/arm/translate-m-nocp.c +++ b/target/arm/translate-m-nocp.c @@ -143,8 +143,8 @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel); if (s->fp_excp_el != 0) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return true; } @@ -376,7 +376,7 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno, if (!vfp_access_check_m(s, true)) { /* * This was only a conditional exception, so override - * gen_exception_insn()'s default to DISAS_NORETURN + * gen_exception_insn_el()'s default to DISAS_NORETURN */ s->base.is_jmp = DISAS_NEXT; break; @@ -532,7 +532,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno, if (!vfp_access_check_m(s, true)) { /* * This was only a conditional exception, so override - * gen_exception_insn()'s default to DISAS_NORETURN + * gen_exception_insn_el()'s default to DISAS_NORETURN */ s->base.is_jmp = DISAS_NEXT; break; @@ -765,14 +765,14 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a) } if (a->cp != 10) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), default_exception_el(s)); return true; } if (s->fp_excp_el != 0) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return true; } diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index 4267d43cc7..5aec2a1555 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -100,8 +100,8 @@ bool mve_eci_check(DisasContext *s) return true; default: /* Reserved value: INVSTATE UsageFault */ - gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); return false; } } diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c index 0f797c56fd..82fdbcae53 100644 --- a/target/arm/translate-vfp.c +++ b/target/arm/translate-vfp.c @@ -230,7 +230,7 @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled) int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa; uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc); - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el); return false; } @@ -260,8 +260,8 @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update) * the encoding space handled by the patterns in m-nocp.decode, * and for them we may need to raise NOCP here. */ - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return false; } diff --git a/target/arm/translate.c b/target/arm/translate.c index 9cb31663dd..44f462a3a3 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1100,8 +1100,8 @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, s->base.is_jmp = DISAS_NORETURN; } -void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, - uint32_t syn, uint32_t target_el) +void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, uint32_t target_el) { gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el)); } @@ -1117,8 +1117,8 @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) void unallocated_encoding(DisasContext *s) { /* Unallocated and reserved encodings are uncategorized */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), + default_exception_el(s)); } /* Force a TB lookup after an instruction that changes the CPU state. */ @@ -2869,8 +2869,8 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, undef: /* If we get here then some access check did not pass */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_uncategorized(), exc_target); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_uncategorized(), exc_target); return false; } @@ -5094,7 +5094,8 @@ static void gen_srs(DisasContext *s, * For the UNPREDICTABLE cases we choose to UNDEF. */ if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) { - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_uncategorized(), 3); return; } @@ -8479,8 +8480,8 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a) * Do the check-and-raise-exception by hand. */ if (s->fp_excp_el) { - gen_exception_insn(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), s->fp_excp_el); + gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); return true; } } @@ -8582,8 +8583,8 @@ static bool trans_LE(DisasContext *s, arg_LE *a) tmp = load_cpu_field(v7m.ltpsize); tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc); tcg_temp_free_i32(tmp); - gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); gen_set_label(skipexc); } @@ -9053,8 +9054,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * UsageFault exception. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { - gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); return; } @@ -9063,8 +9064,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, + syn_illegalstate(), default_exception_el(s)); return; } @@ -9633,8 +9634,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(dc)); + gen_exception_insn_el(dc, dc->pc_curr, EXCP_UDEF, + syn_illegalstate(), default_exception_el(dc)); return; } @@ -9707,8 +9708,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) */ tcg_remove_ops_after(dc->insn_eci_rewind); dc->condjmp = 0; - gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(dc)); + gen_exception_insn_el(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(dc)); } arm_post_translate_insn(dc); diff --git a/target/arm/translate.h b/target/arm/translate.h index c57830126b..9ae76535ad 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -279,8 +279,8 @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label); void arm_gen_test_cc(int cc, TCGLabel *label); MemOp pow2_align(unsigned i); void unallocated_encoding(DisasContext *s); -void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, - uint32_t syn, uint32_t target_el); +void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, + uint32_t syn, uint32_t target_el); /* Return state of Alternate Half-precision flag, caller frees result */ static inline TCGv_i32 get_ahp_flag(void) From 486d6c9699a5fc1f11c48dbe73b46e183020fa49 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: [PATCH 065/180] target/arm: Introduce gen_exception_insn Create a new wrapper function that passes the default exception target to gen_exception_insn_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 15 ++++++--------- target/arm/translate-m-nocp.c | 3 +-- target/arm/translate-mve.c | 3 +-- target/arm/translate.c | 29 +++++++++++++---------------- target/arm/translate.h | 1 + 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 14bc80dba0..0581118f56 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1816,8 +1816,7 @@ static void gen_sysreg_undef(DisasContext *s, bool isread, } else { syndrome = syn_uncategorized(); } - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syndrome, - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome); } /* MRS - move from system register @@ -2069,8 +2068,8 @@ static void disas_exc(DisasContext *s, uint32_t insn) switch (op2_ll) { case 1: /* SVC */ gen_ss_advance(s); - gen_exception_insn_el(s, s->base.pc_next, EXCP_SWI, - syn_aa64_svc(imm16), default_exception_el(s)); + gen_exception_insn(s, s->base.pc_next, EXCP_SWI, + syn_aa64_svc(imm16)); break; case 2: /* HVC */ if (s->current_el == 0) { @@ -14725,8 +14724,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate()); return; } @@ -14757,9 +14755,8 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) if (s->btype != 0 && s->guarded_page && !btype_destination_ok(insn, s->bt, s->btype)) { - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_btitrap(s->btype), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, + syn_btitrap(s->btype)); return; } } else { diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c index 636bfb1788..4029d7fdd4 100644 --- a/target/arm/translate-m-nocp.c +++ b/target/arm/translate-m-nocp.c @@ -765,8 +765,7 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a) } if (a->cp != 10) { - gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP, - syn_uncategorized(), default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized()); return true; } diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index 5aec2a1555..0cf1b5ea4f 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -100,8 +100,7 @@ bool mve_eci_check(DisasContext *s) return true; default: /* Reserved value: INVSTATE UsageFault */ - gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized()); return false; } } diff --git a/target/arm/translate.c b/target/arm/translate.c index 44f462a3a3..c7d422b541 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1106,6 +1106,11 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el)); } +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn) +{ + gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s)); +} + static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) { gen_set_condexec(s); @@ -1117,8 +1122,7 @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) void unallocated_encoding(DisasContext *s) { /* Unallocated and reserved encodings are uncategorized */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized()); } /* Force a TB lookup after an instruction that changes the CPU state. */ @@ -2731,8 +2735,6 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, * an exception and return false. Otherwise it will return true, * and set *tgtmode and *regno appropriately. */ - int exc_target = default_exception_el(s); - /* These instructions are present only in ARMv8, or in ARMv7 with the * Virtualization Extensions. */ @@ -2869,8 +2871,7 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn, undef: /* If we get here then some access check did not pass */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_uncategorized(), exc_target); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized()); return false; } @@ -8583,8 +8584,7 @@ static bool trans_LE(DisasContext *s, arg_LE *a) tmp = load_cpu_field(v7m.ltpsize); tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc); tcg_temp_free_i32(tmp); - gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized()); gen_set_label(skipexc); } @@ -9054,8 +9054,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * UsageFault exception. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { - gen_exception_insn_el(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized()); return; } @@ -9064,8 +9063,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(s)); + gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate()); return; } @@ -9634,8 +9632,7 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * Illegal execution state. This has priority over BTI * exceptions, but comes after instruction abort exceptions. */ - gen_exception_insn_el(dc, dc->pc_curr, EXCP_UDEF, - syn_illegalstate(), default_exception_el(dc)); + gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, syn_illegalstate()); return; } @@ -9708,8 +9705,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) */ tcg_remove_ops_after(dc->insn_eci_rewind); dc->condjmp = 0; - gen_exception_insn_el(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(), - default_exception_el(dc)); + gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, + syn_uncategorized()); } arm_post_translate_insn(dc); diff --git a/target/arm/translate.h b/target/arm/translate.h index 9ae76535ad..4575af6e1c 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -281,6 +281,7 @@ MemOp pow2_align(unsigned i); void unallocated_encoding(DisasContext *s); void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, uint32_t syn, uint32_t target_el); +void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn); /* Return state of Alternate Half-precision flag, caller frees result */ static inline TCGv_i32 get_ahp_flag(void) From f0d7c2054aee5d17ed0a84a11cc8c89b38902d3c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:32 +0100 Subject: [PATCH 066/180] target/arm: Create helper_exception_swstep Move the computation from gen_swstep_exception into a helper. This fixes a bug when: - MDSCR_EL1.KDE == 1 to enable debug exceptions within EL_D itself - we singlestep an ERET from EL_D to some lower EL Previously we were computing 'same el' based on the EL which executed the ERET instruction, whereas it ought to be computed based on the EL to which ERET returned. This happens naturally with the new helper, which runs after EL has been changed. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-14-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 16 ++++++++++++++++ target/arm/helper.h | 1 + target/arm/translate.h | 12 +++--------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index a743061e89..a3a1b98de2 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -487,6 +487,22 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) raise_exception(env, EXCP_BKPT, syndrome, debug_el); } +void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) +{ + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + + /* + * If singlestep is targeting a lower EL than the current one, then + * DisasContext.ss_active must be false and we can never get here. + */ + assert(debug_el >= cur_el); + if (debug_el == cur_el) { + syndrome |= 1 << ARM_EL_EC_SHIFT; + } + raise_exception(env, EXCP_UDEF, syndrome, debug_el); +} + #if !defined(CONFIG_USER_ONLY) vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) diff --git a/target/arm/helper.h b/target/arm/helper.h index 5a6802e3fa..db7447d233 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, DEF_HELPER_2(exception_internal, noreturn, env, i32) DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) +DEF_HELPER_2(exception_swstep, noreturn, env, i32) DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) diff --git a/target/arm/translate.h b/target/arm/translate.h index 4575af6e1c..890e73194c 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -341,15 +341,9 @@ static inline void gen_exception(int excp, uint32_t syndrome, /* Generate an architectural singlestep exception */ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) { - bool same_el = (s->debug_target_el == s->current_el); - - /* - * If singlestep is targeting a lower EL than the current one, - * then s->ss_active must be false and we can never get here. - */ - assert(s->debug_target_el >= s->current_el); - - gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el); + /* Fill in the same_el field of the syndrome in the helper. */ + uint32_t syn = syn_swstep(false, isv, ex); + gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn)); } /* From 8480e933edf112d3ee775929106a2bdbaf002fbe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: [PATCH 067/180] target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL We no longer need this value during translation, as it is now handled within the helpers. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-15-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 6 ++---- target/arm/helper.c | 12 ++---------- target/arm/translate-a64.c | 1 - target/arm/translate.c | 1 - target/arm/translate.h | 2 -- 5 files changed, 4 insertions(+), 18 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 50b5a9c9fd..719613ad9e 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3104,11 +3104,9 @@ FIELD(TBFLAG_ANY, BE_DATA, 3, 1) FIELD(TBFLAG_ANY, MMUIDX, 4, 4) /* Target EL if we take a floating-point-disabled exception */ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2) -/* For A-profile only, target EL for debug exceptions. */ -FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2) /* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */ -FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1) -FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1) +FIELD(TBFLAG_ANY, ALIGN_MEM, 10, 1) +FIELD(TBFLAG_ANY, PSTATE__IL, 11, 1) /* * Bit usage when in AArch32 state, both A- and M-profile. diff --git a/target/arm/helper.c b/target/arm/helper.c index ac9942d750..2b2c1998fd 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -11102,18 +11102,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } -static CPUARMTBFlags rebuild_hflags_aprofile(CPUARMState *env) -{ - CPUARMTBFlags flags = {}; - - DP_TBFLAG_ANY(flags, DEBUG_TARGET_EL, arm_debug_target_el(env)); - return flags; -} - static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, ARMMMUIdx mmu_idx) { - CPUARMTBFlags flags = rebuild_hflags_aprofile(env); + CPUARMTBFlags flags = {}; int el = arm_current_el(env); if (arm_sctlr(env, el) & SCTLR_A) { @@ -11139,7 +11131,7 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, ARMMMUIdx mmu_idx) { - CPUARMTBFlags flags = rebuild_hflags_aprofile(env); + CPUARMTBFlags flags = {}; ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx); uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr; uint64_t sctlr; diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 0581118f56..4f6181a548 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -14645,7 +14645,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE); dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS); dc->is_ldex = false; - dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL); /* Bound the number of insns to execute to those left on the page. */ bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; diff --git a/target/arm/translate.c b/target/arm/translate.c index c7d422b541..b8a8972bac 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9350,7 +9350,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT); dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED); } else { - dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL); dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B); dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE); dc->ns = EX_TBFLAG_A32(tb_flags, NS); diff --git a/target/arm/translate.h b/target/arm/translate.h index 890e73194c..8685f55e80 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -59,8 +59,6 @@ typedef struct DisasContext { */ uint32_t svc_imm; int current_el; - /* Debug target exception level for single-step exceptions */ - int debug_target_el; GHashTable *cp_regs; uint64_t features; /* CPU features bits */ bool aarch64; From cc5e672b85da3dd972cc04cd8020aeb5a60519a8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: [PATCH 068/180] target/arm: Move gen_exception to translate.c This function is not required by any other translation file. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 7 +++++++ target/arm/translate.h | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index b8a8972bac..fc5eafaeeb 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,6 +1086,13 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } +static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) +{ + gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome), + tcg_constant_i32(target_el)); +} + static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, uint32_t syn, TCGv_i32 tcg_el) { diff --git a/target/arm/translate.h b/target/arm/translate.h index 8685f55e80..850bcdc155 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -328,14 +328,6 @@ static inline void gen_ss_advance(DisasContext *s) } } -static inline void gen_exception(int excp, uint32_t syndrome, - uint32_t target_el) -{ - gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syndrome), - tcg_constant_i32(target_el)); -} - /* Generate an architectural singlestep exception */ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex) { From bca6f24f0189c0e1a2ff091250d2d46c89a76401 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: [PATCH 069/180] target/arm: Rename gen_exception to gen_exception_el Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index fc5eafaeeb..edb7d3f394 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,7 +1086,7 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } -static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el) +static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) { gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), tcg_constant_i32(syndrome), @@ -9758,16 +9758,16 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) switch (dc->base.is_jmp) { case DISAS_SWI: gen_ss_advance(dc); - gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), + default_exception_el(dc)); break; case DISAS_HVC: gen_ss_advance(dc); - gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); + gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); break; case DISAS_SMC: gen_ss_advance(dc); - gen_exception(EXCP_SMC, syn_aa32_smc(), 3); + gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3); break; case DISAS_NEXT: case DISAS_TOO_MANY: @@ -9828,14 +9828,14 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_helper_yield(cpu_env); break; case DISAS_SWI: - gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), + default_exception_el(dc)); break; case DISAS_HVC: - gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); + gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); break; case DISAS_SMC: - gen_exception(EXCP_SMC, syn_aa32_smc(), 3); + gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3); break; } } From 1a13b9a86334d85546afc4e8b568bee970d7a828 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:33 +0100 Subject: [PATCH 070/180] target/arm: Introduce gen_exception Create a new wrapper function that passes the default exception target to gen_exception_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index edb7d3f394..5a48937ede 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1093,6 +1093,11 @@ static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) tcg_constant_i32(target_el)); } +static void gen_exception(DisasContext *s, int excp, uint32_t syndrome) +{ + gen_exception_el(excp, syndrome, default_exception_el(s)); +} + static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, uint32_t syn, TCGv_i32 tcg_el) { @@ -9758,8 +9763,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) switch (dc->base.is_jmp) { case DISAS_SWI: gen_ss_advance(dc); - gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_ss_advance(dc); @@ -9828,8 +9832,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_helper_yield(cpu_env); break; case DISAS_SWI: - gen_exception_el(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb), - default_exception_el(dc)); + gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); From d6d7f818a9eafeff01d19b70a796bf42248c3690 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: [PATCH 071/180] target/arm: Introduce gen_exception_el_v Split out a common helper function for gen_exception_el and gen_exception_insn_el_v. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-19-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target/arm/translate.c b/target/arm/translate.c index 5a48937ede..fcb6ee648b 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1086,11 +1086,15 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp) s->base.is_jmp = DISAS_NORETURN; } -static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) +static void gen_exception_el_v(int excp, uint32_t syndrome, TCGv_i32 tcg_el) { gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syndrome), - tcg_constant_i32(target_el)); + tcg_constant_i32(syndrome), tcg_el); +} + +static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) +{ + gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el)); } static void gen_exception(DisasContext *s, int excp, uint32_t syndrome) @@ -1107,8 +1111,7 @@ static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, gen_set_condexec(s); gen_set_pc_im(s, pc); } - gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp), - tcg_constant_i32(syn), tcg_el); + gen_exception_el_v(excp, syn, tcg_el); s->base.is_jmp = DISAS_NORETURN; } From eeaf596022233818476bf2d1c7a41011fbba7faa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: [PATCH 072/180] target/arm: Introduce helper_exception_with_syndrome With the helper we can use exception_target_el at runtime, instead of default_exception_el at translate time. While we're at it, remove the DisasContext parameter from gen_exception, as it is no longer used. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-20-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.h | 1 + target/arm/op_helper.c | 10 ++++++++++ target/arm/translate.c | 18 +++++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/target/arm/helper.h b/target/arm/helper.h index db7447d233..07d45faf49 100644 --- a/target/arm/helper.h +++ b/target/arm/helper.h @@ -45,6 +45,7 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(exception_internal, noreturn, env, i32) +DEF_HELPER_3(exception_with_syndrome, noreturn, env, i32, i32) DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32) DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32) DEF_HELPER_2(exception_swstep, noreturn, env, i32) diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 8a6a3b8551..c5bde1cfcc 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -399,6 +399,16 @@ void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp, raise_exception(env, excp, syndrome, target_el); } +/* + * Raise an exception with the specified syndrome register value + * to the default target el. + */ +void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp, + uint32_t syndrome) +{ + raise_exception(env, excp, syndrome, exception_target_el(env)); +} + uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~CPSR_EXEC; diff --git a/target/arm/translate.c b/target/arm/translate.c index fcb6ee648b..81c27e7c70 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1097,9 +1097,10 @@ static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el) gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el)); } -static void gen_exception(DisasContext *s, int excp, uint32_t syndrome) +static void gen_exception(int excp, uint32_t syndrome) { - gen_exception_el(excp, syndrome, default_exception_el(s)); + gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp), + tcg_constant_i32(syndrome)); } static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp, @@ -1123,7 +1124,14 @@ void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp, void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn) { - gen_exception_insn_el(s, pc, excp, syn, default_exception_el(s)); + if (s->aarch64) { + gen_a64_set_pc_im(pc); + } else { + gen_set_condexec(s); + gen_set_pc_im(s, pc); + } + gen_exception(excp, syn); + s->base.is_jmp = DISAS_NORETURN; } static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn) @@ -9766,7 +9774,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) switch (dc->base.is_jmp) { case DISAS_SWI: gen_ss_advance(dc); - gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); + gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_ss_advance(dc); @@ -9835,7 +9843,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) gen_helper_yield(cpu_env); break; case DISAS_SWI: - gen_exception(dc, EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); + gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb)); break; case DISAS_HVC: gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2); From 82303761c6fccfd7b166949149fedae9cee15efd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: [PATCH 073/180] target/arm: Remove default_exception_el This function is no longer used. At the same time, remove DisasContext.secure_routed_to_el3, as it in turn becomes unused. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 5 ----- target/arm/translate.c | 5 ----- target/arm/translate.h | 16 ---------------- 3 files changed, 26 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 4f6181a548..4c64546090 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -14585,11 +14585,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, dc->condjmp = 0; dc->aarch64 = true; - /* If we are coming from secure EL0 in a system with a 32-bit EL3, then - * there is no secure EL1, so we route exceptions to EL3. - */ - dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3); dc->thumb = false; dc->sctlr_b = 0; dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE; diff --git a/target/arm/translate.c b/target/arm/translate.c index 81c27e7c70..6617de775f 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9319,11 +9319,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->condjmp = 0; dc->aarch64 = false; - /* If we are coming from secure EL0 in a system with a 32-bit EL3, then - * there is no secure EL1, so we route exceptions to EL3. - */ - dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3); dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB); dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE; condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC); diff --git a/target/arm/translate.h b/target/arm/translate.h index 850bcdc155..88dc18a034 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -43,8 +43,6 @@ typedef struct DisasContext { int fp_excp_el; /* FP exception EL or 0 if enabled */ int sve_excp_el; /* SVE exception EL or 0 if enabled */ int vl; /* current vector length in bytes */ - /* Flag indicating that exceptions from secure mode are routed to EL3. */ - bool secure_routed_to_el3; bool vfp_enabled; /* FP enabled via FPSCR.EN */ int vec_len; int vec_stride; @@ -199,20 +197,6 @@ static inline int get_mem_index(DisasContext *s) return arm_to_core_mmu_idx(s->mmu_idx); } -/* Function used to determine the target exception EL when otherwise not known - * or default. - */ -static inline int default_exception_el(DisasContext *s) -{ - /* If we are coming from secure EL0 in a system with a 32-bit EL3, then - * there is no secure EL1, so we route exceptions to EL3. Otherwise, - * exceptions can only be routed to ELs above 1, so we target the higher of - * 1 or the current EL. - */ - return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3) - ? 3 : MAX(1, s->current_el); -} - static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn) { /* We don't need to save all of the syndrome so we mask and shift From 04eacf6e79e7489579d188acbfe3046874d7ec3e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:34 +0100 Subject: [PATCH 074/180] target/arm: Create raise_exception_debug Handle the debug vs current el exception test in one place. Leave EXCP_BKPT alone, since that treats debug < current differently. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-22-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/debug_helper.c | 44 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index a3a1b98de2..26004df99b 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,6 +12,26 @@ #include "exec/helper-proto.h" +/* + * Raise an exception to the debug target el. + * Modify syndrome to indicate when origin and target EL are the same. + */ +G_NORETURN static void +raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome) +{ + int debug_el = arm_debug_target_el(env); + int cur_el = arm_current_el(env); + + /* + * If singlestep is targeting a lower EL than the current one, then + * DisasContext.ss_active must be false and we can never get here. + * Similarly for watchpoint and breakpoint matches. + */ + assert(debug_el >= cur_el); + syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT; + raise_exception(env, excp, syndrome, debug_el); +} + /* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */ static bool aa64_generate_debug_exceptions(CPUARMState *env) { @@ -418,19 +438,16 @@ void arm_debug_excp_handler(CPUState *cs) if (wp_hit) { if (wp_hit->flags & BP_CPU) { bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0; - bool same_el = arm_debug_target_el(env) == arm_current_el(env); cs->watchpoint_hit = NULL; env->exception.fsr = arm_debug_exception_fsr(env); env->exception.vaddress = wp_hit->hitaddr; - raise_exception(env, EXCP_DATA_ABORT, - syn_watchpoint(same_el, 0, wnr), - arm_debug_target_el(env)); + raise_exception_debug(env, EXCP_DATA_ABORT, + syn_watchpoint(0, 0, wnr)); } } else { uint64_t pc = is_a64(env) ? env->pc : env->regs[15]; - bool same_el = (arm_debug_target_el(env) == arm_current_el(env)); /* * (1) GDB breakpoints should be handled first. @@ -450,9 +467,7 @@ void arm_debug_excp_handler(CPUState *cs) * exception/security level. */ env->exception.vaddress = 0; - raise_exception(env, EXCP_PREFETCH_ABORT, - syn_breakpoint(same_el), - arm_debug_target_el(env)); + raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0)); } } @@ -489,18 +504,7 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome) void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome) { - int debug_el = arm_debug_target_el(env); - int cur_el = arm_current_el(env); - - /* - * If singlestep is targeting a lower EL than the current one, then - * DisasContext.ss_active must be false and we can never get here. - */ - assert(debug_el >= cur_el); - if (debug_el == cur_el) { - syndrome |= 1 << ARM_EL_EC_SHIFT; - } - raise_exception(env, EXCP_UDEF, syndrome, debug_el); + raise_exception_debug(env, EXCP_UDEF, syndrome); } #if !defined(CONFIG_USER_ONLY) From 38e8a13c116b114c100f488dc6a32c9c9df3ccd0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: [PATCH 075/180] target/arm: Move arm_debug_target_el to debug_helper.c This function is no longer used outside debug_helper.c. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-23-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 21 --------------------- target/arm/debug_helper.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 719613ad9e..161ac9fa2e 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -2986,27 +2986,6 @@ typedef enum ARMASIdx { ARMASIdx_TagS = 3, } ARMASIdx; -/* Return the Exception Level targeted by debug exceptions. */ -static inline int arm_debug_target_el(CPUARMState *env) -{ - bool secure = arm_is_secure(env); - bool route_to_el2 = false; - - if (arm_is_el2_enabled(env)) { - route_to_el2 = env->cp15.hcr_el2 & HCR_TGE || - env->cp15.mdcr_el2 & MDCR_TDE; - } - - if (route_to_el2) { - return 2; - } else if (arm_feature(env, ARM_FEATURE_EL3) && - !arm_el_is_aa64(env, 3) && secure) { - return 3; - } else { - return 1; - } -} - static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu) { /* If all the CLIDR.Ctypem bits are 0 there are no caches, and diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 26004df99b..b18a6bd3a2 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -12,6 +12,27 @@ #include "exec/helper-proto.h" +/* Return the Exception Level targeted by debug exceptions. */ +static int arm_debug_target_el(CPUARMState *env) +{ + bool secure = arm_is_secure(env); + bool route_to_el2 = false; + + if (arm_is_el2_enabled(env)) { + route_to_el2 = env->cp15.hcr_el2 & HCR_TGE || + env->cp15.mdcr_el2 & MDCR_TDE; + } + + if (route_to_el2) { + return 2; + } else if (arm_feature(env, ARM_FEATURE_EL3) && + !arm_el_is_aa64(env, 3) && secure) { + return 3; + } else { + return 1; + } +} + /* * Raise an exception to the debug target el. * Modify syndrome to indicate when origin and target EL are the same. From 02e1de14bcf7cc686bf4f542b36033521f22d1ee Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: [PATCH 076/180] target/arm: Fix Secure PL1 tests in fp_exception_el We were using arm_is_secure and is_a64, which are tests against the current EL, as opposed to arm_el_is_aa64 and arm_is_secure_below_el3, which can be applied to a different EL than current. Consolidate the two tests. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20220609202901.1177572-24-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 2b2c1998fd..b95aa53474 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10879,27 +10879,22 @@ int fp_exception_el(CPUARMState *env, int cur_el) int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN); switch (fpen) { + case 1: + if (cur_el != 0) { + break; + } + /* fall through */ case 0: case 2: - if (cur_el == 0 || cur_el == 1) { - /* Trap to PL1, which might be EL1 or EL3 */ - if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) { - return 3; - } - return 1; - } - if (cur_el == 3 && !is_a64(env)) { - /* Secure PL1 running at EL3 */ + /* Trap from Secure PL0 or PL1 to Secure PL1. */ + if (!arm_el_is_aa64(env, 3) + && (cur_el == 3 || arm_is_secure_below_el3(env))) { return 3; } - break; - case 1: - if (cur_el == 0) { + if (cur_el <= 1) { return 1; } break; - case 3: - break; } } From 284ad5e70c41e02553aeb2c1eaf4e828499cb315 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: [PATCH 077/180] tests/qtest: Reduce npcm7xx_sdhci test image size Creating 1GB image for a simple qtest is unnecessary and could lead to failures. We reduce the image size to 1MB to reduce the test overhead. Signed-off-by: Hao Wu Message-id: 20220609214125.4192212-1-wuhaotsh@google.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- tests/qtest/npcm7xx_sdhci-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c index aa35a77e8d..5d68540e52 100644 --- a/tests/qtest/npcm7xx_sdhci-test.c +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -24,7 +24,7 @@ #define NPCM7XX_REG_SIZE 0x100 #define NPCM7XX_MMC_BA 0xF0842000 #define NPCM7XX_BLK_SIZE 512 -#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 20) char *sd_path; From bfe43e3d14687f2149451f278671c2c552d96b0a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: [PATCH 078/180] target/arm: Adjust format test in scr_write Because reset always initializes the AA64 version, SCR_EL3, test the mode of EL3 instead of the type of the cpreg. Signed-off-by: Richard Henderson Message-id: 20220609214657.1217913-2-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/helper.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index b95aa53474..ff9f9fe6ee 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1738,12 +1738,14 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) uint32_t valid_mask = 0x3fff; ARMCPU *cpu = env_archcpu(env); - if (ri->state == ARM_CP_STATE_AA64) { - if (arm_feature(env, ARM_FEATURE_AARCH64) && - !cpu_isar_feature(aa64_aa32_el1, cpu)) { - value |= SCR_FW | SCR_AW; /* these two bits are RES1. */ - } - valid_mask &= ~SCR_NET; + /* + * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always + * passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64. + * Instead, choose the format based on the mode of EL3. + */ + if (arm_el_is_aa64(env, 3)) { + value |= SCR_FW | SCR_AW; /* RES1 */ + valid_mask &= ~SCR_NET; /* RES0 */ if (cpu_isar_feature(aa64_ras, cpu)) { valid_mask |= SCR_TERR; From 6bcbb07af6a601b2521b07a639861218fbf0c87e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 10 Jun 2022 14:32:35 +0100 Subject: [PATCH 079/180] target/arm: SCR_EL3.RW is RAO/WI without AArch32 EL[12] Since DDI0487F.a, the RW bit is RAO/WI. When specifically targeting such a cpu, e.g. cortex-a76, it is legitimate to ignore the bit within the secure monitor. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1062 Signed-off-by: Richard Henderson Message-id: 20220609214657.1217913-3-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/cpu.h | 5 +++++ target/arm/helper.c | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 161ac9fa2e..df677b2d5d 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3854,6 +3854,11 @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; } +static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2; +} + static inline bool isar_feature_aa64_ras(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0; diff --git a/target/arm/helper.c b/target/arm/helper.c index ff9f9fe6ee..6457e6301c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1747,6 +1747,10 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) value |= SCR_FW | SCR_AW; /* RES1 */ valid_mask &= ~SCR_NET; /* RES0 */ + if (!cpu_isar_feature(aa64_aa32_el1, cpu) && + !cpu_isar_feature(aa64_aa32_el2, cpu)) { + value |= SCR_RW; /* RAO/WI */ + } if (cpu_isar_feature(aa64_ras, cpu)) { valid_mask |= SCR_TERR; } From ebf1b4cbb8ec357f5280dc8895548519b65a2d71 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 10 Jun 2022 14:32:36 +0100 Subject: [PATCH 080/180] gdbstub: Don't use GDB syscalls if no GDB is attached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In two places in gdbstub.c we look at gdbserver_state.init to decide whether we're going to do a semihosting syscall via the gdb remote protocol: * when setting up, if the user didn't explicitly select either native semihosting or gdb semihosting, we autoselect, with the intended behaviour "use gdb if gdb is connected" * when the semihosting layer attempts to do a syscall via gdb, we silently ignore it if the gdbstub wasn't actually set up However, if the user's commandline sets up the gdbstub but tells QEMU to start rather than waiting for a GDB to connect (eg using '-s' but not '-S'), then we will have gdbserver_state.init true but no actual connection; an attempt to use gdb syscalls will then crash because we try to use gdbserver_state.c_cpu when it hasn't been set up: #0 0x00007ffff6803ba8 in qemu_cpu_kick (cpu=0x0) at ../../softmmu/cpus.c:457 #1 0x00007ffff6c03913 in gdb_do_syscallv (cb=0x7ffff6c19944 , fmt=0x7ffff7573b7e "", va=0x7ffff56294c0) at ../../gdbstub.c:2946 #2 0x00007ffff6c19c3a in common_semi_gdb_syscall (cs=0x7ffff83fe060, cb=0x7ffff6c19944 , fmt=0x7ffff7573b75 "isatty,%x") at ../../semihosting/arm-compat-semi.c:494 #3 0x00007ffff6c1a064 in gdb_isattyfn (cs=0x7ffff83fe060, gf=0x7ffff86a3690) at ../../semihosting/arm-compat-semi.c:636 #4 0x00007ffff6c1b20f in do_common_semihosting (cs=0x7ffff83fe060) at ../../semihosting/arm-compat-semi.c:967 #5 0x00007ffff693a037 in handle_semihosting (cs=0x7ffff83fe060) at ../../target/arm/helper.c:10316 You can probably also get into this state via some odd corner cases involving connecting a GDB and then telling it to detach from all the vCPUs. Abstract out the test into a new gdb_attached() function which returns true only if there's actually a GDB connected to the debug stub and attached to at least one vCPU. Reported-by: Liviu Ionescu Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Luc Michel Message-id: 20220526190053.521505-2-peter.maydell@linaro.org --- gdbstub.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index a3ff8702ce..88a34c8f52 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -443,6 +443,15 @@ static int get_char(void) } #endif +/* + * Return true if there is a GDB currently connected to the stub + * and attached to a CPU + */ +static bool gdb_attached(void) +{ + return gdbserver_state.init && gdbserver_state.c_cpu; +} + static enum { GDB_SYS_UNKNOWN, GDB_SYS_ENABLED, @@ -464,8 +473,7 @@ int use_gdb_syscalls(void) /* -semihosting-config target=auto */ /* On the first call check if gdb is connected and remember. */ if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { - gdb_syscall_mode = gdbserver_state.init ? - GDB_SYS_ENABLED : GDB_SYS_DISABLED; + gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED; } return gdb_syscall_mode == GDB_SYS_ENABLED; } @@ -2886,7 +2894,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va) target_ulong addr; uint64_t i64; - if (!gdbserver_state.init) { + if (!gdb_attached()) { return; } From 90c072e063737e9e8f431489bbd334452f89056e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 10 Jun 2022 14:32:36 +0100 Subject: [PATCH 081/180] semihosting/config: Merge --semihosting-config option groups Currently we mishandle the --semihosting-config option if the user specifies it on the command line more than once. For example with: --semihosting-config target=gdb --semihosting-config arg=foo,arg=bar the function qemu_semihosting_config_options() is called twice, once for each argument. But that function expects to be called only once, and it always unconditionally sets the semihosting.enabled, semihost_chardev and semihosting.target variables. This means that if any of those options were set anywhere except the last --semihosting-config option on the command line, those settings are ignored. In the example above, 'target=gdb' in the first option is overridden by an implied default 'target=auto' in the second. The QemuOptsList machinery has a flag for handling this kind of "option group is setting global state": by setting .merge_lists = true; we make the machinery merge all the --semihosting-config arguments the user passes into a single set of options and call our qemu_semihosting_config_options() just once. Signed-off-by: Peter Maydell Reviewed-by: Luc Michel Message-id: 20220526190053.521505-3-peter.maydell@linaro.org --- semihosting/config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/semihosting/config.c b/semihosting/config.c index 50d82108e6..3afacf54ab 100644 --- a/semihosting/config.c +++ b/semihosting/config.c @@ -27,6 +27,7 @@ QemuOptsList qemu_semihosting_config_opts = { .name = "semihosting-config", + .merge_lists = true, .implied_opt_name = "enable", .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head), .desc = { From 1ed771b21cdb86486bd8b840d1b91bb1cd9d945e Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 31 Jan 2022 13:37:24 -0700 Subject: [PATCH 082/180] bsd-user/freebsd/os-syscall.c: lock_iovec lock_iovec will lock an I/O vec and the memory to which it refers and create a iovec in the host space that refers to it, with full error unwinding. Add helper_iovec_unlock to unlock the partially locked iovec in case there's an error. The code will be used in iovec_unlock when that is committed. Note: memory handling likely could be rewritten to use q_autofree. That will be explored in the future since what we have now works well enough. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/freebsd/os-syscall.c | 102 ++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index d272478e7b..67851937a8 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -73,6 +73,108 @@ bool is_error(abi_long ret) return (abi_ulong)ret >= (abi_ulong)(-4096); } +/* + * Unlocks a iovec. Unlike unlock_iovec, it assumes the tvec array itself is + * already locked from target_addr. It will be unlocked as well as all the iovec + * elements. + */ +static void helper_unlock_iovec(struct target_iovec *target_vec, + abi_ulong target_addr, struct iovec *vec, + int count, int copy) +{ + for (int i = 0; i < count; i++) { + abi_ulong base = tswapal(target_vec[i].iov_base); + + if (vec[i].iov_base) { + unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); + } + } + unlock_user(target_vec, target_addr, 0); +} + +struct iovec *lock_iovec(int type, abi_ulong target_addr, + int count, int copy) +{ + struct target_iovec *target_vec; + struct iovec *vec; + abi_ulong total_len, max_len; + int i; + int err = 0; + + if (count == 0) { + errno = 0; + return NULL; + } + if (count < 0 || count > IOV_MAX) { + errno = EINVAL; + return NULL; + } + + vec = g_try_new0(struct iovec, count); + if (vec == NULL) { + errno = ENOMEM; + return NULL; + } + + target_vec = lock_user(VERIFY_READ, target_addr, + count * sizeof(struct target_iovec), 1); + if (target_vec == NULL) { + err = EFAULT; + goto fail2; + } + + max_len = 0x7fffffff & MIN(TARGET_PAGE_MASK, PAGE_MASK); + total_len = 0; + + for (i = 0; i < count; i++) { + abi_ulong base = tswapal(target_vec[i].iov_base); + abi_long len = tswapal(target_vec[i].iov_len); + + if (len < 0) { + err = EINVAL; + goto fail; + } else if (len == 0) { + /* Zero length pointer is ignored. */ + vec[i].iov_base = 0; + } else { + vec[i].iov_base = lock_user(type, base, len, copy); + /* + * If the first buffer pointer is bad, this is a fault. But + * subsequent bad buffers will result in a partial write; this is + * realized by filling the vector with null pointers and zero + * lengths. + */ + if (!vec[i].iov_base) { + if (i == 0) { + err = EFAULT; + goto fail; + } else { + /* + * Fail all the subsequent addresses, they are already + * zero'd. + */ + goto out; + } + } + if (len > max_len - total_len) { + len = max_len - total_len; + } + } + vec[i].iov_len = len; + total_len += len; + } +out: + unlock_user(target_vec, target_addr, 0); + return vec; + +fail: + helper_unlock_iovec(target_vec, target_addr, vec, i, copy); +fail2: + g_free(vec); + errno = err; + return NULL; +} + /* * do_syscall() should always have a single exit point at the end so that * actions, such as logging of syscall results, can be performed. All errnos From 883808d84895804a3a98e211001c3edf42355b66 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 31 Jan 2022 13:40:36 -0700 Subject: [PATCH 083/180] bsd-user/freebsd/os-syscall.c: unlock_iovec Releases the references to the iovec created by lock_iovec. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/freebsd/os-syscall.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 67851937a8..52093d479d 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -175,6 +175,20 @@ fail2: return NULL; } +void unlock_iovec(struct iovec *vec, abi_ulong target_addr, + int count, int copy) +{ + struct target_iovec *target_vec; + + target_vec = lock_user(VERIFY_READ, target_addr, + count * sizeof(struct target_iovec), 1); + if (target_vec) { + helper_unlock_iovec(target_vec, target_addr, vec, count, copy); + } + + g_free(vec); +} + /* * do_syscall() should always have a single exit point at the end so that * actions, such as logging of syscall results, can be performed. All errnos From db69788703c5fdc590c96815c0eeeebc6a32d3e7 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 31 Jan 2022 13:55:12 -0700 Subject: [PATCH 084/180] bsd-user/freebsd/os-syscall.c: Tracing and error boilerplate Add in the tracing and this system call not implemented boilerplate. Do this by moving the guts of do_freebsd_syscall to freebsd_syscall. Put the tracing in the wrapper function. Since freebsd_syscall is a singleton static function, it will almost certainly be inlined. Fix comments that referred to do_syscall since that was renamed some tie ago. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/freebsd/os-syscall.c | 44 +++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 52093d479d..1c4c9983f1 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -190,16 +190,52 @@ void unlock_iovec(struct iovec *vec, abi_ulong target_addr, } /* - * do_syscall() should always have a single exit point at the end so that - * actions, such as logging of syscall results, can be performed. All errnos - * that do_syscall() returns must be -TARGET_. + * All errnos that freebsd_syscall() returns must be -TARGET_. + */ +static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5, abi_long arg6, abi_long arg7, + abi_long arg8) +{ + abi_long ret; + + switch (num) { + default: + qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num); + ret = -TARGET_ENOSYS; + break; + } + + return ret; +} + +/* + * do_freebsd_syscall() should always have a single exit point at the end so + * that actions, such as logging of syscall results, can be performed. This + * as a wrapper around freebsd_syscall() so that actually happens. Since + * that is a singleton, modern compilers will inline it anyway... */ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8) { - return 0; + CPUState *cpu = env_cpu(cpu_env); + int ret; + + trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + if (do_strace) { + print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + } + + ret = freebsd_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6, + arg7, arg8); + if (do_strace) { + print_freebsd_syscall_ret(num, ret); + } + trace_guest_user_syscall_ret(cpu, num, ret); + + return ret; } void syscall_init(void) From 80da1b00886782520286e26f39ce8e21c1855072 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 31 Jan 2022 16:10:10 -0700 Subject: [PATCH 085/180] bsd-user/bsd-file.h: Add implementations for read, pread, readv and preadv Implement do_bsd_{read,pread,readv,preadv}. Connect them to the system call table. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/bsd-file.h | 79 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 28 +++++++++++++ 2 files changed, 107 insertions(+) diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h index a6bff3b8c2..839f8c5c55 100644 --- a/bsd-user/bsd-file.h +++ b/bsd-user/bsd-file.h @@ -27,4 +27,83 @@ extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count, extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count, int copy); +ssize_t safe_read(int fd, void *buf, size_t nbytes); +ssize_t safe_pread(int fd, void *buf, size_t nbytes, off_t offset); +ssize_t safe_readv(int fd, const struct iovec *iov, int iovcnt); +ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); + +/* read(2) */ +static abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_read(arg1, p, arg3)); + unlock_user(p, arg2, ret); + + return ret; +} + +/* pread(2) */ +static abi_long do_bsd_pread(void *cpu_env, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (p == NULL) { + return -TARGET_EFAULT; + } + if (regpairs_aligned(cpu_env) != 0) { + arg4 = arg5; + arg5 = arg6; + } + ret = get_errno(safe_pread(arg1, p, arg3, target_arg64(arg4, arg5))); + unlock_user(p, arg2, ret); + + return ret; +} + +/* readv(2) */ +static abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); + + if (vec != NULL) { + ret = get_errno(safe_readv(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 1); + } else { + ret = -host_to_target_errno(errno); + } + + return ret; +} + +/* preadv(2) */ +static abi_long do_bsd_preadv(void *cpu_env, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) +{ + abi_long ret; + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 1); + + if (vec != NULL) { + if (regpairs_aligned(cpu_env) != 0) { + arg4 = arg5; + arg5 = arg6; + } + ret = get_errno(safe_preadv(arg1, vec, arg3, target_arg64(arg4, arg5))); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } + + return ret; +} + #endif /* BSD_FILE_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 1c4c9983f1..8ca92f2985 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -42,6 +42,14 @@ #include "bsd-file.h" +/* I/O */ +safe_syscall3(ssize_t, read, int, fd, void *, buf, size_t, nbytes); +safe_syscall4(ssize_t, pread, int, fd, void *, buf, size_t, nbytes, off_t, + offset); +safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt); +safe_syscall4(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt, + off_t, offset); + void target_set_brk(abi_ulong new_brk) { } @@ -200,6 +208,26 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long ret; switch (num) { + + /* + * File system calls. + */ + case TARGET_FREEBSD_NR_read: /* read(2) */ + ret = do_bsd_read(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pread: /* pread(2) */ + ret = do_bsd_pread(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); + break; + + case TARGET_FREEBSD_NR_readv: /* readv(2) */ + ret = do_bsd_readv(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_preadv: /* preadv(2) */ + ret = do_bsd_preadv(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); + break; + default: qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num); ret = -TARGET_ENOSYS; From 770d8abae736535c9bff17ee82bd48aea0e5fea4 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 31 Jan 2022 16:34:03 -0700 Subject: [PATCH 086/180] bsd-user/bsd-file.h: Meat of the write system calls Implement write, writev, pwrite and pwritev and connect them to the system call dispatch routine. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/bsd-file.h | 84 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 22 +++++++++ 2 files changed, 106 insertions(+) diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h index 839f8c5c55..e9e2c85eb6 100644 --- a/bsd-user/bsd-file.h +++ b/bsd-user/bsd-file.h @@ -32,6 +32,11 @@ ssize_t safe_pread(int fd, void *buf, size_t nbytes, off_t offset); ssize_t safe_readv(int fd, const struct iovec *iov, int iovcnt); ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); +ssize_t safe_write(int fd, void *buf, size_t nbytes); +ssize_t safe_pwrite(int fd, void *buf, size_t nbytes, off_t offset); +ssize_t safe_writev(int fd, const struct iovec *iov, int iovcnt); +ssize_t safe_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); + /* read(2) */ static abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3) { @@ -106,4 +111,83 @@ static abi_long do_bsd_preadv(void *cpu_env, abi_long arg1, return ret; } +/* write(2) */ +static abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long nbytes, ret; + void *p; + + /* nbytes < 0 implies that it was larger than SIZE_MAX. */ + nbytes = arg3; + if (nbytes < 0) { + return -TARGET_EINVAL; + } + p = lock_user(VERIFY_READ, arg2, nbytes, 1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_write(arg1, p, arg3)); + unlock_user(p, arg2, 0); + + return ret; +} + +/* pwrite(2) */ +static abi_long do_bsd_pwrite(void *cpu_env, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) +{ + abi_long ret; + void *p; + + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (p == NULL) { + return -TARGET_EFAULT; + } + if (regpairs_aligned(cpu_env) != 0) { + arg4 = arg5; + arg5 = arg6; + } + ret = get_errno(safe_pwrite(arg1, p, arg3, target_arg64(arg4, arg5))); + unlock_user(p, arg2, 0); + + return ret; +} + +/* writev(2) */ +static abi_long do_bsd_writev(abi_long arg1, abi_long arg2, abi_long arg3) +{ + abi_long ret; + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + + if (vec != NULL) { + ret = get_errno(safe_writev(arg1, vec, arg3)); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } + + return ret; +} + +/* pwritev(2) */ +static abi_long do_bsd_pwritev(void *cpu_env, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) +{ + abi_long ret; + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); + + if (vec != NULL) { + if (regpairs_aligned(cpu_env) != 0) { + arg4 = arg5; + arg5 = arg6; + } + ret = get_errno(safe_pwritev(arg1, vec, arg3, target_arg64(arg4, arg5))); + unlock_iovec(vec, arg2, arg3, 0); + } else { + ret = -host_to_target_errno(errno); + } + + return ret; +} + #endif /* BSD_FILE_H */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 8ca92f2985..3a33d54fa4 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -50,6 +50,13 @@ safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt); safe_syscall4(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt, off_t, offset); +safe_syscall3(ssize_t, write, int, fd, void *, buf, size_t, nbytes); +safe_syscall4(ssize_t, pwrite, int, fd, void *, buf, size_t, nbytes, off_t, + offset); +safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt); +safe_syscall4(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt, + off_t, offset); + void target_set_brk(abi_ulong new_brk) { } @@ -226,6 +233,21 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_FREEBSD_NR_preadv: /* preadv(2) */ ret = do_bsd_preadv(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); + + case TARGET_FREEBSD_NR_write: /* write(2) */ + ret = do_bsd_write(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pwrite: /* pwrite(2) */ + ret = do_bsd_pwrite(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); + break; + + case TARGET_FREEBSD_NR_writev: /* writev(2) */ + ret = do_bsd_writev(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_pwritev: /* pwritev(2) */ + ret = do_bsd_pwritev(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); break; default: From 9554d33076771dcc284dc3fa1a87cd0e24b91d9d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 31 Jan 2022 17:03:30 -0700 Subject: [PATCH 087/180] bsd-user/freebsd/os-syscall.c: Implement exit Implement the exit system call. Bring in bsd-proc.h to contain all the process system call implementation and helper routines. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Richard Henderson Reviewed-by: Kyle Evans --- bsd-user/bsd-proc.h | 42 +++++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-syscall.c | 7 ++++++ 2 files changed, 49 insertions(+) create mode 100644 bsd-user/bsd-proc.h diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h new file mode 100644 index 0000000000..68b66e571d --- /dev/null +++ b/bsd-user/bsd-proc.h @@ -0,0 +1,42 @@ +/* + * process related system call shims and definitions + * + * Copyright (c) 2013-2014 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef BSD_PROC_H_ +#define BSD_PROC_H_ + +#include +#include +#include +#include +#include + +/* exit(2) */ +static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1) +{ +#ifdef TARGET_GPROF + _mcleanup(); +#endif + gdb_exit(arg1); + qemu_plugin_user_exit(); + _exit(arg1); + + return 0; +} + +#endif /* !BSD_PROC_H_ */ diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c index 3a33d54fa4..71aa0d38e0 100644 --- a/bsd-user/freebsd/os-syscall.c +++ b/bsd-user/freebsd/os-syscall.c @@ -41,6 +41,7 @@ #include "user/syscall-trace.h" #include "bsd-file.h" +#include "bsd-proc.h" /* I/O */ safe_syscall3(ssize_t, read, int, fd, void *, buf, size_t, nbytes); @@ -215,6 +216,12 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long ret; switch (num) { + /* + * process system calls + */ + case TARGET_FREEBSD_NR_exit: /* exit(2) */ + ret = do_bsd_exit(cpu_env, arg1); + break; /* * File system calls. From a6bc80f7b11188d86010a2d511498fba2fe4b629 Mon Sep 17 00:00:00 2001 From: Marcin Nowakowski Date: Wed, 26 May 2021 11:35:06 +0200 Subject: [PATCH 088/180] target/mips: Fix WatchHi.M handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bit 31 (M) of WatchHiN register is a read-only register indicating whether the next WatchHi register is present. It must not be reset during user writes to the register. Signed-off-by: Marcin Nowakowski Reviewed-by: David Daney Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220511212953.74738-1-philmd@fungible.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- target/mips/cpu.c | 2 +- target/mips/cpu.h | 1 + target/mips/tcg/sysemu/cp0_helper.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index ad74fbe636..c15c955367 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -305,7 +305,7 @@ static void mips_cpu_reset(DeviceState *dev) for (i = 0; i < 7; i++) { env->CP0_WatchLo[i] = 0; - env->CP0_WatchHi[i] = 0x80000000; + env->CP0_WatchHi[i] = 1 << CP0WH_M; } env->CP0_WatchLo[7] = 0; env->CP0_WatchHi[7] = 0; diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 5335ac10a3..6b6b8776d1 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1005,6 +1005,7 @@ typedef struct CPUArchState { */ uint64_t CP0_WatchHi[8]; #define CP0WH_ASID 16 +#define CP0WH_M 31 /* * CP0 Register 20 */ diff --git a/target/mips/tcg/sysemu/cp0_helper.c b/target/mips/tcg/sysemu/cp0_helper.c index aae2af6ecc..5da1124589 100644 --- a/target/mips/tcg/sysemu/cp0_helper.c +++ b/target/mips/tcg/sysemu/cp0_helper.c @@ -1396,10 +1396,11 @@ void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel) void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel) { uint64_t mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID); + uint64_t m_bit = env->CP0_WatchHi[sel] & (1 << CP0WH_M); /* read-only */ if ((env->CP0_Config5 >> CP0C5_MI) & 1) { mask |= 0xFFFFFFFF00000000ULL; /* MMID */ } - env->CP0_WatchHi[sel] = arg1 & mask; + env->CP0_WatchHi[sel] = m_bit | (arg1 & mask); env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7); } From 954d1658bde4e756e305334836fd86d398803242 Mon Sep 17 00:00:00 2001 From: Ni Hui Date: Tue, 3 May 2022 21:07:05 +0800 Subject: [PATCH 089/180] target/mips: Fix SAT_S trans helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the SAT_S and SAT_U trans helper confusion. Fixes: 4701d23aef ("target/mips: Convert MSA BIT instruction format to decodetree") Signed-off-by: Ni Hui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220503130708.272850-1-shuizhuyuanluo@126.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/msa_translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/tcg/msa_translate.c b/target/mips/tcg/msa_translate.c index 7576b3ed86..76307102f2 100644 --- a/target/mips/tcg/msa_translate.c +++ b/target/mips/tcg/msa_translate.c @@ -399,7 +399,7 @@ TRANS(BSETI, trans_msa_bit, gen_helper_msa_bseti_df); TRANS(BNEGI, trans_msa_bit, gen_helper_msa_bnegi_df); TRANS(BINSLI, trans_msa_bit, gen_helper_msa_binsli_df); TRANS(BINSRI, trans_msa_bit, gen_helper_msa_binsri_df); -TRANS(SAT_S, trans_msa_bit, gen_helper_msa_sat_u_df); +TRANS(SAT_S, trans_msa_bit, gen_helper_msa_sat_s_df); TRANS(SAT_U, trans_msa_bit, gen_helper_msa_sat_u_df); TRANS(SRARI, trans_msa_bit, gen_helper_msa_srari_df); TRANS(SRLRI, trans_msa_bit, gen_helper_msa_srlri_df); From 7fc235c67f6c136ceba2305bcf2609c46a74620d Mon Sep 17 00:00:00 2001 From: Ni Hui Date: Tue, 3 May 2022 21:07:06 +0800 Subject: [PATCH 090/180] target/mips: Fix df_extract_val() and df_extract_df() dfe lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Actually look into dfe structure data so that df_extract_val() and df_extract_df() can return immediate and datafield other than BYTE. Fixes: 4701d23aef ("target/mips: Convert MSA BIT instruction format to decodetree") Signed-off-by: Ni Hui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220503130708.272850-2-shuizhuyuanluo@126.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/msa_translate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/mips/tcg/msa_translate.c b/target/mips/tcg/msa_translate.c index 76307102f2..aa45bae0aa 100644 --- a/target/mips/tcg/msa_translate.c +++ b/target/mips/tcg/msa_translate.c @@ -68,8 +68,8 @@ struct dfe { static int df_extract_val(DisasContext *ctx, int x, const struct dfe *s) { for (unsigned i = 0; i < 4; i++) { - if (extract32(x, s->start, s->length) == s->mask) { - return extract32(x, 0, s->start); + if (extract32(x, s[i].start, s[i].length) == s[i].mask) { + return extract32(x, 0, s[i].start); } } return -1; @@ -82,7 +82,7 @@ static int df_extract_val(DisasContext *ctx, int x, const struct dfe *s) static int df_extract_df(DisasContext *ctx, int x, const struct dfe *s) { for (unsigned i = 0; i < 4; i++) { - if (extract32(x, s->start, s->length) == s->mask) { + if (extract32(x, s[i].start, s[i].length) == s[i].mask) { return i; } } From 4b532b4f2be28525fd181e43afe13416c462b135 Mon Sep 17 00:00:00 2001 From: Ni Hui Date: Tue, 3 May 2022 21:07:07 +0800 Subject: [PATCH 091/180] target/mips: Fix msa checking condition in trans_msa_elm_fn() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix issue that condition of check_msa_enabled(ctx) is reversed that causes segfault when msa elm_fn op encountered. Fixes: 2f2745c81a ("target/mips: Convert MSA COPY_U opcode to decodetree") Fixes: 97fe675519 ("target/mips: Convert MSA COPY_S and INSERT opcodes to decodetree") Signed-off-by: Ni Hui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220503130708.272850-3-shuizhuyuanluo@126.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/msa_translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/tcg/msa_translate.c b/target/mips/tcg/msa_translate.c index aa45bae0aa..92ccc6f921 100644 --- a/target/mips/tcg/msa_translate.c +++ b/target/mips/tcg/msa_translate.c @@ -599,7 +599,7 @@ static bool trans_msa_elm_fn(DisasContext *ctx, arg_msa_elm_df *a, return false; } - if (check_msa_enabled(ctx)) { + if (!check_msa_enabled(ctx)) { return true; } From ead0bf0d3349522e9e496a2d3bfe344fafc584dc Mon Sep 17 00:00:00 2001 From: Ni Hui Date: Tue, 3 May 2022 21:07:08 +0800 Subject: [PATCH 092/180] target/mips: Do not treat msa INSERT as NOP when wd is zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only for msa COPY_U/COPY_S with wd zero, we treat it as NOP. Move this special rule into COPY_U and COPY_S trans function. Fixes: 97fe675519 ("target/mips: Convert MSA COPY_S and INSERT opcodes to decodetree") Signed-off-by: Ni Hui Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220503130708.272850-4-shuizhuyuanluo@126.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/msa_translate.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/target/mips/tcg/msa_translate.c b/target/mips/tcg/msa_translate.c index 92ccc6f921..0b3dd0957c 100644 --- a/target/mips/tcg/msa_translate.c +++ b/target/mips/tcg/msa_translate.c @@ -603,11 +603,6 @@ static bool trans_msa_elm_fn(DisasContext *ctx, arg_msa_elm_df *a, return true; } - if (a->wd == 0) { - /* Treat as NOP. */ - return true; - } - gen_msa_elm[a->df](cpu_env, tcg_constant_i32(a->wd), tcg_constant_i32(a->ws), @@ -624,6 +619,11 @@ static bool trans_msa_elm_fn(DisasContext *ctx, arg_msa_elm_df *a, static bool trans_COPY_U(DisasContext *ctx, arg_msa_elm_df *a) { + if (a->wd == 0) { + /* Treat as NOP. */ + return true; + } + static gen_helper_piii * const gen_msa_copy_u[4] = { gen_helper_msa_copy_u_b, gen_helper_msa_copy_u_h, NULL_IF_MIPS32(gen_helper_msa_copy_u_w), NULL @@ -634,6 +634,11 @@ static bool trans_COPY_U(DisasContext *ctx, arg_msa_elm_df *a) static bool trans_COPY_S(DisasContext *ctx, arg_msa_elm_df *a) { + if (a->wd == 0) { + /* Treat as NOP. */ + return true; + } + static gen_helper_piii * const gen_msa_copy_s[4] = { gen_helper_msa_copy_s_b, gen_helper_msa_copy_s_h, gen_helper_msa_copy_s_w, NULL_IF_MIPS32(gen_helper_msa_copy_s_d) From 857816a42b8436021c00d48ab71366aef561be3c Mon Sep 17 00:00:00 2001 From: Ni Hui Date: Wed, 4 May 2022 10:33:19 +0800 Subject: [PATCH 093/180] target/mips: Fix store adress of high 64bit in helper_msa_st_b() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fix the issue that helper_msa_st_b() write high 64bit data to where the low 64bit resides, leaving high 64bit undefined. Fixes: 68ad9260e0 ("target/mips: Use 8-byte memory ops for msa load/store") Signed-off-by: Ni Hui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504023319.12923-1-shuizhuyuanluo@126.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/msa_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c index 4dde5d639a..736283e2af 100644 --- a/target/mips/tcg/msa_helper.c +++ b/target/mips/tcg/msa_helper.c @@ -8329,7 +8329,7 @@ void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, /* Store 8 bytes at a time. Vector element ordering makes this LE. */ cpu_stq_le_data_ra(env, addr + 0, pwd->d[0], ra); - cpu_stq_le_data_ra(env, addr + 0, pwd->d[1], ra); + cpu_stq_le_data_ra(env, addr + 8, pwd->d[1], ra); } void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, From 1d29f899e7f2ae9bd1bc3eb0c59e72fe932f53a6 Mon Sep 17 00:00:00 2001 From: Ni Hui Date: Tue, 3 May 2022 22:42:41 +0800 Subject: [PATCH 094/180] target/mips: Fix FTRUNC_S and FTRUNC_U trans helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the FTRUNC_S and FTRUNC_U trans helper problem. Fixes: 5c5b64000c ("target/mips: Convert MSA 2RF instruction format to decodetree") Signed-off-by: nihui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220503144241.289239-1-shuizhuyuanluo@126.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/msa_translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/mips/tcg/msa_translate.c b/target/mips/tcg/msa_translate.c index 0b3dd0957c..1bcdbb1121 100644 --- a/target/mips/tcg/msa_translate.c +++ b/target/mips/tcg/msa_translate.c @@ -752,8 +752,8 @@ static bool trans_msa_2rf(DisasContext *ctx, arg_msa_r *a, } TRANS(FCLASS, trans_msa_2rf, gen_helper_msa_fclass_df); -TRANS(FTRUNC_S, trans_msa_2rf, gen_helper_msa_fclass_df); -TRANS(FTRUNC_U, trans_msa_2rf, gen_helper_msa_ftrunc_s_df); +TRANS(FTRUNC_S, trans_msa_2rf, gen_helper_msa_ftrunc_s_df); +TRANS(FTRUNC_U, trans_msa_2rf, gen_helper_msa_ftrunc_u_df); TRANS(FSQRT, trans_msa_2rf, gen_helper_msa_fsqrt_df); TRANS(FRSQRT, trans_msa_2rf, gen_helper_msa_frsqrt_df); TRANS(FRCP, trans_msa_2rf, gen_helper_msa_frcp_df); From a1b092537ac52b9a19e14ea163cb653149efcbb8 Mon Sep 17 00:00:00 2001 From: Stefan Pejic Date: Wed, 4 May 2022 13:03:57 +0200 Subject: [PATCH 095/180] target/mips: Fix emulation of nanoMIPS MTHLIP instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field ac in nanoMIPS instruction MTHLIP rs, ac is specified in nanoMIPS documentation as opcode[15..14] (2 bits). However, in the current QEMU code, the corresponding argument passed to the helper gen_helper_mthlip() has the value of opcode[15..11] (5 bits). Right shift the value of this argument by three bits to fix this. Signed-off-by: Stefan Pejic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504110403.613168-2-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/nanomips_translate.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 916cece4d2..58ae35a156 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -1597,7 +1597,7 @@ static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc, check_dsp(ctx); switch (extract32(ctx->opcode, 12, 2)) { case NM_MTHLIP: - tcg_gen_movi_tl(t0, v2); + tcg_gen_movi_tl(t0, v2 >> 3); gen_helper_mthlip(t0, v0_t, cpu_env); break; case NM_SHILOV: From 9e4f726d4f489e9f1cd675f4e5ce300f7677ed40 Mon Sep 17 00:00:00 2001 From: Dragan Mladjenovic Date: Wed, 4 May 2022 13:03:58 +0200 Subject: [PATCH 096/180] target/mips: Fix emulation of nanoMIPS EXTRV_S.H instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field rs in the instruction EXTRV_S.H rt, ac, rs is specified in nanoMIPS documentation as opcode[20..16]. It is, however, erroneously considered as opcode[25..21] in the current QEMU implementation. In function gen_pool32axf_2_nanomips_insn(), the variable v0_t corresponds to rt/opcode[25..21], and v1_t corresponds to rs/opcode[20..16]), and v0_t is by mistake passed to the helper gen_helper_extr_s_h(). Use v1_t rather than v0_t in the invocation of gen_helper_extr_s_h() to fix this. Signed-off-by: Dragan Mladjenovic Signed-off-by: Stefan Pejic Fixes: 8b3698b294 ("target/mips: Add emulation of DSP ASE for nanoMIPS") Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504110403.613168-3-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/nanomips_translate.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 58ae35a156..9ee4df2135 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -2036,7 +2036,7 @@ static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc, case NM_EXTRV_S_H: check_dsp(ctx); tcg_gen_movi_tl(t0, rd >> 3); - gen_helper_extr_s_h(t0, t0, v0_t, cpu_env); + gen_helper_extr_s_h(t0, t0, v1_t, cpu_env); gen_store_gpr(t0, ret); break; } From 5de4359b4f303faf5eecc7c37668a6bef77cb656 Mon Sep 17 00:00:00 2001 From: Dragan Mladjenovic Date: Wed, 4 May 2022 13:03:59 +0200 Subject: [PATCH 097/180] target/mips: Fix emulation of nanoMIPS BPOSGE32C instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are currently two problems related to the emulation of the instruction BPOSGE32C. The nanoMIPS instruction BPOSGE32C belongs to DSP R3 instructions (actually, as of now, it is the only instruction of DSP R3). The presence of DSP R3 instructions in QEMU is indicated by the flag MIPS_HFLAG_DSP_R3 (0x20000000). This flag is currently being properly set in CPUMIPSState's hflags (for example, for I7200 nanoMIPS CPU). However, it is not propagated to DisasContext's hflags, since the flag MIPS_HFLAG_DSP_R3 is not set in MIPS_HFLAG_TMASK (while similar flags MIPS_HFLAG_DSP_R2 and MIPS_HFLAG_DSP are set in this mask, and there is no problem in functioning check_dsp_r2(), check_dsp()). This means the function check_dsp_r3() currently does not work properly, and the emulation of BPOSGE32C can not work properly as well. Change MIPS_HFLAG_TMASK from 0x1F5807FF to 0x3F5807FF (logical OR with 0x20000000) to fix this. Additionally, check_cp1_enabled() is currently incorrectly called while emulating BPOSGE32C. BPOSGE32C is in the same pool (P.BR1) as FPU branch instruction BC1EQZC and BC1NEZC, but it not a part of FPU (CP1) instructions, and check_cp1_enabled() should not be involved while emulating BPOSGE32C. Rearrange invocations of check_cp1_enabled() within P.BR1 pool handling to affect only BC1EQZC and BC1NEZC emulation, and not BPOSGE32C emulation. Signed-off-by: Dragan Mladjenovic Signed-off-by: Stefan Pejic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504110403.613168-4-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/cpu.h | 2 +- target/mips/tcg/nanomips_translate.c.inc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 6b6b8776d1..42efa989e4 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1077,7 +1077,7 @@ typedef struct CPUArchState { #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x1F5807FF +#define MIPS_HFLAG_TMASK 0x3F5807FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ /* * The KSU flags must be the lowest bits in hflags. The flag order diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 9ee4df2135..941cfaa6bb 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -4478,12 +4478,13 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) case NM_P_BR3A: s = sextract32(ctx->opcode, 0, 1) << 14 | extract32(ctx->opcode, 1, 13) << 1; - check_cp1_enabled(ctx); switch (extract32(ctx->opcode, 16, 5)) { case NM_BC1EQZC: + check_cp1_enabled(ctx); gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s); break; case NM_BC1NEZC: + check_cp1_enabled(ctx); gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s); break; case NM_BPOSGE32C: From 14668cfaaf4d6f818d9e6b58dd44b75842654e2a Mon Sep 17 00:00:00 2001 From: Dragan Mladjenovic Date: Wed, 4 May 2022 13:04:00 +0200 Subject: [PATCH 098/180] target/mips: Fix emulation of nanoMIPS BNEC[32] instruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If both rs and rt are the same register, the nanoMIPS instruction BNEC[32] rs, rt, address is equivalent to NOP (branch is not taken and there is no delay slot). This commit provides such behavior. Without this commit, this scenario results in an incorrect behavior. Signed-off-by: Dragan Mladjenovic Signed-off-by: Stefan Pejic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504110403.613168-5-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/nanomips_translate.c.inc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 941cfaa6bb..1ee5c8c8d4 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -4528,7 +4528,12 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) switch (extract32(ctx->opcode, 14, 2)) { case NM_BNEC: check_nms(ctx); - gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); + if (rs == rt) { + /* NOP */ + ctx->hflags |= MIPS_HFLAG_FBNSLOT; + } else { + gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); + } break; case NM_BLTC: if (rs != 0 && rt != 0 && rs == rt) { From db7596989a67a8f838416f687431f3a0ccb181a0 Mon Sep 17 00:00:00 2001 From: Dragan Mladjenovic Date: Wed, 4 May 2022 13:04:01 +0200 Subject: [PATCH 099/180] target/mips: Fix handling of unaligned memory access for nanoMIPS ISA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nanoMIPS ISA does not support unaligned memory access. Adjust DisasContext's default_tcg_memop_mask to reflect this. Signed-off-by: Dragan Mladjenovic Signed-off-by: Stefan Pejic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504110403.613168-6-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/translate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 6de5b66650..5f460fb687 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -16023,8 +16023,9 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) #else ctx->mem_idx = hflags_mmu_index(ctx->hflags); #endif - ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 | - INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN; + ctx->default_tcg_memop_mask = (!(ctx->insn_flags & ISA_NANOMIPS32) && + (ctx->insn_flags & (ISA_MIPS_R6 | + INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN; /* * Execute a branch and its delay slot as a single instruction. From f1663114dfb452acd2abd6585f66779ef6a84010 Mon Sep 17 00:00:00 2001 From: Stefan Pejic Date: Wed, 4 May 2022 13:04:02 +0200 Subject: [PATCH 100/180] target/mips: Add missing default cases for some nanoMIPS pools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch statements for the code segments that handle nanoMIPS instruction pools P.LL, P.SC, P.SHIFT, P.LS.S1, P.LS.E0, PP.LSXS do not have proper default case, resulting in not generating reserved instruction exception for certain illegal opcodes. Fix this by adding default cases for these switch statements that trigger reserved instruction exception. Signed-off-by: Stefan Pejic Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220504110403.613168-7-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/tcg/nanomips_translate.c.inc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 1ee5c8c8d4..c0ba2bf1b1 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -2707,6 +2707,9 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) case NM_SDC1XS: tcg_gen_shli_tl(t0, t0, 3); break; + default: + gen_reserved_instruction(ctx); + goto out; } } gen_op_addr_add(ctx, t0, t0, t1); @@ -2797,6 +2800,7 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) break; } +out: tcg_temp_free(t0); tcg_temp_free(t1); } @@ -3944,6 +3948,9 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) gen_shift_imm(ctx, OPC_ROTR, rt, rs, extract32(ctx->opcode, 0, 5)); break; + default: + gen_reserved_instruction(ctx); + break; } } break; @@ -4245,6 +4252,9 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) check_xnp(ctx); gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); break; + default: + gen_reserved_instruction(ctx); + break; } break; case NM_P_SC: @@ -4257,6 +4267,9 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5), false); break; + default: + gen_reserved_instruction(ctx); + break; } break; case NM_CACHE: @@ -4265,6 +4278,9 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) gen_cache_operation(ctx, rt, rs, s); } break; + default: + gen_reserved_instruction(ctx); + break; } break; case NM_P_LS_E0: @@ -4371,6 +4387,9 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) break; } break; + default: + gen_reserved_instruction(ctx); + break; } break; case NM_P_LS_WM: From 8e0e23445acdf1cfbe7714f685c4a7404b3fa467 Mon Sep 17 00:00:00 2001 From: Stefan Pejic Date: Wed, 4 May 2022 13:04:03 +0200 Subject: [PATCH 101/180] target/mips: Undeprecate nanoMIPS ISA support in QEMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nanoMIPS ISA support in QEMU is actively used by MediaTek and is planned to be maintained and potentially extended by MediaTek in future. Un-orphan nanoMIPS ISA support in QEMU by setting a maintainer from MediaTek and remove deprecation notes from documentation as well. Signed-off-by: Stefan Pejic Message-Id: <20220504110403.613168-8-stefan.pejic@syrmia.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 3 ++- docs/about/deprecated.rst | 30 ------------------------------ 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index b3af081c51..0df25ed4b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -246,7 +246,8 @@ F: docs/system/cpu-models-mips.rst.inc F: tests/tcg/mips/ MIPS TCG CPUs (nanoMIPS ISA) -S: Orphan +M: Stefan Pejic +S: Maintained F: disas/nanomips.* F: target/mips/tcg/*nanomips* diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index aa2e320207..19a91b575f 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -213,17 +213,6 @@ MIPS ``Trap-and-Emul`` KVM support (since 6.0) The MIPS ``Trap-and-Emul`` KVM host and guest support has been removed from Linux upstream kernel, declare it deprecated. -System emulator CPUS --------------------- - -MIPS ``I7200`` CPU Model (since 5.2) -'''''''''''''''''''''''''''''''''''' - -The ``I7200`` guest CPU relies on the nanoMIPS ISA, which is deprecated -(the ISA has never been upstreamed to a compiler toolchain). Therefore -this CPU is also deprecated. - - QEMU API (QAPI) events ---------------------- @@ -337,16 +326,6 @@ The above, converted to the current supported format:: json:{"file.driver":"rbd", "file.pool":"rbd", "file.image":"name"} -linux-user mode CPUs --------------------- - -MIPS ``I7200`` CPU (since 5.2) -'''''''''''''''''''''''''''''' - -The ``I7200`` guest CPU relies on the nanoMIPS ISA, which is deprecated -(the ISA has never been upstreamed to a compiler toolchain). Therefore -this CPU is also deprecated. - Backwards compatibility ----------------------- @@ -376,15 +355,6 @@ versions, aliases will point to newer CPU model versions depending on the machine type, so management software must resolve CPU model aliases before starting a virtual machine. -Guest Emulator ISAs -------------------- - -nanoMIPS ISA -'''''''''''' - -The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain. -As it is hard to generate binaries for it, declare it deprecated. - Tools ----- From 0c285e01280d9bccda36717bad369082356cf8f4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 5 May 2022 11:18:42 +0100 Subject: [PATCH 102/180] hw/block/fdc-sysbus: Always mark sysbus floppy controllers as not having DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sysbus floppy controllers (devices sysbus-fdc and sun-fdtwo) don't support DMA. The core floppy controller code expects this to be indicated by setting FDCtrl::dma_chann to -1. This used to be done in the device instance_init functions sysbus_fdc_initfn() and sun4m_fdc_initfn(), but in commit 1430759ec3e we refactored this code and accidentally lost the setting of dma_chann. For sysbus-fdc this has no ill effects because we were redundantly also setting dma_chann in fdctrl_init_sysbus(), but for sun-fdtwo this means that guests which try to enable DMA on the floppy controller will cause QEMU to crash because FDCtrl::dma is NULL. Set dma_chann to -1 in the common instance init, and remove the redundant code in fdctrl_init_sysbus() that is also setting it. There is a six-year-old FIXME comment in the jazz board code to the effect that in theory it should support doing DMA via a custom DMA controller. If anybody ever chooses to fix that they can do it by adding support for setting both FDCtrl::dma_chann and FDCtrl::dma. (A QOM link property 'dma-controller' on the sysbus device which can be set to an instance of IsaDmaClass is probably the way to go.) Fixes: 1430759ec3 ("hw/block/fdc: Extract SysBus floppy controllers to fdc-sysbus.c") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/958 Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Message-Id: <20220505101842.2757905-1-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/block/fdc-sysbus.c | 16 +++++++++++----- hw/mips/jazz.c | 2 +- include/hw/block/fdc.h | 3 +-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/hw/block/fdc-sysbus.c b/hw/block/fdc-sysbus.c index 57fc8773f1..86ea51d003 100644 --- a/hw/block/fdc-sysbus.c +++ b/hw/block/fdc-sysbus.c @@ -94,18 +94,14 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level) trace_fdctrl_tc_pulse(level); } -void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, - hwaddr mmio_base, DriveInfo **fds) +void fdctrl_init_sysbus(qemu_irq irq, hwaddr mmio_base, DriveInfo **fds) { - FDCtrl *fdctrl; DeviceState *dev; SysBusDevice *sbd; FDCtrlSysBus *sys; dev = qdev_new("sysbus-fdc"); sys = SYSBUS_FDC(dev); - fdctrl = &sys->state; - fdctrl->dma_chann = dma_chann; /* FIXME */ sbd = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(sbd, &error_fatal); sysbus_connect_irq(sbd, 0, irq); @@ -138,6 +134,16 @@ static void sysbus_fdc_common_instance_init(Object *obj) FDCtrlSysBus *sys = SYSBUS_FDC(obj); FDCtrl *fdctrl = &sys->state; + /* + * DMA is not currently supported for sysbus floppy controllers. + * If we wanted to add support then probably the best approach is + * to have a QOM link property 'dma-controller' which the board + * code can set to an instance of IsaDmaClass, and an integer + * property 'dma-channel', so that we can set fdctrl->dma and + * fdctrl->dma_chann accordingly. + */ + fdctrl->dma_chann = -1; + qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */ memory_region_init_io(&fdctrl->iomem, obj, diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 6598d7dddd..96dc6ab32d 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -353,7 +353,7 @@ static void mips_jazz_init(MachineState *machine, fds[n] = drive_get(IF_FLOPPY, 0, n); } /* FIXME: we should enable DMA with a custom IsaDma device */ - fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), -1, 0x80003000, fds); + fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), 0x80003000, fds); /* Real time clock */ mc146818_rtc_init(isa_bus, 1980, NULL); diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h index 1ecca7cac7..35248c0837 100644 --- a/include/hw/block/fdc.h +++ b/include/hw/block/fdc.h @@ -10,8 +10,7 @@ #define TYPE_ISA_FDC "isa-fdc" void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds); -void fdctrl_init_sysbus(qemu_irq irq, int dma_chann, - hwaddr mmio_base, DriveInfo **fds); +void fdctrl_init_sysbus(qemu_irq irq, hwaddr mmio_base, DriveInfo **fds); void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base, DriveInfo **fds, qemu_irq *fdc_tc); From 3f0efcac43707c02525b5bbaf996c6bf80e2f706 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 103/180] hw/acpi/piix4: move xen_enabled() logic from piix4_pm_init() to piix4_pm_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This logic can be included as part of piix4_pm_realize() and does not need to be handled externally. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ani Sinha Message-Id: <20220528091934.15520-2-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index fe5625d07a..bf20fa139b 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -525,6 +525,10 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) s->machine_ready.notify = piix4_pm_machine_ready; qemu_add_machine_init_done_notifier(&s->machine_ready); + if (xen_enabled()) { + s->use_acpi_hotplug_bridge = false; + } + piix4_acpi_system_hot_add_init(pci_address_space_io(dev), pci_get_bus(dev), s); qbus_set_hotplug_handler(BUS(pci_get_bus(dev)), OBJECT(s)); @@ -551,9 +555,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, s->irq = sci_irq; s->smi_irq = smi_irq; s->smm_enabled = smm_enabled; - if (xen_enabled()) { - s->use_acpi_hotplug_bridge = false; - } pci_realize_and_unref(pci_dev, bus, &error_fatal); From 5b07f441022c1114073c05cdffd1bb829cbc31c5 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 104/180] hw/acpi/piix4: change smm_enabled from int to bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation for conversion to a qdev property. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ani Sinha Message-Id: <20220528091934.15520-3-mark.cave-ayland@ilande.co.uk> [PMD: Change simm_enabled from int to bool, suggested by Ani Sinha] Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 4 ++-- include/hw/southbridge/piix.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index bf20fa139b..558c250884 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -74,7 +74,7 @@ struct PIIX4PMState { qemu_irq irq; qemu_irq smi_irq; - int smm_enabled; + bool smm_enabled; bool smm_compat; Notifier machine_ready; Notifier powerdown_notifier; @@ -538,7 +538,7 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int smm_enabled, DeviceState **piix4_pm) + bool smm_enabled, DeviceState **piix4_pm) { PCIDevice *pci_dev; DeviceState *dev; diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index f63f83e5c6..ff8d96ae8c 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -19,7 +19,7 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, - int smm_enabled, DeviceState **piix4_pm); + bool smm_enabled, DeviceState **piix4_pm); /* PIRQRC[A:D]: PIRQx Route Control Registers */ #define PIIX_PIRQCA 0x60 From 7ace6b4f81cffa4595dc94c79583a90c251c9810 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 105/180] hw/acpi/piix4: convert smm_enabled bool to qdev property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the smm_enabled value to be set using a standard qdev property instead of being referenced directly in piix4_pm_init(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ani Sinha Message-Id: <20220528091934.15520-4-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 558c250884..316e41e1d0 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -547,6 +547,7 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, pci_dev = pci_new(devfn, TYPE_PIIX4_PM); dev = DEVICE(pci_dev); qdev_prop_set_uint32(dev, "smb_io_base", smb_io_base); + qdev_prop_set_bit(dev, "smm-enabled", smm_enabled); if (piix4_pm) { *piix4_pm = dev; } @@ -554,7 +555,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, s = PIIX4_PM(dev); s->irq = sci_irq; s->smi_irq = smi_irq; - s->smm_enabled = smm_enabled; pci_realize_and_unref(pci_dev, bus, &error_fatal); @@ -664,6 +664,7 @@ static Property piix4_pm_properties[] = { DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState, acpi_memory_hotplug.is_enabled, true), DEFINE_PROP_BOOL("smm-compat", PIIX4PMState, smm_compat, false), + DEFINE_PROP_BOOL("smm-enabled", PIIX4PMState, smm_enabled, false), DEFINE_PROP_BOOL("x-not-migrate-acpi-index", PIIX4PMState, not_migrate_acpi_index, false), DEFINE_PROP_END_OF_LIST(), From 2bfd0845f076fbec9e1dc17b1f4630b46a401a8a Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 106/180] hw/acpi/piix4: move PIIX4PMState into separate piix4.h header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the QOM types in hw/acpi/piix4.c to be used elsewhere by simply including hw/acpi/piix4.h. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-5-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 43 +------------------- hw/i386/acpi-build.c | 1 + include/hw/acpi/piix4.h | 75 +++++++++++++++++++++++++++++++++++ include/hw/southbridge/piix.h | 2 - 4 files changed, 78 insertions(+), 43 deletions(-) create mode 100644 include/hw/acpi/piix4.h diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 316e41e1d0..c2177c5093 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -28,6 +28,8 @@ #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/pcihp.h" +#include "hw/acpi/piix4.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "sysemu/xen.h" @@ -56,47 +58,6 @@ struct pci_status { uint32_t down; }; -struct PIIX4PMState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - MemoryRegion io; - uint32_t io_base; - - MemoryRegion io_gpe; - ACPIREGS ar; - - APMState apm; - - PMSMBus smb; - uint32_t smb_io_base; - - qemu_irq irq; - qemu_irq smi_irq; - bool smm_enabled; - bool smm_compat; - Notifier machine_ready; - Notifier powerdown_notifier; - - AcpiPciHpState acpi_pci_hotplug; - bool use_acpi_hotplug_bridge; - bool use_acpi_root_pci_hotplug; - bool not_migrate_acpi_index; - - uint8_t disable_s3; - uint8_t disable_s4; - uint8_t s4_val; - - bool cpu_hotplug_legacy; - AcpiCpuHotplug gpe_cpu; - CPUHotplugState cpuhp_state; - - MemHotplugState acpi_memory_hotplug; -}; - -OBJECT_DECLARE_SIMPLE_TYPE(PIIX4PMState, PIIX4_PM) - static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, PCIBus *bus, PIIX4PMState *s); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 73d0bf5937..cad6f5ac41 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -44,6 +44,7 @@ #include "hw/acpi/tpm.h" #include "hw/acpi/vmgenid.h" #include "hw/acpi/erst.h" +#include "hw/acpi/piix4.h" #include "sysemu/tpm_backend.h" #include "hw/rtc/mc146818rtc_regs.h" #include "migration/vmstate.h" diff --git a/include/hw/acpi/piix4.h b/include/hw/acpi/piix4.h new file mode 100644 index 0000000000..32686a75c5 --- /dev/null +++ b/include/hw/acpi/piix4.h @@ -0,0 +1,75 @@ +/* + * ACPI implementation + * + * Copyright (c) 2006 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ + +#ifndef HW_ACPI_PIIX4_H +#define HW_ACPI_PIIX4_H + +#include "hw/pci/pci.h" +#include "hw/acpi/acpi.h" +#include "hw/acpi/cpu_hotplug.h" +#include "hw/acpi/memory_hotplug.h" +#include "hw/acpi/pcihp.h" +#include "hw/i2c/pm_smbus.h" +#include "hw/isa/apm.h" + +#define TYPE_PIIX4_PM "PIIX4_PM" +OBJECT_DECLARE_SIMPLE_TYPE(PIIX4PMState, PIIX4_PM) + +struct PIIX4PMState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ + + MemoryRegion io; + uint32_t io_base; + + MemoryRegion io_gpe; + ACPIREGS ar; + + APMState apm; + + PMSMBus smb; + uint32_t smb_io_base; + + qemu_irq irq; + qemu_irq smi_irq; + bool smm_enabled; + bool smm_compat; + Notifier machine_ready; + Notifier powerdown_notifier; + + AcpiPciHpState acpi_pci_hotplug; + bool use_acpi_hotplug_bridge; + bool use_acpi_root_pci_hotplug; + bool not_migrate_acpi_index; + + uint8_t disable_s3; + uint8_t disable_s4; + uint8_t s4_val; + + bool cpu_hotplug_legacy; + AcpiCpuHotplug gpe_cpu; + CPUHotplugState cpuhp_state; + + MemHotplugState acpi_memory_hotplug; +}; + +#endif diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index ff8d96ae8c..04cbc3fe30 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -15,8 +15,6 @@ #include "hw/pci/pci.h" #include "qom/object.h" -#define TYPE_PIIX4_PM "PIIX4_PM" - I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq, qemu_irq smi_irq, bool smm_enabled, DeviceState **piix4_pm); From 19eb2a0da272289e8879fb2780522f37630ac651 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 107/180] hw/acpi/piix4: alter piix4_pm_init() to return PIIX4PMState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This exposes the PIIX4_PM device to the caller to allow any qdev gpios to be mapped outside of piix4_pm_init(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-6-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 11 ++++------- hw/i386/pc_piix.c | 10 +++++----- hw/isa/piix4.c | 8 +++++--- include/hw/southbridge/piix.h | 7 ++++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index c2177c5093..c4cfb75020 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -497,9 +497,9 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) piix4_pm_add_properties(s); } -I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - bool smm_enabled, DeviceState **piix4_pm) +PIIX4PMState *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + bool smm_enabled) { PCIDevice *pci_dev; DeviceState *dev; @@ -509,9 +509,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, dev = DEVICE(pci_dev); qdev_prop_set_uint32(dev, "smb_io_base", smb_io_base); qdev_prop_set_bit(dev, "smm-enabled", smm_enabled); - if (piix4_pm) { - *piix4_pm = dev; - } s = PIIX4_PM(dev); s->irq = sci_irq; @@ -519,7 +516,7 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, pci_realize_and_unref(pci_dev, bus, &error_fatal); - return s->smb.smbus; + return s; } static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index bd63511c1c..3359b40f54 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -280,14 +280,14 @@ static void pc_init1(MachineState *machine, } if (pcmc->pci_enabled && x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) { - DeviceState *piix4_pm; + PIIX4PMState *piix4_pm; smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0); + piix4_pm = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, + x86ms->gsi[9], smi_irq, + x86_machine_is_smm_enabled(x86ms)); + pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c")); /* TODO: Populate SPD eeprom data. */ - pcms->smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, - x86ms->gsi[9], smi_irq, - x86_machine_is_smm_enabled(x86ms), - &piix4_pm); smbus_eeprom_init(pcms->smbus, 8, NULL, 0); object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 8607e0ac36..7d9bedd1bb 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -293,6 +293,7 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) { PIIX4State *s; + PIIX4PMState *pms; PCIDevice *pci; DeviceState *dev; int devfn = PCI_DEVFN(10, 0); @@ -310,9 +311,10 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci"); if (smbus) { - *smbus = piix4_pm_init(pci_bus, devfn + 3, 0x1100, - qdev_get_gpio_in_named(dev, "isa", 9), - NULL, 0, NULL); + pms = piix4_pm_init(pci_bus, devfn + 3, 0x1100, + qdev_get_gpio_in_named(dev, "isa", 9), + NULL, 0); + *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pms), "i2c")); } pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS); diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 04cbc3fe30..a362ec7484 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -14,10 +14,11 @@ #include "hw/pci/pci.h" #include "qom/object.h" +#include "hw/acpi/piix4.h" -I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - bool smm_enabled, DeviceState **piix4_pm); +PIIX4PMState *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + bool smm_enabled); /* PIRQRC[A:D]: PIRQx Route Control Registers */ #define PIIX_PIRQCA 0x60 From d0af99ac12d381f3dcf451c69a6cef760fdc8252 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 108/180] hw/acpi/piix4: rename piix4_pm_init() to piix4_pm_initfn() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When QOMifying a device it is typical to use _init() as the suffix for an instance_init function, however this name is already in use by the legacy piix4_pm_init() wrapper function. Eventually the wrapper function will be removed, but for now rename it to piix4_pm_initfn() to avoid a naming collision. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-7-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 6 +++--- hw/i386/pc_piix.c | 6 +++--- hw/isa/piix4.c | 6 +++--- include/hw/southbridge/piix.h | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index c4cfb75020..418ec4ee56 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -497,9 +497,9 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) piix4_pm_add_properties(s); } -PIIX4PMState *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - bool smm_enabled) +PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + bool smm_enabled) { PCIDevice *pci_dev; DeviceState *dev; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 3359b40f54..fde0fdc088 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -283,9 +283,9 @@ static void pc_init1(MachineState *machine, PIIX4PMState *piix4_pm; smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0); - piix4_pm = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, - x86ms->gsi[9], smi_irq, - x86_machine_is_smm_enabled(x86ms)); + piix4_pm = piix4_pm_initfn(pci_bus, piix3_devfn + 3, 0xb100, + x86ms->gsi[9], smi_irq, + x86_machine_is_smm_enabled(x86ms)); pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c")); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(pcms->smbus, 8, NULL, 0); diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 7d9bedd1bb..33a7015ea3 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -311,9 +311,9 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci"); if (smbus) { - pms = piix4_pm_init(pci_bus, devfn + 3, 0x1100, - qdev_get_gpio_in_named(dev, "isa", 9), - NULL, 0); + pms = piix4_pm_initfn(pci_bus, devfn + 3, 0x1100, + qdev_get_gpio_in_named(dev, "isa", 9), + NULL, 0); *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pms), "i2c")); } diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index a362ec7484..f75a4adf5f 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -16,9 +16,9 @@ #include "qom/object.h" #include "hw/acpi/piix4.h" -PIIX4PMState *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - bool smm_enabled); +PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, + qemu_irq sci_irq, qemu_irq smi_irq, + bool smm_enabled); /* PIRQRC[A:D]: PIRQx Route Control Registers */ #define PIIX_PIRQCA 0x60 From 29786d42ba4ab6a70d3055083512e0bdd8e2f9ec Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 109/180] hw/acpi/piix4: use qdev gpio to wire up sci_irq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce piix4_pm_init() instance init function and use it to initialise the separate qdev gpio for the SCI IRQ. The sci_irq can now be wired up directly using a qdev gpio instead of having to set the IRQ externally in piix4_pm_initfn(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-9-mark.cave-ayland@ilande.co.uk> [PMD: Partially squash 20220528091934.15520-8-mark.cave-ayland@ilande.co.uk] Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 12 +++++++++--- hw/i386/pc_piix.c | 4 ++-- hw/isa/piix4.c | 6 +++--- include/hw/southbridge/piix.h | 3 +-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 418ec4ee56..fe5ec0a723 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -497,9 +497,15 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp) piix4_pm_add_properties(s); } +static void piix4_pm_init(Object *obj) +{ + PIIX4PMState *s = PIIX4_PM(obj); + + qdev_init_gpio_out(DEVICE(obj), &s->irq, 1); +} + PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - bool smm_enabled) + qemu_irq smi_irq, bool smm_enabled) { PCIDevice *pci_dev; DeviceState *dev; @@ -511,7 +517,6 @@ PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, qdev_prop_set_bit(dev, "smm-enabled", smm_enabled); s = PIIX4_PM(dev); - s->irq = sci_irq; s->smi_irq = smi_irq; pci_realize_and_unref(pci_dev, bus, &error_fatal); @@ -663,6 +668,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) static const TypeInfo piix4_pm_info = { .name = TYPE_PIIX4_PM, .parent = TYPE_PCI_DEVICE, + .instance_init = piix4_pm_init, .instance_size = sizeof(PIIX4PMState), .class_init = piix4_pm_class_init, .interfaces = (InterfaceInfo[]) { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index fde0fdc088..27acba4146 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -283,9 +283,9 @@ static void pc_init1(MachineState *machine, PIIX4PMState *piix4_pm; smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0); - piix4_pm = piix4_pm_initfn(pci_bus, piix3_devfn + 3, 0xb100, - x86ms->gsi[9], smi_irq, + piix4_pm = piix4_pm_initfn(pci_bus, piix3_devfn + 3, 0xb100, smi_irq, x86_machine_is_smm_enabled(x86ms)); + qdev_connect_gpio_out(DEVICE(piix4_pm), 0, x86ms->gsi[9]); pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c")); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(pcms->smbus, 8, NULL, 0); diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 33a7015ea3..0b6ea22143 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -311,9 +311,9 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci"); if (smbus) { - pms = piix4_pm_initfn(pci_bus, devfn + 3, 0x1100, - qdev_get_gpio_in_named(dev, "isa", 9), - NULL, 0); + pms = piix4_pm_initfn(pci_bus, devfn + 3, 0x1100, NULL, 0); + qdev_connect_gpio_out(DEVICE(pms), 0, + qdev_get_gpio_in_named(dev, "isa", 9)); *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pms), "i2c")); } diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index f75a4adf5f..105d158f78 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -17,8 +17,7 @@ #include "hw/acpi/piix4.h" PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - bool smm_enabled); + qemu_irq smi_irq, bool smm_enabled); /* PIRQRC[A:D]: PIRQx Route Control Registers */ #define PIIX_PIRQCA 0x60 From b49e94424cbdc2f02725dcd37b8916ff64f74dcd Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 110/180] hw/acpi/piix4: use qdev gpio to wire up smi_irq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize the SMI IRQ in piix4_pm_init(). The smi_irq can now be wired up directly using a qdev gpio instead of having to set the IRQ externally in piix4_pm_initfn(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-10-mark.cave-ayland@ilande.co.uk> [PMD: Partially squash 20220528091934.15520-8-mark.cave-ayland@ilande.co.uk] Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 4 ++-- hw/i386/pc_piix.c | 3 ++- hw/isa/piix4.c | 2 +- include/hw/southbridge/piix.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index fe5ec0a723..32033bc9d7 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -502,10 +502,11 @@ static void piix4_pm_init(Object *obj) PIIX4PMState *s = PIIX4_PM(obj); qdev_init_gpio_out(DEVICE(obj), &s->irq, 1); + qdev_init_gpio_out_named(DEVICE(obj), &s->smi_irq, "smi-irq", 1); } PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq smi_irq, bool smm_enabled) + bool smm_enabled) { PCIDevice *pci_dev; DeviceState *dev; @@ -517,7 +518,6 @@ PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, qdev_prop_set_bit(dev, "smm-enabled", smm_enabled); s = PIIX4_PM(dev); - s->smi_irq = smi_irq; pci_realize_and_unref(pci_dev, bus, &error_fatal); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 27acba4146..89c4f07c9f 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -283,9 +283,10 @@ static void pc_init1(MachineState *machine, PIIX4PMState *piix4_pm; smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0); - piix4_pm = piix4_pm_initfn(pci_bus, piix3_devfn + 3, 0xb100, smi_irq, + piix4_pm = piix4_pm_initfn(pci_bus, piix3_devfn + 3, 0xb100, x86_machine_is_smm_enabled(x86ms)); qdev_connect_gpio_out(DEVICE(piix4_pm), 0, x86ms->gsi[9]); + qdev_connect_gpio_out_named(DEVICE(piix4_pm), "smi-irq", 0, smi_irq); pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c")); /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(pcms->smbus, 8, NULL, 0); diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 0b6ea22143..775e15eb20 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -311,7 +311,7 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci"); if (smbus) { - pms = piix4_pm_initfn(pci_bus, devfn + 3, 0x1100, NULL, 0); + pms = piix4_pm_initfn(pci_bus, devfn + 3, 0x1100, 0); qdev_connect_gpio_out(DEVICE(pms), 0, qdev_get_gpio_in_named(dev, "isa", 9)); *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pms), "i2c")); diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 105d158f78..b69e0dfb04 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -17,7 +17,7 @@ #include "hw/acpi/piix4.h" PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq smi_irq, bool smm_enabled); + bool smm_enabled); /* PIRQRC[A:D]: PIRQx Route Control Registers */ #define PIIX_PIRQCA 0x60 From ee7318bc09d25aa250f0e58ac1eebf87abc88b03 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 111/180] hw/i386/pc_piix: create PIIX4_PM device directly instead of using piix4_pm_initfn() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all external logic has been removed from piix4_pm_initfn() the PIIX4_PM device can be instantiated directly. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-11-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc_piix.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 89c4f07c9f..7d5546600b 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -47,6 +47,7 @@ #include "hw/xen/xen-x86.h" #include "exec/memory.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/piix4.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/xen.h" @@ -280,11 +281,15 @@ static void pc_init1(MachineState *machine, } if (pcmc->pci_enabled && x86_machine_is_acpi_enabled(X86_MACHINE(pcms))) { - PIIX4PMState *piix4_pm; + PCIDevice *piix4_pm; smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0); - piix4_pm = piix4_pm_initfn(pci_bus, piix3_devfn + 3, 0xb100, - x86_machine_is_smm_enabled(x86ms)); + piix4_pm = pci_new(piix3_devfn + 3, TYPE_PIIX4_PM); + qdev_prop_set_uint32(DEVICE(piix4_pm), "smb_io_base", 0xb100); + qdev_prop_set_bit(DEVICE(piix4_pm), "smm-enabled", + x86_machine_is_smm_enabled(x86ms)); + pci_realize_and_unref(piix4_pm, pci_bus, &error_fatal); + qdev_connect_gpio_out(DEVICE(piix4_pm), 0, x86ms->gsi[9]); qdev_connect_gpio_out_named(DEVICE(piix4_pm), "smi-irq", 0, smi_irq); pcms->smbus = I2C_BUS(qdev_get_child_bus(DEVICE(piix4_pm), "i2c")); From 5a9715c26f19675c32a4113867a3a073fa1e8595 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 112/180] hw/isa/piix4.c: create PIIX4_PM device directly instead of using piix4_pm_initfn() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all external logic has been removed from piix4_pm_initfn() the PIIX4_PM device can be instantiated directly. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-12-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 775e15eb20..9a6d981037 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -34,6 +34,7 @@ #include "hw/timer/i8254.h" #include "hw/rtc/mc146818rtc.h" #include "hw/ide/pci.h" +#include "hw/acpi/piix4.h" #include "migration/vmstate.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" @@ -293,7 +294,6 @@ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) { PIIX4State *s; - PIIX4PMState *pms; PCIDevice *pci; DeviceState *dev; int devfn = PCI_DEVFN(10, 0); @@ -311,10 +311,13 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci"); if (smbus) { - pms = piix4_pm_initfn(pci_bus, devfn + 3, 0x1100, 0); - qdev_connect_gpio_out(DEVICE(pms), 0, + pci = pci_new(devfn + 3, TYPE_PIIX4_PM); + qdev_prop_set_uint32(DEVICE(pci), "smb_io_base", 0x1100); + qdev_prop_set_bit(DEVICE(pci), "smm-enabled", 0); + pci_realize_and_unref(pci, pci_bus, &error_fatal); + qdev_connect_gpio_out(DEVICE(pci), 0, qdev_get_gpio_in_named(dev, "isa", 9)); - *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pms), "i2c")); + *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pci), "i2c")); } pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS); From 65417e548ad4277ee6b08443fd06d4d8446ed05e Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 28 May 2022 10:02:11 +0100 Subject: [PATCH 113/180] hw/acpi/piix4: remove unused piix4_pm_initfn() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is now unused and so can be completely removed. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220528091934.15520-13-mark.cave-ayland@ilande.co.uk> Reviewed-by: Bernhard Beschow Signed-off-by: Philippe Mathieu-Daudé --- hw/acpi/piix4.c | 19 ------------------- include/hw/southbridge/piix.h | 4 ---- 2 files changed, 23 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 32033bc9d7..0a81f1ad93 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -505,25 +505,6 @@ static void piix4_pm_init(Object *obj) qdev_init_gpio_out_named(DEVICE(obj), &s->smi_irq, "smi-irq", 1); } -PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, - bool smm_enabled) -{ - PCIDevice *pci_dev; - DeviceState *dev; - PIIX4PMState *s; - - pci_dev = pci_new(devfn, TYPE_PIIX4_PM); - dev = DEVICE(pci_dev); - qdev_prop_set_uint32(dev, "smb_io_base", smb_io_base); - qdev_prop_set_bit(dev, "smm-enabled", smm_enabled); - - s = PIIX4_PM(dev); - - pci_realize_and_unref(pci_dev, bus, &error_fatal); - - return s; -} - static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width) { PIIX4PMState *s = opaque; diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index b69e0dfb04..976b4da582 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -14,10 +14,6 @@ #include "hw/pci/pci.h" #include "qom/object.h" -#include "hw/acpi/piix4.h" - -PIIX4PMState *piix4_pm_initfn(PCIBus *bus, int devfn, uint32_t smb_io_base, - bool smm_enabled); /* PIRQRC[A:D]: PIRQx Route Control Registers */ #define PIIX_PIRQCA 0x60 From 3963e1398e1b0cbcc0fb21b2cce387ba7f48de5f Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:35 +0200 Subject: [PATCH 114/180] hw/southbridge/piix: Aggregate all PIIX southbridge type names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TYPE_PIIX3_PCI_DEVICE resides there as already, so add the remaining ones, too. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220603185045.143789-2-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix3.c | 3 --- include/hw/isa/isa.h | 2 -- include/hw/southbridge/piix.h | 4 ++++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index bfccd666d4..c92b36c4f2 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -36,9 +36,6 @@ #define XEN_PIIX_NUM_PIRQS 128ULL -#define TYPE_PIIX3_DEVICE "PIIX3" -#define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen" - static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq) { qemu_set_irq(piix3->pic[pic_irq], diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index 6f9380007d..6c8a8a92cb 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -129,6 +129,4 @@ static inline ISABus *isa_bus_from_device(ISADevice *d) return ISA_BUS(qdev_get_parent_bus(DEVICE(d))); } -#define TYPE_PIIX4_PCI_DEVICE "piix4-isa" - #endif diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 976b4da582..3b97186f75 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -64,6 +64,10 @@ typedef struct PIIXState PIIX3State; DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, TYPE_PIIX3_PCI_DEVICE) +#define TYPE_PIIX3_DEVICE "PIIX3" +#define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen" +#define TYPE_PIIX4_PCI_DEVICE "piix4-isa" + PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus); DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus); From 14f94725c91fb9aebbc8d13241c52ba8b30b39d4 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:36 +0200 Subject: [PATCH 115/180] hw/isa/piix4: Use object_initialize_child() for embedded struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Peter Maydell Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-3-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 9a6d981037..1d04fb6a55 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -224,7 +224,7 @@ static void piix4_init(Object *obj) { PIIX4State *s = PIIX4_PCI_DEVICE(obj); - object_initialize(&s->rtc, sizeof(s->rtc), TYPE_MC146818_RTC); + object_initialize_child(obj, "rtc", &s->rtc, TYPE_MC146818_RTC); } static void piix4_class_init(ObjectClass *klass, void *data) From 87e010d6d630470de81039c3dfb614fa79d759bc Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:37 +0200 Subject: [PATCH 116/180] hw/isa/piix4: Move pci_map_irq_fn' near pci_set_irq_fn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pci_map_irq_fn was implemented below type_init() which made it inaccessible to QOM functions. So move it up. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220603185045.143789-4-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 1d04fb6a55..18aa24424f 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -74,6 +74,31 @@ static void piix4_set_irq(void *opaque, int irq_num, int level) } } +static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) +{ + int slot; + + slot = PCI_SLOT(pci_dev->devfn); + + switch (slot) { + /* PIIX4 USB */ + case 10: + return 3; + /* AMD 79C973 Ethernet */ + case 11: + return 1; + /* Crystal 4281 Sound */ + case 12: + return 2; + /* PCI slot 1 to 4 */ + case 18 ... 21: + return ((slot - 18) + irq_num) & 0x03; + /* Unknown device, don't do any translation */ + default: + return irq_num; + } +} + static void piix4_isa_reset(DeviceState *dev) { PIIX4State *d = PIIX4_PCI_DEVICE(dev); @@ -266,31 +291,6 @@ static void piix4_register_types(void) type_init(piix4_register_types) -static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) -{ - int slot; - - slot = PCI_SLOT(pci_dev->devfn); - - switch (slot) { - /* PIIX4 USB */ - case 10: - return 3; - /* AMD 79C973 Ethernet */ - case 11: - return 1; - /* Crystal 4281 Sound */ - case 12: - return 2; - /* PCI slot 1 to 4 */ - case 18 ... 21: - return ((slot - 18) + irq_num) & 0x03; - /* Unknown device, don't do any translation */ - default: - return irq_num; - } -} - DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) { PIIX4State *s; From c397a2d3e45ea72d2513d95c4e5d148fbc301131 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:38 +0200 Subject: [PATCH 117/180] hw/isa/piix4: QOM'ify PCI device creation and wiring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PCI interrupt wiring and device creation were performed in create() functions which are obsolete. Move these tasks into QOM functions to modernize the code. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-5-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 18aa24424f..058bebb5e2 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -35,6 +35,7 @@ #include "hw/rtc/mc146818rtc.h" #include "hw/ide/pci.h" #include "hw/acpi/piix4.h" +#include "hw/usb/hcd-uhci.h" #include "migration/vmstate.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" @@ -46,6 +47,8 @@ struct PIIX4State { qemu_irq *isa; RTCState rtc; + PCIIDEState ide; + UHCIState uhci; /* Reset Control Register */ MemoryRegion rcr_mem; uint8_t rcr; @@ -205,6 +208,7 @@ static const MemoryRegionOps piix4_rcr_ops = { static void piix4_realize(PCIDevice *dev, Error **errp) { PIIX4State *s = PIIX4_PCI_DEVICE(dev); + PCIBus *pci_bus = pci_get_bus(dev); ISABus *isa_bus; qemu_irq *i8259_out_irq; @@ -243,6 +247,21 @@ static void piix4_realize(PCIDevice *dev, Error **errp) return; } s->rtc.irq = isa_get_irq(ISA_DEVICE(&s->rtc), s->rtc.isairq); + + /* IDE */ + qdev_prop_set_int32(DEVICE(&s->ide), "addr", dev->devfn + 1); + if (!qdev_realize(DEVICE(&s->ide), BUS(pci_bus), errp)) { + return; + } + pci_ide_create_devs(PCI_DEVICE(&s->ide)); + + /* USB */ + qdev_prop_set_int32(DEVICE(&s->uhci), "addr", dev->devfn + 2); + if (!qdev_realize(DEVICE(&s->uhci), BUS(pci_bus), errp)) { + return; + } + + pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS); } static void piix4_init(Object *obj) @@ -250,6 +269,8 @@ static void piix4_init(Object *obj) PIIX4State *s = PIIX4_PCI_DEVICE(obj); object_initialize_child(obj, "rtc", &s->rtc, TYPE_MC146818_RTC); + object_initialize_child(obj, "ide", &s->ide, "piix4-ide"); + object_initialize_child(obj, "uhci", &s->uhci, "piix4-usb-uhci"); } static void piix4_class_init(ObjectClass *klass, void *data) @@ -293,7 +314,6 @@ type_init(piix4_register_types) DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) { - PIIX4State *s; PCIDevice *pci; DeviceState *dev; int devfn = PCI_DEVFN(10, 0); @@ -301,15 +321,11 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) pci = pci_create_simple_multifunction(pci_bus, devfn, true, TYPE_PIIX4_PCI_DEVICE); dev = DEVICE(pci); - s = PIIX4_PCI_DEVICE(pci); + if (isa_bus) { *isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); } - pci = pci_create_simple(pci_bus, devfn + 1, "piix4-ide"); - pci_ide_create_devs(pci); - - pci_create_simple(pci_bus, devfn + 2, "piix4-usb-uhci"); if (smbus) { pci = pci_new(devfn + 3, TYPE_PIIX4_PM); qdev_prop_set_uint32(DEVICE(pci), "smb_io_base", 0x1100); @@ -320,7 +336,5 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pci), "i2c")); } - pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS); - return dev; } From e3d198eed1a2f6cc34f781fb3fe5c57caa66cc7c Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:39 +0200 Subject: [PATCH 118/180] hw/isa/piix4: Factor out ISABus retrieval from piix4_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modernizes the code. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220603185045.143789-6-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 6 +----- hw/mips/malta.c | 3 ++- include/hw/southbridge/piix.h | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 058bebb5e2..96df21a610 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -312,7 +312,7 @@ static void piix4_register_types(void) type_init(piix4_register_types) -DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) +DeviceState *piix4_create(PCIBus *pci_bus, I2CBus **smbus) { PCIDevice *pci; DeviceState *dev; @@ -322,10 +322,6 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus) TYPE_PIIX4_PCI_DEVICE); dev = DEVICE(pci); - if (isa_bus) { - *isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); - } - if (smbus) { pci = pci_new(devfn + 3, TYPE_PIIX4_PM); qdev_prop_set_uint32(DEVICE(pci), "smb_io_base", 0x1100); diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 9ffdc5b8f1..e446b25ad0 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1399,7 +1399,8 @@ void mips_malta_init(MachineState *machine) empty_slot_init("GT64120", 0, 0x20000000); /* Southbridge */ - dev = piix4_create(pci_bus, &isa_bus, &smbus); + dev = piix4_create(pci_bus, &smbus); + isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); /* Interrupt controller */ qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq); diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 3b97186f75..dab5c9704e 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -70,6 +70,6 @@ DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus); -DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus); +DeviceState *piix4_create(PCIBus *pci_bus, I2CBus **smbus); #endif From 19e375db22461b255d32704ad289508e0f1d9947 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:40 +0200 Subject: [PATCH 119/180] hw/isa/piix4: QOM'ify PIIX4 PM creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like the real hardware, create the PIIX4 ACPI controller as part of the PIIX4 southbridge. This also mirrors how the IDE and USB functions are already created. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-7-shentey@gmail.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 24 +++++++++++++----------- hw/mips/malta.c | 5 ++++- include/hw/southbridge/piix.h | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index 96df21a610..d97b245df3 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -49,6 +49,7 @@ struct PIIX4State { RTCState rtc; PCIIDEState ide; UHCIState uhci; + PIIX4PMState pm; /* Reset Control Register */ MemoryRegion rcr_mem; uint8_t rcr; @@ -261,6 +262,13 @@ static void piix4_realize(PCIDevice *dev, Error **errp) return; } + /* ACPI controller */ + qdev_prop_set_int32(DEVICE(&s->pm), "addr", dev->devfn + 3); + if (!qdev_realize(DEVICE(&s->pm), BUS(pci_bus), errp)) { + return; + } + qdev_connect_gpio_out(DEVICE(&s->pm), 0, s->isa[9]); + pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS); } @@ -271,6 +279,10 @@ static void piix4_init(Object *obj) object_initialize_child(obj, "rtc", &s->rtc, TYPE_MC146818_RTC); object_initialize_child(obj, "ide", &s->ide, "piix4-ide"); object_initialize_child(obj, "uhci", &s->uhci, "piix4-usb-uhci"); + + object_initialize_child(obj, "pm", &s->pm, TYPE_PIIX4_PM); + qdev_prop_set_uint32(DEVICE(&s->pm), "smb_io_base", 0x1100); + qdev_prop_set_bit(DEVICE(&s->pm), "smm-enabled", 0); } static void piix4_class_init(ObjectClass *klass, void *data) @@ -312,7 +324,7 @@ static void piix4_register_types(void) type_init(piix4_register_types) -DeviceState *piix4_create(PCIBus *pci_bus, I2CBus **smbus) +DeviceState *piix4_create(PCIBus *pci_bus) { PCIDevice *pci; DeviceState *dev; @@ -322,15 +334,5 @@ DeviceState *piix4_create(PCIBus *pci_bus, I2CBus **smbus) TYPE_PIIX4_PCI_DEVICE); dev = DEVICE(pci); - if (smbus) { - pci = pci_new(devfn + 3, TYPE_PIIX4_PM); - qdev_prop_set_uint32(DEVICE(pci), "smb_io_base", 0x1100); - qdev_prop_set_bit(DEVICE(pci), "smm-enabled", 0); - pci_realize_and_unref(pci, pci_bus, &error_fatal); - qdev_connect_gpio_out(DEVICE(pci), 0, - qdev_get_gpio_in_named(dev, "isa", 9)); - *smbus = I2C_BUS(qdev_get_child_bus(DEVICE(pci), "i2c")); - } - return dev; } diff --git a/hw/mips/malta.c b/hw/mips/malta.c index e446b25ad0..be9f26d841 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1238,6 +1238,7 @@ void mips_malta_init(MachineState *machine) int be; MaltaState *s; DeviceState *dev; + DeviceState *pm_dev; s = MIPS_MALTA(qdev_new(TYPE_MIPS_MALTA)); sysbus_realize_and_unref(SYS_BUS_DEVICE(s), &error_fatal); @@ -1399,8 +1400,10 @@ void mips_malta_init(MachineState *machine) empty_slot_init("GT64120", 0, 0x20000000); /* Southbridge */ - dev = piix4_create(pci_bus, &smbus); + dev = piix4_create(pci_bus); isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); + pm_dev = DEVICE(object_resolve_path_component(OBJECT(dev), "pm")); + smbus = I2C_BUS(qdev_get_child_bus(pm_dev, "i2c")); /* Interrupt controller */ qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq); diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index dab5c9704e..2357ce0287 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -70,6 +70,6 @@ DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus); -DeviceState *piix4_create(PCIBus *pci_bus, I2CBus **smbus); +DeviceState *piix4_create(PCIBus *pci_bus); #endif From e8ebf54936fcaa0da1ccd60f2c20df93f5aa68d1 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:41 +0200 Subject: [PATCH 120/180] hw/isa/piix4: Inline and remove piix4_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the previous changesets piix4_create() became a trivial wrapper around more generic functions. Modernize the code. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-8-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix4.c | 13 ------------- hw/mips/malta.c | 5 ++++- include/hw/southbridge/piix.h | 2 -- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c index d97b245df3..15f344dbb7 100644 --- a/hw/isa/piix4.c +++ b/hw/isa/piix4.c @@ -323,16 +323,3 @@ static void piix4_register_types(void) } type_init(piix4_register_types) - -DeviceState *piix4_create(PCIBus *pci_bus) -{ - PCIDevice *pci; - DeviceState *dev; - int devfn = PCI_DEVFN(10, 0); - - pci = pci_create_simple_multifunction(pci_bus, devfn, true, - TYPE_PIIX4_PCI_DEVICE); - dev = DEVICE(pci); - - return dev; -} diff --git a/hw/mips/malta.c b/hw/mips/malta.c index be9f26d841..7a0ec513b0 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1237,6 +1237,7 @@ void mips_malta_init(MachineState *machine) int fl_idx = 0; int be; MaltaState *s; + PCIDevice *piix4; DeviceState *dev; DeviceState *pm_dev; @@ -1400,7 +1401,9 @@ void mips_malta_init(MachineState *machine) empty_slot_init("GT64120", 0, 0x20000000); /* Southbridge */ - dev = piix4_create(pci_bus); + piix4 = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(10, 0), true, + TYPE_PIIX4_PCI_DEVICE); + dev = DEVICE(piix4); isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0")); pm_dev = DEVICE(object_resolve_path_component(OBJECT(dev), "pm")); smbus = I2C_BUS(qdev_get_child_bus(pm_dev, "i2c")); diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 2357ce0287..9a2dd93c2d 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -70,6 +70,4 @@ DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus); -DeviceState *piix4_create(PCIBus *pci_bus); - #endif From 5bf26b9393cc223dedd51cbe045aebc7afaf34ff Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:42 +0200 Subject: [PATCH 121/180] hw/isa/piix3: Move pci_map_irq_fn near pci_set_irq_fn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pci_map_irq_fn was implemented below type_init() which made it inaccessible to QOM functions. So move it up. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220603185045.143789-9-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix3.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index c92b36c4f2..d50a07b58b 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -79,6 +79,17 @@ static void piix3_set_irq(void *opaque, int pirq, int level) piix3_set_irq_level(piix3, pirq, level); } +/* + * Return the global irq number corresponding to a given device irq + * pin. We could also use the bus number to have a more precise mapping. + */ +static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) +{ + int slot_addend; + slot_addend = PCI_SLOT(pci_dev->devfn) - 1; + return (pci_intx + slot_addend) & 3; +} + static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin) { PIIX3State *piix3 = opaque; @@ -367,17 +378,6 @@ static void piix3_register_types(void) type_init(piix3_register_types) -/* - * Return the global irq number corresponding to a given device irq - * pin. We could also use the bus number to have a more precise mapping. - */ -static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) -{ - int slot_addend; - slot_addend = PCI_SLOT(pci_dev->devfn) - 1; - return (pci_intx + slot_addend) & 3; -} - PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus) { PIIX3State *piix3; From fe3055d2929f52c20b37385e2dd039675191bf17 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:43 +0200 Subject: [PATCH 122/180] hw/isa/piix3: QOM'ify PCI device creation and wiring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PCI interrupt wiring was performed in create() functions which are obsolete. Move these tasks into QOM functions to modernize the code. In order to avoid duplicate checking for xen_enabled() the realize methods are now split. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-10-shentey@gmail.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/piix3.c | 67 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index d50a07b58b..89064eb837 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/range.h" +#include "qapi/error.h" #include "hw/southbridge/piix.h" #include "hw/irq.h" #include "hw/isa/isa.h" @@ -278,7 +279,7 @@ static const MemoryRegionOps rcr_ops = { .endianness = DEVICE_LITTLE_ENDIAN }; -static void piix3_realize(PCIDevice *dev, Error **errp) +static void pci_piix3_realize(PCIDevice *dev, Error **errp) { PIIX3State *d = PIIX3_PCI_DEVICE(dev); @@ -317,7 +318,6 @@ static void pci_piix3_class_init(ObjectClass *klass, void *data) dc->desc = "ISA bridge"; dc->vmsd = &vmstate_piix3; dc->hotpluggable = false; - k->realize = piix3_realize; k->vendor_id = PCI_VENDOR_ID_INTEL; /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; @@ -343,11 +343,28 @@ static const TypeInfo piix3_pci_type_info = { }, }; +static void piix3_realize(PCIDevice *dev, Error **errp) +{ + ERRP_GUARD(); + PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev); + PCIBus *pci_bus = pci_get_bus(dev); + + pci_piix3_realize(dev, errp); + if (*errp) { + return; + } + + pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq, + piix3, PIIX_NUM_PIRQS); + pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq); +}; + static void piix3_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->config_write = piix3_write_config; + k->realize = piix3_realize; } static const TypeInfo piix3_info = { @@ -356,11 +373,33 @@ static const TypeInfo piix3_info = { .class_init = piix3_class_init, }; +static void piix3_xen_realize(PCIDevice *dev, Error **errp) +{ + ERRP_GUARD(); + PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev); + PCIBus *pci_bus = pci_get_bus(dev); + + pci_piix3_realize(dev, errp); + if (*errp) { + return; + } + + /* + * Xen supports additional interrupt routes from the PCI devices to + * the IOAPIC: the four pins of each PCI device on the bus are also + * connected to the IOAPIC directly. + * These additional routes can be discovered through ACPI. + */ + pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq, + piix3, XEN_PIIX_NUM_PIRQS); +}; + static void piix3_xen_class_init(ObjectClass *klass, void *data) { PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); k->config_write = piix3_write_config_xen; + k->realize = piix3_xen_realize; }; static const TypeInfo piix3_xen_info = { @@ -382,27 +421,11 @@ PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus) { PIIX3State *piix3; PCIDevice *pci_dev; + const char *type = xen_enabled() ? TYPE_PIIX3_XEN_DEVICE + : TYPE_PIIX3_DEVICE; - /* - * Xen supports additional interrupt routes from the PCI devices to - * the IOAPIC: the four pins of each PCI device on the bus are also - * connected to the IOAPIC directly. - * These additional routes can be discovered through ACPI. - */ - if (xen_enabled()) { - pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, - TYPE_PIIX3_XEN_DEVICE); - piix3 = PIIX3_PCI_DEVICE(pci_dev); - pci_bus_irqs(pci_bus, xen_piix3_set_irq, xen_pci_slot_get_pirq, - piix3, XEN_PIIX_NUM_PIRQS); - } else { - pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, - TYPE_PIIX3_DEVICE); - piix3 = PIIX3_PCI_DEVICE(pci_dev); - pci_bus_irqs(pci_bus, piix3_set_irq, pci_slot_get_pirq, - piix3, PIIX_NUM_PIRQS); - pci_bus_set_route_irq_fn(pci_bus, piix3_route_intx_pin_to_irq); - } + pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, type); + piix3 = PIIX3_PCI_DEVICE(pci_dev); *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0")); return piix3; From 6e8791fb6170a3eca90485056813e8eccb9080a9 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:44 +0200 Subject: [PATCH 123/180] hw/isa/piix3: Factor out ISABus retrieval from piix3_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modernizes the code. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-11-shentey@gmail.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc_piix.c | 3 ++- hw/isa/piix3.c | 3 +-- include/hw/southbridge/piix.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 7d5546600b..70c337c44b 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -207,9 +207,10 @@ static void pc_init1(MachineState *machine, pci_memory, ram_memory); pcms->bus = pci_bus; - piix3 = piix3_create(pci_bus, &isa_bus); + piix3 = piix3_create(pci_bus); piix3->pic = x86ms->gsi; piix3_devfn = piix3->dev.devfn; + isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0")); } else { pci_bus = NULL; i440fx_state = NULL; diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index 89064eb837..d57a7fe6d6 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -417,7 +417,7 @@ static void piix3_register_types(void) type_init(piix3_register_types) -PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus) +PIIX3State *piix3_create(PCIBus *pci_bus) { PIIX3State *piix3; PCIDevice *pci_dev; @@ -426,7 +426,6 @@ PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus) pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, type); piix3 = PIIX3_PCI_DEVICE(pci_dev); - *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0")); return piix3; } diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index 9a2dd93c2d..f805fb8683 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -68,6 +68,6 @@ DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, #define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen" #define TYPE_PIIX4_PCI_DEVICE "piix4-isa" -PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus); +PIIX3State *piix3_create(PCIBus *pci_bus); #endif From 988fb613215993dd0ce642b89ca8182c479d39dd Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 3 Jun 2022 20:50:45 +0200 Subject: [PATCH 124/180] hw/isa/piix3: Inline and remove piix3_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the previous changesets piix3_create() became a trivial wrapper around more generic functions. Modernize the code. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Message-Id: <20220603185045.143789-12-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc_piix.c | 6 +++++- hw/isa/piix3.c | 13 ------------- include/hw/southbridge/piix.h | 2 -- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 70c337c44b..0fc2361ffe 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -197,6 +197,9 @@ static void pc_init1(MachineState *machine, if (pcmc->pci_enabled) { PIIX3State *piix3; + PCIDevice *pci_dev; + const char *type = xen_enabled() ? TYPE_PIIX3_XEN_DEVICE + : TYPE_PIIX3_DEVICE; pci_bus = i440fx_init(host_type, pci_type, @@ -207,7 +210,8 @@ static void pc_init1(MachineState *machine, pci_memory, ram_memory); pcms->bus = pci_bus; - piix3 = piix3_create(pci_bus); + pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, type); + piix3 = PIIX3_PCI_DEVICE(pci_dev); piix3->pic = x86ms->gsi; piix3_devfn = piix3->dev.devfn; isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0")); diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index d57a7fe6d6..6388558f92 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -416,16 +416,3 @@ static void piix3_register_types(void) } type_init(piix3_register_types) - -PIIX3State *piix3_create(PCIBus *pci_bus) -{ - PIIX3State *piix3; - PCIDevice *pci_dev; - const char *type = xen_enabled() ? TYPE_PIIX3_XEN_DEVICE - : TYPE_PIIX3_DEVICE; - - pci_dev = pci_create_simple_multifunction(pci_bus, -1, true, type); - piix3 = PIIX3_PCI_DEVICE(pci_dev); - - return piix3; -} diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h index f805fb8683..2693778b23 100644 --- a/include/hw/southbridge/piix.h +++ b/include/hw/southbridge/piix.h @@ -68,6 +68,4 @@ DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE, #define TYPE_PIIX3_XEN_DEVICE "PIIX3-xen" #define TYPE_PIIX4_PCI_DEVICE "piix4-isa" -PIIX3State *piix3_create(PCIBus *pci_bus); - #endif From 94c720f39ede609ca659e9e351d634711656dbb4 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 29 May 2022 20:40:04 +0200 Subject: [PATCH 125/180] hw/i386/microvm-dt: Force explicit failure if retrieving QOM property fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New code will be added where this is best practice. So update existing code as well. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220529184006.10712-2-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/microvm-dt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/i386/microvm-dt.c b/hw/i386/microvm-dt.c index 9c3c4995b4..fde74819f2 100644 --- a/hw/i386/microvm-dt.c +++ b/hw/i386/microvm-dt.c @@ -32,6 +32,7 @@ */ #include "qemu/osdep.h" #include "qemu/cutils.h" +#include "qapi/error.h" #include "sysemu/device_tree.h" #include "hw/char/serial.h" #include "hw/i386/fw_cfg.h" @@ -187,8 +188,8 @@ static void dt_add_ioapic(MicrovmMachineState *mms, SysBusDevice *dev) static void dt_add_isa_serial(MicrovmMachineState *mms, ISADevice *dev) { const char compat[] = "ns16550"; - uint32_t irq = object_property_get_int(OBJECT(dev), "irq", NULL); - hwaddr base = object_property_get_int(OBJECT(dev), "iobase", NULL); + uint32_t irq = object_property_get_int(OBJECT(dev), "irq", &error_fatal); + hwaddr base = object_property_get_int(OBJECT(dev), "iobase", &error_fatal); hwaddr size = 8; char *nodename; From 8f3428cc8555c5226711f3b32073070d2481f5c8 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 29 May 2022 20:40:05 +0200 Subject: [PATCH 126/180] hw/i386/microvm-dt: Determine mc146818rtc's IRQ number from QOM property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 3b004a16540aa41f2aa6a1ceb0bf306716766914 'hw/rtc/ mc146818rtc: QOM'ify IRQ number' mc146818rtc's IRQ number is configurable. Fix microvm-dt to respect its value. Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220529184006.10712-3-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/microvm-dt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i386/microvm-dt.c b/hw/i386/microvm-dt.c index fde74819f2..287818c641 100644 --- a/hw/i386/microvm-dt.c +++ b/hw/i386/microvm-dt.c @@ -209,7 +209,7 @@ static void dt_add_isa_serial(MicrovmMachineState *mms, ISADevice *dev) static void dt_add_isa_rtc(MicrovmMachineState *mms, ISADevice *dev) { const char compat[] = "motorola,mc146818"; - uint32_t irq = RTC_ISA_IRQ; + uint32_t irq = object_property_get_uint(OBJECT(dev), "irq", &error_fatal); hwaddr base = RTC_ISA_BASE; hwaddr size = 8; char *nodename; From 5b21b331beaa20225b481ea068e21dcb65aba598 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 29 May 2022 20:40:06 +0200 Subject: [PATCH 127/180] hw/rtc/mc146818rtc: QOM'ify io_base offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exposing the io_base offset as a QOM property not only allows it to be configurable but also to be displayed in HMP: Before: (qemu) info qtree ... dev: mc146818rtc, id "" gpio-out "" 1 base_year = 0 (0x0) irq = 8 (0x8) lost_tick_policy = "discard" After: dev: mc146818rtc, id "" gpio-out "" 1 base_year = 0 (0x0) iobase = 112 (0x70) irq = 8 (0x8) lost_tick_policy = "discard" Signed-off-by: Bernhard Beschow Reviewed-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220529184006.10712-4-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/microvm-dt.c | 2 +- hw/rtc/mc146818rtc.c | 9 ++++++--- include/hw/rtc/mc146818rtc.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/i386/microvm-dt.c b/hw/i386/microvm-dt.c index 287818c641..b3049e4f9f 100644 --- a/hw/i386/microvm-dt.c +++ b/hw/i386/microvm-dt.c @@ -210,7 +210,7 @@ static void dt_add_isa_rtc(MicrovmMachineState *mms, ISADevice *dev) { const char compat[] = "motorola,mc146818"; uint32_t irq = object_property_get_uint(OBJECT(dev), "irq", &error_fatal); - hwaddr base = RTC_ISA_BASE; + hwaddr base = object_property_get_uint(OBJECT(dev), "iobase", &error_fatal); hwaddr size = 8; char *nodename; diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index ef9765bb8f..1ebb412479 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -74,6 +74,8 @@ #define RTC_CLOCK_RATE 32768 #define UIP_HOLD_LENGTH (8 * NANOSECONDS_PER_SECOND / 32768) +#define RTC_ISA_BASE 0x70 + static void rtc_set_time(RTCState *s); static void rtc_update_time(RTCState *s); static void rtc_set_cmos(RTCState *s, const struct tm *tm); @@ -941,7 +943,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) qemu_register_suspend_notifier(&s->suspend_notifier); memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2); - isa_register_ioport(isadev, &s->io, RTC_ISA_BASE); + isa_register_ioport(isadev, &s->io, s->io_base); /* register rtc 0x70 port for coalesced_pio */ memory_region_set_flush_coalesced(&s->io); @@ -950,7 +952,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) memory_region_add_subregion(&s->io, 0, &s->coalesced_io); memory_region_add_coalescing(&s->coalesced_io, 0, 1); - qdev_set_legacy_instance_id(dev, RTC_ISA_BASE, 3); + qdev_set_legacy_instance_id(dev, s->io_base, 3); object_property_add_tm(OBJECT(s), "date", rtc_get_date); @@ -983,6 +985,7 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq) static Property mc146818rtc_properties[] = { DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980), + DEFINE_PROP_UINT16("iobase", RTCState, io_base, RTC_ISA_BASE), DEFINE_PROP_UINT8("irq", RTCState, isairq, RTC_ISA_IRQ), DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState, lost_tick_policy, LOST_TICK_POLICY_DISCARD), @@ -1028,7 +1031,7 @@ static void rtc_build_aml(AcpiDevAmlIf *adev, Aml *scope) * does, even though qemu only responds to the first two ports. */ crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, RTC_ISA_BASE, RTC_ISA_BASE, + aml_append(crs, aml_io(AML_DECODE16, s->io_base, s->io_base, 0x01, 0x08)); aml_append(crs, aml_irq_no_flags(s->isairq)); diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h index 33d85753c0..1db0fcee92 100644 --- a/include/hw/rtc/mc146818rtc.h +++ b/include/hw/rtc/mc146818rtc.h @@ -26,6 +26,7 @@ struct RTCState { uint8_t cmos_data[128]; uint8_t cmos_index; uint8_t isairq; + uint16_t io_base; int32_t base_year; uint64_t base_rtc; uint64_t last_update; @@ -49,7 +50,6 @@ struct RTCState { }; #define RTC_ISA_IRQ 8 -#define RTC_ISA_BASE 0x70 ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq); From aa2e535c82eaf090dda5373c276598e4694c9273 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:00 +0200 Subject: [PATCH 128/180] hw: Reuse TYPE_I8042 define MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TYPE_I8042 is exported, so reuse it for consistency. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-2-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc.c | 4 ++-- hw/sparc64/sun4u.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1b6067ff22..af9e5edb04 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1097,7 +1097,7 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, return; } - i8042 = isa_create_simple(isa_bus, "i8042"); + i8042 = isa_create_simple(isa_bus, TYPE_I8042); if (!no_vmport) { isa_create_simple(isa_bus, TYPE_VMPORT); vmmouse = isa_try_new("vmmouse"); @@ -1105,7 +1105,7 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, vmmouse = NULL; } if (vmmouse) { - object_property_set_link(OBJECT(vmmouse), "i8042", OBJECT(i8042), + object_property_set_link(OBJECT(vmmouse), TYPE_I8042, OBJECT(i8042), &error_abort); isa_realize_and_unref(vmmouse, isa_bus, &error_fatal); } diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index d1bc77d27e..0e27715ac4 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -334,7 +334,7 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) parallel_hds_isa_init(s->isa_bus, MAX_PARALLEL_PORTS); /* Keyboard */ - isa_create_simple(s->isa_bus, "i8042"); + isa_create_simple(s->isa_bus, TYPE_I8042); /* Floppy */ for (i = 0; i < MAX_FD; i++) { From bae17e7483de896a1d1922e07c6727ad0536e64c Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:01 +0200 Subject: [PATCH 129/180] hw/audio/cs4231a: Const'ify global tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tables contain spcifically crafted constants for algorithms, so make them immutable. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-3-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/cs4231a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 0723e39430..7f17a72a9c 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -84,7 +84,7 @@ struct CSState { int transferred; int aci_counter; SWVoiceOut *voice; - int16_t *tab; + const int16_t *tab; }; #define MODE2 (1 << 6) @@ -142,13 +142,13 @@ enum { Capture_Lower_Base_Count }; -static int freqs[2][8] = { +static const int freqs[2][8] = { { 8000, 16000, 27420, 32000, -1, -1, 48000, 9000 }, { 5510, 11025, 18900, 22050, 37800, 44100, 33075, 6620 } }; /* Tables courtesy http://hazelware.luggle.com/tutorials/mulawcompression.html */ -static int16_t MuLawDecompressTable[256] = +static const int16_t MuLawDecompressTable[256] = { -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, @@ -184,7 +184,7 @@ static int16_t MuLawDecompressTable[256] = 56, 48, 40, 32, 24, 16, 8, 0 }; -static int16_t ALawDecompressTable[256] = +static const int16_t ALawDecompressTable[256] = { -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, From fc5f89236874bc5af1fa0674da876236cf710774 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:02 +0200 Subject: [PATCH 130/180] hw/i386/pc: Unexport PC_CPU_MODEL_IDS macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macro seems to be used only internally, so remove it. Signed-off-by: Bernhard Beschow Acked-by: Michael S. Tsirkin Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-4-shentey@gmail.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc.c | 9 +++++++++ include/hw/i386/pc.h | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index af9e5edb04..272d7227d5 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -98,6 +98,15 @@ #include "trace.h" #include CONFIG_DEVICES +/* + * Helper for setting model-id for CPU models that changed model-id + * depending on QEMU versions up to QEMU 2.4. + */ +#define PC_CPU_MODEL_IDS(v) \ + { "qemu32-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ + { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ + { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, + GlobalProperty pc_compat_7_0[] = {}; const size_t pc_compat_7_0_len = G_N_ELEMENTS(pc_compat_7_0); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 003a86b721..b58ac343ba 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -288,14 +288,6 @@ extern const size_t pc_compat_1_5_len; extern GlobalProperty pc_compat_1_4[]; extern const size_t pc_compat_1_4_len; -/* Helper for setting model-id for CPU models that changed model-id - * depending on QEMU versions up to QEMU 2.4. - */ -#define PC_CPU_MODEL_IDS(v) \ - { "qemu32-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ - { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ - { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, - #define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \ static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ { \ From 7112ffd93abd075a60e3848d0b9ff4ecaf72a653 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:07 +0200 Subject: [PATCH 131/180] accel/tcg/cpu-exec: Unexport dump_drift_info() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 3a841ab53f165910224dc4bebabf1a8f1d04200c 'qapi: introduce x-query-jit QMP command' basically moved the only function using dump_drift_info() to cpu-exec.c. Therefore, dump_drift_info() doesn't need to be exported any longer. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-9-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- accel/tcg/cpu-exec.c | 2 +- include/exec/cpu-all.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 635aeecc0a..7cbf9996b7 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -1048,7 +1048,7 @@ void tcg_exec_unrealizefn(CPUState *cpu) #ifndef CONFIG_USER_ONLY -void dump_drift_info(GString *buf) +static void dump_drift_info(GString *buf) { if (!icount_enabled()) { return; diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 5d5290deb5..9a716be80d 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -419,8 +419,6 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) } #ifdef CONFIG_TCG -/* accel/tcg/cpu-exec.c */ -void dump_drift_info(GString *buf); /* accel/tcg/translate-all.c */ void dump_exec_info(GString *buf); void dump_opcount_info(GString *buf); From cb76321ecce55cddc7fd86c1c2b705f919c4cb7e Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:03 +0200 Subject: [PATCH 132/180] hw/i386/pc: Unexport functions used only internally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Acked-by: Michael S. Tsirkin Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-5-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/i386/pc.c | 4 ++-- include/hw/i386/pc.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 272d7227d5..774cb2bf07 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -572,7 +572,7 @@ static const char * const fdc_container_path[] = { * Locate the FDC at IO address 0x3f0, in order to configure the CMOS registers * and ACPI objects. */ -ISADevice *pc_find_fdc0(void) +static ISADevice *pc_find_fdc0(void) { int i; Object *container; @@ -716,7 +716,7 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; -void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) +static void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) { static int nb_ne2k = 0; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index b58ac343ba..eb3d093bca 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -167,7 +167,6 @@ void pc_basic_device_init(struct PCMachineState *pcms, ISADevice **rtc_state, bool create_fdctrl, uint32_t hpet_irqs); -void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd); void pc_cmos_init(PCMachineState *pcms, BusState *ide0, BusState *ide1, ISADevice *s); @@ -178,8 +177,6 @@ typedef void (*cpu_set_smm_t)(int smm, void *arg); void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs); -ISADevice *pc_find_fdc0(void); - /* port92.c */ #define PORT92_A20_LINE "a20" From b01841fa85a607aa289d312da892aa444c29e942 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:08 +0200 Subject: [PATCH 133/180] accel/tcg: Inline dump_opcount_info() and remove it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dump_opcount_info() is a one-line wrapper around tcg_dump_op_count() which is also exported. So use the latter directly. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-10-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- accel/tcg/cpu-exec.c | 2 +- accel/tcg/translate-all.c | 5 ----- include/exec/cpu-all.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 7cbf9996b7..a565a3f8ec 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -1091,7 +1091,7 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) return NULL; } - dump_opcount_info(buf); + tcg_dump_op_count(buf); return human_readable_text_from_str(buf); } diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 291034cb09..8fd23a9d05 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2124,11 +2124,6 @@ void dump_exec_info(GString *buf) tcg_dump_info(buf); } -void dump_opcount_info(GString *buf) -{ - tcg_dump_op_count(buf); -} - #else /* CONFIG_USER_ONLY */ void cpu_interrupt(CPUState *cpu, int mask) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 9a716be80d..f5bda2c3ca 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -421,7 +421,6 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) #ifdef CONFIG_TCG /* accel/tcg/translate-all.c */ void dump_exec_info(GString *buf); -void dump_opcount_info(GString *buf); #endif /* CONFIG_TCG */ #endif /* !CONFIG_USER_ONLY */ From 68d58770d761d585002580856c4916e31a3efb3e Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:04 +0200 Subject: [PATCH 134/180] hw/i386/pc: Remove orphan declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernhard Beschow Acked-by: Michael S. Tsirkin Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-6-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- include/hw/i386/pc.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index eb3d093bca..b7735dccfc 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -171,9 +171,6 @@ void pc_cmos_init(PCMachineState *pcms, BusState *ide0, BusState *ide1, ISADevice *s); void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus); -void pc_pci_device_init(PCIBus *pci_bus); - -typedef void (*cpu_set_smm_t)(int smm, void *arg); void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs); From 37da3bcf01ccd19336fd8f43bedcd0841d71bb6a Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:09 +0200 Subject: [PATCH 135/180] docs/devel: Fix link to developer mailing lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ammends commit 9f73de8df0335c9387f4ee39e207a65a1615676f 'docs: rSTify the "SubmitAPatch" wiki'. Cc: qemu-stable@nongnu.org Signed-off-by: Bernhard Beschow Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-11-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/submitting-a-patch.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/devel/submitting-a-patch.rst b/docs/devel/submitting-a-patch.rst index d3876ec1b7..09a8d12c2c 100644 --- a/docs/devel/submitting-a-patch.rst +++ b/docs/devel/submitting-a-patch.rst @@ -18,9 +18,9 @@ one-shot fix, the bare minimum we ask is that: `__ policy.) ``git commit -s`` or ``git format-patch -s`` will add one. - All contributions to QEMU must be **sent as patches** to the - qemu-devel `mailing list `__. Patch contributions - should not be posted on the bug tracker, posted on forums, or - externally hosted and linked to. (We have other mailing lists too, + qemu-devel `mailing list `__. + Patch contributions should not be posted on the bug tracker, posted on + forums, or externally hosted and linked to. (We have other mailing lists too, but all patches must go to qemu-devel, possibly with a Cc: to another list.) ``git send-email`` (`step-by-step setup guide `__ and `hints and From 3d9641509ad88eb326f9ea5a9270c9f27e4ddc5f Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:06 +0200 Subject: [PATCH 136/180] hw/net/fsl_etsec/etsec: Remove obsolete and unused etsec_create() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit etsec_create() wraps qdev API which is outdated. It is also unused, so remove it. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Mark Cave-Ayland Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-8-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/net/fsl_etsec/etsec.c | 23 ----------------------- hw/net/fsl_etsec/etsec.h | 7 ------- 2 files changed, 30 deletions(-) diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index 4e6cc708de..b75d8e3dce 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -443,26 +443,3 @@ static void etsec_register_types(void) } type_init(etsec_register_types) - -DeviceState *etsec_create(hwaddr base, - MemoryRegion * mr, - NICInfo * nd, - qemu_irq tx_irq, - qemu_irq rx_irq, - qemu_irq err_irq) -{ - DeviceState *dev; - - dev = qdev_new("eTSEC"); - qdev_set_nic_properties(dev, nd); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, tx_irq); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, rx_irq); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, err_irq); - - memory_region_add_subregion(mr, base, - SYS_BUS_DEVICE(dev)->mmio[0].memory); - - return dev; -} diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h index fddf551544..3c625c955c 100644 --- a/hw/net/fsl_etsec/etsec.h +++ b/hw/net/fsl_etsec/etsec.h @@ -155,13 +155,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(eTSEC, ETSEC_COMMON) #define eTSEC_TRANSMIT 1 #define eTSEC_RECEIVE 2 -DeviceState *etsec_create(hwaddr base, - MemoryRegion *mr, - NICInfo *nd, - qemu_irq tx_irq, - qemu_irq rx_irq, - qemu_irq err_irq); - void etsec_update_irq(eTSEC *etsec); void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr); From b1f66fab45e795eca94f61674be1ef5ce223f65d Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 5 Jun 2022 17:19:08 +0200 Subject: [PATCH 137/180] hw/mips/boston: Initialize g_autofree pointers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes compilation due to false positives with -Werror: In file included from /usr/include/glib-2.0/glib.h:114, from qemu/src/include/glib-compat.h:32, from qemu/src/include/qemu/osdep.h:144, from ../src/hw/mips/boston.c:20: In function ‘g_autoptr_cleanup_generic_gfree’, inlined from ‘boston_mach_init’ at ../src/hw/mips/boston.c:790:52: /usr/include/glib-2.0/glib/glib-autocleanups.h:28:3: error: ‘dtb_load_data’ may be used uninitialized [-Werror=maybe-uninitialized] 28 | g_free (*pp); | ^~~~~~~~~~~~ ../src/hw/mips/boston.c: In function ‘boston_mach_init’: ../src/hw/mips/boston.c:790:52: note: ‘dtb_load_data’ was declared here 790 | g_autofree const void *dtb_file_data, *dtb_load_data; | ^~~~~~~~~~~~~ In function ‘g_autoptr_cleanup_generic_gfree’, inlined from ‘boston_mach_init’ at ../src/hw/mips/boston.c:790:36: /usr/include/glib-2.0/glib/glib-autocleanups.h:28:3: error: ‘dtb_file_data’ may be used uninitialized [-Werror=maybe-uninitialized] 28 | g_free (*pp); | ^~~~~~~~~~~~ ../src/hw/mips/boston.c: In function ‘boston_mach_init’: ../src/hw/mips/boston.c:790:36: note: ‘dtb_file_data’ was declared here 790 | g_autofree const void *dtb_file_data, *dtb_load_data; | ^~~~~~~~~~~~~ cc1: all warnings being treated as errors Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20220605151908.30566-1-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/boston.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 59ca08b93a..1debca18ec 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -787,7 +787,8 @@ static void boston_mach_init(MachineState *machine) if (kernel_size > 0) { int dt_size; - g_autofree const void *dtb_file_data, *dtb_load_data; + g_autofree const void *dtb_file_data = NULL; + g_autofree const void *dtb_load_data = NULL; hwaddr dtb_paddr = QEMU_ALIGN_UP(kernel_high, 64 * KiB); hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0(NULL, dtb_paddr); From c304d11f45777eba014c394e09f8a9aacf2a928d Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:07 +0200 Subject: [PATCH 138/180] accel/tcg/cpu-exec: Unexport dump_drift_info() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 3a841ab53f165910224dc4bebabf1a8f1d04200c 'qapi: introduce x-query-jit QMP command' basically moved the only function using dump_drift_info() to cpu-exec.c. Therefore, dump_drift_info() doesn't need to be exported any longer. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-9-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- accel/tcg/cpu-exec.c | 2 +- include/exec/cpu-all.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 635aeecc0a..7cbf9996b7 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -1048,7 +1048,7 @@ void tcg_exec_unrealizefn(CPUState *cpu) #ifndef CONFIG_USER_ONLY -void dump_drift_info(GString *buf) +static void dump_drift_info(GString *buf) { if (!icount_enabled()) { return; diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 5d5290deb5..9a716be80d 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -419,8 +419,6 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) } #ifdef CONFIG_TCG -/* accel/tcg/cpu-exec.c */ -void dump_drift_info(GString *buf); /* accel/tcg/translate-all.c */ void dump_exec_info(GString *buf); void dump_opcount_info(GString *buf); From ea7c4527832ebe11e5f9349489e6c2784a27db69 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:08 +0200 Subject: [PATCH 139/180] accel/tcg: Inline dump_opcount_info() and remove it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dump_opcount_info() is a one-line wrapper around tcg_dump_op_count() which is also exported. So use the latter directly. Signed-off-by: Bernhard Beschow Reviewed-by: Philippe Mathieu-Daudé Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-10-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- accel/tcg/cpu-exec.c | 2 +- accel/tcg/translate-all.c | 5 ----- include/exec/cpu-all.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 7cbf9996b7..a565a3f8ec 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -1091,7 +1091,7 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) return NULL; } - dump_opcount_info(buf); + tcg_dump_op_count(buf); return human_readable_text_from_str(buf); } diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 291034cb09..8fd23a9d05 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2124,11 +2124,6 @@ void dump_exec_info(GString *buf) tcg_dump_info(buf); } -void dump_opcount_info(GString *buf) -{ - tcg_dump_op_count(buf); -} - #else /* CONFIG_USER_ONLY */ void cpu_interrupt(CPUState *cpu, int mask) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 9a716be80d..f5bda2c3ca 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -421,7 +421,6 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr) #ifdef CONFIG_TCG /* accel/tcg/translate-all.c */ void dump_exec_info(GString *buf); -void dump_opcount_info(GString *buf); #endif /* CONFIG_TCG */ #endif /* !CONFIG_USER_ONLY */ From 6e0c18598814bffb67204a90890fb7b34cad288a Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Fri, 20 May 2022 20:01:09 +0200 Subject: [PATCH 140/180] docs/devel: Fix link to developer mailing lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ammends commit 9f73de8df0335c9387f4ee39e207a65a1615676f 'docs: rSTify the "SubmitAPatch" wiki'. Cc: qemu-stable@nongnu.org Signed-off-by: Bernhard Beschow Acked-by: Mark Cave-Ayland Message-Id: <20220520180109.8224-11-shentey@gmail.com> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/submitting-a-patch.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/devel/submitting-a-patch.rst b/docs/devel/submitting-a-patch.rst index d3876ec1b7..09a8d12c2c 100644 --- a/docs/devel/submitting-a-patch.rst +++ b/docs/devel/submitting-a-patch.rst @@ -18,9 +18,9 @@ one-shot fix, the bare minimum we ask is that: `__ policy.) ``git commit -s`` or ``git format-patch -s`` will add one. - All contributions to QEMU must be **sent as patches** to the - qemu-devel `mailing list `__. Patch contributions - should not be posted on the bug tracker, posted on forums, or - externally hosted and linked to. (We have other mailing lists too, + qemu-devel `mailing list `__. + Patch contributions should not be posted on the bug tracker, posted on + forums, or externally hosted and linked to. (We have other mailing lists too, but all patches must go to qemu-devel, possibly with a Cc: to another list.) ``git send-email`` (`step-by-step setup guide `__ and `hints and From b2df786170a4954d6346c284b8351ca79265d190 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 13 Jun 2022 18:12:52 +0100 Subject: [PATCH 141/180] test/tcg/arm: Use -mfloat-abi=soft for test-armv6m-undef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC11 from crossbuild-essential-armhf from ubuntu 22.04 errors: cc1: error: ‘-mfloat-abi=hard’: selected architecture lacks an FPU Signed-off-by: Richard Henderson Reviewed-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220604032713.174976-1-richard.henderson@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20220613171258.1905715-2-alex.bennee@linaro.org> --- tests/tcg/arm/Makefile.softmmu-target | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/arm/Makefile.softmmu-target b/tests/tcg/arm/Makefile.softmmu-target index 3fe237ba39..7df88ddea8 100644 --- a/tests/tcg/arm/Makefile.softmmu-target +++ b/tests/tcg/arm/Makefile.softmmu-target @@ -20,7 +20,7 @@ LDFLAGS+=-nostdlib -N -static # Specific Test Rules -test-armv6m-undef: EXTRA_CFLAGS+=-mcpu=cortex-m0 +test-armv6m-undef: EXTRA_CFLAGS+=-mcpu=cortex-m0 -mfloat-abi=soft run-test-armv6m-undef: QEMU_OPTS+=-semihosting -M microbit -kernel run-plugin-test-armv6m-undef-%: QEMU_OPTS+=-semihosting -M microbit -kernel From 6012d96379873825ab20d629b828e833023feb9d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 13 Jun 2022 18:12:53 +0100 Subject: [PATCH 142/180] tests/tcg/i386: Use explicit suffix on fist insns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a number of assembler warnings of the form: test-i386.c: Assembler messages: test-i386.c:869: Warning: no instruction mnemonic suffix given and no register operands; using default for `fist' Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220527171143.168276-1-richard.henderson@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20220613171258.1905715-3-alex.bennee@linaro.org> --- tests/tcg/i386/test-i386-fp-exceptions.c | 24 ++++++++++++------------ tests/tcg/i386/test-i386.c | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/tcg/i386/test-i386-fp-exceptions.c b/tests/tcg/i386/test-i386-fp-exceptions.c index dfb7117c17..d445f13c33 100644 --- a/tests/tcg/i386/test-i386-fp-exceptions.c +++ b/tests/tcg/i386/test-i386-fp-exceptions.c @@ -423,35 +423,35 @@ int main(void) } __asm__ volatile ("fnclex"); - __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (1.5L) : "st"); + __asm__ volatile ("fistps %0" : "=m" (res_16) : "t" (1.5L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != PE) { printf("FAIL: fistp inexact\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (32767.5L) : "st"); + __asm__ volatile ("fistps %0" : "=m" (res_16) : "t" (32767.5L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fistp 32767.5\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (-32768.51L) : "st"); + __asm__ volatile ("fistps %0" : "=m" (res_16) : "t" (-32768.51L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fistp -32768.51\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (ld_nan) : "st"); + __asm__ volatile ("fistps %0" : "=m" (res_16) : "t" (ld_nan) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fistp nan\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : + __asm__ volatile ("fistps %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { @@ -538,49 +538,49 @@ int main(void) } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (1.5L) : "st"); + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (1.5L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != PE) { printf("FAIL: fisttp inexact\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (32768.0L) : "st"); + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (32768.0L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fisttp 32768\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (32768.5L) : "st"); + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (32768.5L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fisttp 32768.5\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (-32769.0L) : "st"); + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (-32769.0L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fisttp -32769\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (-32769.5L) : "st"); + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (-32769.5L) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fisttp -32769.5\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (ld_nan) : "st"); + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (ld_nan) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { printf("FAIL: fisttp nan\n"); ret = 1; } __asm__ volatile ("fnclex"); - __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : + __asm__ volatile ("fisttps %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : "st"); __asm__ volatile ("fnstsw" : "=a" (sw)); if ((sw & EXC) != IE) { diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c index 18d5609665..ac8d5a3c1f 100644 --- a/tests/tcg/i386/test-i386.c +++ b/tests/tcg/i386/test-i386.c @@ -866,7 +866,7 @@ void test_fcvt(double a) uint16_t val16; val16 = (fpuc & ~0x0c00) | (i << 10); asm volatile ("fldcw %0" : : "m" (val16)); - asm volatile ("fist %0" : "=m" (wa) : "t" (a)); + asm volatile ("fists %0" : "=m" (wa) : "t" (a)); asm volatile ("fistl %0" : "=m" (ia) : "t" (a)); asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st"); asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a)); From 72ec89bfc5291b8e322a1a60d96d7f43c0375f16 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 13 Jun 2022 18:12:54 +0100 Subject: [PATCH 143/180] gitlab-ci: Fix the build-cfi-aarch64 and build-cfi-ppc64-s390x jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The job definitions recently got a second "variables:" section by accident and thus are failing now if one tries to run them. Merge the two sections into one again to fix the issue. And while we're at it, bump the timeout here (70 minutes are currently not enough for the aarch64 job). The jobs are marked as manual anyway, so if the user starts them, they want to see their result for sure and then it's annoying if the job timeouts too early. Fixes: e312d1fdbb ("gitlab: convert build/container jobs to .base_job_template") Signed-off-by: Thomas Huth Acked-by: Richard Henderson Message-Id: <20220603124809.70794-1-thuth@redhat.com> Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Message-Id: <20220613171258.1905715-4-alex.bennee@linaro.org> --- .gitlab-ci.d/buildtest.yml | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 544385f5be..cb7cad44b5 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -357,16 +357,15 @@ build-cfi-aarch64: --enable-safe-stack --enable-slirp=git TARGETS: aarch64-softmmu MAKE_CHECK_ARGS: check-build - timeout: 70m - artifacts: - expire_in: 2 days - paths: - - build - variables: # FIXME: This job is often failing, likely due to out-of-memory problems in # the constrained containers of the shared runners. Thus this is marked as # skipped until the situation has been solved. QEMU_JOB_SKIPPED: 1 + timeout: 90m + artifacts: + expire_in: 2 days + paths: + - build check-cfi-aarch64: extends: .native_test_job_template @@ -398,16 +397,15 @@ build-cfi-ppc64-s390x: --enable-safe-stack --enable-slirp=git TARGETS: ppc64-softmmu s390x-softmmu MAKE_CHECK_ARGS: check-build - timeout: 70m - artifacts: - expire_in: 2 days - paths: - - build - variables: # FIXME: This job is often failing, likely due to out-of-memory problems in # the constrained containers of the shared runners. Thus this is marked as # skipped until the situation has been solved. QEMU_JOB_SKIPPED: 1 + timeout: 80m + artifacts: + expire_in: 2 days + paths: + - build check-cfi-ppc64-s390x: extends: .native_test_job_template From ab698a4d8b32be717a675880935c774be66f0d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 13 Jun 2022 18:12:55 +0100 Subject: [PATCH 144/180] tests/docker: fix the IMAGE for build invocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We inadvertently broke the ability to run local builds when the code was re-factored. The result was the run stanza failing to find the docker image with it's qemu/ prefix. Signed-off-by: Alex Bennée Fixes: d39eaa2266 ("tests/docker: simplify docker-TEST@IMAGE targets") Reviewed-by: Richard Henderson Message-Id: <20220613171258.1905715-5-alex.bennee@linaro.org> --- tests/docker/Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index e68f91b853..ef4518d9eb 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -171,7 +171,7 @@ DOCKER_TESTS := $(if $(TESTS), $(filter $(TESTS), $(__TESTS)), $(__TESTS)) $(foreach i,$(filter-out $(DOCKER_PARTIAL_IMAGES),$(DOCKER_IMAGES)), \ $(foreach t,$(DOCKER_TESTS), \ $(eval .PHONY: docker-$t@$i) \ - $(eval docker-$t@$i: docker-image-$i; @$(MAKE) docker-run TEST=$t IMAGE=$i) \ + $(eval docker-$t@$i: docker-image-$i; @$(MAKE) docker-run TEST=$t IMAGE=qemu/$i) \ ) \ $(foreach t,$(DOCKER_TESTS), \ $(eval docker-all-tests: docker-$t@$i) \ From c48a5c4741d663a77ab3a2b0c1df3a58de6ee340 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 13 Jun 2022 18:12:56 +0100 Subject: [PATCH 145/180] tests/tcg: disable xtensa-linux-user again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The move from tests/tcg/configure.sh started enabling the container image for xtensa-linux-user, which fails because the compiler does not have the full set of headers. The cause is the "xtensa*-softmmu)" case in tests/tcg/configure.sh which became just "xtensa*)" in the new probe_target_compiler shell function. Look out for xtensa*-linux-user and do not configure it. Reported-by: Alex Bennée Signed-off-by: Paolo Bonzini Message-Id: <20220608135727.1341946-1-pbonzini@redhat.com> Fixes: cd362defbb ("tests/tcg: merge configure.sh back into main configure script") Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220613171258.1905715-6-alex.bennee@linaro.org> --- configure | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configure b/configure index e69537c756..4b12a8094c 100755 --- a/configure +++ b/configure @@ -2024,7 +2024,6 @@ probe_target_compiler() { container_cross_prefix=x86_64-linux-gnu- ;; xtensa*) - # FIXME: xtensa-linux-user? container_hosts=x86_64 container_image=debian-xtensa-cross @@ -2481,6 +2480,10 @@ for target in $target_list; do echo "# Automatically generated by configure - do not modify" > $config_target_mak echo "TARGET_NAME=$arch" >> $config_target_mak case $target in + xtensa*-linux-user) + # the toolchain is not complete with headers, only build softmmu tests + continue + ;; *-softmmu) test -f $source_path/tests/tcg/$arch/Makefile.softmmu-target || continue qemu="qemu-system-$arch" From 34776d80f312f36c8cbdf632337dc087e724b568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 13 Jun 2022 18:12:57 +0100 Subject: [PATCH 146/180] gitlab: compare CIRRUS_nn vars against 'null' not "" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GitLab variable comparisons don't have shell like semantics where an unset variable compares equal to empty string. We need to explicitly test against 'null' to detect an unset variable. Signed-off-by: Daniel P. Berrangé Tested-by: Richard Henderson Reviewed-by: Richard Henderson Reviewed-by: Thomas Huth Message-Id: <20220608160651.248781-1-berrange@redhat.com> Signed-off-by: Alex Bennée Message-Id: <20220613171258.1905715-7-alex.bennee@linaro.org> --- .gitlab-ci.d/base.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.d/base.yml b/.gitlab-ci.d/base.yml index f334f3ded7..69b36c148a 100644 --- a/.gitlab-ci.d/base.yml +++ b/.gitlab-ci.d/base.yml @@ -13,7 +13,7 @@ ############################################################# # Cirrus jobs can't run unless the creds / target repo are set - - if: '$QEMU_JOB_CIRRUS && ($CIRRUS_GITHUB_REPO == "" || $CIRRUS_API_TOKEN == "")' + - if: '$QEMU_JOB_CIRRUS && ($CIRRUS_GITHUB_REPO == null || $CIRRUS_API_TOKEN == null)' when: never # Publishing jobs should only run on the default branch in upstream From b56d1ee9514be227854a589b4e11551bed4448a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 13 Jun 2022 18:12:58 +0100 Subject: [PATCH 147/180] .gitlab: use less aggressive nproc on our aarch64/32 runners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running on all 80 cores of our aarch64 runner does occasionally trigger a race condition which fails the build. However the CI system is not the time and place to play with much heisenbugs so turn down the nproc to "only" use 40 cores in the build. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Tested-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220613171258.1905715-8-alex.bennee@linaro.org> --- .../custom-runners/ubuntu-20.04-aarch32.yml | 4 ++-- .../custom-runners/ubuntu-20.04-aarch64.yml | 24 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml index 47856ac53c..1998460d06 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml @@ -19,5 +19,5 @@ ubuntu-20.04-aarch32-all: - mkdir build - cd build - ../configure --cross-prefix=arm-linux-gnueabihf- - - make --output-sync -j`nproc` - - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc --ignore=40` + - make --output-sync -j`nproc --ignore=40` check V=1 diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml index 951e490db1..65718a188a 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml @@ -17,9 +17,9 @@ ubuntu-20.04-aarch64-all-linux-static: - mkdir build - cd build - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh - - make --output-sync -j`nproc` - - make --output-sync -j`nproc` check V=1 - - make --output-sync -j`nproc` check-tcg V=1 + - make --output-sync -j`nproc --ignore=40` + - make --output-sync -j`nproc --ignore=40` check V=1 + - make --output-sync -j`nproc --ignore=40` check-tcg V=1 ubuntu-20.04-aarch64-all: needs: [] @@ -38,8 +38,8 @@ ubuntu-20.04-aarch64-all: - mkdir build - cd build - ../configure --disable-libssh - - make --output-sync -j`nproc` - - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc --ignore=40` + - make --output-sync -j`nproc --ignore=40` check V=1 ubuntu-20.04-aarch64-alldbg: needs: [] @@ -55,8 +55,8 @@ ubuntu-20.04-aarch64-alldbg: - cd build - ../configure --enable-debug --disable-libssh - make clean - - make --output-sync -j`nproc` - - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc --ignore=40` + - make --output-sync -j`nproc --ignore=40` check V=1 ubuntu-20.04-aarch64-clang: needs: [] @@ -75,8 +75,8 @@ ubuntu-20.04-aarch64-clang: - mkdir build - cd build - ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers - - make --output-sync -j`nproc` - - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc --ignore=40` + - make --output-sync -j`nproc --ignore=40` check V=1 ubuntu-20.04-aarch64-tci: needs: [] @@ -95,7 +95,7 @@ ubuntu-20.04-aarch64-tci: - mkdir build - cd build - ../configure --disable-libssh --enable-tcg-interpreter - - make --output-sync -j`nproc` + - make --output-sync -j`nproc --ignore=40` ubuntu-20.04-aarch64-notcg: needs: [] @@ -114,5 +114,5 @@ ubuntu-20.04-aarch64-notcg: - mkdir build - cd build - ../configure --disable-libssh --disable-tcg - - make --output-sync -j`nproc` - - make --output-sync -j`nproc` check V=1 + - make --output-sync -j`nproc --ignore=40` + - make --output-sync -j`nproc --ignore=40` check V=1 From e561b3b7df11875d7bd3b8670598cae5601a7f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 5 Jun 2022 10:51:30 +0200 Subject: [PATCH 148/180] ui/gtk-gl-area: implement GL context destruction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The counterpart function for gd_gl_area_create_context() is currently empty. Implement the gd_gl_area_destroy_context() function to avoid GL context leaks. Signed-off-by: Volker Rümelin Message-Id: <20220605085131.7711-1-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- ui/gtk-gl-area.c | 8 +++++++- ui/trace-events | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index fc5a082eb8..0e20ea031d 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -201,7 +201,13 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx) { - /* FIXME */ + GdkGLContext *current_ctx = gdk_gl_context_get_current(); + + trace_gd_gl_area_destroy_context(ctx, current_ctx); + if (ctx == current_ctx) { + gdk_gl_context_clear_current(); + } + g_clear_object(&ctx); } void gd_gl_area_scanout_texture(DisplayChangeListener *dcl, diff --git a/ui/trace-events b/ui/trace-events index f78b5e6606..1040ba0f88 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -26,6 +26,7 @@ gd_key_event(const char *tab, int gdk_keycode, int qkeycode, const char *action) gd_grab(const char *tab, const char *device, const char *reason) "tab=%s, dev=%s, reason=%s" gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s" gd_keymap_windowing(const char *name) "backend=%s" +gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, current_ctx=%p" # vnc-auth-sasl.c # vnc-auth-vencrypt.c From 09053670c9b83f1f4759f37e62a6f2b1a5bbd105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 5 Jun 2022 10:51:31 +0200 Subject: [PATCH 149/180] ui/gtk-gl-area: create the requested GL context version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since about 2018 virglrenderer (commit fa835b0f88 "vrend: don't hardcode context version") tries to open the highest available GL context version. This is done by creating the known GL context versions from the highest to the lowest until (*create_gl_context) returns a context != NULL. This does not work properly with the current QEMU gd_gl_area_create_context() function, because gdk_gl_context_realize() on Wayland creates a version 3.0 legacy context if the requested GL context version can't be created. In order for virglrenderer to find the highest available GL context version, return NULL if the created context version is lower than the requested version. This fixes the following error: QEMU started with -device virtio-vga-gl -display gtk,gl=on. Under Wayland, the guest window remains black and the following information can be seen on the host. gl_version 30 - compat profile (qemu:5978): Gdk-WARNING **: 16:19:01.533: gdk_gl_context_set_required_version - GL context versions less than 3.2 are not supported. (qemu:5978): Gdk-WARNING **: 16:19:01.537: gdk_gl_context_set_required_version - GL context versions less than 3.2 are not supported. (qemu:5978): Gdk-WARNING **: 16:19:01.554: gdk_gl_context_set_required_version - GL context versions less than 3.2 are not supported. vrend_renderer_fill_caps: Entering with stale GL error: 1282 To reproduce this error, an OpenGL driver is required on the host that doesn't have the latest OpenGL extensions fully implemented. An example for this is the Intel i965 driver on a Haswell processor. Signed-off-by: Volker Rümelin Message-Id: <20220605085131.7711-2-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- ui/gtk-gl-area.c | 31 ++++++++++++++++++++++++++++++- ui/trace-events | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 0e20ea031d..2e0129c28c 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -170,6 +170,23 @@ void gd_gl_area_switch(DisplayChangeListener *dcl, } } +static int gd_cmp_gl_context_version(int major, int minor, QEMUGLParams *params) +{ + if (major > params->major_ver) { + return 1; + } + if (major < params->major_ver) { + return -1; + } + if (minor > params->minor_ver) { + return 1; + } + if (minor < params->minor_ver) { + return -1; + } + return 0; +} + QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { @@ -177,8 +194,8 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, GdkWindow *window; GdkGLContext *ctx; GError *err = NULL; + int major, minor; - gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); window = gtk_widget_get_window(vc->gfx.drawing_area); ctx = gdk_window_create_gl_context(window, &err); if (err) { @@ -196,6 +213,18 @@ QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, g_clear_object(&ctx); return NULL; } + + gdk_gl_context_make_current(ctx); + gdk_gl_context_get_version(ctx, &major, &minor); + gdk_gl_context_clear_current(); + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); + + if (gd_cmp_gl_context_version(major, minor, params) == -1) { + /* created ctx version < requested version */ + g_clear_object(&ctx); + } + + trace_gd_gl_area_create_context(ctx, params->major_ver, params->minor_ver); return ctx; } diff --git a/ui/trace-events b/ui/trace-events index 1040ba0f88..a922f00e10 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -26,6 +26,7 @@ gd_key_event(const char *tab, int gdk_keycode, int qkeycode, const char *action) gd_grab(const char *tab, const char *device, const char *reason) "tab=%s, dev=%s, reason=%s" gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s" gd_keymap_windowing(const char *name) "backend=%s" +gd_gl_area_create_context(void *ctx, int major, int minor) "ctx=%p, major=%d, minor=%d" gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, current_ctx=%p" # vnc-auth-sasl.c From 2910abd6b4364ee96d2339b2be8858246fcd3161 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 29 May 2022 17:25:08 +0900 Subject: [PATCH 150/180] ui/cocoa: Fix poweroff request code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220529082508.89097-1-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/cocoa.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 09a62817f2..84c84e98fc 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -35,6 +35,7 @@ #include "ui/kbd-state.h" #include "sysemu/sysemu.h" #include "sysemu/runstate.h" +#include "sysemu/runstate-action.h" #include "sysemu/cpu-throttle.h" #include "qapi/error.h" #include "qapi/qapi-commands-block.h" @@ -1290,7 +1291,10 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven { COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n"); - qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI); + with_iothread_lock(^{ + shutdown_action = SHUTDOWN_ACTION_POWEROFF; + qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI); + }); /* * Sleep here, because returning will cause OSX to kill us From d7d34918551dc48a2f6b42b44a12c7a9183f89e6 Mon Sep 17 00:00:00 2001 From: "Hongren (Zenithal) Zheng" Date: Thu, 19 May 2022 20:38:10 +0800 Subject: [PATCH 151/180] hw/usb: Add CanoKey Implementation This commit added a new emulated device called CanoKey to QEMU. CanoKey implements platform independent features in canokey-core https://github.com/canokeys/canokey-core, and leaves the USB implementation to the platform. In this commit the USB part was implemented in QEMU using QEMU's USB APIs, therefore the emulated CanoKey can communicate with the guest OS using USB. Signed-off-by: Hongren (Zenithal) Zheng Message-Id: Signed-off-by: Gerd Hoffmann --- hw/usb/canokey.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++ hw/usb/canokey.h | 69 +++++++++++ 2 files changed, 369 insertions(+) create mode 100644 hw/usb/canokey.c create mode 100644 hw/usb/canokey.h diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c new file mode 100644 index 0000000000..6cb8b7cdb0 --- /dev/null +++ b/hw/usb/canokey.c @@ -0,0 +1,300 @@ +/* + * CanoKey QEMU device implementation. + * + * Copyright (c) 2021-2022 Canokeys.org + * Written by Hongren (Zenithal) Zheng + * + * This code is licensed under the Apache-2.0. + */ + +#include "qemu/osdep.h" +#include + +#include "qemu/module.h" +#include "qapi/error.h" +#include "hw/usb.h" +#include "hw/qdev-properties.h" +#include "desc.h" +#include "canokey.h" + +#define CANOKEY_EP_IN(ep) ((ep) & 0x7F) + +#define CANOKEY_VENDOR_NUM 0x20a0 +#define CANOKEY_PRODUCT_NUM 0x42d2 + +/* + * placeholder, canokey-qemu implements its own usb desc + * Namely we do not use usb_desc_handle_contorl + */ +enum { + STR_MANUFACTURER = 1, + STR_PRODUCT, + STR_SERIALNUMBER +}; + +static const USBDescStrings desc_strings = { + [STR_MANUFACTURER] = "canokeys.org", + [STR_PRODUCT] = "CanoKey QEMU", + [STR_SERIALNUMBER] = "0" +}; + +static const USBDescDevice desc_device_canokey = { + .bcdUSB = 0x0, + .bMaxPacketSize0 = 16, + .bNumConfigurations = 0, + .confs = NULL, +}; + +static const USBDesc desc_canokey = { + .id = { + .idVendor = CANOKEY_VENDOR_NUM, + .idProduct = CANOKEY_PRODUCT_NUM, + .bcdDevice = 0x0100, + .iManufacturer = STR_MANUFACTURER, + .iProduct = STR_PRODUCT, + .iSerialNumber = STR_SERIALNUMBER, + }, + .full = &desc_device_canokey, + .high = &desc_device_canokey, + .str = desc_strings, +}; + + +/* + * libcanokey-qemu.so side functions + * All functions are called from canokey_emu_device_loop + */ +int canokey_emu_stall_ep(void *base, uint8_t ep) +{ + CanoKeyState *key = base; + uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */ + key->ep_in_size[ep_in] = 0; + key->ep_in_state[ep_in] = CANOKEY_EP_IN_STALL; + return 0; +} + +int canokey_emu_set_address(void *base, uint8_t addr) +{ + CanoKeyState *key = base; + key->dev.addr = addr; + return 0; +} + +int canokey_emu_prepare_receive( + void *base, uint8_t ep, uint8_t *pbuf, uint16_t size) +{ + CanoKeyState *key = base; + key->ep_out[ep] = pbuf; + key->ep_out_size[ep] = size; + return 0; +} + +int canokey_emu_transmit( + void *base, uint8_t ep, const uint8_t *pbuf, uint16_t size) +{ + CanoKeyState *key = base; + uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */ + memcpy(key->ep_in[ep_in] + key->ep_in_size[ep_in], + pbuf, size); + key->ep_in_size[ep_in] += size; + key->ep_in_state[ep_in] = CANOKEY_EP_IN_READY; + /* + * ready for more data in device loop + * + * Note: this is a quirk for CanoKey CTAPHID + * because it calls multiple emu_transmit in one device_loop + * but w/o data_in it would stuck in device_loop + * This has no side effect for CCID as it is strictly + * OUT then IN transfer + * However it has side effect for Control transfer + */ + if (ep_in != 0) { + canokey_emu_data_in(ep_in); + } + return 0; +} + +uint32_t canokey_emu_get_rx_data_size(void *base, uint8_t ep) +{ + CanoKeyState *key = base; + return key->ep_out_size[ep]; +} + +/* + * QEMU side functions + */ +static void canokey_handle_reset(USBDevice *dev) +{ + CanoKeyState *key = CANOKEY(dev); + for (int i = 0; i != CANOKEY_EP_NUM; ++i) { + key->ep_in_state[i] = CANOKEY_EP_IN_WAIT; + key->ep_in_pos[i] = 0; + key->ep_in_size[i] = 0; + } + canokey_emu_reset(); +} + +static void canokey_handle_control(USBDevice *dev, USBPacket *p, + int request, int value, int index, int length, uint8_t *data) +{ + CanoKeyState *key = CANOKEY(dev); + + canokey_emu_setup(request, value, index, length); + + uint32_t dir_in = request & DeviceRequest; + if (!dir_in) { + /* OUT */ + if (key->ep_out[0] != NULL) { + memcpy(key->ep_out[0], data, length); + } + canokey_emu_data_out(p->ep->nr, data); + } + + canokey_emu_device_loop(); + + /* IN */ + switch (key->ep_in_state[0]) { + case CANOKEY_EP_IN_WAIT: + p->status = USB_RET_NAK; + break; + case CANOKEY_EP_IN_STALL: + p->status = USB_RET_STALL; + break; + case CANOKEY_EP_IN_READY: + memcpy(data, key->ep_in[0], key->ep_in_size[0]); + p->actual_length = key->ep_in_size[0]; + /* reset state */ + key->ep_in_state[0] = CANOKEY_EP_IN_WAIT; + key->ep_in_size[0] = 0; + key->ep_in_pos[0] = 0; + break; + } +} + +static void canokey_handle_data(USBDevice *dev, USBPacket *p) +{ + CanoKeyState *key = CANOKEY(dev); + + uint8_t ep_in = CANOKEY_EP_IN(p->ep->nr); + uint8_t ep_out = p->ep->nr; + uint32_t in_len; + uint32_t out_pos; + uint32_t out_len; + switch (p->pid) { + case USB_TOKEN_OUT: + usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size); + out_pos = 0; + while (out_pos != p->iov.size) { + /* + * key->ep_out[ep_out] set by prepare_receive + * to be a buffer inside libcanokey-qemu.so + * key->ep_out_size[ep_out] set by prepare_receive + * to be the buffer length + */ + out_len = MIN(p->iov.size - out_pos, key->ep_out_size[ep_out]); + memcpy(key->ep_out[ep_out], + key->ep_out_buffer[ep_out] + out_pos, out_len); + out_pos += out_len; + /* update ep_out_size to actual len */ + key->ep_out_size[ep_out] = out_len; + canokey_emu_data_out(ep_out, NULL); + } + break; + case USB_TOKEN_IN: + if (key->ep_in_pos[ep_in] == 0) { /* first time IN */ + canokey_emu_data_in(ep_in); + canokey_emu_device_loop(); /* may call transmit multiple times */ + } + switch (key->ep_in_state[ep_in]) { + case CANOKEY_EP_IN_WAIT: + /* NAK for early INTR IN */ + p->status = USB_RET_NAK; + break; + case CANOKEY_EP_IN_STALL: + p->status = USB_RET_STALL; + break; + case CANOKEY_EP_IN_READY: + /* submit part of ep_in buffer to USBPacket */ + in_len = MIN(key->ep_in_size[ep_in] - key->ep_in_pos[ep_in], + p->iov.size); + usb_packet_copy(p, + key->ep_in[ep_in] + key->ep_in_pos[ep_in], in_len); + key->ep_in_pos[ep_in] += in_len; + /* reset state if all data submitted */ + if (key->ep_in_pos[ep_in] == key->ep_in_size[ep_in]) { + key->ep_in_state[ep_in] = CANOKEY_EP_IN_WAIT; + key->ep_in_size[ep_in] = 0; + key->ep_in_pos[ep_in] = 0; + } + break; + } + break; + default: + p->status = USB_RET_STALL; + break; + } +} + +static void canokey_realize(USBDevice *base, Error **errp) +{ + CanoKeyState *key = CANOKEY(base); + + if (key->file == NULL) { + error_setg(errp, "You must provide file=/path/to/canokey-file"); + return; + } + + usb_desc_init(base); + + for (int i = 0; i != CANOKEY_EP_NUM; ++i) { + key->ep_in_state[i] = CANOKEY_EP_IN_WAIT; + key->ep_in_size[i] = 0; + key->ep_in_pos[i] = 0; + } + + if (canokey_emu_init(key, key->file)) { + error_setg(errp, "canokey can not create or read %s", key->file); + return; + } +} + +static void canokey_unrealize(USBDevice *base) +{ +} + +static Property canokey_properties[] = { + DEFINE_PROP_STRING("file", CanoKeyState, file), + DEFINE_PROP_END_OF_LIST(), +}; + +static void canokey_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->product_desc = "CanoKey QEMU"; + uc->usb_desc = &desc_canokey; + uc->handle_reset = canokey_handle_reset; + uc->handle_control = canokey_handle_control; + uc->handle_data = canokey_handle_data; + uc->handle_attach = usb_desc_attach; + uc->realize = canokey_realize; + uc->unrealize = canokey_unrealize; + dc->desc = "CanoKey QEMU"; + device_class_set_props(dc, canokey_properties); + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo canokey_info = { + .name = TYPE_CANOKEY, + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(CanoKeyState), + .class_init = canokey_class_init +}; + +static void canokey_register_types(void) +{ + type_register_static(&canokey_info); +} + +type_init(canokey_register_types) diff --git a/hw/usb/canokey.h b/hw/usb/canokey.h new file mode 100644 index 0000000000..24cf304203 --- /dev/null +++ b/hw/usb/canokey.h @@ -0,0 +1,69 @@ +/* + * CanoKey QEMU device header. + * + * Copyright (c) 2021-2022 Canokeys.org + * Written by Hongren (Zenithal) Zheng + * + * This code is licensed under the Apache-2.0. + */ + +#ifndef CANOKEY_H +#define CANOKEY_H + +#include "hw/qdev-core.h" + +#define TYPE_CANOKEY "canokey" +#define CANOKEY(obj) \ + OBJECT_CHECK(CanoKeyState, (obj), TYPE_CANOKEY) + +/* + * State of Canokey (i.e. hw/canokey.c) + */ + +/* CTRL INTR BULK */ +#define CANOKEY_EP_NUM 3 +/* BULK/INTR IN can be up to 1352 bytes, e.g. get key info */ +#define CANOKEY_EP_IN_BUFFER_SIZE 2048 +/* BULK OUT can be up to 270 bytes, e.g. PIV import cert */ +#define CANOKEY_EP_OUT_BUFFER_SIZE 512 + +typedef enum { + CANOKEY_EP_IN_WAIT, + CANOKEY_EP_IN_READY, + CANOKEY_EP_IN_STALL +} CanoKeyEPState; + +typedef struct CanoKeyState { + USBDevice dev; + + /* IN packets from canokey device loop */ + uint8_t ep_in[CANOKEY_EP_NUM][CANOKEY_EP_IN_BUFFER_SIZE]; + /* + * See canokey_emu_transmit + * + * For large INTR IN, receive multiple data from canokey device loop + * in this case ep_in_size would increase with every call + */ + uint32_t ep_in_size[CANOKEY_EP_NUM]; + /* + * Used in canokey_handle_data + * for IN larger than p->iov.size, we would do multiple handle_data() + * + * The difference between ep_in_pos and ep_in_size: + * We first increase ep_in_size to fill ep_in buffer in device_loop, + * then use ep_in_pos to submit data from ep_in buffer in handle_data + */ + uint32_t ep_in_pos[CANOKEY_EP_NUM]; + CanoKeyEPState ep_in_state[CANOKEY_EP_NUM]; + + /* OUT pointer to canokey recv buffer */ + uint8_t *ep_out[CANOKEY_EP_NUM]; + uint32_t ep_out_size[CANOKEY_EP_NUM]; + /* For large BULK OUT, multiple write to ep_out is needed */ + uint8_t ep_out_buffer[CANOKEY_EP_NUM][CANOKEY_EP_OUT_BUFFER_SIZE]; + + /* Properties */ + char *file; /* canokey-file */ +} CanoKeyState; + +#endif /* CANOKEY_H */ From d37d0e0e855222b89008930b8675198ce74f8d4f Mon Sep 17 00:00:00 2001 From: "Hongren (Zenithal) Zheng" Date: Thu, 19 May 2022 20:38:30 +0800 Subject: [PATCH 152/180] hw/usb/canokey: Add trace events Signed-off-by: Hongren (Zenithal) Zheng Message-Id: Signed-off-by: Gerd Hoffmann --- hw/usb/canokey.c | 13 +++++++++++++ hw/usb/trace-events | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c index 6cb8b7cdb0..4a08b1cbd7 100644 --- a/hw/usb/canokey.c +++ b/hw/usb/canokey.c @@ -14,6 +14,7 @@ #include "qapi/error.h" #include "hw/usb.h" #include "hw/qdev-properties.h" +#include "trace.h" #include "desc.h" #include "canokey.h" @@ -66,6 +67,7 @@ static const USBDesc desc_canokey = { */ int canokey_emu_stall_ep(void *base, uint8_t ep) { + trace_canokey_emu_stall_ep(ep); CanoKeyState *key = base; uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */ key->ep_in_size[ep_in] = 0; @@ -75,6 +77,7 @@ int canokey_emu_stall_ep(void *base, uint8_t ep) int canokey_emu_set_address(void *base, uint8_t addr) { + trace_canokey_emu_set_address(addr); CanoKeyState *key = base; key->dev.addr = addr; return 0; @@ -83,6 +86,7 @@ int canokey_emu_set_address(void *base, uint8_t addr) int canokey_emu_prepare_receive( void *base, uint8_t ep, uint8_t *pbuf, uint16_t size) { + trace_canokey_emu_prepare_receive(ep, size); CanoKeyState *key = base; key->ep_out[ep] = pbuf; key->ep_out_size[ep] = size; @@ -92,6 +96,7 @@ int canokey_emu_prepare_receive( int canokey_emu_transmit( void *base, uint8_t ep, const uint8_t *pbuf, uint16_t size) { + trace_canokey_emu_transmit(ep, size); CanoKeyState *key = base; uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */ memcpy(key->ep_in[ep_in] + key->ep_in_size[ep_in], @@ -125,6 +130,7 @@ uint32_t canokey_emu_get_rx_data_size(void *base, uint8_t ep) */ static void canokey_handle_reset(USBDevice *dev) { + trace_canokey_handle_reset(); CanoKeyState *key = CANOKEY(dev); for (int i = 0; i != CANOKEY_EP_NUM; ++i) { key->ep_in_state[i] = CANOKEY_EP_IN_WAIT; @@ -137,6 +143,7 @@ static void canokey_handle_reset(USBDevice *dev) static void canokey_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { + trace_canokey_handle_control_setup(request, value, index, length); CanoKeyState *key = CANOKEY(dev); canokey_emu_setup(request, value, index, length); @@ -144,6 +151,7 @@ static void canokey_handle_control(USBDevice *dev, USBPacket *p, uint32_t dir_in = request & DeviceRequest; if (!dir_in) { /* OUT */ + trace_canokey_handle_control_out(); if (key->ep_out[0] != NULL) { memcpy(key->ep_out[0], data, length); } @@ -163,6 +171,7 @@ static void canokey_handle_control(USBDevice *dev, USBPacket *p, case CANOKEY_EP_IN_READY: memcpy(data, key->ep_in[0], key->ep_in_size[0]); p->actual_length = key->ep_in_size[0]; + trace_canokey_handle_control_in(p->actual_length); /* reset state */ key->ep_in_state[0] = CANOKEY_EP_IN_WAIT; key->ep_in_size[0] = 0; @@ -182,6 +191,7 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p) uint32_t out_len; switch (p->pid) { case USB_TOKEN_OUT: + trace_canokey_handle_data_out(ep_out, p->iov.size); usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size); out_pos = 0; while (out_pos != p->iov.size) { @@ -226,6 +236,7 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p) key->ep_in_size[ep_in] = 0; key->ep_in_pos[ep_in] = 0; } + trace_canokey_handle_data_in(ep_in, in_len); break; } break; @@ -237,6 +248,7 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p) static void canokey_realize(USBDevice *base, Error **errp) { + trace_canokey_realize(); CanoKeyState *key = CANOKEY(base); if (key->file == NULL) { @@ -260,6 +272,7 @@ static void canokey_realize(USBDevice *base, Error **errp) static void canokey_unrealize(USBDevice *base) { + trace_canokey_unrealize(); } static Property canokey_properties[] = { diff --git a/hw/usb/trace-events b/hw/usb/trace-events index 9773cb5330..914ca71668 100644 --- a/hw/usb/trace-events +++ b/hw/usb/trace-events @@ -345,3 +345,19 @@ usb_serial_set_baud(int bus, int addr, int baud) "dev %d:%u baud rate %d" usb_serial_set_data(int bus, int addr, int parity, int data, int stop) "dev %d:%u parity %c, data bits %d, stop bits %d" usb_serial_set_flow_control(int bus, int addr, int index) "dev %d:%u flow control %d" usb_serial_set_xonxoff(int bus, int addr, uint8_t xon, uint8_t xoff) "dev %d:%u xon 0x%x xoff 0x%x" + +# canokey.c +canokey_emu_stall_ep(uint8_t ep) "ep %d" +canokey_emu_set_address(uint8_t addr) "addr %d" +canokey_emu_prepare_receive(uint8_t ep, uint16_t size) "ep %d size %d" +canokey_emu_transmit(uint8_t ep, uint16_t size) "ep %d size %d" +canokey_thread_start(void) +canokey_thread_stop(void) +canokey_handle_reset(void) +canokey_handle_control_setup(int request, int value, int index, int length) "request 0x%04X value 0x%04X index 0x%04X length 0x%04X" +canokey_handle_control_out(void) +canokey_handle_control_in(int actual_len) "len %d" +canokey_handle_data_out(uint8_t ep_out, uint32_t out_len) "ep %d len %d" +canokey_handle_data_in(uint8_t ep_in, uint32_t in_len) "ep %d len %d" +canokey_realize(void) +canokey_unrealize(void) From 8caef8507809634fc70ecb1faa898a0edaf1ae5c Mon Sep 17 00:00:00 2001 From: "Hongren (Zenithal) Zheng" Date: Thu, 19 May 2022 20:38:57 +0800 Subject: [PATCH 153/180] meson: Add CanoKey Signed-off-by: Hongren (Zenithal) Zheng Message-Id: Signed-off-by: Gerd Hoffmann --- hw/usb/Kconfig | 5 +++++ hw/usb/meson.build | 5 +++++ meson.build | 6 ++++++ meson_options.txt | 2 ++ scripts/meson-buildoptions.sh | 3 +++ 5 files changed, 21 insertions(+) diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig index 53f8283ffd..ce4f433976 100644 --- a/hw/usb/Kconfig +++ b/hw/usb/Kconfig @@ -119,6 +119,11 @@ config USB_U2F default y depends on USB +config USB_CANOKEY + bool + default y + depends on USB + config IMX_USBPHY bool default y diff --git a/hw/usb/meson.build b/hw/usb/meson.build index de853d780d..793df42e21 100644 --- a/hw/usb/meson.build +++ b/hw/usb/meson.build @@ -63,6 +63,11 @@ if u2f.found() softmmu_ss.add(when: 'CONFIG_USB_U2F', if_true: [u2f, files('u2f-emulated.c')]) endif +# CanoKey +if canokey.found() + softmmu_ss.add(when: 'CONFIG_USB_CANOKEY', if_true: [canokey, files('canokey.c')]) +endif + # usb redirect if usbredir.found() usbredir_ss = ss.source_set() diff --git a/meson.build b/meson.build index 21cd949082..0c2e11ff07 100644 --- a/meson.build +++ b/meson.build @@ -1408,6 +1408,12 @@ if have_system method: 'pkg-config', kwargs: static_kwargs) endif +canokey = not_found +if have_system + canokey = dependency('canokey-qemu', required: get_option('canokey'), + method: 'pkg-config', + kwargs: static_kwargs) +endif usbredir = not_found if not get_option('usb_redir').auto() or have_system usbredir = dependency('libusbredirparser-0.5', required: get_option('usb_redir'), diff --git a/meson_options.txt b/meson_options.txt index 2de94af037..0e8197386b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -189,6 +189,8 @@ option('spice_protocol', type : 'feature', value : 'auto', description: 'Spice protocol support') option('u2f', type : 'feature', value : 'auto', description: 'U2F emulation support') +option('canokey', type : 'feature', value : 'auto', + description: 'CanoKey support') option('usb_redir', type : 'feature', value : 'auto', description: 'libusbredir support') option('l2tpv3', type : 'feature', value : 'auto', diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 00ea4d8cd1..1fc1d2e2c3 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -73,6 +73,7 @@ meson_options_help() { printf "%s\n" ' bpf eBPF support' printf "%s\n" ' brlapi brlapi character device driver' printf "%s\n" ' bzip2 bzip2 support for DMG images' + printf "%s\n" ' canokey CanoKey support' printf "%s\n" ' cap-ng cap_ng support' printf "%s\n" ' capstone Whether and how to find the capstone library' printf "%s\n" ' cloop cloop image format support' @@ -204,6 +205,8 @@ _meson_option_parse() { --disable-brlapi) printf "%s" -Dbrlapi=disabled ;; --enable-bzip2) printf "%s" -Dbzip2=enabled ;; --disable-bzip2) printf "%s" -Dbzip2=disabled ;; + --enable-canokey) printf "%s" -Dcanokey=enabled ;; + --disable-canokey) printf "%s" -Dcanokey=disabled ;; --enable-cap-ng) printf "%s" -Dcap_ng=enabled ;; --disable-cap-ng) printf "%s" -Dcap_ng=disabled ;; --enable-capstone) printf "%s" -Dcapstone=enabled ;; From 994e735c830f01e58710fdc01f5c527ed2ac7aba Mon Sep 17 00:00:00 2001 From: "Hongren (Zenithal) Zheng" Date: Thu, 19 May 2022 20:39:38 +0800 Subject: [PATCH 154/180] docs: Add CanoKey documentation Signed-off-by: Hongren (Zenithal) Zheng Message-Id: Signed-off-by: Gerd Hoffmann --- docs/system/device-emulation.rst | 1 + docs/system/devices/canokey.rst | 168 +++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 docs/system/devices/canokey.rst diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst index 3b729b920d..0506006056 100644 --- a/docs/system/device-emulation.rst +++ b/docs/system/device-emulation.rst @@ -92,3 +92,4 @@ Emulated Devices devices/vhost-user.rst devices/virtio-pmem.rst devices/vhost-user-rng.rst + devices/canokey.rst diff --git a/docs/system/devices/canokey.rst b/docs/system/devices/canokey.rst new file mode 100644 index 0000000000..169f99b8eb --- /dev/null +++ b/docs/system/devices/canokey.rst @@ -0,0 +1,168 @@ +.. _canokey: + +CanoKey QEMU +------------ + +CanoKey [1]_ is an open-source secure key with supports of + +* U2F / FIDO2 with Ed25519 and HMAC-secret +* OpenPGP Card V3.4 with RSA4096, Ed25519 and more [2]_ +* PIV (NIST SP 800-73-4) +* HOTP / TOTP +* NDEF + +All these platform-independent features are in canokey-core [3]_. + +For different platforms, CanoKey has different implementations, +including both hardware implementions and virtual cards: + +* CanoKey STM32 [4]_ +* CanoKey Pigeon [5]_ +* (virt-card) CanoKey USB/IP +* (virt-card) CanoKey FunctionFS + +In QEMU, yet another CanoKey virt-card is implemented. +CanoKey QEMU exposes itself as a USB device to the guest OS. + +With the same software configuration as a hardware key, +the guest OS can use all the functionalities of a secure key as if +there was actually an hardware key plugged in. + +CanoKey QEMU provides much convenience for debuging: + +* libcanokey-qemu supports debuging output thus developers can + inspect what happens inside a secure key +* CanoKey QEMU supports trace event thus event +* QEMU USB stack supports pcap thus USB packet between the guest + and key can be captured and analysed + +Then for developers: + +* For developers on software with secure key support (e.g. FIDO2, OpenPGP), + they can see what happens inside the secure key +* For secure key developers, USB packets between guest OS and CanoKey + can be easily captured and analysed + +Also since this is a virtual card, it can be easily used in CI for testing +on code coping with secure key. + +Building +======== + +libcanokey-qemu is required to use CanoKey QEMU. + +.. code-block:: shell + + git clone https://github.com/canokeys/canokey-qemu + mkdir canokey-qemu/build + pushd canokey-qemu/build + +If you want to install libcanokey-qemu in a different place, +add ``-DCMAKE_INSTALL_PREFIX=/path/to/your/place`` to cmake below. + +.. code-block:: shell + + cmake .. + make + make install # may need sudo + popd + +Then configuring and building: + +.. code-block:: shell + + # depending on your env, lib/pkgconfig can be lib64/pkgconfig + export PKG_CONFIG_PATH=/path/to/your/place/lib/pkgconfig:$PKG_CONFIG_PATH + ./configure --enable-canokey && make + +Using CanoKey QEMU +================== + +CanoKey QEMU stores all its data on a file of the host specified by the argument +when invoking qemu. + +.. parsed-literal:: + + |qemu_system| -usb -device canokey,file=$HOME/.canokey-file + +Note: you should keep this file carefully as it may contain your private key! + +The first time when the file is used, it is created and initialized by CanoKey, +afterwards CanoKey QEMU would just read this file. + +After the guest OS boots, you can check that there is a USB device. + +For example, If the guest OS is an Linux machine. You may invoke lsusb +and find CanoKey QEMU there: + +.. code-block:: shell + + $ lsusb + Bus 001 Device 002: ID 20a0:42d4 Clay Logic CanoKey QEMU + +You may setup the key as guided in [6]_. The console for the key is at [7]_. + +Debuging +======== + +CanoKey QEMU consists of two parts, ``libcanokey-qemu.so`` and ``canokey.c``, +the latter of which resides in QEMU. The former provides core functionality +of a secure key while the latter provides platform-dependent functions: +USB packet handling. + +If you want to trace what happens inside the secure key, when compiling +libcanokey-qemu, you should add ``-DQEMU_DEBUG_OUTPUT=ON`` in cmake command +line: + +.. code-block:: shell + + cmake .. -DQEMU_DEBUG_OUTPUT=ON + +If you want to trace events happened in canokey.c, use + +.. parsed-literal:: + + |qemu_system| --trace "canokey_*" \\ + -usb -device canokey,file=$HOME/.canokey-file + +If you want to capture USB packets between the guest and the host, you can: + +.. parsed-literal:: + + |qemu_system| -usb -device canokey,file=$HOME/.canokey-file,pcap=key.pcap + +Limitations +=========== + +Currently libcanokey-qemu.so has dozens of global variables as it was originally +designed for embedded systems. Thus one qemu instance can not have +multiple CanoKey QEMU running, namely you can not + +.. parsed-literal:: + + |qemu_system| -usb -device canokey,file=$HOME/.canokey-file \\ + -device canokey,file=$HOME/.canokey-file2 + +Also, there is no lock on canokey-file, thus two CanoKey QEMU instance +can not read one canokey-file at the same time. + +Another limitation is that this device is not compatible with ``qemu-xhci``, +in that this device would hang when there are FIDO2 packets (traffic on +interrupt endpoints). If you do not use FIDO2 then it works as intended, +but for full functionality you should use old uhci/ehci bus and attach canokey +to it, for example + +.. parsed-literal:: + + |qemu_system| -device piix3-usb-uhci,id=uhci -device canokey,bus=uhci.0 + +References +========== + +.. [1] ``_ +.. [2] ``_ +.. [3] ``_ +.. [4] ``_ +.. [5] ``_ +.. [6] ``_ +.. [7] ``_ From adaf4d2e84d30e559327917b0725f98f0d5b8cd4 Mon Sep 17 00:00:00 2001 From: "Hongren (Zenithal) Zheng" Date: Thu, 19 May 2022 20:40:03 +0800 Subject: [PATCH 155/180] docs/system/devices/usb: Add CanoKey to USB devices examples Signed-off-by: Hongren (Zenithal) Zheng Message-Id: Signed-off-by: Gerd Hoffmann --- docs/system/devices/usb.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/system/devices/usb.rst b/docs/system/devices/usb.rst index afb7d6c226..872d916758 100644 --- a/docs/system/devices/usb.rst +++ b/docs/system/devices/usb.rst @@ -199,6 +199,10 @@ option or the ``device_add`` monitor command. Available devices are: ``u2f-{emulated,passthru}`` Universal Second Factor device +``canokey`` + An Open-source Secure Key implementing FIDO2, OpenPGP, PIV and more. + For more information, see :ref:`canokey`. + Physical port addressing ^^^^^^^^^^^^^^^^^^^^^^^^ From 5028d66cb2fb5ec6c2997b1ab274230ffdd57bbc Mon Sep 17 00:00:00 2001 From: "Hongren (Zenithal) Zheng" Date: Thu, 19 May 2022 20:40:55 +0800 Subject: [PATCH 156/180] MAINTAINERS: add myself as CanoKey maintainer Signed-off-by: Hongren (Zenithal) Zheng Message-Id: Signed-off-by: Gerd Hoffmann --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0df25ed4b0..4cf6174f9f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2427,6 +2427,14 @@ F: hw/intc/s390_flic*.c F: include/hw/s390x/s390_flic.h L: qemu-s390x@nongnu.org +CanoKey +M: Hongren (Zenithal) Zheng +S: Maintained +R: Canokeys.org +F: hw/usb/canokey.c +F: hw/usb/canokey.h +F: docs/system/devices/canokey.rst + Subsystems ---------- Overall Audio backends From f471e8b060798f26a7fc339c6152f82f22a7b33d Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Sun, 8 May 2022 17:32:22 +0200 Subject: [PATCH 157/180] hw/usb/hcd-ehci: fix writeback order The 'active' bit passes control over a qTD between the guest and the controller: set to 1 by guest to enable execution by the controller, and the controller sets it to '0' to hand back control to the guest. ehci_state_writeback write two dwords to main memory using DMA: the third dword of the qTD (containing dt, total bytes to transfer, cpage, cerr and status) and the fourth dword of the qTD (containing the offset). This commit makes sure the fourth dword is written before the third, avoiding a race condition where a new offset written into the qTD by the guest after it observed the status going to go to '0' gets overwritten by a 'late' DMA writeback of the previous offset. This race condition could lead to 'cpage out of range (5)' errors, and reproduced by: ./qemu-system-x86_64 -enable-kvm -bios $SEABIOS/bios.bin -m 4096 -device usb-ehci -blockdev driver=file,read-only=on,filename=/home/aengelen/Downloads/openSUSE-Tumbleweed-DVD-i586-Snapshot20220428-Media.iso,node-name=iso -device usb-storage,drive=iso,bootindex=0 -chardev pipe,id=shell,path=/tmp/pipe -device virtio-serial -device virtconsole,chardev=shell -device virtio-rng-pci -serial mon:stdio -nographic (press a key, select 'Installation' (2), and accept the default values. On my machine the 'cpage out of range' is reproduced while loading the Linux Kernel about once per 7 attempts. With the fix in this commit it no longer fails) This problem was previously reported as a seabios problem in https://mail.coreboot.org/hyperkitty/list/seabios@seabios.org/thread/OUTHT5ISSQJGXPNTUPY3O5E5EPZJCHM3/ and as a nixos CI build failure in https://github.com/NixOS/nixpkgs/issues/170803 Signed-off-by: Arnout Engelen Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ehci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 33a8a377bd..d4da8dcb8d 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2011,7 +2011,10 @@ static int ehci_state_writeback(EHCIQueue *q) ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd); qtd = (uint32_t *) &q->qh.next_qtd; addr = NLPTR_GET(p->qtdaddr); - put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 2); + /* First write back the offset */ + put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qtd + 3, 1); + /* Then write back the token, clearing the 'active' bit */ + put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 1); ehci_free_packet(p); /* From 0631d4b448454ae8a1ab091c447e3f71ab6e088a Mon Sep 17 00:00:00 2001 From: Joelle van Dyne Date: Fri, 6 May 2022 21:18:50 -0700 Subject: [PATCH 158/180] usbredir: avoid queuing hello packet on snapshot restore When launching QEMU with "-loadvm", usbredir_create_parser() should avoid setting up the hello packet (just as with "-incoming". On the latest version of libusbredir, usbredirparser_unserialize() will return error if the parser is not "pristine." Signed-off-by: Joelle van Dyne Message-Id: <20220507041850.98716-1-j@getutm.app> Signed-off-by: Gerd Hoffmann --- hw/usb/redirect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index fd7df599bc..1bd30efc3e 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1280,7 +1280,8 @@ static void usbredir_create_parser(USBRedirDevice *dev) } #endif - if (runstate_check(RUN_STATE_INMIGRATE)) { + if (runstate_check(RUN_STATE_INMIGRATE) || + runstate_check(RUN_STATE_PRELAUNCH)) { flags |= usbredirparser_fl_no_hello; } usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, From 45e64ab63d7deb77b9fd1d2a3d43fee5cb17a5b5 Mon Sep 17 00:00:00 2001 From: Dongwon Kim Date: Thu, 5 May 2022 14:40:30 -0700 Subject: [PATCH 159/180] virtio-gpu: update done only on the scanout associated with rect It only needs to update the scanouts containing the rect area coming with the resource-flush request from the guest. Cc: Gerd Hoffmann Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim Message-Id: <20220505214030.4261-1-dongwon.kim@intel.com> Signed-off-by: Gerd Hoffmann --- hw/display/virtio-gpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index cd4a56056f..55c6dd5763 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -514,6 +514,9 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { scanout = &g->parent_obj.scanout[i]; if (scanout->resource_id == res->resource_id && + rf.r.x >= scanout->x && rf.r.y >= scanout->y && + rf.r.x + rf.r.width <= scanout->x + scanout->width && + rf.r.y + rf.r.height <= scanout->y + scanout->height && console_has_gl(scanout->con)) { dpy_gl_update(scanout->con, 0, 0, scanout->width, scanout->height); From 362239c05f28e8185d00d66884729a726ec4d226 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 26 Feb 2022 20:55:14 +0900 Subject: [PATCH 160/180] ui/console: Do not return a value with ui_info The returned value is not used and misleading. Signed-off-by: Akihiko Odaki Message-Id: <20220226115516.59830-2-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- hw/display/virtio-gpu-base.c | 6 +++--- hw/display/virtio-vga.c | 5 ++--- hw/vfio/display.c | 8 +++----- include/ui/console.h | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index 790cec333c..b21d6e5b0b 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -69,12 +69,12 @@ static void virtio_gpu_notify_event(VirtIOGPUBase *g, uint32_t event_type) virtio_notify_config(&g->parent_obj); } -static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) +static void virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) { VirtIOGPUBase *g = opaque; if (idx >= g->conf.max_outputs) { - return -1; + return; } g->req_state[idx].x = info->xoff; @@ -92,7 +92,7 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) /* send event to guest */ virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY); - return 0; + return; } static void diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index c206b5da38..4dcb34c4a7 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -47,15 +47,14 @@ static void virtio_vga_base_text_update(void *opaque, console_ch_t *chardata) } } -static int virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) +static void virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) { VirtIOVGABase *vvga = opaque; VirtIOGPUBase *g = vvga->vgpu; if (g->hw_ops->ui_info) { - return g->hw_ops->ui_info(g, idx, info); + g->hw_ops->ui_info(g, idx, info); } - return -1; } static void virtio_vga_base_gl_block(void *opaque, bool block) diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 89bc90508f..78f4d82c1c 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -106,14 +106,14 @@ err: return; } -static int vfio_display_edid_ui_info(void *opaque, uint32_t idx, - QemuUIInfo *info) +static void vfio_display_edid_ui_info(void *opaque, uint32_t idx, + QemuUIInfo *info) { VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; if (!dpy->edid_regs) { - return 0; + return; } if (info->width && info->height) { @@ -121,8 +121,6 @@ static int vfio_display_edid_ui_info(void *opaque, uint32_t idx, } else { vfio_display_edid_update(vdev, false, 0, 0); } - - return 0; } static void vfio_display_edid_init(VFIOPCIDevice *vdev) diff --git a/include/ui/console.h b/include/ui/console.h index c44b28a972..642d6f5248 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -432,7 +432,7 @@ typedef struct GraphicHwOps { bool gfx_update_async; /* if true, calls graphic_hw_update_done() */ void (*text_update)(void *opaque, console_ch_t *text); void (*update_interval)(void *opaque, uint64_t interval); - int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info); + void (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info); void (*gl_block)(void *opaque, bool block); } GraphicHwOps; From aeffd071ed818fa83c723fe8e2715144ee8385c7 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 26 Feb 2022 20:55:15 +0900 Subject: [PATCH 161/180] ui: Deliver refresh rate via QemuUIInfo This change adds a new member, refresh_rate to QemuUIInfo in include/ui/console.h. It represents the refresh rate of the physical display backend, and it is more appropriate than GUI update interval as the refresh rate which the emulated device reports: - sdl may set GUI update interval shorter than the refresh rate of the physical display to respond to user-generated events. - sdl and vnc aggressively changes GUI update interval, but a guests is typically not designed to respond to frequent refresh rate changes, or frequent "display mode" changes in general. The frequency of refresh rate changes of the physical display backend matches better to the guest's expectation. QemuUIInfo also has other members representing "display mode", which makes it suitable for refresh rate representation. It has a throttling of update notifications, and prevents frequent changes of the display mode. Signed-off-by: Akihiko Odaki Message-Id: <20220226115516.59830-3-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- hw/display/xenfb.c | 14 +++++++++++--- include/ui/console.h | 2 +- include/ui/gtk.h | 2 +- ui/console.c | 6 ------ ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 3 +-- ui/gtk.c | 45 +++++++++++++++++++++++++------------------- 7 files changed, 42 insertions(+), 34 deletions(-) diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index cea10fe3c7..50857cd97a 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -777,16 +777,24 @@ static void xenfb_update(void *opaque) xenfb->up_fullscreen = 0; } -static void xenfb_update_interval(void *opaque, uint64_t interval) +static void xenfb_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) { struct XenFB *xenfb = opaque; + uint32_t refresh_rate; if (xenfb->feature_update) { #ifdef XENFB_TYPE_REFRESH_PERIOD if (xenfb_queue_full(xenfb)) { return; } - xenfb_send_refresh_period(xenfb, interval); + + refresh_rate = info->refresh_rate; + if (!refresh_rate) { + refresh_rate = 75; + } + + /* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */ + xenfb_send_refresh_period(xenfb, 1000 * 1000 / refresh_rate); #endif } } @@ -983,5 +991,5 @@ struct XenDevOps xen_framebuffer_ops = { static const GraphicHwOps xenfb_ops = { .invalidate = xenfb_invalidate, .gfx_update = xenfb_update, - .update_interval = xenfb_update_interval, + .ui_info = xenfb_ui_info, }; diff --git a/include/ui/console.h b/include/ui/console.h index 642d6f5248..b64d824360 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -139,6 +139,7 @@ typedef struct QemuUIInfo { int yoff; uint32_t width; uint32_t height; + uint32_t refresh_rate; } QemuUIInfo; /* cursor data format is 32bit RGBA */ @@ -431,7 +432,6 @@ typedef struct GraphicHwOps { void (*gfx_update)(void *opaque); bool gfx_update_async; /* if true, calls graphic_hw_update_done() */ void (*text_update)(void *opaque, console_ch_t *text); - void (*update_interval)(void *opaque, uint64_t interval); void (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info); void (*gl_block)(void *opaque, bool block); } GraphicHwOps; diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 101b147d1b..ae0f53740d 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -155,7 +155,7 @@ extern bool gtk_use_gl_area; /* ui/gtk.c */ void gd_update_windowsize(VirtualConsole *vc); -int gd_monitor_update_interval(GtkWidget *widget); +void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget); void gd_hw_gl_flushed(void *vc); /* ui/gtk-egl.c */ diff --git a/ui/console.c b/ui/console.c index 36c80cd1de..9331b85203 100644 --- a/ui/console.c +++ b/ui/console.c @@ -160,7 +160,6 @@ static void gui_update(void *opaque) uint64_t dcl_interval; DisplayState *ds = opaque; DisplayChangeListener *dcl; - QemuConsole *con; ds->refreshing = true; dpy_refresh(ds); @@ -175,11 +174,6 @@ static void gui_update(void *opaque) } if (ds->update_interval != interval) { ds->update_interval = interval; - QTAILQ_FOREACH(con, &consoles, next) { - if (con->hw_ops->update_interval) { - con->hw_ops->update_interval(con->hw, interval); - } - } trace_console_refresh(interval); } ds->last_update = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index e3bd4bc274..b5bffbab25 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -140,8 +140,8 @@ void gd_egl_refresh(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); - vc->gfx.dcl.update_interval = gd_monitor_update_interval( - vc->window ? vc->window : vc->gfx.drawing_area); + gd_update_monitor_refresh_rate( + vc, vc->window ? vc->window : vc->gfx.drawing_area); if (!vc->gfx.esurface) { gd_egl_init(vc); diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2e0129c28c..682638a197 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -121,8 +121,7 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); - vc->gfx.dcl.update_interval = gd_monitor_update_interval( - vc->window ? vc->window : vc->gfx.drawing_area); + gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area); if (!vc->gfx.gls) { if (!gtk_widget_get_realized(vc->gfx.drawing_area)) { diff --git a/ui/gtk.c b/ui/gtk.c index c57c36749e..2a791dd2aa 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -710,11 +710,20 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event, return TRUE; } -static void gd_set_ui_info(VirtualConsole *vc, gint width, gint height) +static void gd_set_ui_refresh_rate(VirtualConsole *vc, int refresh_rate) { QemuUIInfo info; - memset(&info, 0, sizeof(info)); + info = *dpy_get_ui_info(vc->gfx.dcl.con); + info.refresh_rate = refresh_rate; + dpy_set_ui_info(vc->gfx.dcl.con, &info, true); +} + +static void gd_set_ui_size(VirtualConsole *vc, gint width, gint height) +{ + QemuUIInfo info; + + info = *dpy_get_ui_info(vc->gfx.dcl.con); info.width = width; info.height = height; dpy_set_ui_info(vc->gfx.dcl.con, &info, true); @@ -738,33 +747,32 @@ static void gd_resize_event(GtkGLArea *area, { VirtualConsole *vc = (void *)opaque; - gd_set_ui_info(vc, width, height); + gd_set_ui_size(vc, width, height); } #endif -/* - * If available, return the update interval of the monitor in ms, - * else return 0 (the default update interval). - */ -int gd_monitor_update_interval(GtkWidget *widget) +void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget) { #ifdef GDK_VERSION_3_22 GdkWindow *win = gtk_widget_get_window(widget); + int refresh_rate; if (win) { GdkDisplay *dpy = gtk_widget_get_display(widget); GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win); - int refresh_rate = gdk_monitor_get_refresh_rate(monitor); /* [mHz] */ - - if (refresh_rate) { - /* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */ - return MIN(1000 * 1000 / refresh_rate, - GUI_REFRESH_INTERVAL_DEFAULT); - } + refresh_rate = gdk_monitor_get_refresh_rate(monitor); /* [mHz] */ + } else { + refresh_rate = 0; } + + gd_set_ui_refresh_rate(vc, refresh_rate); + + /* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */ + vc->gfx.dcl.update_interval = refresh_rate ? + MIN(1000 * 1000 / refresh_rate, GUI_REFRESH_INTERVAL_DEFAULT) : + GUI_REFRESH_INTERVAL_DEFAULT; #endif - return 0; } static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) @@ -801,8 +809,7 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) return FALSE; } - vc->gfx.dcl.update_interval = - gd_monitor_update_interval(vc->window ? vc->window : s->window); + gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : s->window); fbw = surface_width(vc->gfx.ds); fbh = surface_height(vc->gfx.ds); @@ -1691,7 +1698,7 @@ static gboolean gd_configure(GtkWidget *widget, { VirtualConsole *vc = opaque; - gd_set_ui_info(vc, cfg->width, cfg->height); + gd_set_ui_size(vc, cfg->width, cfg->height); return FALSE; } From b95b56311a0890da0c9f7fc624529c3d7f8dbce0 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 26 Feb 2022 20:55:16 +0900 Subject: [PATCH 162/180] virtio-gpu: Respect UI refresh rate for EDID Signed-off-by: Akihiko Odaki Message-Id: <20220226115516.59830-4-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- hw/display/virtio-gpu-base.c | 1 + hw/display/virtio-gpu.c | 1 + include/hw/virtio/virtio-gpu.h | 1 + 3 files changed, 3 insertions(+) diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index b21d6e5b0b..a29f191aa8 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -79,6 +79,7 @@ static void virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) g->req_state[idx].x = info->xoff; g->req_state[idx].y = info->yoff; + g->req_state[idx].refresh_rate = info->refresh_rate; g->req_state[idx].width = info->width; g->req_state[idx].height = info->height; g->req_state[idx].width_mm = info->width_mm; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 55c6dd5763..20cc703dcc 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -217,6 +217,7 @@ virtio_gpu_generate_edid(VirtIOGPU *g, int scanout, .height_mm = b->req_state[scanout].height_mm, .prefx = b->req_state[scanout].width, .prefy = b->req_state[scanout].height, + .refresh_rate = b->req_state[scanout].refresh_rate, }; edid->size = cpu_to_le32(sizeof(edid->edid)); diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index afff9e158e..2e28507efe 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -80,6 +80,7 @@ struct virtio_gpu_scanout { struct virtio_gpu_requested_state { uint16_t width_mm, height_mm; uint32_t width, height; + uint32_t refresh_rate; int x, y; }; From 9e4067b8a41514c8f5715a2c735c3ac03e5d70c8 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 26 May 2022 14:54:32 +0300 Subject: [PATCH 163/180] MAINTAINERS: update Vladimir's address and repositories Signed-off-by: Vladimir Sementsov-Ogievskiy Message-id: 20220526115432.138384-1-vsementsov@yandex-team.ru Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 4cf6174f9f..5ba93348aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2546,7 +2546,7 @@ F: scsi/* Block Jobs M: John Snow -M: Vladimir Sementsov-Ogievskiy +M: Vladimir Sementsov-Ogievskiy L: qemu-block@nongnu.org S: Supported F: blockjob.c @@ -2571,7 +2571,7 @@ F: block/aio_task.c F: util/qemu-co-shared-resource.c F: include/qemu/co-shared-resource.h T: git https://gitlab.com/jsnow/qemu.git jobs -T: git https://src.openvz.org/scm/~vsementsov/qemu.git jobs +T: git https://gitlab.com/vsementsov/qemu.git block Block QAPI, monitor, command line M: Markus Armbruster @@ -2592,7 +2592,7 @@ F: include/hw/cxl/ Dirty Bitmaps M: Eric Blake -M: Vladimir Sementsov-Ogievskiy +M: Vladimir Sementsov-Ogievskiy R: John Snow L: qemu-block@nongnu.org S: Supported @@ -2606,6 +2606,7 @@ F: util/hbitmap.c F: tests/unit/test-hbitmap.c F: docs/interop/bitmaps.rst T: git https://repo.or.cz/qemu/ericb.git bitmaps +T: git https://gitlab.com/vsementsov/qemu.git block Character device backends M: Marc-André Lureau @@ -2816,16 +2817,17 @@ F: scripts/*.py F: tests/*.py Benchmark util -M: Vladimir Sementsov-Ogievskiy +M: Vladimir Sementsov-Ogievskiy S: Maintained F: scripts/simplebench/ -T: git https://src.openvz.org/scm/~vsementsov/qemu.git simplebench +T: git https://gitlab.com/vsementsov/qemu.git simplebench Transactions helper -M: Vladimir Sementsov-Ogievskiy +M: Vladimir Sementsov-Ogievskiy S: Maintained F: include/qemu/transactions.h F: util/transactions.c +T: git https://gitlab.com/vsementsov/qemu.git block QAPI M: Markus Armbruster @@ -3402,7 +3404,7 @@ F: block/iscsi-opts.c Network Block Device (NBD) M: Eric Blake -M: Vladimir Sementsov-Ogievskiy +M: Vladimir Sementsov-Ogievskiy L: qemu-block@nongnu.org S: Maintained F: block/nbd* @@ -3414,7 +3416,7 @@ F: docs/interop/nbd.txt F: docs/tools/qemu-nbd.rst F: tests/qemu-iotests/tests/*nbd* T: git https://repo.or.cz/qemu/ericb.git nbd -T: git https://src.openvz.org/scm/~vsementsov/qemu.git nbd +T: git https://gitlab.com/vsementsov/qemu.git block NFS M: Peter Lieven @@ -3499,13 +3501,13 @@ F: block/dmg.c parallels M: Stefan Hajnoczi M: Denis V. Lunev -M: Vladimir Sementsov-Ogievskiy +M: Vladimir Sementsov-Ogievskiy L: qemu-block@nongnu.org S: Supported F: block/parallels.c F: block/parallels-ext.c F: docs/interop/parallels.txt -T: git https://src.openvz.org/scm/~vsementsov/qemu.git parallels +T: git https://gitlab.com/vsementsov/qemu.git block qed M: Stefan Hajnoczi From e2848bc574fe2715c694bf8fe9a1ba7f78a1125a Mon Sep 17 00:00:00 2001 From: Sam Li Date: Tue, 31 May 2022 18:50:11 +0800 Subject: [PATCH 164/180] Use io_uring_register_ring_fd() to skip fd operations Linux recently added a new io_uring(7) optimization API that QEMU doesn't take advantage of yet. The liburing library that QEMU uses has added a corresponding new API calling io_uring_register_ring_fd(). When this API is called after creating the ring, the io_uring_submit() library function passes a flag to the io_uring_enter(2) syscall allowing it to skip the ring file descriptor fdget()/fdput() operations. This saves some CPU cycles. Signed-off-by: Sam Li Message-id: 20220531105011.111082-1-faithilikerun@gmail.com Signed-off-by: Stefan Hajnoczi --- block/io_uring.c | 12 +++++++++++- meson.build | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/block/io_uring.c b/block/io_uring.c index 0b401512b9..d48e472e74 100644 --- a/block/io_uring.c +++ b/block/io_uring.c @@ -18,6 +18,7 @@ #include "qapi/error.h" #include "trace.h" + /* io_uring ring size */ #define MAX_ENTRIES 128 @@ -434,8 +435,17 @@ LuringState *luring_init(Error **errp) } ioq_init(&s->io_q); - return s; +#ifdef CONFIG_LIBURING_REGISTER_RING_FD + if (io_uring_register_ring_fd(&s->ring) < 0) { + /* + * Only warn about this error: we will fallback to the non-optimized + * io_uring operations. + */ + warn_report("failed to register linux io_uring ring file descriptor"); + } +#endif + return s; } void luring_cleanup(LuringState *s) diff --git a/meson.build b/meson.build index 0c2e11ff07..9e65cc5367 100644 --- a/meson.build +++ b/meson.build @@ -1752,6 +1752,7 @@ config_host_data.set('CONFIG_LIBNFS', libnfs.found()) config_host_data.set('CONFIG_LIBSSH', libssh.found()) config_host_data.set('CONFIG_LINUX_AIO', libaio.found()) config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found()) +config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include ', dependencies:linux_io_uring)) config_host_data.set('CONFIG_LIBPMEM', libpmem.found()) config_host_data.set('CONFIG_NUMA', numa.found()) config_host_data.set('CONFIG_OPENGL', opengl.found()) From 217c7f01adaf2853951d4725e3527ae70c45fbfc Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:21 -0400 Subject: [PATCH 165/180] qdev: unplug blocker for devices Add blocker to prevent hot-unplug of devices TYPE_VFIO_USER_SERVER, which is introduced shortly, attaches itself to a PCIDevice on which it depends. If the attached PCIDevice gets removed while the server in use, it could cause it crash. To prevent this, TYPE_VFIO_USER_SERVER adds an unplug blocker for the PCIDevice. Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: c41ef80b7cc063314d629737bed2159e5713f2e0.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/core/qdev.c | 24 ++++++++++++++++++++++++ include/hw/qdev-core.h | 29 +++++++++++++++++++++++++++++ softmmu/qdev-monitor.c | 4 ++++ 3 files changed, 57 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 84f3019440..0806d8fcaa 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -468,6 +468,28 @@ char *qdev_get_dev_path(DeviceState *dev) return NULL; } +void qdev_add_unplug_blocker(DeviceState *dev, Error *reason) +{ + dev->unplug_blockers = g_slist_prepend(dev->unplug_blockers, reason); +} + +void qdev_del_unplug_blocker(DeviceState *dev, Error *reason) +{ + dev->unplug_blockers = g_slist_remove(dev->unplug_blockers, reason); +} + +bool qdev_unplug_blocked(DeviceState *dev, Error **errp) +{ + ERRP_GUARD(); + + if (dev->unplug_blockers) { + error_propagate(errp, error_copy(dev->unplug_blockers->data)); + return true; + } + + return false; +} + static bool device_get_realized(Object *obj, Error **errp) { DeviceState *dev = DEVICE(obj); @@ -704,6 +726,8 @@ static void device_finalize(Object *obj) DeviceState *dev = DEVICE(obj); + g_assert(!dev->unplug_blockers); + QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) { QLIST_REMOVE(ngl, node); qemu_free_irqs(ngl->in, ngl->num_in); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 92c3d65208..98774e2835 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -193,6 +193,7 @@ struct DeviceState { int instance_id_alias; int alias_required_for_version; ResettableState reset; + GSList *unplug_blockers; }; struct DeviceListener { @@ -419,6 +420,34 @@ void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, void qdev_machine_creation_done(void); bool qdev_machine_modified(void); +/** + * qdev_add_unplug_blocker: Add an unplug blocker to a device + * + * @dev: Device to be blocked from unplug + * @reason: Reason for blocking + */ +void qdev_add_unplug_blocker(DeviceState *dev, Error *reason); + +/** + * qdev_del_unplug_blocker: Remove an unplug blocker from a device + * + * @dev: Device to be unblocked + * @reason: Pointer to the Error used with qdev_add_unplug_blocker. + * Used as a handle to lookup the blocker for deletion. + */ +void qdev_del_unplug_blocker(DeviceState *dev, Error *reason); + +/** + * qdev_unplug_blocked: Confirm if a device is blocked from unplug + * + * @dev: Device to be tested + * @reason: Returns one of the reasons why the device is blocked, + * if any + * + * Returns: true if device is blocked from unplug, false otherwise + */ +bool qdev_unplug_blocked(DeviceState *dev, Error **errp); + /** * GpioPolarity: Polarity of a GPIO line * diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index bb5897fc76..4b0ef65780 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -899,6 +899,10 @@ void qdev_unplug(DeviceState *dev, Error **errp) HotplugHandlerClass *hdc; Error *local_err = NULL; + if (qdev_unplug_blocked(dev, errp)) { + return; + } + if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) { error_setg(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); return; From 661e21c48e9e0bea2a23d22cdbb83e02234fb164 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:22 -0400 Subject: [PATCH 166/180] remote/machine: add HotplugHandler for remote machine Allow hotplugging of PCI(e) devices to remote machine Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: d1e6cfa0afb528ad343758f9b1d918be0175c5e5.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/machine.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/remote/machine.c b/hw/remote/machine.c index 92d71d47bb..a97e53e250 100644 --- a/hw/remote/machine.c +++ b/hw/remote/machine.c @@ -20,6 +20,7 @@ #include "qapi/error.h" #include "hw/pci/pci_host.h" #include "hw/remote/iohub.h" +#include "hw/qdev-core.h" static void remote_machine_init(MachineState *machine) { @@ -53,14 +54,19 @@ static void remote_machine_init(MachineState *machine) pci_bus_irqs(pci_host->bus, remote_iohub_set_irq, remote_iohub_map_irq, &s->iohub, REMOTE_IOHUB_NB_PIRQS); + + qbus_set_hotplug_handler(BUS(pci_host->bus), OBJECT(s)); } static void remote_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->init = remote_machine_init; mc->desc = "Experimental remote machine"; + + hc->unplug = qdev_simple_device_unplug_cb; } static const TypeInfo remote_machine = { @@ -68,6 +74,10 @@ static const TypeInfo remote_machine = { .parent = TYPE_MACHINE, .instance_size = sizeof(RemoteMachineState), .class_init = remote_machine_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void remote_machine_register_types(void) From 9b5b473eae3fa0450a7fce21f7e01f3ab1136bb8 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:23 -0400 Subject: [PATCH 167/180] remote/machine: add vfio-user property Add vfio-user to x-remote machine. It is a boolean, which indicates if the machine supports vfio-user protocol. The machine configures the bus differently vfio-user and multiprocess protocols, so this property informs it on how to configure the bus. This property should be short lived. Once vfio-user fully replaces multiprocess, this property could be removed. Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: 5d51a152a419cbda35d070b8e49b772b60a7230a.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/machine.c | 23 +++++++++++++++++++++++ include/hw/remote/machine.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/hw/remote/machine.c b/hw/remote/machine.c index a97e53e250..9f3cdc55c3 100644 --- a/hw/remote/machine.c +++ b/hw/remote/machine.c @@ -58,6 +58,25 @@ static void remote_machine_init(MachineState *machine) qbus_set_hotplug_handler(BUS(pci_host->bus), OBJECT(s)); } +static bool remote_machine_get_vfio_user(Object *obj, Error **errp) +{ + RemoteMachineState *s = REMOTE_MACHINE(obj); + + return s->vfio_user; +} + +static void remote_machine_set_vfio_user(Object *obj, bool value, Error **errp) +{ + RemoteMachineState *s = REMOTE_MACHINE(obj); + + if (phase_check(PHASE_MACHINE_CREATED)) { + error_setg(errp, "Error enabling vfio-user - machine already created"); + return; + } + + s->vfio_user = value; +} + static void remote_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -67,6 +86,10 @@ static void remote_machine_class_init(ObjectClass *oc, void *data) mc->desc = "Experimental remote machine"; hc->unplug = qdev_simple_device_unplug_cb; + + object_class_property_add_bool(oc, "vfio-user", + remote_machine_get_vfio_user, + remote_machine_set_vfio_user); } static const TypeInfo remote_machine = { diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h index 2a2a33c4b2..8d0fa98d33 100644 --- a/include/hw/remote/machine.h +++ b/include/hw/remote/machine.h @@ -22,6 +22,8 @@ struct RemoteMachineState { RemotePCIHost *host; RemoteIOHubState iohub; + + bool vfio_user; }; /* Used to pass to co-routine device and ioc. */ From 55116968deb09fdae198cecaa45f4e5532d5445a Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:24 -0400 Subject: [PATCH 168/180] vfio-user: build library add the libvfio-user library as a submodule. build it as a meson subproject. libvfio-user is distributed with BSD 3-Clause license and json-c with MIT (Expat) license Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: c2adec87958b081d1dc8775d4aa05c897912f025.1655151679.git.jag.raman@oracle.com [Changed submodule URL to QEMU's libvfio-user mirror on GitLab. The QEMU project mirrors its dependencies so that it can provide full source code even in the event that its dependencies become unavailable. Note that the mirror repo is manually updated, so please contact me to make newer libvfio-user commits available. If I become a bottleneck we can set up a cronjob. Updated scripts/meson-buildoptions.sh to match the meson_options.txt change. Failure to do so can result in scripts/meson-buildoptions.sh being modified by the build system later on and you end up with a dirty working tree. --Stefan] Signed-off-by: Stefan Hajnoczi --- .gitlab-ci.d/buildtest.yml | 1 + .gitmodules | 3 +++ Kconfig.host | 4 ++++ MAINTAINERS | 1 + configure | 17 +++++++++++++++++ hw/remote/Kconfig | 4 ++++ hw/remote/meson.build | 2 ++ meson.build | 23 ++++++++++++++++++++++- meson_options.txt | 2 ++ scripts/meson-buildoptions.sh | 4 ++++ subprojects/libvfio-user | 1 + tests/docker/dockerfiles/centos8.docker | 2 ++ 12 files changed, 63 insertions(+), 1 deletion(-) create mode 160000 subprojects/libvfio-user diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index cb7cad44b5..8a4353ef93 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -168,6 +168,7 @@ build-system-centos: IMAGE: centos8 CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system --enable-modules --enable-trace-backends=dtrace --enable-docs + --enable-vfio-user-server TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu MAKE_CHECK_ARGS: check-build diff --git a/.gitmodules b/.gitmodules index b8bff47df8..aedd9a03d4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,6 @@ [submodule "tests/lcitool/libvirt-ci"] path = tests/lcitool/libvirt-ci url = https://gitlab.com/libvirt/libvirt-ci.git +[submodule "subprojects/libvfio-user"] + path = subprojects/libvfio-user + url = https://gitlab.com/qemu-project/libvfio-user.git diff --git a/Kconfig.host b/Kconfig.host index 1165c4eacd..d763d89269 100644 --- a/Kconfig.host +++ b/Kconfig.host @@ -42,3 +42,7 @@ config MULTIPROCESS_ALLOWED config FUZZ bool select SPARSE_MEM + +config VFIO_USER_SERVER_ALLOWED + bool + imply VFIO_USER_SERVER diff --git a/MAINTAINERS b/MAINTAINERS index 5ba93348aa..d0fcaf0edb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3642,6 +3642,7 @@ F: hw/remote/proxy-memory-listener.c F: include/hw/remote/proxy-memory-listener.h F: hw/remote/iohub.c F: include/hw/remote/iohub.h +F: subprojects/libvfio-user EBPF: M: Jason Wang diff --git a/configure b/configure index 4b12a8094c..c14e7f590a 100755 --- a/configure +++ b/configure @@ -315,6 +315,7 @@ meson_args="" ninja="" bindir="bin" skip_meson=no +vfio_user_server="disabled" # The following Meson options are handled manually (still they # are included in the automatically generated help message) @@ -909,6 +910,10 @@ for opt do ;; --disable-blobs) meson_option_parse --disable-install-blobs "" ;; + --enable-vfio-user-server) vfio_user_server="enabled" + ;; + --disable-vfio-user-server) vfio_user_server="disabled" + ;; --enable-tcmalloc) meson_option_parse --enable-malloc=tcmalloc tcmalloc ;; --enable-jemalloc) meson_option_parse --enable-malloc=jemalloc jemalloc @@ -2132,6 +2137,17 @@ write_container_target_makefile() { +########################################## +# check for vfio_user_server + +case "$vfio_user_server" in + enabled ) + if test "$git_submodules_action" != "ignore"; then + git_submodules="${git_submodules} subprojects/libvfio-user" + fi + ;; +esac + ########################################## # End of CC checks # After here, no more $cc or $ld runs @@ -2672,6 +2688,7 @@ if test "$skip_meson" = no; then test "$slirp" != auto && meson_option_add "-Dslirp=$slirp" test "$smbd" != '' && meson_option_add "-Dsmbd=$smbd" test "$tcg" != enabled && meson_option_add "-Dtcg=$tcg" + test "$vfio_user_server" != auto && meson_option_add "-Dvfio_user_server=$vfio_user_server" run_meson() { NINJA=$ninja $meson setup --prefix "$prefix" "$@" $cross_arg "$PWD" "$source_path" } diff --git a/hw/remote/Kconfig b/hw/remote/Kconfig index 08c16e235f..2d6b4f4cf4 100644 --- a/hw/remote/Kconfig +++ b/hw/remote/Kconfig @@ -2,3 +2,7 @@ config MULTIPROCESS bool depends on PCI && PCI_EXPRESS && KVM select REMOTE_PCIHOST + +config VFIO_USER_SERVER + bool + depends on MULTIPROCESS diff --git a/hw/remote/meson.build b/hw/remote/meson.build index e6a5574242..7da83350c8 100644 --- a/hw/remote/meson.build +++ b/hw/remote/meson.build @@ -7,6 +7,8 @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('iohub.c')) +remote_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_true: libvfio_user_dep) + specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('memory.c')) specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy-memory-listener.c')) diff --git a/meson.build b/meson.build index 9e65cc5367..ca19ddc30c 100644 --- a/meson.build +++ b/meson.build @@ -308,6 +308,10 @@ multiprocess_allowed = get_option('multiprocess') \ .require(targetos == 'linux', error_message: 'Multiprocess QEMU is supported only on Linux') \ .allowed() +vfio_user_server_allowed = get_option('vfio_user_server') \ + .require(targetos == 'linux', error_message: 'vfio-user server is supported only on Linux') \ + .allowed() + have_tpm = get_option('tpm') \ .require(targetos != 'windows', error_message: 'TPM emulation only available on POSIX systems') \ .allowed() @@ -2380,7 +2384,8 @@ host_kconfig = \ (have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \ ('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \ (have_pvrdma ? ['CONFIG_PVRDMA=y'] : []) + \ - (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + (multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \ + (vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ] @@ -2672,6 +2677,21 @@ if have_system endif endif +libvfio_user_dep = not_found +if have_system and vfio_user_server_allowed + have_internal = fs.exists(meson.current_source_dir() / 'subprojects/libvfio-user/meson.build') + + if not have_internal + error('libvfio-user source not found - please pull git submodule') + endif + + libvfio_user_proj = subproject('libvfio-user') + + libvfio_user_lib = libvfio_user_proj.get_variable('libvfio_user_dep') + + libvfio_user_dep = declare_dependency(dependencies: [libvfio_user_lib]) +endif + fdt = not_found if have_system fdt_opt = get_option('fdt') @@ -3790,6 +3810,7 @@ summary_info += {'target list': ' '.join(target_dirs)} if have_system summary_info += {'default devices': get_option('default_devices')} summary_info += {'out of process emulation': multiprocess_allowed} + summary_info += {'vfio-user server': vfio_user_server_allowed} endif summary(summary_info, bool_yn: true, section: 'Targets and accelerators') diff --git a/meson_options.txt b/meson_options.txt index 0e8197386b..f3e2f22c1e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -88,6 +88,8 @@ option('cfi_debug', type: 'boolean', value: 'false', description: 'Verbose errors in case of CFI violation') option('multiprocess', type: 'feature', value: 'auto', description: 'Out of process device emulation support') +option('vfio_user_server', type: 'feature', value: 'disabled', + description: 'vfio-user server support') option('dbus_display', type: 'feature', value: 'auto', description: '-display dbus support') option('tpm', type : 'feature', value : 'auto', diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 1fc1d2e2c3..24eb5f35ea 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -153,6 +153,8 @@ meson_options_help() { printf "%s\n" ' usb-redir libusbredir support' printf "%s\n" ' vde vde network backend support' printf "%s\n" ' vdi vdi image format support' + printf "%s\n" ' vfio-user-server' + printf "%s\n" ' vfio-user server support' printf "%s\n" ' vhost-crypto vhost-user crypto backend support' printf "%s\n" ' vhost-kernel vhost kernel backend support' printf "%s\n" ' vhost-net vhost-net kernel acceleration support' @@ -415,6 +417,8 @@ _meson_option_parse() { --disable-vde) printf "%s" -Dvde=disabled ;; --enable-vdi) printf "%s" -Dvdi=enabled ;; --disable-vdi) printf "%s" -Dvdi=disabled ;; + --enable-vfio-user-server) printf "%s" -Dvfio_user_server=enabled ;; + --disable-vfio-user-server) printf "%s" -Dvfio_user_server=disabled ;; --enable-vhost-crypto) printf "%s" -Dvhost_crypto=enabled ;; --disable-vhost-crypto) printf "%s" -Dvhost_crypto=disabled ;; --enable-vhost-kernel) printf "%s" -Dvhost_kernel=enabled ;; diff --git a/subprojects/libvfio-user b/subprojects/libvfio-user new file mode 160000 index 0000000000..0b28d20557 --- /dev/null +++ b/subprojects/libvfio-user @@ -0,0 +1 @@ +Subproject commit 0b28d205572c80b568a1003db2c8f37ca333e4d7 diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index 4b20925bbf..10618bfa83 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -51,6 +51,7 @@ RUN dnf update -y && \ libbpf-devel \ libcacard-devel \ libcap-ng-devel \ + libcmocka-devel \ libcurl-devel \ libdrm-devel \ libepoxy-devel \ @@ -59,6 +60,7 @@ RUN dnf update -y && \ libgcrypt-devel \ libiscsi-devel \ libjpeg-devel \ + json-c-devel \ libnfs-devel \ libpmem-devel \ libpng-devel \ From 8f9a9259d32c1b6ba41a38ad99fc67bcc0da0131 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:25 -0400 Subject: [PATCH 169/180] vfio-user: define vfio-user-server object Define vfio-user object which is remote process server for QEMU. Setup object initialization functions and properties necessary to instantiate the object Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: e45a17001e9b38f451543a664ababdf860e5f2f2.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 1 + hw/remote/machine.c | 27 +++++ hw/remote/meson.build | 1 + hw/remote/trace-events | 3 + hw/remote/vfio-user-obj.c | 210 ++++++++++++++++++++++++++++++++++++ include/hw/remote/machine.h | 2 + qapi/qom.json | 20 +++- 7 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 hw/remote/vfio-user-obj.c diff --git a/MAINTAINERS b/MAINTAINERS index d0fcaf0edb..cbac72e239 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3643,6 +3643,7 @@ F: include/hw/remote/proxy-memory-listener.h F: hw/remote/iohub.c F: include/hw/remote/iohub.h F: subprojects/libvfio-user +F: hw/remote/vfio-user-obj.c EBPF: M: Jason Wang diff --git a/hw/remote/machine.c b/hw/remote/machine.c index 9f3cdc55c3..4d008ed721 100644 --- a/hw/remote/machine.c +++ b/hw/remote/machine.c @@ -77,6 +77,28 @@ static void remote_machine_set_vfio_user(Object *obj, bool value, Error **errp) s->vfio_user = value; } +static bool remote_machine_get_auto_shutdown(Object *obj, Error **errp) +{ + RemoteMachineState *s = REMOTE_MACHINE(obj); + + return s->auto_shutdown; +} + +static void remote_machine_set_auto_shutdown(Object *obj, bool value, + Error **errp) +{ + RemoteMachineState *s = REMOTE_MACHINE(obj); + + s->auto_shutdown = value; +} + +static void remote_machine_instance_init(Object *obj) +{ + RemoteMachineState *s = REMOTE_MACHINE(obj); + + s->auto_shutdown = true; +} + static void remote_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -90,12 +112,17 @@ static void remote_machine_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, "vfio-user", remote_machine_get_vfio_user, remote_machine_set_vfio_user); + + object_class_property_add_bool(oc, "auto-shutdown", + remote_machine_get_auto_shutdown, + remote_machine_set_auto_shutdown); } static const TypeInfo remote_machine = { .name = TYPE_REMOTE_MACHINE, .parent = TYPE_MACHINE, .instance_size = sizeof(RemoteMachineState), + .instance_init = remote_machine_instance_init, .class_init = remote_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, diff --git a/hw/remote/meson.build b/hw/remote/meson.build index 7da83350c8..0eb5a0f375 100644 --- a/hw/remote/meson.build +++ b/hw/remote/meson.build @@ -6,6 +6,7 @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('iohub.c')) +remote_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_true: files('vfio-user-obj.c')) remote_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_true: libvfio_user_dep) diff --git a/hw/remote/trace-events b/hw/remote/trace-events index 0b23974f90..7da12f0d96 100644 --- a/hw/remote/trace-events +++ b/hw/remote/trace-events @@ -2,3 +2,6 @@ mpqemu_send_io_error(int cmd, int size, int nfds) "send command %d size %d, %d file descriptors to remote process" mpqemu_recv_io_error(int cmd, int size, int nfds) "failed to receive %d size %d, %d file descriptors to remote process" + +# vfio-user-obj.c +vfu_prop(const char *prop, const char *val) "vfu: setting %s as %s" diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c new file mode 100644 index 0000000000..bc49adcc27 --- /dev/null +++ b/hw/remote/vfio-user-obj.c @@ -0,0 +1,210 @@ +/** + * QEMU vfio-user-server server object + * + * Copyright © 2022 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL-v2, version 2 or later. + * + * See the COPYING file in the top-level directory. + * + */ + +/** + * Usage: add options: + * -machine x-remote,vfio-user=on,auto-shutdown=on + * -device ,id= + * -object x-vfio-user-server,id=,type=unix,path=, + * device= + * + * Note that x-vfio-user-server object must be used with x-remote machine only. + * This server could only support PCI devices for now. + * + * type - SocketAddress type - presently "unix" alone is supported. Required + * option + * + * path - named unix socket, it will be created by the server. It is + * a required option + * + * device - id of a device on the server, a required option. PCI devices + * alone are supported presently. + */ + +#include "qemu/osdep.h" + +#include "qom/object.h" +#include "qom/object_interfaces.h" +#include "qemu/error-report.h" +#include "trace.h" +#include "sysemu/runstate.h" +#include "hw/boards.h" +#include "hw/remote/machine.h" +#include "qapi/error.h" +#include "qapi/qapi-visit-sockets.h" + +#define TYPE_VFU_OBJECT "x-vfio-user-server" +OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) + +/** + * VFU_OBJECT_ERROR - reports an error message. If auto_shutdown + * is set, it aborts the machine on error. Otherwise, it logs an + * error message without aborting. + */ +#define VFU_OBJECT_ERROR(o, fmt, ...) \ + { \ + if (vfu_object_auto_shutdown()) { \ + error_setg(&error_abort, (fmt), ## __VA_ARGS__); \ + } else { \ + error_report((fmt), ## __VA_ARGS__); \ + } \ + } \ + +struct VfuObjectClass { + ObjectClass parent_class; + + unsigned int nr_devs; +}; + +struct VfuObject { + /* private */ + Object parent; + + SocketAddress *socket; + + char *device; + + Error *err; +}; + +static bool vfu_object_auto_shutdown(void) +{ + bool auto_shutdown = true; + Error *local_err = NULL; + + if (!current_machine) { + return auto_shutdown; + } + + auto_shutdown = object_property_get_bool(OBJECT(current_machine), + "auto-shutdown", + &local_err); + + /* + * local_err would be set if no such property exists - safe to ignore. + * Unlikely scenario as auto-shutdown is always defined for + * TYPE_REMOTE_MACHINE, and TYPE_VFU_OBJECT only works with + * TYPE_REMOTE_MACHINE + */ + if (local_err) { + auto_shutdown = true; + error_free(local_err); + } + + return auto_shutdown; +} + +static void vfu_object_set_socket(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + VfuObject *o = VFU_OBJECT(obj); + + qapi_free_SocketAddress(o->socket); + + o->socket = NULL; + + visit_type_SocketAddress(v, name, &o->socket, errp); + + if (o->socket->type != SOCKET_ADDRESS_TYPE_UNIX) { + error_setg(errp, "vfu: Unsupported socket type - %s", + SocketAddressType_str(o->socket->type)); + qapi_free_SocketAddress(o->socket); + o->socket = NULL; + return; + } + + trace_vfu_prop("socket", o->socket->u.q_unix.path); +} + +static void vfu_object_set_device(Object *obj, const char *str, Error **errp) +{ + VfuObject *o = VFU_OBJECT(obj); + + g_free(o->device); + + o->device = g_strdup(str); + + trace_vfu_prop("device", str); +} + +static void vfu_object_init(Object *obj) +{ + VfuObjectClass *k = VFU_OBJECT_GET_CLASS(obj); + VfuObject *o = VFU_OBJECT(obj); + + k->nr_devs++; + + if (!object_dynamic_cast(OBJECT(current_machine), TYPE_REMOTE_MACHINE)) { + error_setg(&o->err, "vfu: %s only compatible with %s machine", + TYPE_VFU_OBJECT, TYPE_REMOTE_MACHINE); + return; + } +} + +static void vfu_object_finalize(Object *obj) +{ + VfuObjectClass *k = VFU_OBJECT_GET_CLASS(obj); + VfuObject *o = VFU_OBJECT(obj); + + k->nr_devs--; + + qapi_free_SocketAddress(o->socket); + + o->socket = NULL; + + g_free(o->device); + + o->device = NULL; + + if (!k->nr_devs && vfu_object_auto_shutdown()) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } +} + +static void vfu_object_class_init(ObjectClass *klass, void *data) +{ + VfuObjectClass *k = VFU_OBJECT_CLASS(klass); + + k->nr_devs = 0; + + object_class_property_add(klass, "socket", "SocketAddress", NULL, + vfu_object_set_socket, NULL, NULL); + object_class_property_set_description(klass, "socket", + "SocketAddress " + "(ex: type=unix,path=/tmp/sock). " + "Only UNIX is presently supported"); + object_class_property_add_str(klass, "device", NULL, + vfu_object_set_device); + object_class_property_set_description(klass, "device", + "device ID - only PCI devices " + "are presently supported"); +} + +static const TypeInfo vfu_object_info = { + .name = TYPE_VFU_OBJECT, + .parent = TYPE_OBJECT, + .instance_size = sizeof(VfuObject), + .instance_init = vfu_object_init, + .instance_finalize = vfu_object_finalize, + .class_size = sizeof(VfuObjectClass), + .class_init = vfu_object_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + +static void vfu_register_types(void) +{ + type_register_static(&vfu_object_info); +} + +type_init(vfu_register_types); diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h index 8d0fa98d33..ac32fda387 100644 --- a/include/hw/remote/machine.h +++ b/include/hw/remote/machine.h @@ -24,6 +24,8 @@ struct RemoteMachineState { RemoteIOHubState iohub; bool vfio_user; + + bool auto_shutdown; }; /* Used to pass to co-routine device and ioc. */ diff --git a/qapi/qom.json b/qapi/qom.json index 6a653c6636..80dd419b39 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -734,6 +734,20 @@ { 'struct': 'RemoteObjectProperties', 'data': { 'fd': 'str', 'devid': 'str' } } +## +# @VfioUserServerProperties: +# +# Properties for x-vfio-user-server objects. +# +# @socket: socket to be used by the libvfio-user library +# +# @device: the ID of the device to be emulated at the server +# +# Since: 7.1 +## +{ 'struct': 'VfioUserServerProperties', + 'data': { 'socket': 'SocketAddress', 'device': 'str' } } + ## # @RngProperties: # @@ -874,7 +888,8 @@ 'tls-creds-psk', 'tls-creds-x509', 'tls-cipher-suites', - { 'name': 'x-remote-object', 'features': [ 'unstable' ] } + { 'name': 'x-remote-object', 'features': [ 'unstable' ] }, + { 'name': 'x-vfio-user-server', 'features': [ 'unstable' ] } ] } ## @@ -938,7 +953,8 @@ 'tls-creds-psk': 'TlsCredsPskProperties', 'tls-creds-x509': 'TlsCredsX509Properties', 'tls-cipher-suites': 'TlsCredsProperties', - 'x-remote-object': 'RemoteObjectProperties' + 'x-remote-object': 'RemoteObjectProperties', + 'x-vfio-user-server': 'VfioUserServerProperties' } } ## From 87f7249ff6e37c541609e40b17d249af533003e1 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:26 -0400 Subject: [PATCH 170/180] vfio-user: instantiate vfio-user context create a context with the vfio-user library to run a PCI device Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: a452871ac8c812ff96fc4f0ce6037f4769953fab.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/vfio-user-obj.c | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index bc49adcc27..68f8a9dfa9 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -40,6 +40,9 @@ #include "hw/remote/machine.h" #include "qapi/error.h" #include "qapi/qapi-visit-sockets.h" +#include "qemu/notify.h" +#include "sysemu/sysemu.h" +#include "libvfio-user.h" #define TYPE_VFU_OBJECT "x-vfio-user-server" OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) @@ -73,8 +76,14 @@ struct VfuObject { char *device; Error *err; + + Notifier machine_done; + + vfu_ctx_t *vfu_ctx; }; +static void vfu_object_init_ctx(VfuObject *o, Error **errp); + static bool vfu_object_auto_shutdown(void) { bool auto_shutdown = true; @@ -107,6 +116,11 @@ static void vfu_object_set_socket(Object *obj, Visitor *v, const char *name, { VfuObject *o = VFU_OBJECT(obj); + if (o->vfu_ctx) { + error_setg(errp, "vfu: Unable to set socket property - server busy"); + return; + } + qapi_free_SocketAddress(o->socket); o->socket = NULL; @@ -122,17 +136,69 @@ static void vfu_object_set_socket(Object *obj, Visitor *v, const char *name, } trace_vfu_prop("socket", o->socket->u.q_unix.path); + + vfu_object_init_ctx(o, errp); } static void vfu_object_set_device(Object *obj, const char *str, Error **errp) { VfuObject *o = VFU_OBJECT(obj); + if (o->vfu_ctx) { + error_setg(errp, "vfu: Unable to set device property - server busy"); + return; + } + g_free(o->device); o->device = g_strdup(str); trace_vfu_prop("device", str); + + vfu_object_init_ctx(o, errp); +} + +/* + * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' + * properties. It also depends on devices instantiated in QEMU. These + * dependencies are not available during the instance_init phase of this + * object's life-cycle. As such, the server is initialized after the + * machine is setup. machine_init_done_notifier notifies TYPE_VFU_OBJECT + * when the machine is setup, and the dependencies are available. + */ +static void vfu_object_machine_done(Notifier *notifier, void *data) +{ + VfuObject *o = container_of(notifier, VfuObject, machine_done); + Error *err = NULL; + + vfu_object_init_ctx(o, &err); + + if (err) { + error_propagate(&error_abort, err); + } +} + +static void vfu_object_init_ctx(VfuObject *o, Error **errp) +{ + ERRP_GUARD(); + + if (o->vfu_ctx || !o->socket || !o->device || + !phase_check(PHASE_MACHINE_READY)) { + return; + } + + if (o->err) { + error_propagate(errp, o->err); + o->err = NULL; + return; + } + + o->vfu_ctx = vfu_create_ctx(VFU_TRANS_SOCK, o->socket->u.q_unix.path, 0, + o, VFU_DEV_TYPE_PCI); + if (o->vfu_ctx == NULL) { + error_setg(errp, "vfu: Failed to create context - %s", strerror(errno)); + return; + } } static void vfu_object_init(Object *obj) @@ -147,6 +213,12 @@ static void vfu_object_init(Object *obj) TYPE_VFU_OBJECT, TYPE_REMOTE_MACHINE); return; } + + if (!phase_check(PHASE_MACHINE_READY)) { + o->machine_done.notify = vfu_object_machine_done; + qemu_add_machine_init_done_notifier(&o->machine_done); + } + } static void vfu_object_finalize(Object *obj) @@ -160,6 +232,11 @@ static void vfu_object_finalize(Object *obj) o->socket = NULL; + if (o->vfu_ctx) { + vfu_destroy_ctx(o->vfu_ctx); + o->vfu_ctx = NULL; + } + g_free(o->device); o->device = NULL; @@ -167,6 +244,11 @@ static void vfu_object_finalize(Object *obj) if (!k->nr_devs && vfu_object_auto_shutdown()) { qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); } + + if (o->machine_done.notify) { + qemu_remove_machine_init_done_notifier(&o->machine_done); + o->machine_done.notify = NULL; + } } static void vfu_object_class_init(ObjectClass *klass, void *data) From a6e8d6d98e61a270bcbd1e611f2e1d71a80d86c5 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:27 -0400 Subject: [PATCH 171/180] vfio-user: find and init PCI device Find the PCI device with specified id. Initialize the device context with the QEMU PCI device Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: 7798dbd730099b33fdd00c4c202cfe79e5c5c151.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/vfio-user-obj.c | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index 68f8a9dfa9..3ca6aa2b45 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -43,6 +43,8 @@ #include "qemu/notify.h" #include "sysemu/sysemu.h" #include "libvfio-user.h" +#include "hw/qdev-core.h" +#include "hw/pci/pci.h" #define TYPE_VFU_OBJECT "x-vfio-user-server" OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) @@ -80,6 +82,10 @@ struct VfuObject { Notifier machine_done; vfu_ctx_t *vfu_ctx; + + PCIDevice *pci_dev; + + Error *unplug_blocker; }; static void vfu_object_init_ctx(VfuObject *o, Error **errp); @@ -181,6 +187,9 @@ static void vfu_object_machine_done(Notifier *notifier, void *data) static void vfu_object_init_ctx(VfuObject *o, Error **errp) { ERRP_GUARD(); + DeviceState *dev = NULL; + vfu_pci_type_t pci_type = VFU_PCI_TYPE_CONVENTIONAL; + int ret; if (o->vfu_ctx || !o->socket || !o->device || !phase_check(PHASE_MACHINE_READY)) { @@ -199,6 +208,53 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) error_setg(errp, "vfu: Failed to create context - %s", strerror(errno)); return; } + + dev = qdev_find_recursive(sysbus_get_default(), o->device); + if (dev == NULL) { + error_setg(errp, "vfu: Device %s not found", o->device); + goto fail; + } + + if (!object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + error_setg(errp, "vfu: %s not a PCI device", o->device); + goto fail; + } + + o->pci_dev = PCI_DEVICE(dev); + + object_ref(OBJECT(o->pci_dev)); + + if (pci_is_express(o->pci_dev)) { + pci_type = VFU_PCI_TYPE_EXPRESS; + } + + ret = vfu_pci_init(o->vfu_ctx, pci_type, PCI_HEADER_TYPE_NORMAL, 0); + if (ret < 0) { + error_setg(errp, + "vfu: Failed to attach PCI device %s to context - %s", + o->device, strerror(errno)); + goto fail; + } + + error_setg(&o->unplug_blocker, + "vfu: %s for %s must be deleted before unplugging", + TYPE_VFU_OBJECT, o->device); + qdev_add_unplug_blocker(DEVICE(o->pci_dev), o->unplug_blocker); + + return; + +fail: + vfu_destroy_ctx(o->vfu_ctx); + if (o->unplug_blocker && o->pci_dev) { + qdev_del_unplug_blocker(DEVICE(o->pci_dev), o->unplug_blocker); + error_free(o->unplug_blocker); + o->unplug_blocker = NULL; + } + if (o->pci_dev) { + object_unref(OBJECT(o->pci_dev)); + o->pci_dev = NULL; + } + o->vfu_ctx = NULL; } static void vfu_object_init(Object *obj) @@ -241,6 +297,17 @@ static void vfu_object_finalize(Object *obj) o->device = NULL; + if (o->unplug_blocker && o->pci_dev) { + qdev_del_unplug_blocker(DEVICE(o->pci_dev), o->unplug_blocker); + error_free(o->unplug_blocker); + o->unplug_blocker = NULL; + } + + if (o->pci_dev) { + object_unref(OBJECT(o->pci_dev)); + o->pci_dev = NULL; + } + if (!k->nr_devs && vfu_object_auto_shutdown()) { qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); } From 9fb3fba14953958944aea18f7a5720456b7fac8f Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:28 -0400 Subject: [PATCH 172/180] vfio-user: run vfio-user context Setup a handler to run vfio-user context. The context is driven by messages to the file descriptor associated with it - get the fd for the context and hook up the handler with it Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: e934b0090529d448b6a7972b21dfc3d7421ce494.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/vfio-user-obj.c | 118 +++++++++++++++++++++++++++++++++++++- qapi/misc.json | 31 ++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index 3ca6aa2b45..178bd6f8ed 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -27,6 +27,9 @@ * * device - id of a device on the server, a required option. PCI devices * alone are supported presently. + * + * notes - x-vfio-user-server could block IO and monitor during the + * initialization phase. */ #include "qemu/osdep.h" @@ -40,11 +43,14 @@ #include "hw/remote/machine.h" #include "qapi/error.h" #include "qapi/qapi-visit-sockets.h" +#include "qapi/qapi-events-misc.h" #include "qemu/notify.h" +#include "qemu/thread.h" #include "sysemu/sysemu.h" #include "libvfio-user.h" #include "hw/qdev-core.h" #include "hw/pci/pci.h" +#include "qemu/timer.h" #define TYPE_VFU_OBJECT "x-vfio-user-server" OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) @@ -86,6 +92,8 @@ struct VfuObject { PCIDevice *pci_dev; Error *unplug_blocker; + + int vfu_poll_fd; }; static void vfu_object_init_ctx(VfuObject *o, Error **errp); @@ -164,6 +172,78 @@ static void vfu_object_set_device(Object *obj, const char *str, Error **errp) vfu_object_init_ctx(o, errp); } +static void vfu_object_ctx_run(void *opaque) +{ + VfuObject *o = opaque; + const char *vfu_id; + char *vfu_path, *pci_dev_path; + int ret = -1; + + while (ret != 0) { + ret = vfu_run_ctx(o->vfu_ctx); + if (ret < 0) { + if (errno == EINTR) { + continue; + } else if (errno == ENOTCONN) { + vfu_id = object_get_canonical_path_component(OBJECT(o)); + vfu_path = object_get_canonical_path(OBJECT(o)); + g_assert(o->pci_dev); + pci_dev_path = object_get_canonical_path(OBJECT(o->pci_dev)); + /* o->device is a required property and is non-NULL here */ + g_assert(o->device); + qapi_event_send_vfu_client_hangup(vfu_id, vfu_path, + o->device, pci_dev_path); + qemu_set_fd_handler(o->vfu_poll_fd, NULL, NULL, NULL); + o->vfu_poll_fd = -1; + object_unparent(OBJECT(o)); + g_free(vfu_path); + g_free(pci_dev_path); + break; + } else { + VFU_OBJECT_ERROR(o, "vfu: Failed to run device %s - %s", + o->device, strerror(errno)); + break; + } + } + } +} + +static void vfu_object_attach_ctx(void *opaque) +{ + VfuObject *o = opaque; + GPollFD pfds[1]; + int ret; + + qemu_set_fd_handler(o->vfu_poll_fd, NULL, NULL, NULL); + + pfds[0].fd = o->vfu_poll_fd; + pfds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR; + +retry_attach: + ret = vfu_attach_ctx(o->vfu_ctx); + if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + /** + * vfu_object_attach_ctx can block QEMU's main loop + * during attach - the monitor and other IO + * could be unresponsive during this time. + */ + (void)qemu_poll_ns(pfds, 1, 500 * (int64_t)SCALE_MS); + goto retry_attach; + } else if (ret < 0) { + VFU_OBJECT_ERROR(o, "vfu: Failed to attach device %s to context - %s", + o->device, strerror(errno)); + return; + } + + o->vfu_poll_fd = vfu_get_poll_fd(o->vfu_ctx); + if (o->vfu_poll_fd < 0) { + VFU_OBJECT_ERROR(o, "vfu: Failed to get poll fd %s", o->device); + return; + } + + qemu_set_fd_handler(o->vfu_poll_fd, vfu_object_ctx_run, NULL, o); +} + /* * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' * properties. It also depends on devices instantiated in QEMU. These @@ -184,6 +264,20 @@ static void vfu_object_machine_done(Notifier *notifier, void *data) } } +/** + * vfu_object_init_ctx: Create and initialize libvfio-user context. Add + * an unplug blocker for the associated PCI device. Setup a FD handler + * to process incoming messages in the context's socket. + * + * The socket and device properties are mandatory, and this function + * will not create the context without them - the setters for these + * properties should call this function when the property is set. The + * machine should also be ready when this function is invoked - it is + * because QEMU objects are initialized before devices, and the + * associated PCI device wouldn't be available at the object + * initialization time. Until these conditions are satisfied, this + * function would return early without performing any task. + */ static void vfu_object_init_ctx(VfuObject *o, Error **errp) { ERRP_GUARD(); @@ -202,7 +296,8 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) return; } - o->vfu_ctx = vfu_create_ctx(VFU_TRANS_SOCK, o->socket->u.q_unix.path, 0, + o->vfu_ctx = vfu_create_ctx(VFU_TRANS_SOCK, o->socket->u.q_unix.path, + LIBVFIO_USER_FLAG_ATTACH_NB, o, VFU_DEV_TYPE_PCI); if (o->vfu_ctx == NULL) { error_setg(errp, "vfu: Failed to create context - %s", strerror(errno)); @@ -241,6 +336,21 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) TYPE_VFU_OBJECT, o->device); qdev_add_unplug_blocker(DEVICE(o->pci_dev), o->unplug_blocker); + ret = vfu_realize_ctx(o->vfu_ctx); + if (ret < 0) { + error_setg(errp, "vfu: Failed to realize device %s- %s", + o->device, strerror(errno)); + goto fail; + } + + o->vfu_poll_fd = vfu_get_poll_fd(o->vfu_ctx); + if (o->vfu_poll_fd < 0) { + error_setg(errp, "vfu: Failed to get poll fd %s", o->device); + goto fail; + } + + qemu_set_fd_handler(o->vfu_poll_fd, vfu_object_attach_ctx, NULL, o); + return; fail: @@ -275,6 +385,7 @@ static void vfu_object_init(Object *obj) qemu_add_machine_init_done_notifier(&o->machine_done); } + o->vfu_poll_fd = -1; } static void vfu_object_finalize(Object *obj) @@ -288,6 +399,11 @@ static void vfu_object_finalize(Object *obj) o->socket = NULL; + if (o->vfu_poll_fd != -1) { + qemu_set_fd_handler(o->vfu_poll_fd, NULL, NULL, NULL); + o->vfu_poll_fd = -1; + } + if (o->vfu_ctx) { vfu_destroy_ctx(o->vfu_ctx); o->vfu_ctx = NULL; diff --git a/qapi/misc.json b/qapi/misc.json index 45344483cd..27ef5a2b20 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -553,3 +553,34 @@ ## { 'event': 'RTC_CHANGE', 'data': { 'offset': 'int', 'qom-path': 'str' } } + +## +# @VFU_CLIENT_HANGUP: +# +# Emitted when the client of a TYPE_VFIO_USER_SERVER closes the +# communication channel +# +# @vfu-id: ID of the TYPE_VFIO_USER_SERVER object. It is the last component +# of @vfu-qom-path referenced below +# +# @vfu-qom-path: path to the TYPE_VFIO_USER_SERVER object in the QOM tree +# +# @dev-id: ID of attached PCI device +# +# @dev-qom-path: path to attached PCI device in the QOM tree +# +# Since: 7.1 +# +# Example: +# +# <- { "event": "VFU_CLIENT_HANGUP", +# "data": { "vfu-id": "vfu1", +# "vfu-qom-path": "/objects/vfu1", +# "dev-id": "sas1", +# "dev-qom-path": "/machine/peripheral/sas1" }, +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } +# +## +{ 'event': 'VFU_CLIENT_HANGUP', + 'data': { 'vfu-id': 'str', 'vfu-qom-path': 'str', + 'dev-id': 'str', 'dev-qom-path': 'str' } } From 90072f29d677d60694cad09c1d648f38a1e20456 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:29 -0400 Subject: [PATCH 173/180] vfio-user: handle PCI config space accesses Define and register handlers for PCI config space accesses Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: be9d2ccf9b1d24e50dcd9c23404dbf284142cec7.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/trace-events | 2 ++ hw/remote/vfio-user-obj.c | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/hw/remote/trace-events b/hw/remote/trace-events index 7da12f0d96..2ef7884346 100644 --- a/hw/remote/trace-events +++ b/hw/remote/trace-events @@ -5,3 +5,5 @@ mpqemu_recv_io_error(int cmd, int size, int nfds) "failed to receive %d size %d, # vfio-user-obj.c vfu_prop(const char *prop, const char *val) "vfu: setting %s as %s" +vfu_cfg_read(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u -> 0x%x" +vfu_cfg_write(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u <- 0x%x" diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index 178bd6f8ed..cef473cb98 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -46,6 +46,7 @@ #include "qapi/qapi-events-misc.h" #include "qemu/notify.h" #include "qemu/thread.h" +#include "qemu/main-loop.h" #include "sysemu/sysemu.h" #include "libvfio-user.h" #include "hw/qdev-core.h" @@ -244,6 +245,45 @@ retry_attach: qemu_set_fd_handler(o->vfu_poll_fd, vfu_object_ctx_run, NULL, o); } +static ssize_t vfu_object_cfg_access(vfu_ctx_t *vfu_ctx, char * const buf, + size_t count, loff_t offset, + const bool is_write) +{ + VfuObject *o = vfu_get_private(vfu_ctx); + uint32_t pci_access_width = sizeof(uint32_t); + size_t bytes = count; + uint32_t val = 0; + char *ptr = buf; + int len; + + /* + * Writes to the BAR registers would trigger an update to the + * global Memory and IO AddressSpaces. But the remote device + * never uses the global AddressSpaces, therefore overlapping + * memory regions are not a problem + */ + while (bytes > 0) { + len = (bytes > pci_access_width) ? pci_access_width : bytes; + if (is_write) { + memcpy(&val, ptr, len); + pci_host_config_write_common(o->pci_dev, offset, + pci_config_size(o->pci_dev), + val, len); + trace_vfu_cfg_write(offset, val); + } else { + val = pci_host_config_read_common(o->pci_dev, offset, + pci_config_size(o->pci_dev), len); + memcpy(ptr, &val, len); + trace_vfu_cfg_read(offset, val); + } + offset += len; + ptr += len; + bytes -= len; + } + + return count; +} + /* * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' * properties. It also depends on devices instantiated in QEMU. These @@ -336,6 +376,17 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) TYPE_VFU_OBJECT, o->device); qdev_add_unplug_blocker(DEVICE(o->pci_dev), o->unplug_blocker); + ret = vfu_setup_region(o->vfu_ctx, VFU_PCI_DEV_CFG_REGION_IDX, + pci_config_size(o->pci_dev), &vfu_object_cfg_access, + VFU_REGION_FLAG_RW | VFU_REGION_FLAG_ALWAYS_CB, + NULL, 0, -1, 0); + if (ret < 0) { + error_setg(errp, + "vfu: Failed to setup config space handlers for %s- %s", + o->device, strerror(errno)); + goto fail; + } + ret = vfu_realize_ctx(o->vfu_ctx); if (ret < 0) { error_setg(errp, "vfu: Failed to realize device %s- %s", From 253007d14712fb172a59f164fe5828565e2af112 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:30 -0400 Subject: [PATCH 174/180] vfio-user: IOMMU support for remote device Assign separate address space for each device in the remote processes. Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: afe0b0a97582cdad42b5b25636a29c523265a10a.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 2 + hw/remote/iommu.c | 131 ++++++++++++++++++++++++++++++++++++++ hw/remote/machine.c | 13 +++- hw/remote/meson.build | 1 + include/hw/remote/iommu.h | 40 ++++++++++++ 5 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 hw/remote/iommu.c create mode 100644 include/hw/remote/iommu.h diff --git a/MAINTAINERS b/MAINTAINERS index cbac72e239..563259101b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3644,6 +3644,8 @@ F: hw/remote/iohub.c F: include/hw/remote/iohub.h F: subprojects/libvfio-user F: hw/remote/vfio-user-obj.c +F: hw/remote/iommu.c +F: include/hw/remote/iommu.h EBPF: M: Jason Wang diff --git a/hw/remote/iommu.c b/hw/remote/iommu.c new file mode 100644 index 0000000000..fd723d91f3 --- /dev/null +++ b/hw/remote/iommu.c @@ -0,0 +1,131 @@ +/** + * IOMMU for remote device + * + * Copyright © 2022 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" + +#include "hw/remote/iommu.h" +#include "hw/pci/pci_bus.h" +#include "hw/pci/pci.h" +#include "exec/memory.h" +#include "exec/address-spaces.h" +#include "trace.h" + +/** + * IOMMU for TYPE_REMOTE_MACHINE - manages DMA address space isolation + * for remote machine. It is used by TYPE_VFIO_USER_SERVER. + * + * - Each TYPE_VFIO_USER_SERVER instance handles one PCIDevice on a PCIBus. + * There is one RemoteIommu per PCIBus, so the RemoteIommu tracks multiple + * PCIDevices by maintaining a ->elem_by_devfn mapping. + * + * - memory_region_init_iommu() is not used because vfio-user MemoryRegions + * will be added to the elem->mr container instead. This is more natural + * than implementing the IOMMUMemoryRegionClass APIs since vfio-user + * provides something that is close to a full-fledged MemoryRegion and + * not like an IOMMU mapping. + * + * - When a device is hot unplugged, the elem->mr reference is dropped so + * all vfio-user MemoryRegions associated with this vfio-user server are + * destroyed. + */ + +static AddressSpace *remote_iommu_find_add_as(PCIBus *pci_bus, + void *opaque, int devfn) +{ + RemoteIommu *iommu = opaque; + RemoteIommuElem *elem = NULL; + + qemu_mutex_lock(&iommu->lock); + + elem = g_hash_table_lookup(iommu->elem_by_devfn, INT2VOIDP(devfn)); + + if (!elem) { + elem = g_malloc0(sizeof(RemoteIommuElem)); + g_hash_table_insert(iommu->elem_by_devfn, INT2VOIDP(devfn), elem); + } + + if (!elem->mr) { + elem->mr = MEMORY_REGION(object_new(TYPE_MEMORY_REGION)); + memory_region_set_size(elem->mr, UINT64_MAX); + address_space_init(&elem->as, elem->mr, NULL); + } + + qemu_mutex_unlock(&iommu->lock); + + return &elem->as; +} + +void remote_iommu_unplug_dev(PCIDevice *pci_dev) +{ + AddressSpace *as = pci_device_iommu_address_space(pci_dev); + RemoteIommuElem *elem = NULL; + + if (as == &address_space_memory) { + return; + } + + elem = container_of(as, RemoteIommuElem, as); + + address_space_destroy(&elem->as); + + object_unref(elem->mr); + + elem->mr = NULL; +} + +static void remote_iommu_init(Object *obj) +{ + RemoteIommu *iommu = REMOTE_IOMMU(obj); + + iommu->elem_by_devfn = g_hash_table_new_full(NULL, NULL, NULL, g_free); + + qemu_mutex_init(&iommu->lock); +} + +static void remote_iommu_finalize(Object *obj) +{ + RemoteIommu *iommu = REMOTE_IOMMU(obj); + + qemu_mutex_destroy(&iommu->lock); + + g_hash_table_destroy(iommu->elem_by_devfn); + + iommu->elem_by_devfn = NULL; +} + +void remote_iommu_setup(PCIBus *pci_bus) +{ + RemoteIommu *iommu = NULL; + + g_assert(pci_bus); + + iommu = REMOTE_IOMMU(object_new(TYPE_REMOTE_IOMMU)); + + pci_setup_iommu(pci_bus, remote_iommu_find_add_as, iommu); + + object_property_add_child(OBJECT(pci_bus), "remote-iommu", OBJECT(iommu)); + + object_unref(OBJECT(iommu)); +} + +static const TypeInfo remote_iommu_info = { + .name = TYPE_REMOTE_IOMMU, + .parent = TYPE_OBJECT, + .instance_size = sizeof(RemoteIommu), + .instance_init = remote_iommu_init, + .instance_finalize = remote_iommu_finalize, +}; + +static void remote_iommu_register_types(void) +{ + type_register_static(&remote_iommu_info); +} + +type_init(remote_iommu_register_types) diff --git a/hw/remote/machine.c b/hw/remote/machine.c index 4d008ed721..cbb2add291 100644 --- a/hw/remote/machine.c +++ b/hw/remote/machine.c @@ -20,6 +20,7 @@ #include "qapi/error.h" #include "hw/pci/pci_host.h" #include "hw/remote/iohub.h" +#include "hw/remote/iommu.h" #include "hw/qdev-core.h" static void remote_machine_init(MachineState *machine) @@ -99,6 +100,16 @@ static void remote_machine_instance_init(Object *obj) s->auto_shutdown = true; } +static void remote_machine_dev_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + qdev_unrealize(dev); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + remote_iommu_unplug_dev(PCI_DEVICE(dev)); + } +} + static void remote_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -107,7 +118,7 @@ static void remote_machine_class_init(ObjectClass *oc, void *data) mc->init = remote_machine_init; mc->desc = "Experimental remote machine"; - hc->unplug = qdev_simple_device_unplug_cb; + hc->unplug = remote_machine_dev_unplug_cb; object_class_property_add_bool(oc, "vfio-user", remote_machine_get_vfio_user, diff --git a/hw/remote/meson.build b/hw/remote/meson.build index 0eb5a0f375..ab25c04906 100644 --- a/hw/remote/meson.build +++ b/hw/remote/meson.build @@ -6,6 +6,7 @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c')) remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('iohub.c')) +remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('iommu.c')) remote_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_true: files('vfio-user-obj.c')) remote_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_true: libvfio_user_dep) diff --git a/include/hw/remote/iommu.h b/include/hw/remote/iommu.h new file mode 100644 index 0000000000..33b68a8f4b --- /dev/null +++ b/include/hw/remote/iommu.h @@ -0,0 +1,40 @@ +/** + * Copyright © 2022 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef REMOTE_IOMMU_H +#define REMOTE_IOMMU_H + +#include "hw/pci/pci_bus.h" +#include "hw/pci/pci.h" + +#ifndef INT2VOIDP +#define INT2VOIDP(i) (void *)(uintptr_t)(i) +#endif + +typedef struct RemoteIommuElem { + MemoryRegion *mr; + + AddressSpace as; +} RemoteIommuElem; + +#define TYPE_REMOTE_IOMMU "x-remote-iommu" +OBJECT_DECLARE_SIMPLE_TYPE(RemoteIommu, REMOTE_IOMMU) + +struct RemoteIommu { + Object parent; + + GHashTable *elem_by_devfn; + + QemuMutex lock; +}; + +void remote_iommu_setup(PCIBus *pci_bus); + +void remote_iommu_unplug_dev(PCIDevice *pci_dev); + +#endif From 15ccf9bee7804bfd969c171fc15ddc25f18431e3 Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:31 -0400 Subject: [PATCH 175/180] vfio-user: handle DMA mappings Define and register callbacks to manage the RAM regions used for device DMA Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: faacbcd45c4d02c591f0dbfdc19041fbb3eae7eb.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/machine.c | 5 ++++ hw/remote/trace-events | 2 ++ hw/remote/vfio-user-obj.c | 55 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/hw/remote/machine.c b/hw/remote/machine.c index cbb2add291..645b54343d 100644 --- a/hw/remote/machine.c +++ b/hw/remote/machine.c @@ -22,6 +22,7 @@ #include "hw/remote/iohub.h" #include "hw/remote/iommu.h" #include "hw/qdev-core.h" +#include "hw/remote/iommu.h" static void remote_machine_init(MachineState *machine) { @@ -51,6 +52,10 @@ static void remote_machine_init(MachineState *machine) pci_host = PCI_HOST_BRIDGE(rem_host); + if (s->vfio_user) { + remote_iommu_setup(pci_host->bus); + } + remote_iohub_init(&s->iohub); pci_bus_irqs(pci_host->bus, remote_iohub_set_irq, remote_iohub_map_irq, diff --git a/hw/remote/trace-events b/hw/remote/trace-events index 2ef7884346..f945c7e33b 100644 --- a/hw/remote/trace-events +++ b/hw/remote/trace-events @@ -7,3 +7,5 @@ mpqemu_recv_io_error(int cmd, int size, int nfds) "failed to receive %d size %d, vfu_prop(const char *prop, const char *val) "vfu: setting %s as %s" vfu_cfg_read(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u -> 0x%x" vfu_cfg_write(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u <- 0x%x" +vfu_dma_register(uint64_t gpa, size_t len) "vfu: registering GPA 0x%"PRIx64", %zu bytes" +vfu_dma_unregister(uint64_t gpa) "vfu: unregistering GPA 0x%"PRIx64"" diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index cef473cb98..7b21f77052 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -284,6 +284,54 @@ static ssize_t vfu_object_cfg_access(vfu_ctx_t *vfu_ctx, char * const buf, return count; } +static void dma_register(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info) +{ + VfuObject *o = vfu_get_private(vfu_ctx); + AddressSpace *dma_as = NULL; + MemoryRegion *subregion = NULL; + g_autofree char *name = NULL; + struct iovec *iov = &info->iova; + + if (!info->vaddr) { + return; + } + + name = g_strdup_printf("mem-%s-%"PRIx64"", o->device, + (uint64_t)info->vaddr); + + subregion = g_new0(MemoryRegion, 1); + + memory_region_init_ram_ptr(subregion, NULL, name, + iov->iov_len, info->vaddr); + + dma_as = pci_device_iommu_address_space(o->pci_dev); + + memory_region_add_subregion(dma_as->root, (hwaddr)iov->iov_base, subregion); + + trace_vfu_dma_register((uint64_t)iov->iov_base, iov->iov_len); +} + +static void dma_unregister(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info) +{ + VfuObject *o = vfu_get_private(vfu_ctx); + AddressSpace *dma_as = NULL; + MemoryRegion *mr = NULL; + ram_addr_t offset; + + mr = memory_region_from_host(info->vaddr, &offset); + if (!mr) { + return; + } + + dma_as = pci_device_iommu_address_space(o->pci_dev); + + memory_region_del_subregion(dma_as->root, mr); + + object_unparent((OBJECT(mr))); + + trace_vfu_dma_unregister((uint64_t)info->iova.iov_base); +} + /* * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' * properties. It also depends on devices instantiated in QEMU. These @@ -387,6 +435,13 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) goto fail; } + ret = vfu_setup_device_dma(o->vfu_ctx, &dma_register, &dma_unregister); + if (ret < 0) { + error_setg(errp, "vfu: Failed to setup DMA handlers for %s", + o->device); + goto fail; + } + ret = vfu_realize_ctx(o->vfu_ctx); if (ret < 0) { error_setg(errp, "vfu: Failed to realize device %s- %s", From 3123f93d6b85b69ab77f409456fac8ded895efed Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:32 -0400 Subject: [PATCH 176/180] vfio-user: handle PCI BAR accesses Determine the BARs used by the PCI device and register handlers to manage the access to the same. Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: 3373e10b5be5f42846f0632d4382466e1698c505.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/trace-events | 3 + hw/remote/vfio-user-obj.c | 190 ++++++++++++++++++++++++++++++++ include/exec/memory.h | 3 + softmmu/physmem.c | 4 +- tests/qtest/fuzz/generic_fuzz.c | 9 +- 5 files changed, 203 insertions(+), 6 deletions(-) diff --git a/hw/remote/trace-events b/hw/remote/trace-events index f945c7e33b..847d50d88f 100644 --- a/hw/remote/trace-events +++ b/hw/remote/trace-events @@ -9,3 +9,6 @@ vfu_cfg_read(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u -> 0x%x" vfu_cfg_write(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u <- 0x%x" vfu_dma_register(uint64_t gpa, size_t len) "vfu: registering GPA 0x%"PRIx64", %zu bytes" vfu_dma_unregister(uint64_t gpa) "vfu: unregistering GPA 0x%"PRIx64"" +vfu_bar_register(int i, uint64_t addr, uint64_t size) "vfu: BAR %d: addr 0x%"PRIx64" size 0x%"PRIx64"" +vfu_bar_rw_enter(const char *op, uint64_t addr) "vfu: %s request for BAR address 0x%"PRIx64"" +vfu_bar_rw_exit(const char *op, uint64_t addr) "vfu: Finished %s of BAR address 0x%"PRIx64"" diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index 7b21f77052..dd760a99e2 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -52,6 +52,7 @@ #include "hw/qdev-core.h" #include "hw/pci/pci.h" #include "qemu/timer.h" +#include "exec/memory.h" #define TYPE_VFU_OBJECT "x-vfio-user-server" OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) @@ -332,6 +333,193 @@ static void dma_unregister(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info) trace_vfu_dma_unregister((uint64_t)info->iova.iov_base); } +static int vfu_object_mr_rw(MemoryRegion *mr, uint8_t *buf, hwaddr offset, + hwaddr size, const bool is_write) +{ + uint8_t *ptr = buf; + bool release_lock = false; + uint8_t *ram_ptr = NULL; + MemTxResult result; + int access_size; + uint64_t val; + + if (memory_access_is_direct(mr, is_write)) { + /** + * Some devices expose a PCI expansion ROM, which could be buffer + * based as compared to other regions which are primarily based on + * MemoryRegionOps. memory_region_find() would already check + * for buffer overflow, we don't need to repeat it here. + */ + ram_ptr = memory_region_get_ram_ptr(mr); + + if (is_write) { + memcpy((ram_ptr + offset), buf, size); + } else { + memcpy(buf, (ram_ptr + offset), size); + } + + return 0; + } + + while (size) { + /** + * The read/write logic used below is similar to the ones in + * flatview_read/write_continue() + */ + release_lock = prepare_mmio_access(mr); + + access_size = memory_access_size(mr, size, offset); + + if (is_write) { + val = ldn_he_p(ptr, access_size); + + result = memory_region_dispatch_write(mr, offset, val, + size_memop(access_size), + MEMTXATTRS_UNSPECIFIED); + } else { + result = memory_region_dispatch_read(mr, offset, &val, + size_memop(access_size), + MEMTXATTRS_UNSPECIFIED); + + stn_he_p(ptr, access_size, val); + } + + if (release_lock) { + qemu_mutex_unlock_iothread(); + release_lock = false; + } + + if (result != MEMTX_OK) { + return -1; + } + + size -= access_size; + ptr += access_size; + offset += access_size; + } + + return 0; +} + +static size_t vfu_object_bar_rw(PCIDevice *pci_dev, int pci_bar, + hwaddr bar_offset, char * const buf, + hwaddr len, const bool is_write) +{ + MemoryRegionSection section = { 0 }; + uint8_t *ptr = (uint8_t *)buf; + MemoryRegion *section_mr = NULL; + uint64_t section_size; + hwaddr section_offset; + hwaddr size = 0; + + while (len) { + section = memory_region_find(pci_dev->io_regions[pci_bar].memory, + bar_offset, len); + + if (!section.mr) { + warn_report("vfu: invalid address 0x%"PRIx64"", bar_offset); + return size; + } + + section_mr = section.mr; + section_offset = section.offset_within_region; + section_size = int128_get64(section.size); + + if (is_write && section_mr->readonly) { + warn_report("vfu: attempting to write to readonly region in " + "bar %d - [0x%"PRIx64" - 0x%"PRIx64"]", + pci_bar, bar_offset, + (bar_offset + section_size)); + memory_region_unref(section_mr); + return size; + } + + if (vfu_object_mr_rw(section_mr, ptr, section_offset, + section_size, is_write)) { + warn_report("vfu: failed to %s " + "[0x%"PRIx64" - 0x%"PRIx64"] in bar %d", + is_write ? "write to" : "read from", bar_offset, + (bar_offset + section_size), pci_bar); + memory_region_unref(section_mr); + return size; + } + + size += section_size; + bar_offset += section_size; + ptr += section_size; + len -= section_size; + + memory_region_unref(section_mr); + } + + return size; +} + +/** + * VFU_OBJECT_BAR_HANDLER - macro for defining handlers for PCI BARs. + * + * To create handler for BAR number 2, VFU_OBJECT_BAR_HANDLER(2) would + * define vfu_object_bar2_handler + */ +#define VFU_OBJECT_BAR_HANDLER(BAR_NO) \ + static ssize_t vfu_object_bar##BAR_NO##_handler(vfu_ctx_t *vfu_ctx, \ + char * const buf, size_t count, \ + loff_t offset, const bool is_write) \ + { \ + VfuObject *o = vfu_get_private(vfu_ctx); \ + PCIDevice *pci_dev = o->pci_dev; \ + \ + return vfu_object_bar_rw(pci_dev, BAR_NO, offset, \ + buf, count, is_write); \ + } \ + +VFU_OBJECT_BAR_HANDLER(0) +VFU_OBJECT_BAR_HANDLER(1) +VFU_OBJECT_BAR_HANDLER(2) +VFU_OBJECT_BAR_HANDLER(3) +VFU_OBJECT_BAR_HANDLER(4) +VFU_OBJECT_BAR_HANDLER(5) +VFU_OBJECT_BAR_HANDLER(6) + +static vfu_region_access_cb_t *vfu_object_bar_handlers[PCI_NUM_REGIONS] = { + &vfu_object_bar0_handler, + &vfu_object_bar1_handler, + &vfu_object_bar2_handler, + &vfu_object_bar3_handler, + &vfu_object_bar4_handler, + &vfu_object_bar5_handler, + &vfu_object_bar6_handler, +}; + +/** + * vfu_object_register_bars - Identify active BAR regions of pdev and setup + * callbacks to handle read/write accesses + */ +static void vfu_object_register_bars(vfu_ctx_t *vfu_ctx, PCIDevice *pdev) +{ + int flags = VFU_REGION_FLAG_RW; + int i; + + for (i = 0; i < PCI_NUM_REGIONS; i++) { + if (!pdev->io_regions[i].size) { + continue; + } + + if ((i == VFU_PCI_DEV_ROM_REGION_IDX) || + pdev->io_regions[i].memory->readonly) { + flags &= ~VFU_REGION_FLAG_WRITE; + } + + vfu_setup_region(vfu_ctx, VFU_PCI_DEV_BAR0_REGION_IDX + i, + (size_t)pdev->io_regions[i].size, + vfu_object_bar_handlers[i], + flags, NULL, 0, -1, 0); + + trace_vfu_bar_register(i, pdev->io_regions[i].addr, + pdev->io_regions[i].size); + } +} + /* * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' * properties. It also depends on devices instantiated in QEMU. These @@ -442,6 +630,8 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) goto fail; } + vfu_object_register_bars(o->vfu_ctx, o->pci_dev); + ret = vfu_realize_ctx(o->vfu_ctx); if (ret < 0) { error_setg(errp, "vfu: Failed to realize device %s- %s", diff --git a/include/exec/memory.h b/include/exec/memory.h index f1c19451bc..a6a0f4d8ad 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2810,6 +2810,9 @@ MemTxResult address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr, const void *buf, hwaddr len); +int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr); +bool prepare_mmio_access(MemoryRegion *mr); + static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) { if (is_write) { diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 657841eed0..fb16be57a6 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -2719,7 +2719,7 @@ void memory_region_flush_rom_device(MemoryRegion *mr, hwaddr addr, hwaddr size) invalidate_and_set_dirty(mr, addr, size); } -static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) +int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) { unsigned access_size_max = mr->ops->valid.max_access_size; @@ -2746,7 +2746,7 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) return l; } -static bool prepare_mmio_access(MemoryRegion *mr) +bool prepare_mmio_access(MemoryRegion *mr) { bool release_lock = false; diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index 25df19fd5a..447ffe8178 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -144,7 +144,7 @@ static void *pattern_alloc(pattern p, size_t len) return buf; } -static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) +static int fuzz_memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) { unsigned access_size_max = mr->ops->valid.max_access_size; @@ -242,11 +242,12 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr) /* * If mr1 isn't RAM, address_space_translate doesn't update l. Use - * memory_access_size to identify the number of bytes that it is safe - * to write without accidentally writing to another MemoryRegion. + * fuzz_memory_access_size to identify the number of bytes that it + * is safe to write without accidentally writing to another + * MemoryRegion. */ if (!memory_region_is_ram(mr1)) { - l = memory_access_size(mr1, l, addr1); + l = fuzz_memory_access_size(mr1, l, addr1); } if (memory_region_is_ram(mr1) || memory_region_is_romd(mr1) || From 08cf3dc611991e9697f62458107e13f2c582869a Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:33 -0400 Subject: [PATCH 177/180] vfio-user: handle device interrupts Forward remote device's interrupts to the guest Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Message-id: 9523479eaafe050677f4de2af5dd0df18c27cfd9.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- MAINTAINERS | 1 + hw/pci/msi.c | 49 +++++++-- hw/pci/msix.c | 35 ++++++- hw/pci/pci.c | 13 +++ hw/remote/machine.c | 16 ++- hw/remote/trace-events | 1 + hw/remote/vfio-user-obj.c | 167 ++++++++++++++++++++++++++++++ include/hw/pci/msi.h | 1 + include/hw/pci/msix.h | 1 + include/hw/pci/pci.h | 13 +++ include/hw/remote/vfio-user-obj.h | 6 ++ stubs/meson.build | 1 + stubs/vfio-user-obj.c | 6 ++ 13 files changed, 298 insertions(+), 12 deletions(-) create mode 100644 include/hw/remote/vfio-user-obj.h create mode 100644 stubs/vfio-user-obj.c diff --git a/MAINTAINERS b/MAINTAINERS index 563259101b..aaa649a50d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3644,6 +3644,7 @@ F: hw/remote/iohub.c F: include/hw/remote/iohub.h F: subprojects/libvfio-user F: hw/remote/vfio-user-obj.c +F: include/hw/remote/vfio-user-obj.h F: hw/remote/iommu.c F: include/hw/remote/iommu.h diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 47d2b0f33c..5c471b9616 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -134,7 +134,7 @@ void msi_set_message(PCIDevice *dev, MSIMessage msg) pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data); } -MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector) +static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector) { uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); bool msi64bit = flags & PCI_MSI_FLAGS_64BIT; @@ -159,6 +159,11 @@ MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector) return msg; } +MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector) +{ + return dev->msi_prepare_message(dev, vector); +} + bool msi_enabled(const PCIDevice *dev) { return msi_present(dev) && @@ -241,6 +246,8 @@ int msi_init(struct PCIDevice *dev, uint8_t offset, 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors)); } + dev->msi_prepare_message = msi_prepare_message; + return 0; } @@ -256,6 +263,7 @@ void msi_uninit(struct PCIDevice *dev) cap_size = msi_cap_sizeof(flags); pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size); dev->cap_present &= ~QEMU_PCI_CAP_MSI; + dev->msi_prepare_message = NULL; MSI_DEV_PRINTF(dev, "uninit\n"); } @@ -307,6 +315,39 @@ bool msi_is_masked(const PCIDevice *dev, unsigned int vector) return mask & (1U << vector); } +void msi_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp) +{ + ERRP_GUARD(); + uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); + bool msi64bit = flags & PCI_MSI_FLAGS_64BIT; + uint32_t irq_state, vector_mask, pending; + + if (vector > PCI_MSI_VECTORS_MAX) { + error_setg(errp, "msi: vector %d not allocated. max vector is %d", + vector, PCI_MSI_VECTORS_MAX); + return; + } + + vector_mask = (1U << vector); + + irq_state = pci_get_long(dev->config + msi_mask_off(dev, msi64bit)); + + if (mask) { + irq_state |= vector_mask; + } else { + irq_state &= ~vector_mask; + } + + pci_set_long(dev->config + msi_mask_off(dev, msi64bit), irq_state); + + pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit)); + if (!mask && (pending & vector_mask)) { + pending &= ~vector_mask; + pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending); + msi_notify(dev, vector); + } +} + void msi_notify(PCIDevice *dev, unsigned int vector) { uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); @@ -334,11 +375,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector) void msi_send_message(PCIDevice *dev, MSIMessage msg) { - MemTxAttrs attrs = {}; - - attrs.requester_id = pci_requester_id(dev); - address_space_stl_le(&dev->bus_master_as, msg.address, msg.data, - attrs, NULL); + dev->msi_trigger(dev, msg); } /* Normally called by pci_default_write_config(). */ diff --git a/hw/pci/msix.c b/hw/pci/msix.c index ae9331cd0b..1e381a9813 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -31,7 +31,7 @@ #define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8) #define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8) -MSIMessage msix_get_message(PCIDevice *dev, unsigned vector) +static MSIMessage msix_prepare_message(PCIDevice *dev, unsigned vector) { uint8_t *table_entry = dev->msix_table + vector * PCI_MSIX_ENTRY_SIZE; MSIMessage msg; @@ -41,6 +41,11 @@ MSIMessage msix_get_message(PCIDevice *dev, unsigned vector) return msg; } +MSIMessage msix_get_message(PCIDevice *dev, unsigned vector) +{ + return dev->msix_prepare_message(dev, vector); +} + /* * Special API for POWER to configure the vectors through * a side channel. Should never be used by devices. @@ -131,6 +136,31 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked) } } +void msix_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp) +{ + ERRP_GUARD(); + unsigned offset; + bool was_masked; + + if (vector > dev->msix_entries_nr) { + error_setg(errp, "msix: vector %d not allocated. max vector is %d", + vector, dev->msix_entries_nr); + return; + } + + offset = vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; + + was_masked = msix_is_masked(dev, vector); + + if (mask) { + dev->msix_table[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT; + } else { + dev->msix_table[offset] &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; + } + + msix_handle_mask_update(dev, vector, was_masked); +} + static bool msix_masked(PCIDevice *dev) { return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK; @@ -344,6 +374,8 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, "msix-pba", pba_size); memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio); + dev->msix_prepare_message = msix_prepare_message; + return 0; } @@ -429,6 +461,7 @@ void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar) g_free(dev->msix_entry_used); dev->msix_entry_used = NULL; dev->cap_present &= ~QEMU_PCI_CAP_MSIX; + dev->msix_prepare_message = NULL; } void msix_uninit_exclusive_bar(PCIDevice *dev) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 6e7015329c..2f450f6a72 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -317,6 +317,15 @@ void pci_device_deassert_intx(PCIDevice *dev) } } +static void pci_msi_trigger(PCIDevice *dev, MSIMessage msg) +{ + MemTxAttrs attrs = {}; + + attrs.requester_id = pci_requester_id(dev); + address_space_stl_le(&dev->bus_master_as, msg.address, msg.data, + attrs, NULL); +} + static void pci_reset_regions(PCIDevice *dev) { int r; @@ -1212,6 +1221,8 @@ static void pci_qdev_unrealize(DeviceState *dev) pci_device_deassert_intx(pci_dev); do_pci_unregister_device(pci_dev); + + pci_dev->msi_trigger = NULL; } void pci_register_bar(PCIDevice *pci_dev, int region_num, @@ -2251,6 +2262,8 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) } pci_set_power(pci_dev, true); + + pci_dev->msi_trigger = pci_msi_trigger; } PCIDevice *pci_new_multifunction(int devfn, bool multifunction, diff --git a/hw/remote/machine.c b/hw/remote/machine.c index 645b54343d..75d550daae 100644 --- a/hw/remote/machine.c +++ b/hw/remote/machine.c @@ -23,6 +23,8 @@ #include "hw/remote/iommu.h" #include "hw/qdev-core.h" #include "hw/remote/iommu.h" +#include "hw/remote/vfio-user-obj.h" +#include "hw/pci/msi.h" static void remote_machine_init(MachineState *machine) { @@ -54,13 +56,17 @@ static void remote_machine_init(MachineState *machine) if (s->vfio_user) { remote_iommu_setup(pci_host->bus); + + msi_nonbroken = true; + + vfu_object_set_bus_irq(pci_host->bus); + } else { + remote_iohub_init(&s->iohub); + + pci_bus_irqs(pci_host->bus, remote_iohub_set_irq, remote_iohub_map_irq, + &s->iohub, REMOTE_IOHUB_NB_PIRQS); } - remote_iohub_init(&s->iohub); - - pci_bus_irqs(pci_host->bus, remote_iohub_set_irq, remote_iohub_map_irq, - &s->iohub, REMOTE_IOHUB_NB_PIRQS); - qbus_set_hotplug_handler(BUS(pci_host->bus), OBJECT(s)); } diff --git a/hw/remote/trace-events b/hw/remote/trace-events index 847d50d88f..c167b3c7a5 100644 --- a/hw/remote/trace-events +++ b/hw/remote/trace-events @@ -12,3 +12,4 @@ vfu_dma_unregister(uint64_t gpa) "vfu: unregistering GPA 0x%"PRIx64"" vfu_bar_register(int i, uint64_t addr, uint64_t size) "vfu: BAR %d: addr 0x%"PRIx64" size 0x%"PRIx64"" vfu_bar_rw_enter(const char *op, uint64_t addr) "vfu: %s request for BAR address 0x%"PRIx64"" vfu_bar_rw_exit(const char *op, uint64_t addr) "vfu: Finished %s of BAR address 0x%"PRIx64"" +vfu_interrupt(int pirq) "vfu: sending interrupt to device - PIRQ %d" diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index dd760a99e2..5ecdec06f6 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -53,6 +53,9 @@ #include "hw/pci/pci.h" #include "qemu/timer.h" #include "exec/memory.h" +#include "hw/pci/msi.h" +#include "hw/pci/msix.h" +#include "hw/remote/vfio-user-obj.h" #define TYPE_VFU_OBJECT "x-vfio-user-server" OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) @@ -96,6 +99,10 @@ struct VfuObject { Error *unplug_blocker; int vfu_poll_fd; + + MSITriggerFunc *default_msi_trigger; + MSIPrepareMessageFunc *default_msi_prepare_message; + MSIxPrepareMessageFunc *default_msix_prepare_message; }; static void vfu_object_init_ctx(VfuObject *o, Error **errp); @@ -520,6 +527,155 @@ static void vfu_object_register_bars(vfu_ctx_t *vfu_ctx, PCIDevice *pdev) } } +static int vfu_object_map_irq(PCIDevice *pci_dev, int intx) +{ + int pci_bdf = PCI_BUILD_BDF(pci_bus_num(pci_get_bus(pci_dev)), + pci_dev->devfn); + + return pci_bdf; +} + +static void vfu_object_set_irq(void *opaque, int pirq, int level) +{ + PCIBus *pci_bus = opaque; + PCIDevice *pci_dev = NULL; + vfu_ctx_t *vfu_ctx = NULL; + int pci_bus_num, devfn; + + if (level) { + pci_bus_num = PCI_BUS_NUM(pirq); + devfn = PCI_BDF_TO_DEVFN(pirq); + + /* + * pci_find_device() performs at O(1) if the device is attached + * to the root PCI bus. Whereas, if the device is attached to a + * secondary PCI bus (such as when a root port is involved), + * finding the parent PCI bus could take O(n) + */ + pci_dev = pci_find_device(pci_bus, pci_bus_num, devfn); + + vfu_ctx = pci_dev->irq_opaque; + + g_assert(vfu_ctx); + + vfu_irq_trigger(vfu_ctx, 0); + } +} + +static MSIMessage vfu_object_msi_prepare_msg(PCIDevice *pci_dev, + unsigned int vector) +{ + MSIMessage msg; + + msg.address = 0; + msg.data = vector; + + return msg; +} + +static void vfu_object_msi_trigger(PCIDevice *pci_dev, MSIMessage msg) +{ + vfu_ctx_t *vfu_ctx = pci_dev->irq_opaque; + + vfu_irq_trigger(vfu_ctx, msg.data); +} + +static void vfu_object_setup_msi_cbs(VfuObject *o) +{ + o->default_msi_trigger = o->pci_dev->msi_trigger; + o->default_msi_prepare_message = o->pci_dev->msi_prepare_message; + o->default_msix_prepare_message = o->pci_dev->msix_prepare_message; + + o->pci_dev->msi_trigger = vfu_object_msi_trigger; + o->pci_dev->msi_prepare_message = vfu_object_msi_prepare_msg; + o->pci_dev->msix_prepare_message = vfu_object_msi_prepare_msg; +} + +static void vfu_object_restore_msi_cbs(VfuObject *o) +{ + o->pci_dev->msi_trigger = o->default_msi_trigger; + o->pci_dev->msi_prepare_message = o->default_msi_prepare_message; + o->pci_dev->msix_prepare_message = o->default_msix_prepare_message; +} + +static void vfu_msix_irq_state(vfu_ctx_t *vfu_ctx, uint32_t start, + uint32_t count, bool mask) +{ + VfuObject *o = vfu_get_private(vfu_ctx); + Error *err = NULL; + uint32_t vector; + + for (vector = start; vector < count; vector++) { + msix_set_mask(o->pci_dev, vector, mask, &err); + if (err) { + VFU_OBJECT_ERROR(o, "vfu: %s: %s", o->device, + error_get_pretty(err)); + error_free(err); + err = NULL; + } + } +} + +static void vfu_msi_irq_state(vfu_ctx_t *vfu_ctx, uint32_t start, + uint32_t count, bool mask) +{ + VfuObject *o = vfu_get_private(vfu_ctx); + Error *err = NULL; + uint32_t vector; + + for (vector = start; vector < count; vector++) { + msi_set_mask(o->pci_dev, vector, mask, &err); + if (err) { + VFU_OBJECT_ERROR(o, "vfu: %s: %s", o->device, + error_get_pretty(err)); + error_free(err); + err = NULL; + } + } +} + +static int vfu_object_setup_irqs(VfuObject *o, PCIDevice *pci_dev) +{ + vfu_ctx_t *vfu_ctx = o->vfu_ctx; + int ret; + + ret = vfu_setup_device_nr_irqs(vfu_ctx, VFU_DEV_INTX_IRQ, 1); + if (ret < 0) { + return ret; + } + + if (msix_nr_vectors_allocated(pci_dev)) { + ret = vfu_setup_device_nr_irqs(vfu_ctx, VFU_DEV_MSIX_IRQ, + msix_nr_vectors_allocated(pci_dev)); + vfu_setup_irq_state_callback(vfu_ctx, VFU_DEV_MSIX_IRQ, + &vfu_msix_irq_state); + } else if (msi_nr_vectors_allocated(pci_dev)) { + ret = vfu_setup_device_nr_irqs(vfu_ctx, VFU_DEV_MSI_IRQ, + msi_nr_vectors_allocated(pci_dev)); + vfu_setup_irq_state_callback(vfu_ctx, VFU_DEV_MSI_IRQ, + &vfu_msi_irq_state); + } + + if (ret < 0) { + return ret; + } + + vfu_object_setup_msi_cbs(o); + + pci_dev->irq_opaque = vfu_ctx; + + return 0; +} + +void vfu_object_set_bus_irq(PCIBus *pci_bus) +{ + int bus_num = pci_bus_num(pci_bus); + int max_bdf = PCI_BUILD_BDF(bus_num, PCI_DEVFN_MAX - 1); + + pci_bus_irqs(pci_bus, vfu_object_set_irq, vfu_object_map_irq, pci_bus, + max_bdf); +} + /* * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' * properties. It also depends on devices instantiated in QEMU. These @@ -632,6 +788,13 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) vfu_object_register_bars(o->vfu_ctx, o->pci_dev); + ret = vfu_object_setup_irqs(o, o->pci_dev); + if (ret < 0) { + error_setg(errp, "vfu: Failed to setup interrupts for %s", + o->device); + goto fail; + } + ret = vfu_realize_ctx(o->vfu_ctx); if (ret < 0) { error_setg(errp, "vfu: Failed to realize device %s- %s", @@ -657,6 +820,8 @@ fail: o->unplug_blocker = NULL; } if (o->pci_dev) { + vfu_object_restore_msi_cbs(o); + o->pci_dev->irq_opaque = NULL; object_unref(OBJECT(o->pci_dev)); o->pci_dev = NULL; } @@ -716,6 +881,8 @@ static void vfu_object_finalize(Object *obj) } if (o->pci_dev) { + vfu_object_restore_msi_cbs(o); + o->pci_dev->irq_opaque = NULL; object_unref(OBJECT(o->pci_dev)); o->pci_dev = NULL; } diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h index 4087688486..58aa576215 100644 --- a/include/hw/pci/msi.h +++ b/include/hw/pci/msi.h @@ -43,6 +43,7 @@ void msi_notify(PCIDevice *dev, unsigned int vector); void msi_send_message(PCIDevice *dev, MSIMessage msg); void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len); unsigned int msi_nr_vectors_allocated(const PCIDevice *dev); +void msi_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp); static inline bool msi_present(const PCIDevice *dev) { diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h index 4c4a60c739..4f1cda0ebe 100644 --- a/include/hw/pci/msix.h +++ b/include/hw/pci/msix.h @@ -36,6 +36,7 @@ void msix_clr_pending(PCIDevice *dev, int vector); int msix_vector_use(PCIDevice *dev, unsigned vector); void msix_vector_unuse(PCIDevice *dev, unsigned vector); void msix_unuse_all_vectors(PCIDevice *dev); +void msix_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp); void msix_notify(PCIDevice *dev, unsigned vector); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 44dacfa224..b54b6ef88f 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -16,6 +16,7 @@ extern bool pci_available; #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) #define PCI_BUILD_BDF(bus, devfn) ((bus << 8) | (devfn)) +#define PCI_BDF_TO_DEVFN(x) ((x) & 0xff) #define PCI_BUS_MAX 256 #define PCI_DEVFN_MAX 256 #define PCI_SLOT_MAX 32 @@ -127,6 +128,10 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type); typedef void PCIUnregisterFunc(PCIDevice *pci_dev); +typedef void MSITriggerFunc(PCIDevice *dev, MSIMessage msg); +typedef MSIMessage MSIPrepareMessageFunc(PCIDevice *dev, unsigned vector); +typedef MSIMessage MSIxPrepareMessageFunc(PCIDevice *dev, unsigned vector); + typedef struct PCIIORegion { pcibus_t addr; /* current PCI mapping address. -1 means not mapped */ #define PCI_BAR_UNMAPPED (~(pcibus_t)0) @@ -329,6 +334,14 @@ struct PCIDevice { /* Space to store MSIX table & pending bit array */ uint8_t *msix_table; uint8_t *msix_pba; + + /* May be used by INTx or MSI during interrupt notification */ + void *irq_opaque; + + MSITriggerFunc *msi_trigger; + MSIPrepareMessageFunc *msi_prepare_message; + MSIxPrepareMessageFunc *msix_prepare_message; + /* MemoryRegion container for msix exclusive BAR setup */ MemoryRegion msix_exclusive_bar; /* Memory Regions for MSIX table and pending bit entries. */ diff --git a/include/hw/remote/vfio-user-obj.h b/include/hw/remote/vfio-user-obj.h new file mode 100644 index 0000000000..87ab78b875 --- /dev/null +++ b/include/hw/remote/vfio-user-obj.h @@ -0,0 +1,6 @@ +#ifndef VFIO_USER_OBJ_H +#define VFIO_USER_OBJ_H + +void vfu_object_set_bus_irq(PCIBus *pci_bus); + +#endif diff --git a/stubs/meson.build b/stubs/meson.build index 6f80fec761..d8f3fd5c44 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -60,3 +60,4 @@ if have_system else stub_ss.add(files('qdev.c')) endif +stub_ss.add(when: 'CONFIG_VFIO_USER_SERVER', if_false: files('vfio-user-obj.c')) diff --git a/stubs/vfio-user-obj.c b/stubs/vfio-user-obj.c new file mode 100644 index 0000000000..79100d768e --- /dev/null +++ b/stubs/vfio-user-obj.c @@ -0,0 +1,6 @@ +#include "qemu/osdep.h" +#include "hw/remote/vfio-user-obj.h" + +void vfu_object_set_bus_irq(PCIBus *pci_bus) +{ +} From 78e27dfa8d1c91171d49660aa50cbe6c424d41be Mon Sep 17 00:00:00 2001 From: Jagannathan Raman Date: Mon, 13 Jun 2022 16:26:34 -0400 Subject: [PATCH 178/180] vfio-user: handle reset of remote device Adds handler to reset a remote device Signed-off-by: Elena Ufimtseva Signed-off-by: John G Johnson Signed-off-by: Jagannathan Raman Reviewed-by: Stefan Hajnoczi Message-id: 112eeadf3bc4c6cdb100bc3f9a6fcfc20b467c1b.1655151679.git.jag.raman@oracle.com Signed-off-by: Stefan Hajnoczi --- hw/remote/vfio-user-obj.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c index 5ecdec06f6..c6cc53acf2 100644 --- a/hw/remote/vfio-user-obj.c +++ b/hw/remote/vfio-user-obj.c @@ -676,6 +676,20 @@ void vfu_object_set_bus_irq(PCIBus *pci_bus) max_bdf); } +static int vfu_object_device_reset(vfu_ctx_t *vfu_ctx, vfu_reset_type_t type) +{ + VfuObject *o = vfu_get_private(vfu_ctx); + + /* vfu_object_ctx_run() handles lost connection */ + if (type == VFU_RESET_LOST_CONN) { + return 0; + } + + qdev_reset_all(DEVICE(o->pci_dev)); + + return 0; +} + /* * TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device' * properties. It also depends on devices instantiated in QEMU. These @@ -795,6 +809,12 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp) goto fail; } + ret = vfu_setup_device_reset_cb(o->vfu_ctx, &vfu_object_device_reset); + if (ret < 0) { + error_setg(errp, "vfu: Failed to setup reset callback"); + goto fail; + } + ret = vfu_realize_ctx(o->vfu_ctx); if (ret < 0) { error_setg(errp, "vfu: Failed to realize device %s- %s", From f387cac5af030a58ac5a0dacf64cab5e5a4fe5c7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jun 2022 17:47:11 +0100 Subject: [PATCH 179/180] linux-aio: fix unbalanced plugged counter in laio_io_unplug() Every laio_io_plug() call has a matching laio_io_unplug() call. There is a plugged counter that tracks the number of levels of plugging and allows for nesting. The plugged counter must reflect the balance between laio_io_plug() and laio_io_unplug() calls accurately. Otherwise I/O stalls occur since io_submit(2) calls are skipped while plugged. Reported-by: Nikolay Tenev Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20220609164712.1539045-2-stefanha@redhat.com Cc: Stefano Garzarella Fixes: 68d7946648 ("linux-aio: add `dev_max_batch` parameter to laio_io_unplug()") [Stefano Garzarella suggested adding a Fixes tag. --Stefan] Signed-off-by: Stefan Hajnoczi --- block/linux-aio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index 4c423fcccf..6078da7e42 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -363,8 +363,10 @@ void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s, uint64_t dev_max_batch) { assert(s->io_q.plugged); + s->io_q.plugged--; + if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch) || - (--s->io_q.plugged == 0 && + (!s->io_q.plugged && !s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending))) { ioq_submit(s); } From 99b969fbe105117f5af6060d3afef40ca39cc9c1 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 9 Jun 2022 17:47:12 +0100 Subject: [PATCH 180/180] linux-aio: explain why max batch is checked in laio_io_unplug() It may not be obvious why laio_io_unplug() checks max batch. I discussed this with Stefano and have added a comment summarizing the reason. Cc: Stefano Garzarella Cc: Kevin Wolf Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20220609164712.1539045-3-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- block/linux-aio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/block/linux-aio.c b/block/linux-aio.c index 6078da7e42..9c2393a2f7 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -365,6 +365,12 @@ void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s, assert(s->io_q.plugged); s->io_q.plugged--; + /* + * Why max batch checking is performed here: + * Another BDS may have queued requests with a higher dev_max_batch and + * therefore in_queue could now exceed our dev_max_batch. Re-check the max + * batch so we can honor our device's dev_max_batch. + */ if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch) || (!s->io_q.plugged && !s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending))) {