* Meson version update

* fix search path when configuring with --cpu
 * support for measured SEV boot with -kernel (Dov)
 * fix missing BQL locks (Emanuele)
 * retrieve applesmc key from the host (Pedro)
 * KVM PV feature documentation (Vitaly)
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmFcMzwUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroOkigf/QbWFnBvd1haj3BWB9vrf5viEq2Fp
 j5wIXZz/FsCFYS4u+MVzI3L0MBb8ROkgsHg1yO1Ol4Kx3m5nZ7kJSbCxI6GG+Ry3
 1dNrN/0ncbjXJfFGZAADSeA+ajOnahvKII5LZE6XYk2SxFfjKmfj3iePDIb/Wil+
 AXa1UfKu8ETC0hLDlq+HVspQOskmpzCVw0v5Xf5hyBp9vrSIyMl1sR63qe5TKWnd
 L8cX8TRxi5Z5dHb+ZvB2Fd3vpMc8YrOkQOrl0RBnRk95vT1psDHArJhC5tIFEvIO
 H9PNfCX4mAPMeOawzhGAMmF/tsxuFPKGrVvU67xI2jzpbnlYnee7IwvBGg==
 =vlRk
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* Meson version update
* fix search path when configuring with --cpu
* support for measured SEV boot with -kernel (Dov)
* fix missing BQL locks (Emanuele)
* retrieve applesmc key from the host (Pedro)
* KVM PV feature documentation (Vitaly)

# gpg: Signature made Tue 05 Oct 2021 04:13:00 AM PDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]

* remotes/bonzini/tags/for-upstream:
  meson: show library versions in the summary
  target/xtensa: list cores in a text file
  hexagon: use env keyword argument to pass PYTHONPATH
  meson: switch minimum meson version to 0.58.2, minimum recommended to 0.59.2
  meson: bump submodule to 0.59.2
  migration: add missing qemu_mutex_lock_iothread in migration_completion
  migration: block-dirty-bitmap: add missing qemu_mutex_lock_iothread
  configure, meson: move CPU_CFLAGS out of QEMU_CFLAGS
  hw/misc: applesmc: use host osk as default on macs
  x86/sev: generate SEV kernel loader hashes in x86_load_linux
  sev/i386: Introduce sev_add_kernel_loader_hashes for measured linux boot
  i386: docs: Briefly describe KVM PV features

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-10-05 11:29:42 -07:00
commit 08a9b68dc0
23 changed files with 597 additions and 126 deletions

19
configure vendored
View File

@ -142,11 +142,11 @@ lines: ${BASH_LINENO[*]}"
}
do_cc() {
do_compiler "$cc" "$@"
do_compiler "$cc" $CPU_CFLAGS "$@"
}
do_cxx() {
do_compiler "$cxx" "$@"
do_compiler "$cxx" $CPU_CFLAGS "$@"
}
# Append $2 to the variable named $1, with space separation
@ -1688,7 +1688,6 @@ esac
eval "cross_cc_${cpu}=\$cc"
cross_cc_vars="$cross_cc_vars cross_cc_${cpu}"
QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS"
# For user-mode emulation the host arch has to be one we explicitly
# support, even if we're using TCI.
@ -1995,7 +1994,7 @@ python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0]
python="$python -B"
if test -z "$meson"; then
if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.55.3; then
if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.59.2; then
meson=meson
elif test $git_submodules_action != 'ignore' ; then
meson=git
@ -5114,9 +5113,9 @@ if test "$skip_meson" = no; then
echo "c_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
echo "[binaries]" >> $cross
echo "c = [$(meson_quote $cc)]" >> $cross
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross
test -n "$objcc" && echo "objc = [$(meson_quote $objcc)]" >> $cross
echo "c = [$(meson_quote $cc $CPU_CFLAGS)]" >> $cross
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx $CPU_CFLAGS)]" >> $cross
test -n "$objcc" && echo "objc = [$(meson_quote $objcc $CPU_CFLAGS)]" >> $cross
echo "ar = [$(meson_quote $ar)]" >> $cross
echo "nm = [$(meson_quote $nm)]" >> $cross
echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross
@ -5164,10 +5163,6 @@ if test "$skip_meson" = no; then
mv $cross config-meson.cross
rm -rf meson-private meson-info meson-logs
unset staticpic
if ! version_ge "$($meson --version)" 0.56.0; then
staticpic=$(if test "$pie" = yes; then echo true; else echo false; fi)
fi
NINJA=$ninja $meson setup \
--prefix "$prefix" \
--libdir "$libdir" \
@ -5187,7 +5182,6 @@ if test "$skip_meson" = no; then
-Dwerror=$(if test "$werror" = yes; then echo true; else echo false; fi) \
-Dstrip=$(if test "$strip_opt" = yes; then echo true; else echo false; fi) \
-Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \
${staticpic:+-Db_staticpic=$staticpic} \
-Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \
-Db_lto=$lto -Dcfi=$cfi -Dcfi_debug=$cfi_debug \
-Dmalloc=$malloc -Dmalloc_trim=$malloc_trim -Dsparse=$sparse \
@ -5223,6 +5217,7 @@ else
perl -i -ne '
s/^gettext = true$/gettext = auto/;
s/^gettext = false$/gettext = disabled/;
/^b_staticpic/ && next;
print;' meson-private/cmd_line.txt
fi
fi

View File

