Misc HW patch queue

- hmp: Shorter 'info qtree' output (Zoltan)
 - qdev: Add a granule_mode property (Eric)
 - Some ERRP_GUARD() fixes (Zhao)
 - Doc & style fixes in docs/interop/firmware.json (Thomas)
 - hw/xen: Housekeeping (Phil)
 - hw/ppc/mac99: Change timebase frequency 25 -> 100 MHz (Mark)
 - hw/intc/apic: Memory leak fix (Paolo)
 - hw/intc/grlib_irqmp: Ensure ncpus value is in range (Clément)
 - hw/m68k/mcf5208: Add support for reset (Angelo)
 - hw/i386/pc: Housekeeping (Phil)
 - hw/core/smp: Remove/deprecate parameter=0,1 adapting test-smp-parse (Zhao)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmXstpMACgkQ4+MsLN6t
 wN6XBw//dNItFhf1YX+Au4cNoQVDgHE9RtzEIGOnwcL1CgrA9rAQQfLRE5KWM6sN
 1qiPh+T6SPxtiQ2rw4AIpsI7TXjO72b/RDWpUUSwnfH39eC77pijkxIK+i9mYI9r
 p0sPjuP6OfolUFYeSbYX+DmNZh1ONPf27JATJQEf0st8dyswn7lTQvJEaQ97kwxv
 UKA0JD5l9LZV8Zr92cgCzlrfLcbVblJGux9GYIL09yN78yqBuvTm77GBC/rvC+5Q
 fQC5PQswJZ0+v32AXIfSysMp2R6veo4By7VH9Lp51E/u9jpc4ZbcDzxzaJWE6zOR
 fZ01nFzou1qtUfZi+MxNiDR96LP6YoT9xFdGYfNS6AowZn8kymCs3eo7M9uvb+rN
 A2Sgis9rXcjsR4e+w1YPBXwpalJnLwB0QYhEOStR8wo1ceg7GBG6zHUJV89OGzsA
 KS8X0aV1Ulkdm/2H6goEhzrcC6FWLg8pBJpfKK8JFWxXNrj661xM0AAFVL9we356
 +ymthS2x/RTABSI+1Lfsoo6/SyXoimFXJJWA82q9Yzoaoq2gGMWnfwqxfix6JrrA
 PuMnNP5WNvh04iWcNz380P0psLVteHWcVfTRN3JvcJ9iJ2bpjcU1mQMJtvSF9wBn
 Y8kiJTUmZCu3br2e5EfxmypM/h8y29VD/1mxPk8Dtcq3gjx9AU4=
 =juZH
 -----END PGP SIGNATURE-----

Merge tag 'hw-misc-20240309' of https://github.com/philmd/qemu into staging

Misc HW patch queue

