* 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:
commit
08a9b68dc0
19
configure
vendored
19
configure
vendored
@ -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
|
||||
|
@ -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
100
docs/system/i386/kvm-pv.rst
Normal 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.
|
@ -26,6 +26,7 @@ Architectural features
|
||||
:maxdepth: 1
|
||||
|
||||
i386/cpu
|
||||
i386/kvm-pv
|
||||
i386/sgx
|
||||
|
||||
.. _pcsys_005freq:
|
||||
|
@ -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";
|
||||
|
@ -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
2
meson
@ -1 +1 @@
|
||||
Subproject commit 776acd2a805c9b42b4f0375150977df42130317f
|
||||
Subproject commit b25d94e7c77fda05a7fdfe8afe562cf9760d69da
|
162
meson.build
162
meson.build
@ -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')
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
9
target/xtensa/cores.list
Normal 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
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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()])
|
||||
|
@ -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')
|
||||
|
@ -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': [],
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user