@ -37,14 +37,14 @@ endif
if build_docs
SPHINX_ARGS += ['-Dversion=' + meson.project_version(), '-Drelease=' + config_host['PKGVERSION']]
sphinx_extn_depends = [ meson.source_root() / 'docs/sphinx/depfile.py',
meson.source_root() / 'docs/sphinx/hxtool.py',
meson.source_root() / 'docs/sphinx/kerneldoc.py',
meson.source_root() / 'docs/sphinx/kernellog.py',
meson.source_root() / 'docs/sphinx/qapidoc.py',
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
sphinx_extn_depends = [ meson.current_source_dir() / 'sphinx/depfile.py',
meson.current_source_dir() / 'sphinx/hxtool.py',
meson.current_source_dir() / 'sphinx/kerneldoc.py',
meson.current_source_dir() / 'sphinx/kernellog.py',
meson.current_source_dir() / 'sphinx/qapidoc.py',
meson.current_source_dir() / 'sphinx/qmp_lexer.py',
qapi_gen_depends ]
sphinx_template_files = [ meson.source_root() / 'docs/_templates/footer.html' ]
sphinx_template_files = [ meson.project_source_root() / 'docs/_templates/footer.html' ]
have_ga = have_tools and config_host.has_key('CONFIG_GUEST_AGENT')

100
docs/system/i386/kvm-pv.rst Normal file
View File

@ -0,0 +1,100 @@
Paravirtualized KVM features
============================
Description
-----------
In some cases when implementing hardware interfaces in software is slow, ``KVM``
implements its own paravirtualized interfaces.
Setup
-----
Paravirtualized ``KVM`` features are represented as CPU flags. The following
features are enabled by default for any CPU model when ``KVM`` acceleration is
enabled:
- ``kvmclock``
- ``kvm-nopiodelay``
- ``kvm-asyncpf``
- ``kvm-steal-time``
- ``kvm-pv-eoi``
- ``kvmclock-stable-bit``
``kvm-msi-ext-dest-id`` feature is enabled by default in x2apic mode with split
irqchip (e.g. "-machine ...,kernel-irqchip=split -cpu ...,x2apic").
Note: when CPU model ``host`` is used, QEMU passes through all supported
paravirtualized ``KVM`` features to the guest.
Existing features
-----------------
``kvmclock``
Expose a ``KVM`` specific paravirtualized clocksource to the guest. Supported
since Linux v2.6.26.
``kvm-nopiodelay``
The guest doesn't need to perform delays on PIO operations. Supported since
Linux v2.6.26.
``kvm-mmu``
This feature is deprecated.
``kvm-asyncpf``
Enable asynchronous page fault mechanism. Supported since Linux v2.6.38.
Note: since Linux v5.10 the feature is deprecated and not enabled by ``KVM``.
Use ``kvm-asyncpf-int`` instead.
``kvm-steal-time``
Enable stolen (when guest vCPU is not running) time accounting. Supported
since Linux v3.1.
``kvm-pv-eoi``
Enable paravirtualized end-of-interrupt signaling. Supported since Linux
v3.10.
``kvm-pv-unhalt``
Enable paravirtualized spinlocks support. Supported since Linux v3.12.
``kvm-pv-tlb-flush``
Enable paravirtualized TLB flush mechanism. Supported since Linux v4.16.
``kvm-pv-ipi``
Enable paravirtualized IPI mechanism. Supported since Linux v4.19.
``kvm-poll-control``
Enable host-side polling on HLT control from the guest. Supported since Linux
v5.10.
``kvm-pv-sched-yield``
Enable paravirtualized sched yield feature. Supported since Linux v5.10.
``kvm-asyncpf-int``
Enable interrupt based asynchronous page fault mechanism. Supported since Linux
v5.10.
``kvm-msi-ext-dest-id``
Support 'Extended Destination ID' for external interrupts. The feature allows
to use up to 32768 CPUs without IRQ remapping (but other limits may apply making
the number of supported vCPUs for a given configuration lower). Supported since
Linux v5.10.
``kvmclock-stable-bit``
Tell the guest that guest visible TSC value can be fully trusted for kvmclock
computations and no warps are expected. Supported since Linux v2.6.35.
Supplementary features
----------------------
``kvm-pv-enforce-cpuid``
Limit the supported paravirtualized feature set to the exposed features only.
Note, by default, ``KVM`` allows the guest to use all currently supported
paravirtualized features even when they were not announced in guest visible
CPUIDs. Supported since Linux v5.10.
Useful links
------------
Please refer to Documentation/virt/kvm in Linux for additional details.

View File

@ -26,6 +26,7 @@ Architectural features
:maxdepth: 1
i386/cpu
i386/kvm-pv
i386/sgx
.. _pcsys_005freq:

View File

@ -47,6 +47,7 @@
#include "hw/i386/fw_cfg.h"
#include "hw/intc/i8259.h"
#include "hw/rtc/mc146818rtc.h"
#include "target/i386/sev_i386.h"
#include "hw/acpi/cpu_hotplug.h"
#include "hw/irq.h"
@ -780,6 +781,7 @@ void x86_load_linux(X86MachineState *x86ms,
const char *initrd_filename = machine->initrd_filename;
const char *dtb_filename = machine->dtb;
const char *kernel_cmdline = machine->kernel_cmdline;
SevKernelLoaderContext sev_load_ctx = {};
/* Align to 16 bytes as a paranoia measure */
cmdline_size = (strlen(kernel_cmdline) + 16) & ~15;
@ -926,6 +928,8 @@ void x86_load_linux(X86MachineState *x86ms,
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline) + 1);
fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
sev_load_ctx.cmdline_data = (char *)kernel_cmdline;
sev_load_ctx.cmdline_size = strlen(kernel_cmdline) + 1;
if (protocol >= 0x202) {
stl_p(header + 0x228, cmdline_addr);
@ -1007,6 +1011,8 @@ void x86_load_linux(X86MachineState *x86ms,
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
sev_load_ctx.initrd_data = initrd_data;
sev_load_ctx.initrd_size = initrd_size;
stl_p(header + 0x218, initrd_addr);
stl_p(header + 0x21c, initrd_size);
@ -1065,15 +1071,32 @@ void x86_load_linux(X86MachineState *x86ms,
load_image_size(dtb_filename, setup_data->data, dtb_size);
}
/*
* If we're starting an encrypted VM, it will be OVMF based, which uses the
* efi stub for booting and doesn't require any values to be placed in the
* kernel header. We therefore don't update the header so the hash of the
* kernel on the other side of the fw_cfg interface matches the hash of the
* file the user passed in.
*/
if (!sev_enabled()) {
memcpy(setup, header, MIN(sizeof(header), setup_size));
}
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
sev_load_ctx.kernel_data = (char *)kernel;
sev_load_ctx.kernel_size = kernel_size;
fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
sev_load_ctx.setup_data = (char *)setup;
sev_load_ctx.setup_size = setup_size;
if (sev_enabled()) {
sev_add_kernel_loader_hashes(&sev_load_ctx, &error_fatal);
}
option_rom[nb_option_roms].bootindex = 0;
option_rom[nb_option_roms].name = "linuxboot.bin";

View File

@ -38,6 +38,171 @@
#include "qemu/timer.h"
#include "qom/object.h"
#if defined(__APPLE__) && defined(__MACH__)
#include <IOKit/IOKitLib.h>
enum {
kSMCSuccess = 0x00,
kSMCKeyNotFound = 0x84
};
enum {
kSMCUserClientOpen = 0x00,
kSMCUserClientClose = 0x01,
kSMCHandleYPCEvent = 0x02,
kSMCReadKey = 0x05,
kSMCGetKeyInfo = 0x09
};
typedef struct SMCVersion {
uint8_t major;
uint8_t minor;
uint8_t build;
uint8_t reserved;
uint16_t release;
} SMCVersion;
typedef struct SMCPLimitData {
uint16_t version;
uint16_t length;
uint32_t cpuPLimit;
uint32_t gpuPLimit;
uint32_t memPLimit;
} SMCPLimitData;
typedef struct SMCKeyInfoData {
IOByteCount dataSize;
uint32_t dataType;
uint8_t dataAttributes;
} SMCKeyInfoData;
typedef struct {
uint32_t key;
SMCVersion vers;
SMCPLimitData pLimitData;
SMCKeyInfoData keyInfo;
uint8_t result;
uint8_t status;
uint8_t data8;
uint32_t data32;
uint8_t bytes[32];
} SMCParamStruct;
static IOReturn smc_call_struct_method(uint32_t selector,
SMCParamStruct *inputStruct,
SMCParamStruct *outputStruct)
{
IOReturn ret;
size_t inputStructCnt = sizeof(SMCParamStruct);
size_t outputStructCnt = sizeof(SMCParamStruct);
io_service_t smcService = IO_OBJECT_NULL;
io_connect_t smcConnect = IO_OBJECT_NULL;
smcService = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("AppleSMC"));
if (smcService == IO_OBJECT_NULL) {
ret = kIOReturnNotFound;
goto exit;
}
ret = IOServiceOpen(smcService, mach_task_self(), 1, &smcConnect);
if (ret != kIOReturnSuccess) {
smcConnect = IO_OBJECT_NULL;
goto exit;
}
if (smcConnect == IO_OBJECT_NULL) {
ret = kIOReturnError;
goto exit;
}
ret = IOConnectCallMethod(smcConnect, kSMCUserClientOpen,
NULL, 0, NULL, 0,
NULL, NULL, NULL, NULL);
if (ret != kIOReturnSuccess) {
goto exit;
}
ret = IOConnectCallStructMethod(smcConnect, selector,
inputStruct, inputStructCnt,
outputStruct, &outputStructCnt);
exit:
if (smcConnect != IO_OBJECT_NULL) {
IOConnectCallMethod(smcConnect, kSMCUserClientClose,
NULL, 0, NULL, 0, NULL,
NULL, NULL, NULL);
IOServiceClose(smcConnect);
}
return ret;
}
static IOReturn smc_read_key(uint32_t key,
uint8_t *bytes,
IOByteCount *dataSize)
{
IOReturn ret;
SMCParamStruct inputStruct;
SMCParamStruct outputStruct;
if (key == 0 || bytes == NULL) {
ret = kIOReturnCannotWire;
goto exit;
}
/* determine key's data size */
memset(&inputStruct, 0, sizeof(SMCParamStruct));
inputStruct.data8 = kSMCGetKeyInfo;
inputStruct.key = key;
memset(&outputStruct, 0, sizeof(SMCParamStruct));
ret = smc_call_struct_method(kSMCHandleYPCEvent, &inputStruct, &outputStruct);
if (ret != kIOReturnSuccess) {
goto exit;
}
if (outputStruct.result == kSMCKeyNotFound) {
ret = kIOReturnNotFound;
goto exit;
}
if (outputStruct.result != kSMCSuccess) {
ret = kIOReturnInternalError;
goto exit;
}
/* get key value */
memset(&inputStruct, 0, sizeof(SMCParamStruct));
inputStruct.data8 = kSMCReadKey;
inputStruct.key = key;
inputStruct.keyInfo.dataSize = outputStruct.keyInfo.dataSize;
memset(&outputStruct, 0, sizeof(SMCParamStruct));
ret = smc_call_struct_method(kSMCHandleYPCEvent, &inputStruct, &outputStruct);
if (ret != kIOReturnSuccess) {
goto exit;
}
if (outputStruct.result == kSMCKeyNotFound) {
ret = kIOReturnNotFound;
goto exit;
}
if (outputStruct.result != kSMCSuccess) {
ret = kIOReturnInternalError;
goto exit;
}
memset(bytes, 0, *dataSize);
if (*dataSize > inputStruct.keyInfo.dataSize) {
*dataSize = inputStruct.keyInfo.dataSize;
}
memcpy(bytes, outputStruct.bytes, *dataSize);
exit:
return ret;
}
#endif
/* #define DEBUG_SMC */
#define APPLESMC_DEFAULT_IOBASE 0x300
@ -315,6 +480,7 @@ static const MemoryRegionOps applesmc_err_io_ops = {
static void applesmc_isa_realize(DeviceState *dev, Error **errp)
{
AppleSMCState *s = APPLE_SMC(dev);
bool valid_key = false;
memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s,
"applesmc-data", 1);
@ -331,7 +497,31 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)
isa_register_ioport(&s->parent_obj, &s->io_err,
s->iobase + APPLESMC_ERR_PORT);
if (!s->osk || (strlen(s->osk) != 64)) {
if (s->osk) {
valid_key = strlen(s->osk) == 64;
} else {
#if defined(__APPLE__) && defined(__MACH__)
IOReturn ret;
IOByteCount size = 32;
ret = smc_read_key('OSK0', (uint8_t *) default_osk, &size);
if (ret != kIOReturnSuccess) {
goto failure;
}
ret = smc_read_key('OSK1', (uint8_t *) default_osk + size, &size);
if (ret != kIOReturnSuccess) {
goto failure;
}
warn_report("Using AppleSMC with host key");
valid_key = true;
s->osk = default_osk;
failure:;
#endif
}
if (!valid_key) {
warn_report("Using AppleSMC with invalid key");
s->osk = default_osk;
}

2
meson

@ -1 +1 @@
Subproject commit 776acd2a805c9b42b4f0375150977df42130317f
Subproject commit b25d94e7c77fda05a7fdfe8afe562cf9760d69da

View File

@ -1,14 +1,10 @@
project('qemu', ['c'], meson_version: '>=0.55.0',
default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto'] +
(meson.version().version_compare('>=0.56.0') ? [ 'b_staticpic=false' ] : []),
version: run_command('head', meson.source_root() / 'VERSION').stdout().strip())
project('qemu', ['c'], meson_version: '>=0.58.2',
default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
'b_staticpic=false'],
version: files('VERSION'))
not_found = dependency('', required: false)
if meson.version().version_compare('>=0.56.0')
keyval = import('keyval')
else
keyval = import('unstable-keyval')
endif
ss = import('sourceset')
fs = import('fs')
@ -1972,21 +1968,21 @@ genh += configure_file(output: 'config-host.h', configuration: config_host_data)
hxtool = find_program('scripts/hxtool')
shaderinclude = find_program('scripts/shaderinclude.pl')
qapi_gen = find_program('scripts/qapi-gen.py')
qapi_gen_depends = [ meson.source_root() / 'scripts/qapi/__init__.py',
meson.source_root() / 'scripts/qapi/commands.py',
meson.source_root() / 'scripts/qapi/common.py',
meson.source_root() / 'scripts/qapi/error.py',
meson.source_root() / 'scripts/qapi/events.py',
meson.source_root() / 'scripts/qapi/expr.py',
meson.source_root() / 'scripts/qapi/gen.py',
meson.source_root() / 'scripts/qapi/introspect.py',
meson.source_root() / 'scripts/qapi/parser.py',
meson.source_root() / 'scripts/qapi/schema.py',
meson.source_root() / 'scripts/qapi/source.py',
meson.source_root() / 'scripts/qapi/types.py',
meson.source_root() / 'scripts/qapi/visit.py',
meson.source_root() / 'scripts/qapi/common.py',
meson.source_root() / 'scripts/qapi-gen.py'
qapi_gen_depends = [ meson.current_source_dir() / 'scripts/qapi/__init__.py',
meson.current_source_dir() / 'scripts/qapi/commands.py',
meson.current_source_dir() / 'scripts/qapi/common.py',
meson.current_source_dir() / 'scripts/qapi/error.py',
meson.current_source_dir() / 'scripts/qapi/events.py',
meson.current_source_dir() / 'scripts/qapi/expr.py',
meson.current_source_dir() / 'scripts/qapi/gen.py',
meson.current_source_dir() / 'scripts/qapi/introspect.py',
meson.current_source_dir() / 'scripts/qapi/parser.py',
meson.current_source_dir() / 'scripts/qapi/schema.py',
meson.current_source_dir() / 'scripts/qapi/source.py',
meson.current_source_dir() / 'scripts/qapi/types.py',
meson.current_source_dir() / 'scripts/qapi/visit.py',
meson.current_source_dir() / 'scripts/qapi/common.py',
meson.current_source_dir() / 'scripts/qapi-gen.py'
]
tracetool = [
@ -2635,14 +2631,14 @@ foreach target : target_dirs
if target.endswith('-softmmu')
execs = [{
'name': 'qemu-system-' + target_name,
'gui': false,
'win_subsystem': 'console',
'sources': files('softmmu/main.c'),
'dependencies': []
}]
if targetos == 'windows' and (sdl.found() or gtk.found())
execs += [{
'name': 'qemu-system-' + target_name + 'w',
'gui': true,
'win_subsystem': 'windows',
'sources': files('softmmu/main.c'),
'dependencies': []
}]
@ -2651,7 +2647,7 @@ foreach target : target_dirs
specific_fuzz = specific_fuzz_ss.apply(config_target, strict: false)
execs += [{
'name': 'qemu-fuzz-' + target_name,
'gui': false,
'win_subsystem': 'console',
'sources': specific_fuzz.sources(),
'dependencies': specific_fuzz.dependencies(),
}]
@ -2659,7 +2655,7 @@ foreach target : target_dirs
else
execs = [{
'name': 'qemu-' + target_name,
'gui': false,
'win_subsystem': 'console',
'sources': [],
'dependencies': []
}]
@ -2678,7 +2674,7 @@ foreach target : target_dirs
link_language: link_language,
link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
link_args: link_args,
gui_app: exe['gui'])
win_subsystem: exe['win_subsystem'])
if targetos == 'darwin'
icon = 'pc-bios/qemu.rsrc'
@ -2863,13 +2859,13 @@ summary_info = {}
summary_info += {'git': config_host['GIT']}
summary_info += {'make': config_host['MAKE']}
summary_info += {'python': '@0@ (version: @1@)'.format(python.full_path(), python.language_version())}
summary_info += {'sphinx-build': sphinx_build.found()}
summary_info += {'sphinx-build': sphinx_build}
if config_host.has_key('HAVE_GDB_BIN')
summary_info += {'gdb': config_host['HAVE_GDB_BIN']}
endif
summary_info += {'genisoimage': config_host['GENISOIMAGE']}
if targetos == 'windows' and config_host.has_key('CONFIG_GUEST_AGENT')
summary_info += {'wixl': wixl.found() ? wixl.full_path() : false}
summary_info += {'wixl': wixl}
endif
if slirp_opt != 'disabled' and 'CONFIG_SLIRP_SMBD' in config_host
summary_info += {'smbd': config_host['CONFIG_SMBD_COMMAND']}
@ -2960,7 +2956,7 @@ if get_option('cfi')
summary_info += {'CFI debug support': get_option('cfi_debug')}
endif
summary_info += {'strip binaries': get_option('strip')}
summary_info += {'sparse': sparse.found() ? sparse.full_path() : false}
summary_info += {'sparse': sparse}
summary_info += {'mingw32 support': targetos == 'windows'}
# snarf the cross-compilation information for tests
@ -3032,19 +3028,19 @@ if have_block
summary_info += {'vvfat support': config_host.has_key('CONFIG_VVFAT')}
summary_info += {'qed support': config_host.has_key('CONFIG_QED')}
summary_info += {'parallels support': config_host.has_key('CONFIG_PARALLELS')}
summary_info += {'FUSE exports': fuse.found()}
summary_info += {'FUSE exports': fuse}
endif
summary(summary_info, bool_yn: true, section: 'Block layer support')
# Crypto
summary_info = {}
summary_info += {'TLS priority': config_host['CONFIG_TLS_PRIORITY']}
summary_info += {'GNUTLS support': gnutls.found()}
summary_info += {'GNUTLS support': gnutls}
if gnutls.found()
summary_info += {' GNUTLS crypto': gnutls_crypto.found()}
# TODO: add back version
summary_info += {'libgcrypt': gcrypt.found()}
# TODO: add back version
summary_info += {'nettle': nettle.found()}
endif
summary_info += {'libgcrypt': gcrypt}
summary_info += {'nettle': nettle}
if nettle.found()
summary_info += {' XTS': xts != 'private'}
endif
@ -3056,76 +3052,72 @@ summary(summary_info, bool_yn: true, section: 'Crypto')
# Libraries
summary_info = {}
if targetos == 'darwin'
summary_info += {'Cocoa support': cocoa.found()}
summary_info += {'Cocoa support': cocoa}
endif
# TODO: add back version
summary_info += {'SDL support': sdl.found()}
summary_info += {'SDL image support': sdl_image.found()}
# TODO: add back version
summary_info += {'GTK support': gtk.found()}
summary_info += {'pixman': pixman.found()}
# TODO: add back version
summary_info += {'VTE support': vte.found()}
# TODO: add back version
summary_info += {'slirp support': slirp_opt == 'disabled' ? false : slirp_opt}
summary_info += {'libtasn1': tasn1.found()}
summary_info += {'PAM': pam.found()}
summary_info += {'iconv support': iconv.found()}
summary_info += {'curses support': curses.found()}
# TODO: add back version
summary_info += {'virgl support': virgl.found()}
summary_info += {'curl support': curl.found()}
summary_info += {'Multipath support': mpathpersist.found()}
summary_info += {'VNC support': vnc.found()}
summary_info += {'SDL support': sdl}
summary_info += {'SDL image support': sdl_image}
summary_info += {'GTK support': gtk}
summary_info += {'pixman': pixman}
summary_info += {'VTE support': vte}
summary_info += {'slirp support': slirp_opt == 'internal' ? slirp_opt : slirp}
summary_info += {'libtasn1': tasn1}
summary_info += {'PAM': pam}
summary_info += {'iconv support': iconv}
summary_info += {'curses support': curses}
summary_info += {'virgl support': virgl}
summary_info += {'curl support': curl}
summary_info += {'Multipath support': mpathpersist}
summary_info += {'VNC support': vnc}
if vnc.found()
summary_info += {'VNC SASL support': sasl.found()}
summary_info += {'VNC JPEG support': jpeg.found()}
summary_info += {'VNC PNG support': png.found()}
summary_info += {'VNC SASL support': sasl}
summary_info += {'VNC JPEG support': jpeg}
summary_info += {'VNC PNG support': png}
endif
summary_info += {'brlapi support': brlapi.found()}
summary_info += {'brlapi support': brlapi}
summary_info += {'vde support': config_host.has_key('CONFIG_VDE')}
summary_info += {'netmap support': config_host.has_key('CONFIG_NETMAP')}
summary_info += {'Linux AIO support': config_host.has_key('CONFIG_LINUX_AIO')}
summary_info += {'Linux io_uring support': linux_io_uring.found()}
summary_info += {'ATTR/XATTR support': libattr.found()}
summary_info += {'Linux io_uring support': linux_io_uring}
summary_info += {'ATTR/XATTR support': libattr}
summary_info += {'RDMA support': config_host.has_key('CONFIG_RDMA')}
summary_info += {'PVRDMA support': config_host.has_key('CONFIG_PVRDMA')}
summary_info += {'fdt support': fdt_opt == 'disabled' ? false : fdt_opt}
summary_info += {'libcap-ng support': libcap_ng.found()}
summary_info += {'bpf support': libbpf.found()}
summary_info += {'libcap-ng support': libcap_ng}
summary_info += {'bpf support': libbpf}
# TODO: add back protocol and server version
summary_info += {'spice support': config_host.has_key('CONFIG_SPICE')}
summary_info += {'rbd support': rbd.found()}
summary_info += {'rbd support': rbd}
summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')}
summary_info += {'smartcard support': cacard.found()}
summary_info += {'U2F support': u2f.found()}
summary_info += {'libusb': libusb.found()}
summary_info += {'usb net redir': usbredir.found()}
summary_info += {'smartcard support': cacard}
summary_info += {'U2F support': u2f}
summary_info += {'libusb': libusb}
summary_info += {'usb net redir': usbredir}
summary_info += {'OpenGL support': config_host.has_key('CONFIG_OPENGL')}
summary_info += {'GBM': gbm.found()}
summary_info += {'libiscsi support': libiscsi.found()}
summary_info += {'libnfs support': libnfs.found()}
summary_info += {'GBM': gbm}
summary_info += {'libiscsi support': libiscsi}
summary_info += {'libnfs support': libnfs}
if targetos == 'windows'
if config_host.has_key('CONFIG_GUEST_AGENT')
summary_info += {'QGA VSS support': config_host.has_key('CONFIG_QGA_VSS')}
summary_info += {'QGA w32 disk info': config_host.has_key('CONFIG_QGA_NTDDSCSI')}
endif
endif
summary_info += {'seccomp support': seccomp.found()}
summary_info += {'GlusterFS support': glusterfs.found()}
summary_info += {'seccomp support': seccomp}
summary_info += {'GlusterFS support': glusterfs}
summary_info += {'TPM support': config_host.has_key('CONFIG_TPM')}
summary_info += {'libssh support': config_host.has_key('CONFIG_LIBSSH')}
summary_info += {'lzo support': lzo.found()}
summary_info += {'snappy support': snappy.found()}
summary_info += {'bzip2 support': libbzip2.found()}
summary_info += {'lzfse support': liblzfse.found()}
summary_info += {'zstd support': zstd.found()}
summary_info += {'lzo support': lzo}
summary_info += {'snappy support': snappy}
summary_info += {'bzip2 support': libbzip2}
summary_info += {'lzfse support': liblzfse}
summary_info += {'zstd support': zstd}
summary_info += {'NUMA host support': config_host.has_key('CONFIG_NUMA')}
summary_info += {'libxml2': libxml2.found()}
summary_info += {'capstone': capstone_opt == 'disabled' ? false : capstone_opt}
summary_info += {'libpmem support': libpmem.found()}
summary_info += {'libdaxctl support': libdaxctl.found()}
summary_info += {'libudev': libudev.found()}
summary_info += {'libxml2': libxml2}
summary_info += {'capstone': capstone_opt == 'internal' ? capstone_opt : capstone}
summary_info += {'libpmem support': libpmem}
summary_info += {'libdaxctl support': libdaxctl}
summary_info += {'libudev': libudev}
# Dummy dependency, keep .found()
summary_info += {'FUSE lseek': fuse_lseek.found()}
summary(summary_info, bool_yn: true, section: 'Dependencies')

View File

@ -1215,7 +1215,10 @@ static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque)
{
DBMSaveState *s = &((DBMState *)opaque)->save;
SaveBitmapState *dbms = NULL;
qemu_mutex_lock_iothread();
if (init_dirty_bitmap_migration(s) < 0) {
qemu_mutex_unlock_iothread();
return -1;
}
@ -1223,7 +1226,7 @@ static int dirty_bitmap_save_setup(QEMUFile *f, void *opaque)
send_bitmap_start(f, s, dbms);
}
qemu_put_bitmap_flags(f, DIRTY_BITMAP_MIG_FLAG_EOS);
qemu_mutex_unlock_iothread();
return 0;
}