- hmp: Shorter 'info qtree' output (Zoltan)
- qdev: Add a granule_mode property (Eric)
- Some ERRP_GUARD() fixes (Zhao)
- Doc & style fixes in docs/interop/firmware.json (Thomas)
- hw/xen: Housekeeping (Phil)
- hw/ppc/mac99: Change timebase frequency 25 -> 100 MHz (Mark)
- hw/intc/apic: Memory leak fix (Paolo)
- hw/intc/grlib_irqmp: Ensure ncpus value is in range (Clément)
- hw/m68k/mcf5208: Add support for reset (Angelo)
- hw/i386/pc: Housekeeping (Phil)
- hw/core/smp: Remove/deprecate parameter=0,1 adapting test-smp-parse (Zhao)

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmXstpMACgkQ4+MsLN6t
# wN6XBw//dNItFhf1YX+Au4cNoQVDgHE9RtzEIGOnwcL1CgrA9rAQQfLRE5KWM6sN
# 1qiPh+T6SPxtiQ2rw4AIpsI7TXjO72b/RDWpUUSwnfH39eC77pijkxIK+i9mYI9r
# p0sPjuP6OfolUFYeSbYX+DmNZh1ONPf27JATJQEf0st8dyswn7lTQvJEaQ97kwxv
# UKA0JD5l9LZV8Zr92cgCzlrfLcbVblJGux9GYIL09yN78yqBuvTm77GBC/rvC+5Q
# fQC5PQswJZ0+v32AXIfSysMp2R6veo4By7VH9Lp51E/u9jpc4ZbcDzxzaJWE6zOR
# fZ01nFzou1qtUfZi+MxNiDR96LP6YoT9xFdGYfNS6AowZn8kymCs3eo7M9uvb+rN
# A2Sgis9rXcjsR4e+w1YPBXwpalJnLwB0QYhEOStR8wo1ceg7GBG6zHUJV89OGzsA
# KS8X0aV1Ulkdm/2H6goEhzrcC6FWLg8pBJpfKK8JFWxXNrj661xM0AAFVL9we356
# +ymthS2x/RTABSI+1Lfsoo6/SyXoimFXJJWA82q9Yzoaoq2gGMWnfwqxfix6JrrA
# PuMnNP5WNvh04iWcNz380P0psLVteHWcVfTRN3JvcJ9iJ2bpjcU1mQMJtvSF9wBn
# Y8kiJTUmZCu3br2e5EfxmypM/h8y29VD/1mxPk8Dtcq3gjx9AU4=
# =juZH
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 09 Mar 2024 19:20:51 GMT
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* tag 'hw-misc-20240309' of https://github.com/philmd/qemu: (43 commits)
  hw/m68k/mcf5208: add support for reset
  tests/unit/test-smp-parse: Test "parameter=0" SMP configurations
  tests/unit/test-smp-parse: Test smp_props.has_clusters
  tests/unit/test-smp-parse: Test the full 7-levels topology hierarchy
  tests/unit/test-smp-parse: Test "drawers" and "books" combination case
  tests/unit/test-smp-parse: Test "drawers" parameter in -smp
  tests/unit/test-smp-parse: Test "books" parameter in -smp
  tests/unit/test-smp-parse: Make test cases aware of the book/drawer
  tests/unit/test-smp-parse: Bump max_cpus to 4096
  tests/unit/test-smp-parse: Use CPU number macros in invalid topology case
  tests/unit/test-smp-parse: Drop the unsupported "dies=1" case
  hw/core/machine-smp: Calculate total CPUs once in machine_parse_smp_config()
  hw/core/machine-smp: Deprecate unsupported "parameter=1" SMP configurations
  hw/core/machine-smp: Remove deprecated "parameter=0" SMP configurations
  docs/interop/firmware.json: Fix doc for FirmwareFlashMode
  docs/interop/firmware.json: Align examples
  hw/intc/grlib_irqmp: abort realize when ncpus value is out of range
  mac_newworld: change timebase frequency from 100MHz to 25MHz for mac99 machine
  hmp: Add option to info qtree to omit details
  qdev: Add a granule_mode property
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2024-03-09 20:12:21 +00:00
commit 7489f7f3f8
38 changed files with 1093 additions and 370 deletions

View file

@ -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"

View file

@ -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=<string>`` (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
------------------------------------

View file

@ -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
-----------------------------------------

View file

@ -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',

View file

@ -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,
},

View file

@ -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);
}

View file

@ -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;

View file

@ -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: "

View file

@ -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 --- */
/*

View file

@ -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',

View file

@ -55,11 +55,13 @@
#ifdef CONFIG_XEN
#include <xen/hvm/hvm_info_table.h>
#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)

View file

@ -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;
}

View file

@ -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',

View file

@ -23,6 +23,7 @@
#include "hw/xen/xen-hvm-common.h"
#include "hw/xen/arch_hvm.h"
#include <xen/hvm/e820.h>
#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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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)

View file

@ -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;

View file

@ -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) {

View file

@ -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"

View file

@ -1,3 +1,13 @@
/*
* Copyright (c) 2007, Neocleus Corporation.
* Copyright (c) 2007, Intel Corporation.
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Alex Novik <alex@neocleus.com>
* Allen Kay <allen.m.kay@intel.com>
* Guy Zana <guy@neocleus.com>
*/
#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,

View file

@ -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) \

View file

@ -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;

View file

@ -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)

View file

@ -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) \
{ \

View file

@ -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)

View file

@ -15,7 +15,7 @@
#include "qemu/error-report.h"
#include <xen/hvm/ioreq.h>
extern MemoryRegion ram_memory;
extern MemoryRegion xen_memory;
extern MemoryListener xen_io_listener;
extern DeviceListener xen_device_listener;

33
include/hw/xen/xen_igd.h Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2007, Neocleus Corporation.
* Copyright (c) 2007, Intel Corporation.
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Alex Novik <alex@neocleus.com>
* Allen Kay <allen.m.kay@intel.com>
* Guy Zana <guy@neocleus.com>
*/
#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

View file

@ -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);

View file

@ -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 */

View file

@ -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' ] }

View file

@ -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;

View file

@ -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"

View file

@ -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)

View file

@ -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;

View file

@ -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();