diff --git a/accel/xen/xen-all.c b/accel/xen/xen-all.c index 5ff0cb8bd9..0bdefce537 100644 --- a/accel/xen/xen-all.c +++ b/accel/xen/xen-all.c @@ -15,6 +15,7 @@ #include "hw/xen/xen_native.h" #include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen_pt.h" +#include "hw/xen/xen_igd.h" #include "chardev/char.h" #include "qemu/accel.h" #include "sysemu/cpus.h" diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 8565644da6..dfd681cd02 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -36,22 +36,6 @@ and will cause a warning. The replacement for the ``nodelay`` short-form boolean option is ``nodelay=on`` rather than ``delay=off``. -``-smp`` ("parameter=0" SMP configurations) (since 6.2) -''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Specified CPU topology parameters must be greater than zero. - -In the SMP configuration, users should either provide a CPU topology -parameter with a reasonable value (greater than zero) or just omit it -and QEMU will compute the missing value. - -However, historically it was implicitly allowed for users to provide -a parameter with zero value, which is meaningless and could also possibly -cause unexpected results in the -smp parsing. So support for this kind of -configurations (e.g. -smp 8,sockets=0) is deprecated since 6.2 and will -be removed in the near future, users have to ensure that all the topology -members described with -smp are greater than zero. - Plugin argument passing through ``arg=`` (since 6.1) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' @@ -73,6 +57,20 @@ The ``-p`` option pretends to control the host page size. However, it is not possible to change the host page size, and using the option only causes failures. +``-smp`` (Unsupported "parameter=1" SMP configurations) (since 9.0) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Specified CPU topology parameters must be supported by the machine. + +In the SMP configuration, users should provide the CPU topology parameters that +are supported by the target machine. + +However, historically it was allowed for users to specify the unsupported +topology parameter as "1", which is meaningless. So support for this kind of +configurations (e.g. -smp drawers=1,books=1,clusters=1 for x86 PC machine) is +marked deprecated since 9.0, users have to ensure that all the topology members +described with -smp are supported by the target machine. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 417a0e4fa1..f9cf874f7b 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -489,6 +489,21 @@ The ``-singlestep`` option has been turned into an accelerator property, and given a name that better reflects what it actually does. Use ``-accel tcg,one-insn-per-tb=on`` instead. +``-smp`` ("parameter=0" SMP configurations) (removed in 9.0) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Specified CPU topology parameters must be greater than zero. + +In the SMP configuration, users should either provide a CPU topology +parameter with a reasonable value (greater than zero) or just omit it +and QEMU will compute the missing value. + +However, historically it was implicitly allowed for users to provide +a parameter with zero value, which is meaningless and could also possibly +cause unexpected results in the -smp parsing. So support for this kind of +configurations (e.g. -smp 8,sockets=0) is removed since 9.0, users have +to ensure that all the topology members described with -smp are greater +than zero. User-mode emulator command line arguments ----------------------------------------- diff --git a/docs/interop/firmware.json b/docs/interop/firmware.json index cc8f869186..54a1fc6c10 100644 --- a/docs/interop/firmware.json +++ b/docs/interop/firmware.json @@ -223,7 +223,7 @@ ## -# @FirmwareFlashType: +# @FirmwareFlashMode: # # Describes how the firmware build handles code versus variable # persistence. @@ -435,203 +435,203 @@ # # Examples: # -# { -# "description": "SeaBIOS", -# "interface-types": [ -# "bios" -# ], -# "mapping": { -# "device": "memory", -# "filename": "/usr/share/seabios/bios-256k.bin" -# }, -# "targets": [ -# { -# "architecture": "i386", -# "machines": [ -# "pc-i440fx-*", -# "pc-q35-*" -# ] +# { +# "description": "SeaBIOS", +# "interface-types": [ +# "bios" +# ], +# "mapping": { +# "device": "memory", +# "filename": "/usr/share/seabios/bios-256k.bin" # }, -# { -# "architecture": "x86_64", -# "machines": [ -# "pc-i440fx-*", -# "pc-q35-*" -# ] -# } -# ], -# "features": [ -# "acpi-s3", -# "acpi-s4" -# ], -# "tags": [ -# "CONFIG_BOOTSPLASH=n", -# "CONFIG_ROM_SIZE=256", -# "CONFIG_USE_SMM=n" -# ] -# } +# "targets": [ +# { +# "architecture": "i386", +# "machines": [ +# "pc-i440fx-*", +# "pc-q35-*" +# ] +# }, +# { +# "architecture": "x86_64", +# "machines": [ +# "pc-i440fx-*", +# "pc-q35-*" +# ] +# } +# ], +# "features": [ +# "acpi-s3", +# "acpi-s4" +# ], +# "tags": [ +# "CONFIG_BOOTSPLASH=n", +# "CONFIG_ROM_SIZE=256", +# "CONFIG_USE_SMM=n" +# ] +# } # -# { -# "description": "OVMF with SB+SMM, empty varstore", -# "interface-types": [ -# "uefi" -# ], -# "mapping": { -# "device": "flash", -# "executable": { -# "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd", -# "format": "raw" +# { +# "description": "OVMF with SB+SMM, empty varstore", +# "interface-types": [ +# "uefi" +# ], +# "mapping": { +# "device": "flash", +# "executable": { +# "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd", +# "format": "raw" +# }, +# "nvram-template": { +# "filename": "/usr/share/OVMF/OVMF_VARS.fd", +# "format": "raw" +# } # }, -# "nvram-template": { -# "filename": "/usr/share/OVMF/OVMF_VARS.fd", -# "format": "raw" -# } -# }, -# "targets": [ -# { -# "architecture": "x86_64", -# "machines": [ -# "pc-q35-*" -# ] -# } -# ], -# "features": [ -# "acpi-s3", -# "amd-sev", -# "requires-smm", -# "secure-boot", -# "verbose-dynamic" -# ], -# "tags": [ -# "-a IA32", -# "-a X64", -# "-p OvmfPkg/OvmfPkgIa32X64.dsc", -# "-t GCC48", -# "-b DEBUG", -# "-D SMM_REQUIRE", -# "-D SECURE_BOOT_ENABLE", -# "-D FD_SIZE_4MB" -# ] -# } +# "targets": [ +# { +# "architecture": "x86_64", +# "machines": [ +# "pc-q35-*" +# ] +# } +# ], +# "features": [ +# "acpi-s3", +# "amd-sev", +# "requires-smm", +# "secure-boot", +# "verbose-dynamic" +# ], +# "tags": [ +# "-a IA32", +# "-a X64", +# "-p OvmfPkg/OvmfPkgIa32X64.dsc", +# "-t GCC48", +# "-b DEBUG", +# "-D SMM_REQUIRE", +# "-D SECURE_BOOT_ENABLE", +# "-D FD_SIZE_4MB" +# ] +# } # -# { -# "description": "OVMF with SB+SMM, SB enabled, MS certs enrolled", -# "interface-types": [ -# "uefi" -# ], -# "mapping": { -# "device": "flash", -# "executable": { -# "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd", -# "format": "raw" +# { +# "description": "OVMF with SB+SMM, SB enabled, MS certs enrolled", +# "interface-types": [ +# "uefi" +# ], +# "mapping": { +# "device": "flash", +# "executable": { +# "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd", +# "format": "raw" +# }, +# "nvram-template": { +# "filename": "/usr/share/OVMF/OVMF_VARS.secboot.fd", +# "format": "raw" +# } # }, -# "nvram-template": { -# "filename": "/usr/share/OVMF/OVMF_VARS.secboot.fd", -# "format": "raw" -# } -# }, -# "targets": [ -# { -# "architecture": "x86_64", -# "machines": [ -# "pc-q35-*" -# ] -# } -# ], -# "features": [ -# "acpi-s3", -# "amd-sev", -# "enrolled-keys", -# "requires-smm", -# "secure-boot", -# "verbose-dynamic" -# ], -# "tags": [ -# "-a IA32", -# "-a X64", -# "-p OvmfPkg/OvmfPkgIa32X64.dsc", -# "-t GCC48", -# "-b DEBUG", -# "-D SMM_REQUIRE", -# "-D SECURE_BOOT_ENABLE", -# "-D FD_SIZE_4MB" -# ] -# } +# "targets": [ +# { +# "architecture": "x86_64", +# "machines": [ +# "pc-q35-*" +# ] +# } +# ], +# "features": [ +# "acpi-s3", +# "amd-sev", +# "enrolled-keys", +# "requires-smm", +# "secure-boot", +# "verbose-dynamic" +# ], +# "tags": [ +# "-a IA32", +# "-a X64", +# "-p OvmfPkg/OvmfPkgIa32X64.dsc", +# "-t GCC48", +# "-b DEBUG", +# "-D SMM_REQUIRE", +# "-D SECURE_BOOT_ENABLE", +# "-D FD_SIZE_4MB" +# ] +# } # -# { -# "description": "OVMF with SEV-ES support", -# "interface-types": [ -# "uefi" -# ], -# "mapping": { -# "device": "flash", -# "executable": { -# "filename": "/usr/share/OVMF/OVMF_CODE.fd", -# "format": "raw" +# { +# "description": "OVMF with SEV-ES support", +# "interface-types": [ +# "uefi" +# ], +# "mapping": { +# "device": "flash", +# "executable": { +# "filename": "/usr/share/OVMF/OVMF_CODE.fd", +# "format": "raw" +# }, +# "nvram-template": { +# "filename": "/usr/share/OVMF/OVMF_VARS.fd", +# "format": "raw" +# } # }, -# "nvram-template": { -# "filename": "/usr/share/OVMF/OVMF_VARS.fd", -# "format": "raw" -# } -# }, -# "targets": [ -# { -# "architecture": "x86_64", -# "machines": [ -# "pc-q35-*" -# ] -# } -# ], -# "features": [ -# "acpi-s3", -# "amd-sev", -# "amd-sev-es", -# "verbose-dynamic" -# ], -# "tags": [ -# "-a X64", -# "-p OvmfPkg/OvmfPkgX64.dsc", -# "-t GCC48", -# "-b DEBUG", -# "-D FD_SIZE_4MB" -# ] -# } +# "targets": [ +# { +# "architecture": "x86_64", +# "machines": [ +# "pc-q35-*" +# ] +# } +# ], +# "features": [ +# "acpi-s3", +# "amd-sev", +# "amd-sev-es", +# "verbose-dynamic" +# ], +# "tags": [ +# "-a X64", +# "-p OvmfPkg/OvmfPkgX64.dsc", +# "-t GCC48", +# "-b DEBUG", +# "-D FD_SIZE_4MB" +# ] +# } # -# { -# "description": "UEFI firmware for ARM64 virtual machines", -# "interface-types": [ -# "uefi" -# ], -# "mapping": { -# "device": "flash", -# "executable": { -# "filename": "/usr/share/AAVMF/AAVMF_CODE.fd", -# "format": "raw" +# { +# "description": "UEFI firmware for ARM64 virtual machines", +# "interface-types": [ +# "uefi" +# ], +# "mapping": { +# "device": "flash", +# "executable": { +# "filename": "/usr/share/AAVMF/AAVMF_CODE.fd", +# "format": "raw" +# }, +# "nvram-template": { +# "filename": "/usr/share/AAVMF/AAVMF_VARS.fd", +# "format": "raw" +# } # }, -# "nvram-template": { -# "filename": "/usr/share/AAVMF/AAVMF_VARS.fd", -# "format": "raw" -# } -# }, -# "targets": [ -# { -# "architecture": "aarch64", -# "machines": [ -# "virt-*" -# ] -# } -# ], -# "features": [ +# "targets": [ +# { +# "architecture": "aarch64", +# "machines": [ +# "virt-*" +# ] +# } +# ], +# "features": [ # -# ], -# "tags": [ -# "-a AARCH64", -# "-p ArmVirtPkg/ArmVirtQemu.dsc", -# "-t GCC48", -# "-b DEBUG", -# "-D DEBUG_PRINT_ERROR_LEVEL=0x80000000" -# ] -# } +# ], +# "tags": [ +# "-a AARCH64", +# "-p ArmVirtPkg/ArmVirtQemu.dsc", +# "-t GCC48", +# "-b DEBUG", +# "-D DEBUG_PRINT_ERROR_LEVEL=0x80000000" +# ] +# } ## { 'struct' : 'Firmware', 'data' : { 'description' : 'str', diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index da120f82a3..ad1b1306e3 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -540,9 +540,9 @@ ERST { .name = "qtree", - .args_type = "", - .params = "", - .help = "show device tree", + .args_type = "brief:-b", + .params = "[-b]", + .help = "show device tree (-b: brief, omit properties)", .cmd = hmp_info_qtree, }, diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c index 32776d94df..15fa7dfa84 100644 --- a/hw/arm/xen_arm.c +++ b/hw/arm/xen_arm.c @@ -114,14 +114,14 @@ static void xen_init_ram(MachineState *machine) block_len = GUEST_RAM1_BASE + ram_size[1]; } - memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len, + memory_region_init_ram(&xen_memory, NULL, "xen.ram", block_len, &error_fatal); - memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo", &ram_memory, + memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo", &xen_memory, GUEST_RAM0_BASE, ram_size[0]); memory_region_add_subregion(sysmem, GUEST_RAM0_BASE, &ram_lo); if (ram_size[1] > 0) { - memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi", &ram_memory, + memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi", &xen_memory, GUEST_RAM1_BASE, ram_size[1]); memory_region_add_subregion(sysmem, GUEST_RAM1_BASE, &ram_hi); } diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index 5cbee2f184..683c92aca1 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -206,6 +206,7 @@ static bool con_event(void *_xendev) static bool xen_console_connect(XenDevice *xendev, Error **errp) { + ERRP_GUARD(); XenConsole *con = XEN_CONSOLE_DEVICE(xendev); unsigned int port, limit; diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index 25019c91ee..27864c9507 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -91,6 +91,7 @@ void machine_parse_smp_config(MachineState *ms, unsigned cores = config->has_cores ? config->cores : 0; unsigned threads = config->has_threads ? config->threads : 0; unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0; + unsigned total_cpus; /* * Specified CPU topology parameters must be greater than zero, @@ -105,36 +106,68 @@ void machine_parse_smp_config(MachineState *ms, (config->has_cores && config->cores == 0) || (config->has_threads && config->threads == 0) || (config->has_maxcpus && config->maxcpus == 0)) { - warn_report("Deprecated CPU topology (considered invalid): " - "CPU topology parameters must be greater than zero"); + error_setg(errp, "Invalid CPU topology: " + "CPU topology parameters must be greater than zero"); + return; } /* * If not supported by the machine, a topology parameter must be - * omitted or specified equal to 1. + * omitted. */ - if (!mc->smp_props.dies_supported && dies > 1) { - error_setg(errp, "dies not supported by this machine's CPU topology"); - return; + if (!mc->smp_props.clusters_supported && config->has_clusters) { + if (config->clusters > 1) { + error_setg(errp, "clusters not supported by this " + "machine's CPU topology"); + return; + } else { + /* Here clusters only equals 1 since we've checked zero case. */ + warn_report("Deprecated CPU topology (considered invalid): " + "Unsupported clusters parameter mustn't be " + "specified as 1"); + } } - if (!mc->smp_props.clusters_supported && clusters > 1) { - error_setg(errp, "clusters not supported by this machine's CPU topology"); - return; - } - - dies = dies > 0 ? dies : 1; clusters = clusters > 0 ? clusters : 1; - if (!mc->smp_props.books_supported && books > 1) { - error_setg(errp, "books not supported by this machine's CPU topology"); - return; + if (!mc->smp_props.dies_supported && config->has_dies) { + if (config->dies > 1) { + error_setg(errp, "dies not supported by this " + "machine's CPU topology"); + return; + } else { + /* Here dies only equals 1 since we've checked zero case. */ + warn_report("Deprecated CPU topology (considered invalid): " + "Unsupported dies parameter mustn't be " + "specified as 1"); + } + } + dies = dies > 0 ? dies : 1; + + if (!mc->smp_props.books_supported && config->has_books) { + if (config->books > 1) { + error_setg(errp, "books not supported by this " + "machine's CPU topology"); + return; + } else { + /* Here books only equals 1 since we've checked zero case. */ + warn_report("Deprecated CPU topology (considered invalid): " + "Unsupported books parameter mustn't be " + "specified as 1"); + } } books = books > 0 ? books : 1; - if (!mc->smp_props.drawers_supported && drawers > 1) { - error_setg(errp, - "drawers not supported by this machine's CPU topology"); - return; + if (!mc->smp_props.drawers_supported && config->has_drawers) { + if (config->drawers > 1) { + error_setg(errp, "drawers not supported by this " + "machine's CPU topology"); + return; + } else { + /* Here drawers only equals 1 since we've checked zero case. */ + warn_report("Deprecated CPU topology (considered invalid): " + "Unsupported drawers parameter mustn't be " + "specified as 1"); + } } drawers = drawers > 0 ? drawers : 1; @@ -179,8 +212,8 @@ void machine_parse_smp_config(MachineState *ms, } } - maxcpus = maxcpus > 0 ? maxcpus : drawers * books * sockets * dies * - clusters * cores * threads; + total_cpus = drawers * books * sockets * dies * clusters * cores * threads; + maxcpus = maxcpus > 0 ? maxcpus : total_cpus; cpus = cpus > 0 ? cpus : maxcpus; ms->smp.cpus = cpus; @@ -196,8 +229,7 @@ void machine_parse_smp_config(MachineState *ms, mc->smp_props.has_clusters = config->has_clusters; /* sanity-check of the computed topology */ - if (drawers * books * sockets * dies * clusters * cores * threads != - maxcpus) { + if (total_cpus != maxcpus) { g_autofree char *topo_msg = cpu_hierarchy_to_string(ms); error_setg(errp, "Invalid CPU topology: " "product of the hierarchy must match maxcpus: " diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 1a396521d5..b45e90edb2 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -679,6 +679,20 @@ const PropertyInfo qdev_prop_mig_mode = { .set_default_value = qdev_propinfo_set_default_value_enum, }; +/* --- GranuleMode --- */ + +QEMU_BUILD_BUG_ON(sizeof(GranuleMode) != sizeof(int)); + +const PropertyInfo qdev_prop_granule_mode = { + .name = "GranuleMode", + .description = "granule_mode values, " + "4k, 8k, 16k, 64k, host", + .enum_table = &GranuleMode_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + /* --- Reserved Region --- */ /* diff --git a/hw/i386/meson.build b/hw/i386/meson.build index b9c1ca39cb..d8b70ef3e9 100644 --- a/hw/i386/meson.build +++ b/hw/i386/meson.build @@ -1,7 +1,7 @@ i386_ss = ss.source_set() i386_ss.add(files( 'fw_cfg.c', - 'kvmvapic.c', + 'vapic.c', 'e820_memory_layout.c', 'multiboot.c', 'x86.c', diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index ce6aad758d..319bc4b180 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -55,11 +55,13 @@ #ifdef CONFIG_XEN #include #include "hw/xen/xen_pt.h" +#include "hw/xen/xen_igd.h" #endif #include "hw/xen/xen-x86.h" #include "hw/xen/xen.h" #include "migration/global_state.h" #include "migration/misc.h" +#include "sysemu/runstate.h" #include "sysemu/numa.h" #include "hw/hyperv/vmbus-bridge.h" #include "hw/mem/nvdimm.h" @@ -99,8 +101,7 @@ static void piix_intx_routing_notifier_xen(PCIDevice *dev) } /* PC hardware initialisation */ -static void pc_init1(MachineState *machine, - const char *host_type, const char *pci_type) +static void pc_init1(MachineState *machine, const char *pci_type) { PCMachineState *pcms = PC_MACHINE(machine); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); @@ -192,7 +193,7 @@ static void pc_init1(MachineState *machine, memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); rom_memory = pci_memory; - phb = OBJECT(qdev_new(host_type)); + phb = OBJECT(qdev_new(TYPE_I440FX_PCI_HOST_BRIDGE)); object_property_add_child(OBJECT(machine), "i440fx", phb); object_property_set_link(phb, PCI_HOST_PROP_RAM_MEM, OBJECT(ram_memory), &error_fatal); @@ -382,9 +383,6 @@ static const QEnumLookup PCSouthBridgeOption_lookup = { .size = PC_SOUTH_BRIDGE_OPTION_MAX }; -#define NotifyVmexitOption_str(val) \ - qapi_enum_lookup(&NotifyVmexitOption_lookup, (val)) - static int pc_get_south_bridge(Object *obj, Error **errp) { PCMachineState *pcms = PC_MACHINE(obj); @@ -452,7 +450,7 @@ static void pc_compat_2_0_fn(MachineState *machine) #ifdef CONFIG_ISAPC static void pc_init_isa(MachineState *machine) { - pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, TYPE_I440FX_PCI_DEVICE); + pc_init1(machine, NULL); } #endif @@ -462,9 +460,7 @@ static void pc_xen_hvm_init_pci(MachineState *machine) const char *pci_type = xen_igd_gfx_pt_enabled() ? TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE : TYPE_I440FX_PCI_DEVICE; - pc_init1(machine, - TYPE_I440FX_PCI_HOST_BRIDGE, - pci_type); + pc_init1(machine, pci_type); } static void pc_xen_hvm_init(MachineState *machine) @@ -489,8 +485,7 @@ static void pc_xen_hvm_init(MachineState *machine) if (compat) { \ compat(machine); \ } \ - pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, \ - TYPE_I440FX_PCI_DEVICE); \ + pc_init1(machine, TYPE_I440FX_PCI_DEVICE); \ } \ DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn) diff --git a/hw/i386/kvmvapic.c b/hw/i386/vapic.c similarity index 99% rename from hw/i386/kvmvapic.c rename to hw/i386/vapic.c index 61a65ef2ab..f5b1db7e5f 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/vapic.c @@ -747,8 +747,7 @@ static void do_vapic_enable(CPUState *cs, run_on_cpu_data data) s->state = VAPIC_ACTIVE; } -static void kvmvapic_vm_state_change(void *opaque, bool running, - RunState state) +static void vapic_vm_state_change(void *opaque, bool running, RunState state) { MachineState *ms = MACHINE(qdev_get_machine()); VAPICROMState *s = opaque; @@ -793,7 +792,7 @@ static int vapic_post_load(void *opaque, int version_id) if (!s->vmsentry) { s->vmsentry = - qemu_add_vm_change_state_handler(kvmvapic_vm_state_change, s); + qemu_add_vm_change_state_handler(vapic_vm_state_change, s); } return 0; } diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build index 3dc4c4f106..3f0df8bc07 100644 --- a/hw/i386/xen/meson.build +++ b/hw/i386/xen/meson.build @@ -1,8 +1,10 @@ i386_ss.add(when: 'CONFIG_XEN', if_true: files( - 'xen-hvm.c', 'xen_apic.c', 'xen_pvdevice.c', )) +i386_ss.add(when: ['CONFIG_XEN', xen], if_true: files( + 'xen-hvm.c', +)) i386_ss.add(when: 'CONFIG_XEN_BUS', if_true: files( 'xen_platform.c', diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index f42621e674..7745cb3963 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -23,6 +23,7 @@ #include "hw/xen/xen-hvm-common.h" #include "hw/xen/arch_hvm.h" #include +#include "exec/target_page.h" static MemoryRegion ram_640k, ram_lo, ram_hi; static MemoryRegion *framebuffer; @@ -149,12 +150,12 @@ static void xen_ram_init(PCMachineState *pcms, */ block_len = (4 * GiB) + x86ms->above_4g_mem_size; } - memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len, + memory_region_init_ram(&xen_memory, NULL, "xen.ram", block_len, &error_fatal); - *ram_memory_p = &ram_memory; + *ram_memory_p = &xen_memory; memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k", - &ram_memory, 0, 0xa0000); + &xen_memory, 0, 0xa0000); memory_region_add_subregion(sysmem, 0, &ram_640k); /* Skip of the VGA IO memory space, it will be registered later by the VGA * emulated device. @@ -163,22 +164,23 @@ static void xen_ram_init(PCMachineState *pcms, * the Options ROM, so it is registered here as RAM. */ memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo", - &ram_memory, 0xc0000, + &xen_memory, 0xc0000, x86ms->below_4g_mem_size - 0xc0000); memory_region_add_subregion(sysmem, 0xc0000, &ram_lo); if (x86ms->above_4g_mem_size > 0) { memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi", - &ram_memory, 0x100000000ULL, + &xen_memory, 0x100000000ULL, x86ms->above_4g_mem_size); memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi); } } -static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size) +static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size, + int page_mask) { XenPhysmap *physmap = NULL; - start_addr &= TARGET_PAGE_MASK; + start_addr &= page_mask; QLIST_FOREACH(physmap, &xen_physmap, list) { if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) { @@ -188,9 +190,10 @@ static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size) return NULL; } -static hwaddr xen_phys_offset_to_gaddr(hwaddr phys_offset, ram_addr_t size) +static hwaddr xen_phys_offset_to_gaddr(hwaddr phys_offset, ram_addr_t size, + int page_mask) { - hwaddr addr = phys_offset & TARGET_PAGE_MASK; + hwaddr addr = phys_offset & page_mask; XenPhysmap *physmap = NULL; QLIST_FOREACH(physmap, &xen_physmap, list) { @@ -245,6 +248,9 @@ static int xen_add_to_physmap(XenIOState *state, MemoryRegion *mr, hwaddr offset_within_region) { + unsigned target_page_bits = qemu_target_page_bits(); + int page_size = qemu_target_page_size(); + int page_mask = -page_size; unsigned long nr_pages; int rc = 0; XenPhysmap *physmap = NULL; @@ -252,7 +258,7 @@ static int xen_add_to_physmap(XenIOState *state, hwaddr phys_offset = memory_region_get_ram_addr(mr); const char *mr_name; - if (get_physmapping(start_addr, size)) { + if (get_physmapping(start_addr, size, page_mask)) { return 0; } if (size <= 0) { @@ -292,9 +298,9 @@ go_physmap: return 0; } - pfn = phys_offset >> TARGET_PAGE_BITS; - start_gpfn = start_addr >> TARGET_PAGE_BITS; - nr_pages = size >> TARGET_PAGE_BITS; + pfn = phys_offset >> target_page_bits; + start_gpfn = start_addr >> target_page_bits; + nr_pages = size >> target_page_bits; rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, pfn, start_gpfn); if (rc) { @@ -308,8 +314,8 @@ go_physmap: } rc = xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid, - start_addr >> TARGET_PAGE_BITS, - (start_addr + size - 1) >> TARGET_PAGE_BITS, + start_addr >> target_page_bits, + (start_addr + size - 1) >> target_page_bits, XEN_DOMCTL_MEM_CACHEATTR_WB); if (rc) { error_report("pin_memory_cacheattr failed: %s", strerror(errno)); @@ -321,11 +327,14 @@ static int xen_remove_from_physmap(XenIOState *state, hwaddr start_addr, ram_addr_t size) { + unsigned target_page_bits = qemu_target_page_bits(); + int page_size = qemu_target_page_size(); + int page_mask = -page_size; int rc = 0; XenPhysmap *physmap = NULL; hwaddr phys_offset = 0; - physmap = get_physmapping(start_addr, size); + physmap = get_physmapping(start_addr, size, page_mask); if (physmap == NULL) { return -1; } @@ -336,9 +345,9 @@ static int xen_remove_from_physmap(XenIOState *state, DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at " "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset); - size >>= TARGET_PAGE_BITS; - start_addr >>= TARGET_PAGE_BITS; - phys_offset >>= TARGET_PAGE_BITS; + size >>= target_page_bits; + start_addr >>= target_page_bits; + phys_offset >>= target_page_bits; rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start_addr, phys_offset); if (rc) { @@ -367,13 +376,16 @@ static void xen_sync_dirty_bitmap(XenIOState *state, hwaddr start_addr, ram_addr_t size) { - hwaddr npages = size >> TARGET_PAGE_BITS; + unsigned target_page_bits = qemu_target_page_bits(); + int page_size = qemu_target_page_size(); + int page_mask = -page_size; + hwaddr npages = size >> target_page_bits; const int width = sizeof(unsigned long) * 8; size_t bitmap_size = DIV_ROUND_UP(npages, width); int rc, i, j; const XenPhysmap *physmap = NULL; - physmap = get_physmapping(start_addr, size); + physmap = get_physmapping(start_addr, size, page_mask); if (physmap == NULL) { /* not handled */ return; @@ -387,7 +399,7 @@ static void xen_sync_dirty_bitmap(XenIOState *state, return; } - rc = xen_track_dirty_vram(xen_domid, start_addr >> TARGET_PAGE_BITS, + rc = xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits, npages, dirty_bitmap); if (rc < 0) { #ifndef ENODATA @@ -408,8 +420,7 @@ static void xen_sync_dirty_bitmap(XenIOState *state, j = ctzl(map); map &= ~(1ul << j); memory_region_set_dirty(framebuffer, - (i * width + j) * TARGET_PAGE_SIZE, - TARGET_PAGE_SIZE); + (i * width + j) * page_size, page_size); }; } } @@ -629,17 +640,21 @@ void xen_register_framebuffer(MemoryRegion *mr) void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) { + unsigned target_page_bits = qemu_target_page_bits(); + int page_size = qemu_target_page_size(); + int page_mask = -page_size; + if (unlikely(xen_in_migration)) { int rc; ram_addr_t start_pfn, nb_pages; - start = xen_phys_offset_to_gaddr(start, length); + start = xen_phys_offset_to_gaddr(start, length, page_mask); if (length == 0) { - length = TARGET_PAGE_SIZE; + length = page_size; } - start_pfn = start >> TARGET_PAGE_BITS; - nb_pages = ((start + length + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS) + start_pfn = start >> target_page_bits; + nb_pages = ((start + length + page_size - 1) >> target_page_bits) - start_pfn; rc = xen_modified_memory(xen_domid, start_pfn, nb_pages); if (rc) { @@ -662,6 +677,9 @@ void qmp_xen_set_global_dirty_log(bool enable, Error **errp) void arch_xen_set_memory(XenIOState *state, MemoryRegionSection *section, bool add) { + unsigned target_page_bits = qemu_target_page_bits(); + int page_size = qemu_target_page_size(); + int page_mask = -page_size; hwaddr start_addr = section->offset_within_address_space; ram_addr_t size = int128_get64(section->size); bool log_dirty = memory_region_is_logging(section->mr, DIRTY_MEMORY_VGA); @@ -677,8 +695,8 @@ void arch_xen_set_memory(XenIOState *state, MemoryRegionSection *section, trace_xen_client_set_memory(start_addr, size, log_dirty); - start_addr &= TARGET_PAGE_MASK; - size = TARGET_PAGE_ALIGN(size); + start_addr &= page_mask; + size = ROUND_UP(size, page_size); if (add) { if (!memory_region_is_rom(section->mr)) { @@ -687,8 +705,8 @@ void arch_xen_set_memory(XenIOState *state, MemoryRegionSection *section, } else { mem_type = HVMMEM_ram_ro; if (xen_set_mem_type(xen_domid, mem_type, - start_addr >> TARGET_PAGE_BITS, - size >> TARGET_PAGE_BITS)) { + start_addr >> target_page_bits, + size >> target_page_bits)) { DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n", start_addr); } diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index 144b121d48..c6c51a349c 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -356,6 +356,7 @@ static void grlib_irqmp_realize(DeviceState *dev, Error **errp) error_setg(errp, "Invalid ncpus properties: " "%u, must be 0 < ncpus =< %u.", irqmp->ncpus, IRQMP_MAX_CPU); + return; } qdev_init_gpio_in(dev, grlib_irqmp_set_irq, MAX_PILS); diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index 0cfb806c20..ec14096aa4 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -40,6 +40,8 @@ #define PCSR_PRE_SHIFT 8 #define PCSR_PRE_MASK 0x0f00 +#define RCR_SOFTRST 0x80 + typedef struct { MemoryRegion iomem; qemu_irq irq; @@ -185,12 +187,50 @@ static const MemoryRegionOps m5208_sys_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) +static uint64_t m5208_rcm_read(void *opaque, hwaddr addr, + unsigned size) +{ + return 0; +} + +static void m5208_rcm_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + M68kCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + switch (addr) { + case 0x0: /* RCR */ + if (value & RCR_SOFTRST) { + cpu_reset(cs); + cpu->env.aregs[7] = ldl_phys(cs->as, 0); + cpu->env.pc = ldl_phys(cs->as, 4); + } + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + __func__, addr); + break; + } +} + +static const MemoryRegionOps m5208_rcm_ops = { + .read = m5208_rcm_read, + .write = m5208_rcm_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic, + M68kCPU *cpu) { MemoryRegion *iomem = g_new(MemoryRegion, 1); + MemoryRegion *iomem_rcm = g_new(MemoryRegion, 1); m5208_timer_state *s; int i; + /* RCM */ + memory_region_init_io(iomem_rcm, NULL, &m5208_rcm_ops, cpu, + "m5208-rcm", 0x00000080); + memory_region_add_subregion(address_space, 0xfc0a0000, iomem_rcm); /* SDRAMC. */ memory_region_init_io(iomem, NULL, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000); memory_region_add_subregion(address_space, 0xfc0a8000, iomem); @@ -265,7 +305,7 @@ static void mcf5208evb_init(MachineState *machine) mcf_uart_create_mmap(0xfc064000, pic[27], serial_hd(1)); mcf_uart_create_mmap(0xfc068000, pic[28], serial_hd(2)); - mcf5208_sys_init(address_space_mem, pic); + mcf5208_sys_init(address_space_mem, pic, cpu); mcf_fec_init(address_space_mem, 0xfc030000, pic + 36); diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c index 453fdb9819..89487b49ba 100644 --- a/hw/net/xen_nic.c +++ b/hw/net/xen_nic.c @@ -351,6 +351,7 @@ static bool net_event(void *_xendev) static bool xen_netdev_connect(XenDevice *xendev, Error **errp) { + ERRP_GUARD(); XenNetDev *netdev = XEN_NET_DEVICE(xendev); unsigned int port, rx_copy; diff --git a/hw/pci/msi.c b/hw/pci/msi.c index 041b0bdbec..8104ac1d91 100644 --- a/hw/pci/msi.c +++ b/hw/pci/msi.c @@ -23,6 +23,7 @@ #include "hw/xen/xen.h" #include "qemu/range.h" #include "qapi/error.h" +#include "sysemu/xen.h" #include "hw/i386/kvm/xen_evtchn.h" @@ -308,7 +309,7 @@ bool msi_is_masked(const PCIDevice *dev, unsigned int vector) } data = pci_get_word(dev->config + msi_data_off(dev, msi64bit)); - if (xen_is_pirq_msi(data)) { + if (xen_enabled() && xen_is_pirq_msi(data)) { return false; } diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 3e796d2f6d..ff9e490c4e 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -77,7 +77,7 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 -#define TBFREQ (100UL * 1000UL * 1000UL) +#define TBFREQ (25UL * 1000UL * 1000UL) #define CLOCKFREQ (900UL * 1000UL * 1000UL) #define BUSFREQ (100UL * 1000UL * 1000UL) diff --git a/hw/remote/remote-obj.c b/hw/remote/remote-obj.c index 65b6f7cc86..dc27cc8da1 100644 --- a/hw/remote/remote-obj.c +++ b/hw/remote/remote-obj.c @@ -49,6 +49,7 @@ struct RemoteObject { static void remote_object_set_fd(Object *obj, const char *str, Error **errp) { + ERRP_GUARD(); RemoteObject *o = REMOTE_OBJECT(obj); int fd = -1; diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c index baa1adb9f2..1627da7398 100644 --- a/hw/xen/xen-hvm-common.c +++ b/hw/xen/xen-hvm-common.c @@ -1,6 +1,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" +#include "exec/target_page.h" #include "trace.h" #include "hw/pci/pci_host.h" @@ -9,11 +10,12 @@ #include "hw/boards.h" #include "hw/xen/arch_hvm.h" -MemoryRegion ram_memory; +MemoryRegion xen_memory; void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, Error **errp) { + unsigned target_page_bits = qemu_target_page_bits(); unsigned long nr_pfn; xen_pfn_t *pfn_list; int i; @@ -26,17 +28,17 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, return; } - if (mr == &ram_memory) { + if (mr == &xen_memory) { return; } trace_xen_ram_alloc(ram_addr, size); - nr_pfn = size >> TARGET_PAGE_BITS; + nr_pfn = size >> target_page_bits; pfn_list = g_new(xen_pfn_t, nr_pfn); for (i = 0; i < nr_pfn; i++) { - pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i; + pfn_list[i] = (ram_addr >> target_page_bits) + i; } if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) { @@ -53,7 +55,7 @@ static void xen_set_memory(struct MemoryListener *listener, { XenIOState *state = container_of(listener, XenIOState, memory_listener); - if (section->mr == &ram_memory) { + if (section->mr == &xen_memory) { return; } else { if (add) { diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index 36e6f93c37..a8edabdabc 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -59,7 +59,8 @@ #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" -#include "xen_pt.h" +#include "hw/xen/xen_pt.h" +#include "hw/xen/xen_igd.h" #include "hw/xen/xen.h" #include "hw/xen/xen-legacy-backend.h" #include "qemu/range.h" diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h index 31bcfdf705..095a0f0365 100644 --- a/hw/xen/xen_pt.h +++ b/hw/xen/xen_pt.h @@ -1,3 +1,13 @@ +/* + * Copyright (c) 2007, Neocleus Corporation. + * Copyright (c) 2007, Intel Corporation. + * + * SPDX-License-Identifier: GPL-2.0-only + * + * Alex Novik + * Allen Kay + * Guy Zana + */ #ifndef XEN_PT_H #define XEN_PT_H @@ -5,9 +15,6 @@ #include "xen-host-pci-device.h" #include "qom/object.h" -bool xen_igd_gfx_pt_enabled(void); -void xen_igd_gfx_pt_set(bool value, Error **errp); - void xen_pt_log(const PCIDevice *d, const char *f, ...) G_GNUC_PRINTF(2, 3); #define XEN_PT_ERR(d, _f, _a...) xen_pt_log(d, "%s: Error: "_f, __func__, ##_a) @@ -52,12 +59,6 @@ typedef struct XenPTDeviceClass { XenPTQdevRealize pci_qdev_realize; } XenPTDeviceClass; -uint32_t igd_read_opregion(XenPCIPassthroughState *s); -void xen_igd_reserve_slot(PCIBus *pci_bus); -void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val); -void xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s, - XenHostPCIDevice *dev); - /* function type for config reg */ typedef int (*xen_pt_conf_reg_init) (XenPCIPassthroughState *, XenPTRegInfo *, uint32_t real_offset, @@ -343,11 +344,6 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar) void *pci_assign_dev_load_option_rom(PCIDevice *dev, int *size, unsigned int domain, unsigned int bus, unsigned int slot, unsigned int function); -static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev) -{ - return (xen_igd_gfx_pt_enabled() - && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA)); -} int xen_pt_register_vga_regions(XenHostPCIDevice *dev); int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev); void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev, diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 2b8680b112..ba4cd78238 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -15,7 +15,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/timer.h" -#include "xen_pt.h" +#include "hw/xen/xen_pt.h" +#include "hw/xen/xen_igd.h" #include "hw/xen/xen-legacy-backend.h" #define XEN_PT_MERGE_VALUE(value, data, val_mask) \ diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c index 0aed3bb6fd..6c2e3f4840 100644 --- a/hw/xen/xen_pt_graphics.c +++ b/hw/xen/xen_pt_graphics.c @@ -3,7 +3,8 @@ */ #include "qemu/osdep.h" #include "qapi/error.h" -#include "xen_pt.h" +#include "hw/xen/xen_pt.h" +#include "hw/xen/xen_igd.h" #include "xen-host-pci-device.h" static unsigned long igd_guest_opregion; diff --git a/hw/xen/xen_pt_stub.c b/hw/xen/xen_pt_stub.c index 5c108446a8..72feebeb20 100644 --- a/hw/xen/xen_pt_stub.c +++ b/hw/xen/xen_pt_stub.c @@ -6,7 +6,7 @@ */ #include "qemu/osdep.h" -#include "hw/xen/xen_pt.h" +#include "hw/xen/xen_igd.h" #include "qapi/error.h" bool xen_igd_gfx_pt_enabled(void) diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 5065590281..b958023187 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -288,18 +288,6 @@ extern const size_t pc_compat_2_1_len; extern GlobalProperty pc_compat_2_0[]; extern const size_t pc_compat_2_0_len; -extern GlobalProperty pc_compat_1_7[]; -extern const size_t pc_compat_1_7_len; - -extern GlobalProperty pc_compat_1_6[]; -extern const size_t pc_compat_1_6_len; - -extern GlobalProperty pc_compat_1_5[]; -extern const size_t pc_compat_1_5_len; - -extern GlobalProperty pc_compat_1_4[]; -extern const size_t pc_compat_1_4_len; - #define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \ static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \ { \ diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h index 06c359c190..626be87dd3 100644 --- a/include/hw/qdev-properties-system.h +++ b/include/hw/qdev-properties-system.h @@ -8,6 +8,7 @@ extern const PropertyInfo qdev_prop_macaddr; extern const PropertyInfo qdev_prop_reserved_region; extern const PropertyInfo qdev_prop_multifd_compression; extern const PropertyInfo qdev_prop_mig_mode; +extern const PropertyInfo qdev_prop_granule_mode; extern const PropertyInfo qdev_prop_losttickpolicy; extern const PropertyInfo qdev_prop_blockdev_on_error; extern const PropertyInfo qdev_prop_bios_chs_trans; @@ -47,6 +48,8 @@ extern const PropertyInfo qdev_prop_iothread_vq_mapping_list; #define DEFINE_PROP_MIG_MODE(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_mig_mode, \ MigMode) +#define DEFINE_PROP_GRANULE_MODE(_n, _s, _f, _d) \ + DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_granule_mode, GranuleMode) #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_losttickpolicy, \ LostTickPolicy) diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h index 4b1d728f35..65a51aac2e 100644 --- a/include/hw/xen/xen-hvm-common.h +++ b/include/hw/xen/xen-hvm-common.h @@ -15,7 +15,7 @@ #include "qemu/error-report.h" #include -extern MemoryRegion ram_memory; +extern MemoryRegion xen_memory; extern MemoryListener xen_io_listener; extern DeviceListener xen_device_listener; diff --git a/include/hw/xen/xen_igd.h b/include/hw/xen/xen_igd.h new file mode 100644 index 0000000000..7ffca06c10 --- /dev/null +++ b/include/hw/xen/xen_igd.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2007, Neocleus Corporation. + * Copyright (c) 2007, Intel Corporation. + * + * SPDX-License-Identifier: GPL-2.0-only + * + * Alex Novik + * Allen Kay + * Guy Zana + */ +#ifndef XEN_IGD_H +#define XEN_IGD_H + +#include "hw/xen/xen-host-pci-device.h" + +typedef struct XenPCIPassthroughState XenPCIPassthroughState; + +bool xen_igd_gfx_pt_enabled(void); +void xen_igd_gfx_pt_set(bool value, Error **errp); + +uint32_t igd_read_opregion(XenPCIPassthroughState *s); +void xen_igd_reserve_slot(PCIBus *pci_bus); +void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val); +void xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s, + XenHostPCIDevice *dev); + +static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev) +{ + return (xen_igd_gfx_pt_enabled() + && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA)); +} + +#endif diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h index c8e7c2f6cf..10c2e3082a 100644 --- a/include/sysemu/xen-mapcache.h +++ b/include/sysemu/xen-mapcache.h @@ -10,10 +10,11 @@ #define XEN_MAPCACHE_H #include "exec/cpu-common.h" +#include "sysemu/xen.h" typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset, ram_addr_t size); -#ifdef CONFIG_XEN +#ifdef CONFIG_XEN_IS_POSSIBLE void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque); diff --git a/include/sysemu/xen.h b/include/sysemu/xen.h index bc13ad5692..a9f591f26d 100644 --- a/include/sysemu/xen.h +++ b/include/sysemu/xen.h @@ -10,6 +10,10 @@ #ifndef SYSEMU_XEN_H #define SYSEMU_XEN_H +#ifdef CONFIG_USER_ONLY +#error Cannot include sysemu/xen.h from user emulation +#endif + #include "exec/cpu-common.h" #ifdef NEED_CPU_H @@ -26,16 +30,13 @@ extern bool xen_allowed; #define xen_enabled() (xen_allowed) -#ifndef CONFIG_USER_ONLY void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length); void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, struct MemoryRegion *mr, Error **errp); -#endif #else /* !CONFIG_XEN_IS_POSSIBLE */ #define xen_enabled() 0 -#ifndef CONFIG_USER_ONLY static inline void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) { /* nothing */ @@ -45,7 +46,6 @@ static inline void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, { g_assert_not_reached(); } -#endif #endif /* CONFIG_XEN_IS_POSSIBLE */ diff --git a/qapi/virtio.json b/qapi/virtio.json index a79013fe89..95745fdfd7 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -957,3 +957,21 @@ { 'struct': 'DummyVirtioForceArrays', 'data': { 'unused-iothread-vq-mapping': ['IOThreadVirtQueueMapping'] } } + +## +# @GranuleMode: +# +# @4k: granule page size of 4KiB +# +# @8k: granule page size of 8KiB +# +# @16k: granule page size of 16KiB +# +# @64k: granule page size of 64KiB +# +# @host: granule matches the host page size +# +# Since: 9.0 +## +{ 'enum': 'GranuleMode', + 'data': [ '4k', '8k', '16k', '64k', 'host' ] } diff --git a/stubs/xen-hw-stub.c b/stubs/xen-hw-stub.c index 7d7ffe83a9..6cf0e9a4c1 100644 --- a/stubs/xen-hw-stub.c +++ b/stubs/xen-hw-stub.c @@ -24,10 +24,6 @@ int xen_set_pci_link_route(uint8_t link, uint8_t irq) return -1; } -void xen_hvm_inject_msi(uint64_t addr, uint32_t data) -{ -} - int xen_is_pirq_msi(uint32_t msi_data) { return 0; diff --git a/system/physmem.c b/system/physmem.c index 3adda08ebf..6e9ed97597 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -35,7 +35,7 @@ #include "hw/qdev-core.h" #include "hw/qdev-properties.h" #include "hw/boards.h" -#include "hw/xen/xen.h" +#include "sysemu/xen.h" #include "sysemu/kvm.h" #include "sysemu/tcg.h" #include "sysemu/qtest.h" diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 874d65191c..09e07cab9b 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -744,7 +744,6 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) } #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__) -static void qbus_print(Monitor *mon, BusState *bus, int indent); static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, int indent) @@ -784,13 +783,9 @@ static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int ind static void qdev_print(Monitor *mon, DeviceState *dev, int indent) { ObjectClass *class; - BusState *child; NamedGPIOList *ngl; NamedClockList *ncl; - qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)), - dev->id ? dev->id : ""); - indent += 2; QLIST_FOREACH(ngl, &dev->gpios, node) { if (ngl->num_in) { qdev_printf("gpio-in \"%s\" %d\n", ngl->name ? ngl->name : "", @@ -814,12 +809,9 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); bus_print_dev(dev->parent_bus, mon, dev, indent); - QLIST_FOREACH(child, &dev->child_bus, sibling) { - qbus_print(mon, child, indent); - } } -static void qbus_print(Monitor *mon, BusState *bus, int indent) +static void qbus_print(Monitor *mon, BusState *bus, int indent, bool details) { BusChild *kid; @@ -827,16 +819,27 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent) indent += 2; qdev_printf("type %s\n", object_get_typename(OBJECT(bus))); QTAILQ_FOREACH(kid, &bus->children, sibling) { + BusState *child_bus; DeviceState *dev = kid->child; - qdev_print(mon, dev, indent); + qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)), + dev->id ? dev->id : ""); + if (details) { + qdev_print(mon, dev, indent + 2); + } + QLIST_FOREACH(child_bus, &dev->child_bus, sibling) { + qbus_print(mon, child_bus, indent + 2, details); + } } } #undef qdev_printf void hmp_info_qtree(Monitor *mon, const QDict *qdict) { - if (sysbus_get_default()) - qbus_print(mon, sysbus_get_default(), 0); + bool details = !qdict_get_try_bool(qdict, "brief", false); + + if (sysbus_get_default()) { + qbus_print(mon, sysbus_get_default(), 0, details); + } } void hmp_info_qdm(Monitor *mon, const QDict *qdict) diff --git a/target/i386/sev.c b/target/i386/sev.c index 173de91afe..72930ff0dc 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -1044,6 +1044,7 @@ sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp) int sev_inject_launch_secret(const char *packet_hdr, const char *secret, uint64_t gpa, Error **errp) { + ERRP_GUARD(); struct kvm_sev_launch_secret input; g_autofree guchar *data = NULL, *hdr = NULL; int error, ret = 1; diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 24972666a7..8994337e12 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -20,8 +20,8 @@ #define T true #define F false -#define MIN_CPUS 1 /* set the min CPUs supported by the machine as 1 */ -#define MAX_CPUS 512 /* set the max CPUs supported by the machine as 512 */ +#define MIN_CPUS 1 /* set the min CPUs supported by the machine as 1 */ +#define MAX_CPUS 4096 /* set the max CPUs supported by the machine as 4096 */ #define SMP_MACHINE_NAME "TEST-SMP" @@ -75,6 +75,40 @@ .has_maxcpus = hf, .maxcpus = f, \ } +/* + * Currently a 5-level topology hierarchy is supported on s390 ccw machines + * -drawers/books/sockets/cores/threads + */ +#define SMP_CONFIG_WITH_BOOKS_DRAWERS(ha, a, hb, b, hc, c, hd, \ + d, he, e, hf, f, hg, g) \ + { \ + .has_cpus = ha, .cpus = a, \ + .has_drawers = hb, .drawers = b, \ + .has_books = hc, .books = c, \ + .has_sockets = hd, .sockets = d, \ + .has_cores = he, .cores = e, \ + .has_threads = hf, .threads = f, \ + .has_maxcpus = hg, .maxcpus = g, \ + } + +/* + * Currently QEMU supports up to a 7-level topology hierarchy, which is the + * QEMU's unified abstract representation of CPU topology. + * -drawers/books/sockets/dies/clusters/cores/threads + */ +#define SMP_CONFIG_WITH_FULL_TOPO(a, b, c, d, e, f, g, h, i) \ + { \ + .has_cpus = true, .cpus = a, \ + .has_drawers = true, .drawers = b, \ + .has_books = true, .books = c, \ + .has_sockets = true, .sockets = d, \ + .has_dies = true, .dies = e, \ + .has_clusters = true, .clusters = f, \ + .has_cores = true, .cores = g, \ + .has_threads = true, .threads = h, \ + .has_maxcpus = true, .maxcpus = i, \ + } + /** * @config - the given SMP configuration * @expect_prefer_sockets - the expected parsing result for the @@ -308,6 +342,16 @@ static const struct SMPTestData data_generic_invalid[] = { /* config: -smp 2,clusters=2 */ .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), .expect_error = "clusters not supported by this machine's CPU topology", + }, { + /* config: -smp 2,books=2 */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 2, F, 0, T, 2, F, + 0, F, 0, F, 0, F, 0), + .expect_error = "books not supported by this machine's CPU topology", + }, { + /* config: -smp 2,drawers=2 */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 2, T, 2, F, 0, F, + 0, F, 0, F, 0, F, 0), + .expect_error = "drawers not supported by this machine's CPU topology", }, { /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */ .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8), @@ -323,17 +367,23 @@ static const struct SMPTestData data_generic_invalid[] = { "sockets (2) * cores (4) * threads (2) " "== maxcpus (16) < smp_cpus (18)", }, { - /* config: -smp 1 - * should tweak the supported min CPUs to 2 for testing */ - .config = SMP_CONFIG_GENERIC(T, 1, F, 0, F, 0, F, 0, F, 0), + /* + * config: -smp 1 + * The test machine should tweak the supported min CPUs to + * 2 (MIN_CPUS + 1) for testing. + */ + .config = SMP_CONFIG_GENERIC(T, MIN_CPUS, F, 0, F, 0, F, 0, F, 0), .expect_error = "Invalid SMP CPUs 1. The min CPUs supported " "by machine '" SMP_MACHINE_NAME "' is 2", }, { - /* config: -smp 512 - * should tweak the supported max CPUs to 511 for testing */ - .config = SMP_CONFIG_GENERIC(T, 512, F, 0, F, 0, F, 0, F, 0), - .expect_error = "Invalid SMP CPUs 512. The max CPUs supported " - "by machine '" SMP_MACHINE_NAME "' is 511", + /* + * config: -smp 4096 + * The test machine should tweak the supported max CPUs to + * 4095 (MAX_CPUS - 1) for testing. + */ + .config = SMP_CONFIG_GENERIC(T, 4096, F, 0, F, 0, F, 0, F, 0), + .expect_error = "Invalid SMP CPUs 4096. The max CPUs supported " + "by machine '" SMP_MACHINE_NAME "' is 4095", }, }; @@ -373,11 +423,199 @@ static const struct SMPTestData data_with_clusters_invalid[] = { }, }; +static const struct SMPTestData data_with_books_invalid[] = { + { + /* config: -smp 16,books=2,sockets=2,cores=4,threads=2,maxcpus=16 */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, F, 1, T, 2, T, + 2, T, 4, T, 2, T, 16), + .expect_error = "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " + "books (2) * sockets (2) * cores (4) * threads (2) " + "!= maxcpus (16)", + }, { + /* config: -smp 34,books=2,sockets=2,cores=4,threads=2,maxcpus=32 */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, F, 1, T, 2, T, + 2, T, 4, T, 2, T, 32), + .expect_error = "Invalid CPU topology: " + "maxcpus must be equal to or greater than smp: " + "books (2) * sockets (2) * cores (4) * threads (2) " + "== maxcpus (32) < smp_cpus (34)", + }, +}; + +static const struct SMPTestData data_with_drawers_invalid[] = { + { + /* config: -smp 16,drawers=2,sockets=2,cores=4,threads=2,maxcpus=16 */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, T, 2, F, 1, T, + 2, T, 4, T, 2, T, 16), + .expect_error = "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " + "drawers (2) * sockets (2) * cores (4) * threads (2) " + "!= maxcpus (16)", + }, { + /* config: -smp 34,drawers=2,sockets=2,cores=4,threads=2,maxcpus=32 */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, T, 2, F, 1, T, + 2, T, 4, T, 2, T, 32), + .expect_error = "Invalid CPU topology: " + "maxcpus must be equal to or greater than smp: " + "drawers (2) * sockets (2) * cores (4) * threads (2) " + "== maxcpus (32) < smp_cpus (34)", + }, +}; + +static const struct SMPTestData data_with_drawers_books_invalid[] = { + { + /* + * config: -smp 200,drawers=2,books=2,sockets=2,cores=4,\ + * threads=2,maxcpus=200 + */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 200, T, 3, T, 5, T, + 2, T, 4, T, 2, T, 200), + .expect_error = "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " + "drawers (3) * books (5) * sockets (2) * " + "cores (4) * threads (2) != maxcpus (200)", + }, { + /* + * config: -smp 242,drawers=2,books=2,sockets=2,cores=4,\ + * threads=2,maxcpus=240 + */ + .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 242, T, 3, T, 5, T, + 2, T, 4, T, 2, T, 240), + .expect_error = "Invalid CPU topology: " + "maxcpus must be equal to or greater than smp: " + "drawers (3) * books (5) * sockets (2) * " + "cores (4) * threads (2) " + "== maxcpus (240) < smp_cpus (242)", + }, +}; + +static const struct SMPTestData data_full_topo_invalid[] = { + { + /* + * config: -smp 200,drawers=3,books=5,sockets=2,dies=4,\ + * clusters=2,cores=7,threads=2,maxcpus=200 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(200, 3, 5, 2, 4, 2, 7, 2, 200), + .expect_error = "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " + "drawers (3) * books (5) * sockets (2) * dies (4) * " + "clusters (2) * cores (7) * threads (2) " + "!= maxcpus (200)", + }, { + /* + * config: -smp 3361,drawers=3,books=5,sockets=2,dies=4,\ + * clusters=2,cores=7,threads=2,maxcpus=3360 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(3361, 3, 5, 2, 4, 2, 7, 2, 3360), + .expect_error = "Invalid CPU topology: " + "maxcpus must be equal to or greater than smp: " + "drawers (3) * books (5) * sockets (2) * dies (4) * " + "clusters (2) * cores (7) * threads (2) " + "== maxcpus (3360) < smp_cpus (3361)", + }, { + /* + * config: -smp 1,drawers=3,books=5,sockets=2,dies=4,\ + * clusters=2,cores=7,threads=3,maxcpus=5040 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(3361, 3, 5, 2, 4, 2, 7, 3, 5040), + .expect_error = "Invalid SMP CPUs 5040. The max CPUs supported " + "by machine '" SMP_MACHINE_NAME "' is 4096", + }, +}; + +static const struct SMPTestData data_zero_topo_invalid[] = { + { + /* + * Test "cpus=0". + * config: -smp 0,drawers=1,books=1,sockets=1,dies=1,\ + * clusters=1,cores=1,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(0, 1, 1, 1, 1, 1, 1, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "drawers=0". + * config: -smp 1,drawers=0,books=1,sockets=1,dies=1,\ + * clusters=1,cores=1,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 0, 1, 1, 1, 1, 1, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "books=0". + * config: -smp 1,drawers=1,books=0,sockets=1,dies=1,\ + * clusters=1,cores=1,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 0, 1, 1, 1, 1, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "sockets=0". + * config: -smp 1,drawers=1,books=1,sockets=0,dies=1,\ + * clusters=1,cores=1,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 0, 1, 1, 1, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "dies=0". + * config: -smp 1,drawers=1,books=1,sockets=1,dies=0,\ + * clusters=1,cores=1,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 0, 1, 1, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "clusters=0". + * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ + * clusters=0,cores=1,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 0, 1, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "cores=0". + * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ + * clusters=1,cores=0,threads=1,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 0, 1, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "threads=0". + * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ + * clusters=1,cores=1,threads=0,maxcpus=1 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 0, 1), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, { + /* + * Test "maxcpus=0". + * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\ + * clusters=1,cores=1,threads=1,maxcpus=0 + */ + .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 0), + .expect_error = "Invalid CPU topology: CPU topology parameters must " + "be greater than zero", + }, +}; + static char *smp_config_to_string(const SMPConfiguration *config) { return g_strdup_printf( "(SMPConfiguration) {\n" " .has_cpus = %5s, cpus = %" PRId64 ",\n" + " .has_drawers = %5s, drawers = %" PRId64 ",\n" + " .has_books = %5s, books = %" PRId64 ",\n" " .has_sockets = %5s, sockets = %" PRId64 ",\n" " .has_dies = %5s, dies = %" PRId64 ",\n" " .has_clusters = %5s, clusters = %" PRId64 ",\n" @@ -386,6 +624,8 @@ static char *smp_config_to_string(const SMPConfiguration *config) " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" "}", config->has_cpus ? "true" : "false", config->cpus, + config->has_drawers ? "true" : "false", config->drawers, + config->has_books ? "true" : "false", config->books, config->has_sockets ? "true" : "false", config->sockets, config->has_dies ? "true" : "false", config->dies, config->has_clusters ? "true" : "false", config->clusters, @@ -398,10 +638,10 @@ static char *smp_config_to_string(const SMPConfiguration *config) static unsigned int cpu_topology_get_threads_per_socket(const CpuTopology *topo) { /* Check the divisor to avoid invalid topology examples causing SIGFPE. */ - if (!topo->sockets) { + if (!topo->drawers || !topo->books || !topo->sockets) { return 0; } else { - return topo->max_cpus / topo->sockets; + return topo->max_cpus / topo->drawers / topo->books / topo->sockets; } } @@ -418,11 +658,14 @@ static unsigned int cpu_topology_get_cores_per_socket(const CpuTopology *topo) static char *cpu_topology_to_string(const CpuTopology *topo, unsigned int threads_per_socket, - unsigned int cores_per_socket) + unsigned int cores_per_socket, + bool has_clusters) { return g_strdup_printf( "(CpuTopology) {\n" " .cpus = %u,\n" + " .drawers = %u,\n" + " .books = %u,\n" " .sockets = %u,\n" " .dies = %u,\n" " .clusters = %u,\n" @@ -431,16 +674,20 @@ static char *cpu_topology_to_string(const CpuTopology *topo, " .max_cpus = %u,\n" " .threads_per_socket = %u,\n" " .cores_per_socket = %u,\n" + " .has_clusters = %s,\n" "}", - topo->cpus, topo->sockets, topo->dies, topo->clusters, + topo->cpus, topo->drawers, topo->books, + topo->sockets, topo->dies, topo->clusters, topo->cores, topo->threads, topo->max_cpus, - threads_per_socket, cores_per_socket); + threads_per_socket, cores_per_socket, + has_clusters ? "true" : "false"); } static void check_parse(MachineState *ms, const SMPConfiguration *config, const CpuTopology *expect_topo, const char *expect_err, bool is_valid) { + MachineClass *mc = MACHINE_GET_CLASS(ms); g_autofree char *config_str = smp_config_to_string(config); g_autofree char *expect_topo_str = NULL, *output_topo_str = NULL; unsigned int expect_threads_per_socket, expect_cores_per_socket; @@ -453,20 +700,25 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, cpu_topology_get_cores_per_socket(expect_topo); expect_topo_str = cpu_topology_to_string(expect_topo, expect_threads_per_socket, - expect_cores_per_socket); + expect_cores_per_socket, + config->has_clusters); /* call the generic parser */ machine_parse_smp_config(ms, config, &err); ms_threads_per_socket = machine_topo_get_threads_per_socket(ms); ms_cores_per_socket = machine_topo_get_cores_per_socket(ms); - output_topo_str = cpu_topology_to_string(&ms->smp, ms_threads_per_socket, - ms_cores_per_socket); + output_topo_str = cpu_topology_to_string(&ms->smp, + ms_threads_per_socket, + ms_cores_per_socket, + mc->smp_props.has_clusters); /* when the configuration is supposed to be valid */ if (is_valid) { if ((err == NULL) && (ms->smp.cpus == expect_topo->cpus) && + (ms->smp.drawers == expect_topo->drawers) && + (ms->smp.books == expect_topo->books) && (ms->smp.sockets == expect_topo->sockets) && (ms->smp.dies == expect_topo->dies) && (ms->smp.clusters == expect_topo->clusters) && @@ -474,7 +726,8 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, (ms->smp.threads == expect_topo->threads) && (ms->smp.max_cpus == expect_topo->max_cpus) && (ms_threads_per_socket == expect_threads_per_socket) && - (ms_cores_per_socket == expect_cores_per_socket)) { + (ms_cores_per_socket == expect_cores_per_socket) && + (mc->smp_props.has_clusters == config->has_clusters)) { return; } @@ -558,6 +811,16 @@ static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) data->expect_prefer_sockets.clusters = 1; data->expect_prefer_cores.clusters = 1; } + + if (!mc->smp_props.books_supported) { + data->expect_prefer_sockets.books = 1; + data->expect_prefer_cores.books = 1; + } + + if (!mc->smp_props.drawers_supported) { + data->expect_prefer_sockets.drawers = 1; + data->expect_prefer_cores.drawers = 1; + } } static void machine_base_class_init(ObjectClass *oc, void *data) @@ -575,8 +838,8 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) MachineClass *mc = MACHINE_CLASS(oc); /* Force invalid min CPUs and max CPUs */ - mc->min_cpus = 2; - mc->max_cpus = 511; + mc->min_cpus = MIN_CPUS + 1; + mc->max_cpus = MAX_CPUS - 1; } static void machine_with_dies_class_init(ObjectClass *oc, void *data) @@ -593,6 +856,38 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) mc->smp_props.clusters_supported = true; } +static void machine_with_books_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->smp_props.books_supported = true; +} + +static void machine_with_drawers_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->smp_props.drawers_supported = true; +} + +static void machine_with_drawers_books_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->smp_props.drawers_supported = true; + mc->smp_props.books_supported = true; +} + +static void machine_full_topo_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->smp_props.drawers_supported = true; + mc->smp_props.books_supported = true; + mc->smp_props.dies_supported = true; + mc->smp_props.clusters_supported = true; +} + static void test_generic_valid(const void *opaque) { const char *machine_type = opaque; @@ -607,11 +902,6 @@ static void test_generic_valid(const void *opaque) unsupported_params_init(mc, &data); smp_parse_test(ms, &data, true); - - /* Unsupported parameters can be provided with their values as 1 */ - data.config.has_dies = true; - data.config.dies = 1; - smp_parse_test(ms, &data, true); } object_unref(obj); @@ -736,6 +1026,248 @@ static void test_with_clusters(const void *opaque) object_unref(obj); } +static void test_with_books(const void *opaque) +{ + const char *machine_type = opaque; + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData data = {}; + unsigned int num_books = 2; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); + + /* when books parameter is omitted, it will be set as 1 */ + data.expect_prefer_sockets.books = 1; + data.expect_prefer_cores.books = 1; + + smp_parse_test(ms, &data, true); + + /* when books parameter is specified */ + data.config.has_books = true; + data.config.books = num_books; + if (data.config.has_cpus) { + data.config.cpus *= num_books; + } + if (data.config.has_maxcpus) { + data.config.maxcpus *= num_books; + } + + data.expect_prefer_sockets.books = num_books; + data.expect_prefer_sockets.cpus *= num_books; + data.expect_prefer_sockets.max_cpus *= num_books; + data.expect_prefer_cores.books = num_books; + data.expect_prefer_cores.cpus *= num_books; + data.expect_prefer_cores.max_cpus *= num_books; + + smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_with_books_invalid); i++) { + data = data_with_books_invalid[i]; + unsupported_params_init(mc, &data); + + smp_parse_test(ms, &data, false); + } + + object_unref(obj); +} + +static void test_with_drawers(const void *opaque) +{ + const char *machine_type = opaque; + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData data = {}; + unsigned int num_drawers = 2; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); + + /* when drawers parameter is omitted, it will be set as 1 */ + data.expect_prefer_sockets.drawers = 1; + data.expect_prefer_cores.drawers = 1; + + smp_parse_test(ms, &data, true); + + /* when drawers parameter is specified */ + data.config.has_drawers = true; + data.config.drawers = num_drawers; + if (data.config.has_cpus) { + data.config.cpus *= num_drawers; + } + if (data.config.has_maxcpus) { + data.config.maxcpus *= num_drawers; + } + + data.expect_prefer_sockets.drawers = num_drawers; + data.expect_prefer_sockets.cpus *= num_drawers; + data.expect_prefer_sockets.max_cpus *= num_drawers; + data.expect_prefer_cores.drawers = num_drawers; + data.expect_prefer_cores.cpus *= num_drawers; + data.expect_prefer_cores.max_cpus *= num_drawers; + + smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_with_drawers_invalid); i++) { + data = data_with_drawers_invalid[i]; + unsupported_params_init(mc, &data); + + smp_parse_test(ms, &data, false); + } + + object_unref(obj); +} + +static void test_with_drawers_books(const void *opaque) +{ + const char *machine_type = opaque; + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData data = {}; + unsigned int num_drawers = 5, num_books = 3; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); + + /* + * when drawers and books parameters are omitted, they will + * be both set as 1. + */ + data.expect_prefer_sockets.drawers = 1; + data.expect_prefer_sockets.books = 1; + data.expect_prefer_cores.drawers = 1; + data.expect_prefer_cores.books = 1; + + smp_parse_test(ms, &data, true); + + /* when drawers and books parameters are both specified */ + data.config.has_drawers = true; + data.config.drawers = num_drawers; + data.config.has_books = true; + data.config.books = num_books; + + if (data.config.has_cpus) { + data.config.cpus *= num_drawers * num_books; + } + if (data.config.has_maxcpus) { + data.config.maxcpus *= num_drawers * num_books; + } + + data.expect_prefer_sockets.drawers = num_drawers; + data.expect_prefer_sockets.books = num_books; + data.expect_prefer_sockets.cpus *= num_drawers * num_books; + data.expect_prefer_sockets.max_cpus *= num_drawers * num_books; + + data.expect_prefer_cores.drawers = num_drawers; + data.expect_prefer_cores.books = num_books; + data.expect_prefer_cores.cpus *= num_drawers * num_books; + data.expect_prefer_cores.max_cpus *= num_drawers * num_books; + + smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_with_drawers_books_invalid); i++) { + data = data_with_drawers_books_invalid[i]; + unsupported_params_init(mc, &data); + + smp_parse_test(ms, &data, false); + } + + object_unref(obj); +} + +static void test_full_topo(const void *opaque) +{ + const char *machine_type = opaque; + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData data = {}; + unsigned int drawers = 5, books = 3, dies = 2, clusters = 7, multiplier; + int i; + + multiplier = drawers * books * dies * clusters; + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); + + /* + * when drawers, books, dies and clusters parameters are omitted, + * they will be set as 1. + */ + data.expect_prefer_sockets.drawers = 1; + data.expect_prefer_sockets.books = 1; + data.expect_prefer_sockets.dies = 1; + data.expect_prefer_sockets.clusters = 1; + data.expect_prefer_cores.drawers = 1; + data.expect_prefer_cores.books = 1; + data.expect_prefer_cores.dies = 1; + data.expect_prefer_cores.clusters = 1; + + smp_parse_test(ms, &data, true); + + /* when drawers, books, dies and clusters parameters are specified. */ + data.config.has_drawers = true; + data.config.drawers = drawers; + data.config.has_books = true; + data.config.books = books; + data.config.has_dies = true; + data.config.dies = dies; + data.config.has_clusters = true; + data.config.clusters = clusters; + + if (data.config.has_cpus) { + data.config.cpus *= multiplier; + } + if (data.config.has_maxcpus) { + data.config.maxcpus *= multiplier; + } + + data.expect_prefer_sockets.drawers = drawers; + data.expect_prefer_sockets.books = books; + data.expect_prefer_sockets.dies = dies; + data.expect_prefer_sockets.clusters = clusters; + data.expect_prefer_sockets.cpus *= multiplier; + data.expect_prefer_sockets.max_cpus *= multiplier; + + data.expect_prefer_cores.drawers = drawers; + data.expect_prefer_cores.books = books; + data.expect_prefer_cores.dies = dies; + data.expect_prefer_cores.clusters = clusters; + data.expect_prefer_cores.cpus *= multiplier; + data.expect_prefer_cores.max_cpus *= multiplier; + + smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_full_topo_invalid); i++) { + data = data_full_topo_invalid[i]; + unsupported_params_init(mc, &data); + + smp_parse_test(ms, &data, false); + } + + for (i = 0; i < ARRAY_SIZE(data_zero_topo_invalid); i++) { + data = data_zero_topo_invalid[i]; + unsupported_params_init(mc, &data); + + smp_parse_test(ms, &data, false); + } + + object_unref(obj); +} + /* Type info of the tested machine */ static const TypeInfo smp_machine_types[] = { { @@ -760,6 +1292,22 @@ static const TypeInfo smp_machine_types[] = { .name = MACHINE_TYPE_NAME("smp-with-clusters"), .parent = TYPE_MACHINE, .class_init = machine_with_clusters_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-with-books"), + .parent = TYPE_MACHINE, + .class_init = machine_with_books_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-with-drawers"), + .parent = TYPE_MACHINE, + .class_init = machine_with_drawers_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-with-drawers-books"), + .parent = TYPE_MACHINE, + .class_init = machine_with_drawers_books_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-full-topo"), + .parent = TYPE_MACHINE, + .class_init = machine_full_topo_class_init, } }; @@ -783,6 +1331,18 @@ int main(int argc, char *argv[]) g_test_add_data_func("/test-smp-parse/with_clusters", MACHINE_TYPE_NAME("smp-with-clusters"), test_with_clusters); + g_test_add_data_func("/test-smp-parse/with_books", + MACHINE_TYPE_NAME("smp-with-books"), + test_with_books); + g_test_add_data_func("/test-smp-parse/with_drawers", + MACHINE_TYPE_NAME("smp-with-drawers"), + test_with_drawers); + g_test_add_data_func("/test-smp-parse/with_drawers_books", + MACHINE_TYPE_NAME("smp-with-drawers-books"), + test_with_drawers_books); + g_test_add_data_func("/test-smp-parse/full", + MACHINE_TYPE_NAME("smp-full-topo"), + test_full_topo); g_test_run();