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:
commit
7489f7f3f8
@ -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"
|
||||
|
@ -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
|
||||
------------------------------------
|
||||
|
||||
|
@ -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
|
||||
-----------------------------------------
|
||||
|
@ -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',
|
||||
|
@ -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,
|
||||
},
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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: "
|
||||
|
@ -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 --- */
|
||||
|
||||
/*
|
||||
|
@ -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',
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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',
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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) \
|
||||
{ \
|
||||
|
@ -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)
|
||||
|
@ -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
33
include/hw/xen/xen_igd.h
Normal 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
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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' ] }
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user