View File

@ -3168,7 +3168,10 @@ static void migration_completion(MigrationState *s)
} else if (s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
trace_migration_completion_postcopy_end();
qemu_mutex_lock_iothread();
qemu_savevm_state_complete_postcopy(s->to_dst_file);
qemu_mutex_unlock_iothread();
trace_migration_completion_postcopy_end_after_complete();
} else if (s->state == MIGRATION_STATUS_CANCELLING) {
goto fail;

View File

@ -2,9 +2,9 @@ plugin_ldflags = []
# Modules need more symbols than just those in plugins/qemu-plugins.symbols
if not enable_modules
if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host
plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.build_root() / 'qemu-plugins-ld.symbols')]
plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.project_build_root() / 'qemu-plugins-ld.symbols')]
elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host
plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.build_root() / 'qemu-plugins-ld64.symbols')]
plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.project_build_root() / 'qemu-plugins-ld64.symbols')]
endif
endif

View File

@ -60,11 +60,8 @@ def process_tests(test, targets, suites):
if test['workdir'] is not None:
print('.test.dir.%d := %s' % (i, shlex.quote(test['workdir'])))
if 'depends' in test:
deps = (targets.get(x, []) for x in test['depends'])
deps = itertools.chain.from_iterable(deps)
else:
deps = ['all']
print('.test.name.%d := %s' % (i, test['name']))
print('.test.driver.%d := %s' % (i, driver))

View File

@ -156,7 +156,8 @@ dectree_generated = custom_target(
'dectree_generated.h.inc',
output: 'dectree_generated.h.inc',
depends: [iset_py],
command: ['env', 'PYTHONPATH=' + meson.current_build_dir(), files('dectree.py'), '@OUTPUT@'],
env: {'PYTHONPATH': meson.current_build_dir()},
command: [python, files('dectree.py'), '@OUTPUT@'],
)
hexagon_ss.add(dectree_generated)

View File

@ -81,3 +81,8 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
error_setg(errp, "SEV is not available in this QEMU");
return NULL;
}
bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
{
g_assert_not_reached();
}

View File

@ -23,6 +23,7 @@
#include "qemu/base64.h"
#include "qemu/module.h"
#include "qemu/uuid.h"
#include "crypto/hash.h"
#include "sysemu/kvm.h"
#include "sev_i386.h"
#include "sysemu/sysemu.h"
@ -83,6 +84,32 @@ typedef struct __attribute__((__packed__)) SevInfoBlock {
uint32_t reset_addr;
} SevInfoBlock;
#define SEV_HASH_TABLE_RV_GUID "7255371f-3a3b-4b04-927b-1da6efa8d454"
typedef struct QEMU_PACKED SevHashTableDescriptor {
/* SEV hash table area guest address */
uint32_t base;
/* SEV hash table area size (in bytes) */
uint32_t size;
} SevHashTableDescriptor;
/* hard code sha256 digest size */
#define HASH_SIZE 32
typedef struct QEMU_PACKED SevHashTableEntry {
QemuUUID guid;
uint16_t len;
uint8_t hash[HASH_SIZE];
} SevHashTableEntry;
typedef struct QEMU_PACKED SevHashTable {
QemuUUID guid;
uint16_t len;
SevHashTableEntry cmdline;
SevHashTableEntry initrd;
SevHashTableEntry kernel;
uint8_t padding[];
} SevHashTable;
static SevGuestState *sev_guest;
static Error *sev_mig_blocker;
@ -1071,6 +1098,116 @@ int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
return 0;
}
static const QemuUUID sev_hash_table_header_guid = {
.data = UUID_LE(0x9438d606, 0x4f22, 0x4cc9, 0xb4, 0x79, 0xa7, 0x93,
0xd4, 0x11, 0xfd, 0x21)
};
static const QemuUUID sev_kernel_entry_guid = {
.data = UUID_LE(0x4de79437, 0xabd2, 0x427f, 0xb8, 0x35, 0xd5, 0xb1,
0x72, 0xd2, 0x04, 0x5b)
};
static const QemuUUID sev_initrd_entry_guid = {
.data = UUID_LE(0x44baf731, 0x3a2f, 0x4bd7, 0x9a, 0xf1, 0x41, 0xe2,
0x91, 0x69, 0x78, 0x1d)
};
static const QemuUUID sev_cmdline_entry_guid = {
.data = UUID_LE(0x97d02dd8, 0xbd20, 0x4c94, 0xaa, 0x78, 0xe7, 0x71,
0x4d, 0x36, 0xab, 0x2a)
};
/*
* Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
* which is included in SEV's initial memory measurement.
*/
bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
{
uint8_t *data;
SevHashTableDescriptor *area;
SevHashTable *ht;
uint8_t cmdline_hash[HASH_SIZE];
uint8_t initrd_hash[HASH_SIZE];
uint8_t kernel_hash[HASH_SIZE];
uint8_t *hashp;
size_t hash_len = HASH_SIZE;
int aligned_len;
if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid");
return false;
}
area = (SevHashTableDescriptor *)data;
/*
* Calculate hash of kernel command-line with the terminating null byte. If
* the user doesn't supply a command-line via -append, the 1-byte "\0" will
* be used.
*/
hashp = cmdline_hash;
if (qcrypto_hash_bytes(QCRYPTO_HASH_ALG_SHA256, ctx->cmdline_data,
ctx->cmdline_size, &hashp, &hash_len, errp) < 0) {
return false;
}
assert(hash_len == HASH_SIZE);
/*
* Calculate hash of initrd. If the user doesn't supply an initrd via
* -initrd, an empty buffer will be used (ctx->initrd_size == 0).
*/
hashp = initrd_hash;
if (qcrypto_hash_bytes(QCRYPTO_HASH_ALG_SHA256, ctx->initrd_data,
ctx->initrd_size, &hashp, &hash_len, errp) < 0) {
return false;
}
assert(hash_len == HASH_SIZE);
/* Calculate hash of the kernel */
hashp = kernel_hash;
struct iovec iov[2] = {
{ .iov_base = ctx->setup_data, .iov_len = ctx->setup_size },
{ .iov_base = ctx->kernel_data, .iov_len = ctx->kernel_size }
};
if (qcrypto_hash_bytesv(QCRYPTO_HASH_ALG_SHA256, iov, ARRAY_SIZE(iov),
&hashp, &hash_len, errp) < 0) {
return false;
}
assert(hash_len == HASH_SIZE);
/*
* Populate the hashes table in the guest's memory at the OVMF-designated
* area for the SEV hashes table
*/
ht = qemu_map_ram_ptr(NULL, area->base);
ht->guid = sev_hash_table_header_guid;
ht->len = sizeof(*ht);
ht->cmdline.guid = sev_cmdline_entry_guid;
ht->cmdline.len = sizeof(ht->cmdline);
memcpy(ht->cmdline.hash, cmdline_hash, sizeof(ht->cmdline.hash));
ht->initrd.guid = sev_initrd_entry_guid;
ht->initrd.len = sizeof(ht->initrd);
memcpy(ht->initrd.hash, initrd_hash, sizeof(ht->initrd.hash));
ht->kernel.guid = sev_kernel_entry_guid;
ht->kernel.len = sizeof(ht->kernel);
memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
/* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
aligned_len = ROUND_UP(ht->len, 16);
if (aligned_len != ht->len) {
/* zero the excess data so the measurement can be reliably calculated */
memset(ht->padding, 0, aligned_len - ht->len);
}
if (sev_encrypt_flash((uint8_t *)ht, aligned_len, errp) < 0) {
return false;
}
return true;
}
static void
sev_register_types(void)
{

View File

@ -28,6 +28,17 @@
#define SEV_POLICY_DOMAIN 0x10
#define SEV_POLICY_SEV 0x20
typedef struct SevKernelLoaderContext {
char *setup_data;
size_t setup_size;
char *kernel_data;
size_t kernel_size;
char *initrd_data;
size_t initrd_size;
char *cmdline_data;
size_t cmdline_size;
} SevKernelLoaderContext;
extern bool sev_es_enabled(void);
extern uint64_t sev_get_me_mask(void);
extern SevInfo *sev_get_info(void);
@ -37,5 +48,6 @@ extern char *sev_get_launch_measurement(void);
extern SevCapability *sev_get_capabilities(Error **errp);
extern SevAttestationReport *
sev_get_attestation_report(const char *mnonce, Error **errp);
extern bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp);
#endif

9
target/xtensa/cores.list Normal file
View File

@ -0,0 +1,9 @@
core-dc232b.c
core-dc233c.c
core-de212.c
core-de233_fpu.c
core-dsp3400.c
core-fsf.c
core-sample_controller.c
core-test_kc705_be.c
core-test_mmuhifi_c3.c

View File

@ -66,3 +66,6 @@ static XtensaConfig $NAME __attribute__((unused)) = {
REGISTER_CORE($NAME)
EOF
grep -qxf core-${NAME}.c "$BASE"/cores.list || \
echo core-${NAME}.c >> "$BASE"/cores.list

View File

@ -1,7 +1,7 @@
xtensa_ss = ss.source_set()
xtensa_cores = run_command('sh', '-c', 'cd $MESON_SOURCE_ROOT/$MESON_SUBDIR ; ls -1 core-*.c')
xtensa_ss.add(files(xtensa_cores.stdout().strip().split('\n')))
xtensa_cores = fs.read('cores.list')
xtensa_ss.add(files(xtensa_cores.strip().split('\n')))
xtensa_ss.add(files(
'cpu.c',

View File

@ -1,5 +1,5 @@
test_env = environment()
test_env.set('PYTHONPATH', meson.source_root() / 'scripts')
test_env.set('PYTHONPATH', meson.project_source_root() / 'scripts')
test_env.set('PYTHONIOENCODING', 'utf-8')
schemas = [
@ -248,7 +248,7 @@ if build_docs
# clutter up the build dir with the cache.
command: [SPHINX_ARGS,
'-b', 'text', '-E',
'-c', meson.source_root() / 'docs',
'-c', meson.project_source_root() / 'docs',
'-D', 'master_doc=doc-good',
meson.current_source_dir(),
meson.current_build_dir()])

View File

@ -275,7 +275,7 @@ foreach dir : target_dirs
qtest_env.set('QTEST_QEMU_IMG', './qemu-img')
test_deps += [qemu_img]
endif
qtest_env.set('G_TEST_DBUS_DAEMON', meson.source_root() / 'tests/dbus-vmstate-daemon.sh')
qtest_env.set('G_TEST_DBUS_DAEMON', meson.project_source_root() / 'tests/dbus-vmstate-daemon.sh')
qtest_env.set('QTEST_QEMU_BINARY', './qemu-system-' + target_base)
if have_tools and have_vhost_user_blk_server
qtest_env.set('QTEST_QEMU_STORAGE_DAEMON_BINARY', './storage-daemon/qemu-storage-daemon')

View File

@ -43,7 +43,7 @@ tests = {
'test-keyval': [testqapi],
'test-logging': [],
'test-uuid': [],
'ptimer-test': ['ptimer-test-stubs.c', meson.source_root() / 'hw/core/ptimer.c'],
'ptimer-test': ['ptimer-test-stubs.c', meson.project_source_root() / 'hw/core/ptimer.c'],
'test-qapi-util': [],
}

View File

@ -4,7 +4,7 @@ specific_ss.add(files('control-target.c'))
trace_events_files = []
dtrace = find_program('dtrace', required: 'CONFIG_TRACE_DTRACE' in config_host)
foreach dir : [ '.' ] + trace_events_subdirs
trace_events_file = meson.source_root() / dir / 'trace-events'
trace_events_file = meson.project_source_root() / dir / 'trace-events'
trace_events_files += [ trace_events_file ]
group_name = dir == '.' ? 'root' : dir.underscorify()
group = '--group=' + group_name
@ -70,7 +70,7 @@ foreach d : [
]
gen = custom_target(d[0],
output: d[0],
input: meson.source_root() / 'trace-events',
input: meson.project_source_root() / 'trace-events',
command: [ tracetool, '--group=root', '--format=@0@'.format(d[1]), '@INPUT@', '@OUTPUT@' ],
depend_files: tracetool_depends)
specific_ss.add(when: 'CONFIG_TCG', if_true: gen)