aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-10-13 06:56:45 -0700
committerRichard Henderson <richard.henderson@linaro.org>2021-10-13 06:56:45 -0700
commit946de558354c99e1989621abe053f2ab87dc8de9 (patch)
tree3b8333edfbfa1d6d2c0c17de4d1674463e56fc83
parentee26ce674a93c824713542cec3b6a9ca85459165 (diff)
parenteeecc2ede44b2a5f2551dfcebd561a3945d4c132 (diff)
downloadqemu-946de558354c99e1989621abe053f2ab87dc8de9.zip
qemu-946de558354c99e1989621abe053f2ab87dc8de9.tar.gz
qemu-946de558354c99e1989621abe053f2ab87dc8de9.tar.bz2
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* SEV and SGX cleanups (Philippe, Dov) * bugfixes for "check-block" * bugfix for static build * ObjectOptions cleanups (Thomas) * binutils fix for PVH (Cole) * HVF cleanup (Alex) # gpg: Signature made Wed 13 Oct 2021 01:47:56 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: (40 commits) ebpf: really include it only in system emulators target/i386/sev: Use local variable for kvm_sev_launch_measure target/i386/sev: Use local variable for kvm_sev_launch_start monitor: Tidy up find_device_state() Revert "hw/misc: applesmc: use host osk as default on macs" hw/i386/sgx: Move qmp_query_sgx() and hmp_info_sgx() to hw/i386/sgx.c hw/i386/sgx: Move qmp_query_sgx_capabilities() to hw/i386/sgx.c hw/i386/sgx: Have sgx_epc_get_section() return a boolean MAINTAINERS: Cover SGX documentation file with X86/KVM section hvf: Determine slot count from struct layout tests: tcg: Fix PVH test with binutils 2.36+ qapi: Make some ObjectTypes depend on the build settings MAINTAINERS: Cover SEV-related files with X86/KVM section monitor: Reduce hmp_info_sev() declaration target/i386/sev: Move qmp_query_sev() & hmp_info_sev() to sev.c target/i386/sev: Move qmp_query_sev_launch_measure() to sev.c target/i386/sev: Move qmp_query_sev_capabilities() to sev.c target/i386/sev: Move qmp_sev_inject_launch_secret() to sev.c target/i386/sev: Move qmp_query_sev_attestation_report() to sev.c target/i386/sev: Remove stubs by using code elision ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--MAINTAINERS4
-rw-r--r--accel/hvf/hvf-accel-ops.c2
-rw-r--r--accel/kvm/meson.build1
-rw-r--r--hw/i386/pc_sysfw.c2
-rw-r--r--hw/i386/sgx-stub.c16
-rw-r--r--hw/i386/sgx.c35
-rw-r--r--hw/i386/x86.c2
-rw-r--r--hw/misc/applesmc.c192
-rw-r--r--include/hw/i386/sgx-epc.h2
-rw-r--r--include/hw/i386/sgx.h12
-rw-r--r--include/monitor/hmp-target.h1
-rw-r--r--include/monitor/hmp.h1
-rw-r--r--include/sysemu/sev.h28
-rw-r--r--meson.build9
-rw-r--r--qapi/misc-target.json77
-rw-r--r--qapi/qom.json36
-rw-r--r--softmmu/qdev-monitor.c13
-rw-r--r--target/i386/cpu.c16
-rw-r--r--target/i386/kvm/kvm.c3
-rw-r--r--target/i386/kvm/meson.build8
-rw-r--r--target/i386/kvm/sev-stub.c (renamed from accel/kvm/sev-stub.c)2
-rw-r--r--target/i386/meson.build4
-rw-r--r--target/i386/monitor.c124
-rw-r--r--target/i386/sev-stub.c88
-rw-r--r--target/i386/sev-sysemu-stub.c70
-rw-r--r--target/i386/sev.c201
-rw-r--r--target/i386/sev.h (renamed from target/i386/sev_i386.h)35
-rw-r--r--tests/Makefile.include16
-rw-r--r--tests/qemu-iotests/testrunner.py1
-rw-r--r--tests/tcg/x86_64/system/kernel.ld5
-rw-r--r--util/compatfd.c5
31 files changed, 392 insertions, 619 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 50435b8..cfefe38 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -417,7 +417,10 @@ M: Paolo Bonzini <pbonzini@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com>
L: kvm@vger.kernel.org
S: Supported
+F: docs/amd-memory-encryption.txt
+F: docs/system/i386/sgx.rst
F: target/i386/kvm/
+F: target/i386/sev*
F: scripts/kvm/vmxcap
Guest CPU Cores (other accelerators)
@@ -2502,6 +2505,7 @@ Memory API
M: Paolo Bonzini <pbonzini@redhat.com>
M: Peter Xu <peterx@redhat.com>
M: David Hildenbrand <david@redhat.com>
+R: Philippe Mathieu-Daudé <philmd@redhat.com>
S: Supported
F: include/exec/ioport.h
F: include/exec/memop.h
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index 6cbd2c3..2b2c411 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -321,7 +321,7 @@ static int hvf_accel_init(MachineState *ms)
s = g_new0(HVFState, 1);
- s->num_slots = 32;
+ s->num_slots = ARRAY_SIZE(s->slots);
for (x = 0; x < s->num_slots; ++x) {
s->slots[x].size = 0;
s->slots[x].slot_id = x;
diff --git a/accel/kvm/meson.build b/accel/kvm/meson.build
index 8d219be..397a1fe 100644
--- a/accel/kvm/meson.build
+++ b/accel/kvm/meson.build
@@ -3,6 +3,5 @@ kvm_ss.add(files(
'kvm-all.c',
'kvm-accel-ops.c',
))
-kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 68d6b1f..c8b17af 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -37,7 +37,7 @@
#include "hw/qdev-properties.h"
#include "hw/block/flash.h"
#include "sysemu/kvm.h"
-#include "sysemu/sev.h"
+#include "sev.h"
#define FLASH_SECTOR_SIZE 4096
diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c
index 3be9f5c..c9b379e 100644
--- a/hw/i386/sgx-stub.c
+++ b/hw/i386/sgx-stub.c
@@ -1,26 +1,34 @@
#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
#include "hw/i386/pc.h"
#include "hw/i386/sgx-epc.h"
-#include "hw/i386/sgx.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-misc-target.h"
-SGXInfo *sgx_get_info(Error **errp)
+SGXInfo *qmp_query_sgx(Error **errp)
{
error_setg(errp, "SGX support is not compiled in");
return NULL;
}
-SGXInfo *sgx_get_capabilities(Error **errp)
+SGXInfo *qmp_query_sgx_capabilities(Error **errp)
{
error_setg(errp, "SGX support is not compiled in");
return NULL;
}
+void hmp_info_sgx(Monitor *mon, const QDict *qdict)
+{
+ monitor_printf(mon, "SGX is not available in this QEMU\n");
+}
+
void pc_machine_init_sgx_epc(PCMachineState *pcms)
{
memset(&pcms->sgx_epc, 0, sizeof(SGXEPCState));
}
-int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
{
g_assert_not_reached();
}
diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
index e481e93..1160756 100644
--- a/hw/i386/sgx.c
+++ b/hw/i386/sgx.c
@@ -15,9 +15,11 @@
#include "hw/i386/sgx-epc.h"
#include "hw/mem/memory-device.h"
#include "monitor/qdev.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-misc-target.h"
#include "exec/address-spaces.h"
-#include "hw/i386/sgx.h"
#include "sysemu/hw_accel.h"
#define SGX_MAX_EPC_SECTIONS 8
@@ -57,7 +59,7 @@ static uint64_t sgx_calc_host_epc_section_size(void)
return size;
}
-SGXInfo *sgx_get_capabilities(Error **errp)
+SGXInfo *qmp_query_sgx_capabilities(Error **errp)
{
SGXInfo *info = NULL;
uint32_t eax, ebx, ecx, edx;
@@ -85,7 +87,7 @@ SGXInfo *sgx_get_capabilities(Error **errp)
return info;
}
-SGXInfo *sgx_get_info(Error **errp)
+SGXInfo *qmp_query_sgx(Error **errp)
{
SGXInfo *info = NULL;
X86MachineState *x86ms;
@@ -115,13 +117,34 @@ SGXInfo *sgx_get_info(Error **errp)
return info;
}
-int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+void hmp_info_sgx(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
+
+ if (err) {
+ error_report_err(err);
+ return;
+ }
+ monitor_printf(mon, "SGX support: %s\n",
+ info->sgx ? "enabled" : "disabled");
+ monitor_printf(mon, "SGX1 support: %s\n",
+ info->sgx1 ? "enabled" : "disabled");
+ monitor_printf(mon, "SGX2 support: %s\n",
+ info->sgx2 ? "enabled" : "disabled");
+ monitor_printf(mon, "FLC support: %s\n",
+ info->flc ? "enabled" : "disabled");
+ monitor_printf(mon, "size: %" PRIu64 "\n",
+ info->section_size);
+}
+
+bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
{
PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
SGXEPCDevice *epc;
if (pcms->sgx_epc.size == 0 || pcms->sgx_epc.nr_sections <= section_nr) {
- return 1;
+ return true;
}
epc = pcms->sgx_epc.sections[section_nr];
@@ -129,7 +152,7 @@ int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
*addr = epc->addr;
*size = memory_device_get_region_size(MEMORY_DEVICE(epc), &error_fatal);
- return 0;
+ return false;
}
void pc_machine_init_sgx_epc(PCMachineState *pcms)
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 0c7c054..76de7e2 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -47,7 +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 "target/i386/sev.h"
#include "hw/acpi/cpu_hotplug.h"
#include "hw/irq.h"
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index cec247b..1b9acaf 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -38,171 +38,6 @@
#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
@@ -480,7 +315,6 @@ 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);
@@ -497,31 +331,7 @@ 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) {
- 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) {
+ if (!s->osk || (strlen(s->osk) != 64)) {
warn_report("Using AppleSMC with invalid key");
s->osk = default_osk;
}
diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h
index 65a68ca..a6a65be 100644
--- a/include/hw/i386/sgx-epc.h
+++ b/include/hw/i386/sgx-epc.h
@@ -55,7 +55,7 @@ typedef struct SGXEPCState {
int nr_sections;
} SGXEPCState;
-int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size);
+bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size);
static inline uint64_t sgx_epc_above_4g_end(SGXEPCState *sgx_epc)
{
diff --git a/include/hw/i386/sgx.h b/include/hw/i386/sgx.h
deleted file mode 100644
index 16fc257..0000000
--- a/include/hw/i386/sgx.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef QEMU_SGX_H
-#define QEMU_SGX_H
-
-#include "qom/object.h"
-#include "qapi/error.h"
-#include "qemu/error-report.h"
-#include "qapi/qapi-types-misc-target.h"
-
-SGXInfo *sgx_get_info(Error **errp);
-SGXInfo *sgx_get_capabilities(Error **errp);
-
-#endif
diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h
index dc53add..96956d0 100644
--- a/include/monitor/hmp-target.h
+++ b/include/monitor/hmp-target.h
@@ -49,6 +49,7 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict);
void hmp_mce(Monitor *mon, const QDict *qdict);
void hmp_info_local_apic(Monitor *mon, const QDict *qdict);
void hmp_info_io_apic(Monitor *mon, const QDict *qdict);
+void hmp_info_sev(Monitor *mon, const QDict *qdict);
void hmp_info_sgx(Monitor *mon, const QDict *qdict);
#endif /* MONITOR_HMP_TARGET_H */
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index 3baa105..6bc2763 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -124,7 +124,6 @@ void hmp_info_ramblock(Monitor *mon, const QDict *qdict);
void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict);
void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict);
void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict);
-void hmp_info_sev(Monitor *mon, const QDict *qdict);
void hmp_info_replay(Monitor *mon, const QDict *qdict);
void hmp_replay_break(Monitor *mon, const QDict *qdict);
void hmp_replay_delete_break(Monitor *mon, const QDict *qdict);
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
deleted file mode 100644
index 94d821d..0000000
--- a/include/sysemu/sev.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * QEMU Secure Encrypted Virutualization (SEV) support
- *
- * Copyright: Advanced Micro Devices, 2016-2018
- *
- * Authors:
- * Brijesh Singh <brijesh.singh@amd.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#ifndef QEMU_SEV_H
-#define QEMU_SEV_H
-
-#include "sysemu/kvm.h"
-
-bool sev_enabled(void);
-int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
-int sev_inject_launch_secret(const char *hdr, const char *secret,
- uint64_t gpa, Error **errp);
-
-int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
-void sev_es_set_reset_vector(CPUState *cpu);
-
-#endif
diff --git a/meson.build b/meson.build
index 99a0a3e..c1314ba 100644
--- a/meson.build
+++ b/meson.build
@@ -1420,10 +1420,9 @@ config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + '''
#include <stddef.h>
int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
config_host_data.set('CONFIG_SIGNALFD', cc.links(gnu_source_prefix + '''
- #include <unistd.h>
- #include <sys/syscall.h>
- #include <signal.h>
- int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); }'''))
+ #include <sys/signalfd.h>
+ #include <stddef.h>
+ int main(void) { return signalfd(-1, NULL, SFD_CLOEXEC); }'''))
config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + '''
#include <unistd.h>
#include <fcntl.h>
@@ -2301,8 +2300,6 @@ subdir('bsd-user')
subdir('linux-user')
subdir('ebpf')
-common_ss.add(libbpf)
-
bsd_user_ss.add(files('gdbstub.c'))
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 594fbd1..5aa2b95 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -230,6 +230,46 @@
'if': 'TARGET_I386' }
##
+# @SevAttestationReport:
+#
+# The struct describes attestation report for a Secure Encrypted
+# Virtualization feature.
+#
+# @data: guest attestation report (base64 encoded)
+#
+#
+# Since: 6.1
+##
+{ 'struct': 'SevAttestationReport',
+ 'data': { 'data': 'str'},
+ 'if': 'TARGET_I386' }
+
+##
+# @query-sev-attestation-report:
+#
+# This command is used to get the SEV attestation report, and is
+# supported on AMD X86 platforms only.
+#
+# @mnonce: a random 16 bytes value encoded in base64 (it will be
+# included in report)
+#
+# Returns: SevAttestationReport objects.
+#
+# Since: 6.1
+#
+# Example:
+#
+# -> { "execute" : "query-sev-attestation-report",
+# "arguments": { "mnonce": "aaaaaaa" } }
+# <- { "return" : { "data": "aaaaaaaabbbddddd"} }
+#
+##
+{ 'command': 'query-sev-attestation-report',
+ 'data': { 'mnonce': 'str' },
+ 'returns': 'SevAttestationReport',
+ 'if': 'TARGET_I386' }
+
+##
# @dump-skeys:
#
# Dump guest's storage keys
@@ -298,43 +338,6 @@
##
-# @SevAttestationReport:
-#
-# The struct describes attestation report for a Secure Encrypted Virtualization
-# feature.
-#
-# @data: guest attestation report (base64 encoded)
-#
-#
-# Since: 6.1
-##
-{ 'struct': 'SevAttestationReport',
- 'data': { 'data': 'str'},
- 'if': 'TARGET_I386' }
-
-##
-# @query-sev-attestation-report:
-#
-# This command is used to get the SEV attestation report, and is supported on AMD
-# X86 platforms only.
-#
-# @mnonce: a random 16 bytes value encoded in base64 (it will be included in report)
-#
-# Returns: SevAttestationReport objects.
-#
-# Since: 6.1
-#
-# Example:
-#
-# -> { "execute" : "query-sev-attestation-report", "arguments": { "mnonce": "aaaaaaa" } }
-# <- { "return" : { "data": "aaaaaaaabbbddddd"} }
-#
-##
-{ 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' },
- 'returns': 'SevAttestationReport',
- 'if': 'TARGET_I386' }
-
-##
# @SGXInfo:
#
# Information about intel Safe Guard eXtension (SGX) support
diff --git a/qapi/qom.json b/qapi/qom.json
index 0222bb4..7231ac3 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -794,7 +794,8 @@
'authz-pam',
'authz-simple',
'can-bus',
- 'can-host-socketcan',
+ { 'name': 'can-host-socketcan',
+ 'if': 'CONFIG_LINUX' },
'colo-compare',
'cryptodev-backend',
'cryptodev-backend-builtin',
@@ -808,21 +809,26 @@
'filter-replay',
'filter-rewriter',
'input-barrier',
- 'input-linux',
+ { 'name': 'input-linux',
+ 'if': 'CONFIG_LINUX' },
'iothread',
+ { 'name': 'memory-backend-epc',
+ 'if': 'CONFIG_LINUX' },
'memory-backend-file',
{ 'name': 'memory-backend-memfd',
'if': 'CONFIG_LINUX' },
'memory-backend-ram',
- 'memory-backend-epc',
'pef-guest',
- 'pr-manager-helper',
+ { 'name': 'pr-manager-helper',
+ 'if': 'CONFIG_LINUX' },
'qtest',
'rng-builtin',
'rng-egd',
- 'rng-random',
+ { 'name': 'rng-random',
+ 'if': 'CONFIG_POSIX' },
'secret',
- 'secret_keyring',
+ { 'name': 'secret_keyring',
+ 'if': 'CONFIG_SECRET_KEYRING' },
'sev-guest',
's390-pv-guest',
'throttle-group',
@@ -853,7 +859,8 @@
'authz-listfile': 'AuthZListFileProperties',
'authz-pam': 'AuthZPAMProperties',
'authz-simple': 'AuthZSimpleProperties',
- 'can-host-socketcan': 'CanHostSocketcanProperties',
+ 'can-host-socketcan': { 'type': 'CanHostSocketcanProperties',
+ 'if': 'CONFIG_LINUX' },
'colo-compare': 'ColoCompareProperties',
'cryptodev-backend': 'CryptodevBackendProperties',
'cryptodev-backend-builtin': 'CryptodevBackendProperties',
@@ -867,20 +874,25 @@
'filter-replay': 'NetfilterProperties',
'filter-rewriter': 'FilterRewriterProperties',
'input-barrier': 'InputBarrierProperties',
- 'input-linux': 'InputLinuxProperties',
+ 'input-linux': { 'type': 'InputLinuxProperties',
+ 'if': 'CONFIG_LINUX' },
'iothread': 'IothreadProperties',
+ 'memory-backend-epc': { 'type': 'MemoryBackendEpcProperties',
+ 'if': 'CONFIG_LINUX' },
'memory-backend-file': 'MemoryBackendFileProperties',
'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties',
'if': 'CONFIG_LINUX' },
'memory-backend-ram': 'MemoryBackendProperties',
- 'memory-backend-epc': 'MemoryBackendEpcProperties',
- 'pr-manager-helper': 'PrManagerHelperProperties',
+ 'pr-manager-helper': { 'type': 'PrManagerHelperProperties',
+ 'if': 'CONFIG_LINUX' },
'qtest': 'QtestProperties',
'rng-builtin': 'RngProperties',
'rng-egd': 'RngEgdProperties',
- 'rng-random': 'RngRandomProperties',
+ 'rng-random': { 'type': 'RngRandomProperties',
+ 'if': 'CONFIG_POSIX' },
'secret': 'SecretProperties',
- 'secret_keyring': 'SecretKeyringProperties',
+ 'secret_keyring': { 'type': 'SecretKeyringProperties',
+ 'if': 'CONFIG_SECRET_KEYRING' },
'sev-guest': 'SevGuestProperties',
'throttle-group': 'ThrottleGroupProperties',
'tls-creds-anon': 'TlsCredsAnonProperties',
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 0705f00..3df99ce 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -836,16 +836,12 @@ void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
static DeviceState *find_device_state(const char *id, Error **errp)
{
Object *obj;
+ DeviceState *dev;
if (id[0] == '/') {
obj = object_resolve_path(id, NULL);
} else {
- char *root_path = object_get_canonical_path(qdev_get_peripheral());
- char *path = g_strdup_printf("%s/%s", root_path, id);
-
- g_free(root_path);
- obj = object_resolve_path_type(path, TYPE_DEVICE, NULL);
- g_free(path);
+ obj = object_resolve_path_component(qdev_get_peripheral(), id);
}
if (!obj) {
@@ -854,12 +850,13 @@ static DeviceState *find_device_state(const char *id, Error **errp)
return NULL;
}
- if (!object_dynamic_cast(obj, TYPE_DEVICE)) {
+ dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
+ if (!dev) {
error_setg(errp, "%s is not a hotpluggable device", id);
return NULL;
}
- return DEVICE(obj);
+ return dev;
}
void qdev_unplug(DeviceState *dev, Error **errp)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index a7b1b6a..fc3ed80 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -26,7 +26,8 @@
#include "sysemu/reset.h"
#include "sysemu/hvf.h"
#include "kvm/kvm_i386.h"
-#include "sev_i386.h"
+#include "sev.h"
+#include "qapi/error.h"
#include "qapi/qapi-visit-machine.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qapi-commands-machine-target.h"
@@ -5763,12 +5764,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*edx = 0;
break;
case 0x8000001F:
- *eax = sev_enabled() ? 0x2 : 0;
- *eax |= sev_es_enabled() ? 0x8 : 0;
- *ebx = sev_get_cbit_position();
- *ebx |= sev_get_reduced_phys_bits() << 6;
- *ecx = 0;
- *edx = 0;
+ *eax = *ebx = *ecx = *edx = 0;
+ if (sev_enabled()) {
+ *eax = 0x2;
+ *eax |= sev_es_enabled() ? 0x8 : 0;
+ *ebx = sev_get_cbit_position();
+ *ebx |= sev_get_reduced_phys_bits() << 6;
+ }
break;
default:
/* reserved values: zero */
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index f25837f..0eb7a03 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -28,7 +28,7 @@
#include "sysemu/kvm_int.h"
#include "sysemu/runstate.h"
#include "kvm_i386.h"
-#include "sev_i386.h"
+#include "sev.h"
#include "hyperv.h"
#include "hyperv-proto.h"
@@ -44,7 +44,6 @@
#include "hw/i386/intel_iommu.h"
#include "hw/i386/x86-iommu.h"
#include "hw/i386/e820_memory_layout.h"
-#include "sysemu/sev.h"
#include "hw/pci/pci.h"
#include "hw/pci/msi.h"
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
index 0a53341..736df8b 100644
--- a/target/i386/kvm/meson.build
+++ b/target/i386/kvm/meson.build
@@ -1,8 +1,14 @@
i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
-i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files(
+i386_softmmu_kvm_ss = ss.source_set()
+
+i386_softmmu_kvm_ss.add(files(
'kvm.c',
'kvm-cpu.c',
))
+i386_softmmu_kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
+
i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
+
+i386_softmmu_ss.add_all(when: 'CONFIG_KVM', if_true: i386_softmmu_kvm_ss)
diff --git a/accel/kvm/sev-stub.c b/target/i386/kvm/sev-stub.c
index 9587d1b..6080c00 100644
--- a/accel/kvm/sev-stub.c
+++ b/target/i386/kvm/sev-stub.c
@@ -13,7 +13,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
-#include "sysemu/sev.h"
+#include "sev.h"
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
{
diff --git a/target/i386/meson.build b/target/i386/meson.build
index dac19ec..ae38dc9 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -6,7 +6,7 @@ i386_ss.add(files(
'xsave_helper.c',
'cpu-dump.c',
))
-i386_ss.add(when: 'CONFIG_SEV', if_true: files('host-cpu.c', 'sev.c'), if_false: files('sev-stub.c'))
+i386_ss.add(when: 'CONFIG_SEV', if_true: files('host-cpu.c'))
# x86 cpu type
i386_ss.add(when: 'CONFIG_KVM', if_true: files('host-cpu.c'))
@@ -20,6 +20,8 @@ i386_softmmu_ss.add(files(
'monitor.c',
'cpu-sysemu.c',
))
+i386_softmmu_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-sysemu-stub.c'))
+
i386_user_ss = ss.source_set()
subdir('kvm')
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 196c1c9..8166e17 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -28,14 +28,12 @@
#include "monitor/hmp-target.h"
#include "monitor/hmp.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qerror.h"
#include "sysemu/kvm.h"
-#include "sysemu/sev.h"
#include "qapi/error.h"
-#include "sev_i386.h"
#include "qapi/qapi-commands-misc-target.h"
#include "qapi/qapi-commands-misc.h"
#include "hw/i386/pc.h"
-#include "hw/i386/sgx.h"
/* Perform linear address sign extension */
static hwaddr addr_canonical(CPUArchState *env, hwaddr addr)
@@ -675,123 +673,3 @@ void hmp_info_io_apic(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "This command is obsolete and will be "
"removed soon. Please use 'info pic' instead.\n");
}
-
-SevInfo *qmp_query_sev(Error **errp)
-{
- SevInfo *info;
-
- info = sev_get_info();
- if (!info) {
- error_setg(errp, "SEV feature is not available");
- return NULL;
- }
-
- return info;
-}
-
-void hmp_info_sev(Monitor *mon, const QDict *qdict)
-{
- SevInfo *info = sev_get_info();
-
- if (info && info->enabled) {
- monitor_printf(mon, "handle: %d\n", info->handle);
- monitor_printf(mon, "state: %s\n", SevState_str(info->state));
- monitor_printf(mon, "build: %d\n", info->build_id);
- monitor_printf(mon, "api version: %d.%d\n",
- info->api_major, info->api_minor);
- monitor_printf(mon, "debug: %s\n",
- info->policy & SEV_POLICY_NODBG ? "off" : "on");
- monitor_printf(mon, "key-sharing: %s\n",
- info->policy & SEV_POLICY_NOKS ? "off" : "on");
- } else {
- monitor_printf(mon, "SEV is not enabled\n");
- }
-
- qapi_free_SevInfo(info);
-}
-
-SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
-{
- char *data;
- SevLaunchMeasureInfo *info;
-
- data = sev_get_launch_measurement();
- if (!data) {
- error_setg(errp, "Measurement is not available");
- return NULL;
- }
-
- info = g_malloc0(sizeof(*info));
- info->data = data;
-
- return info;
-}
-
-SevCapability *qmp_query_sev_capabilities(Error **errp)
-{
- return sev_get_capabilities(errp);
-}
-
-#define SEV_SECRET_GUID "4c2eb361-7d9b-4cc3-8081-127c90d3d294"
-struct sev_secret_area {
- uint32_t base;
- uint32_t size;
-};
-
-void qmp_sev_inject_launch_secret(const char *packet_hdr,
- const char *secret,
- bool has_gpa, uint64_t gpa,
- Error **errp)
-{
- if (!has_gpa) {
- uint8_t *data;
- struct sev_secret_area *area;
-
- if (!pc_system_ovmf_table_find(SEV_SECRET_GUID, &data, NULL)) {
- error_setg(errp, "SEV: no secret area found in OVMF,"
- " gpa must be specified.");
- return;
- }
- area = (struct sev_secret_area *)data;
- gpa = area->base;
- }
-
- sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
-}
-
-SevAttestationReport *
-qmp_query_sev_attestation_report(const char *mnonce, Error **errp)
-{
- return sev_get_attestation_report(mnonce, errp);
-}
-
-SGXInfo *qmp_query_sgx(Error **errp)
-{
- return sgx_get_info(errp);
-}
-
-void hmp_info_sgx(Monitor *mon, const QDict *qdict)
-{
- Error *err = NULL;
- g_autoptr(SGXInfo) info = qmp_query_sgx(&err);
-
- if (err) {
- error_report_err(err);
- return;
- }
- monitor_printf(mon, "SGX support: %s\n",
- info->sgx ? "enabled" : "disabled");
- monitor_printf(mon, "SGX1 support: %s\n",
- info->sgx1 ? "enabled" : "disabled");
- monitor_printf(mon, "SGX2 support: %s\n",
- info->sgx2 ? "enabled" : "disabled");
- monitor_printf(mon, "FLC support: %s\n",
- info->flc ? "enabled" : "disabled");
- monitor_printf(mon, "size: %" PRIu64 "\n",
- info->section_size);
-}
-
-SGXInfo *qmp_query_sgx_capabilities(Error **errp)
-{
- return sgx_get_capabilities(errp);
-}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
deleted file mode 100644
index d8e6583..0000000
--- a/target/i386/sev-stub.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * QEMU SEV stub
- *
- * Copyright Advanced Micro Devices 2018
- *
- * Authors:
- * Brijesh Singh <brijesh.singh@amd.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "sev_i386.h"
-
-SevInfo *sev_get_info(void)
-{
- return NULL;
-}
-
-bool sev_enabled(void)
-{
- return false;
-}
-
-uint64_t sev_get_me_mask(void)
-{
- return ~0;
-}
-
-uint32_t sev_get_cbit_position(void)
-{
- return 0;
-}
-
-uint32_t sev_get_reduced_phys_bits(void)
-{
- return 0;
-}
-
-char *sev_get_launch_measurement(void)
-{
- return NULL;
-}
-
-SevCapability *sev_get_capabilities(Error **errp)
-{
- error_setg(errp, "SEV is not available in this QEMU");
- return NULL;
-}
-
-int sev_inject_launch_secret(const char *hdr, const char *secret,
- uint64_t gpa, Error **errp)
-{
- return 1;
-}
-
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
-{
- return 0;
-}
-
-bool sev_es_enabled(void)
-{
- return false;
-}
-
-void sev_es_set_reset_vector(CPUState *cpu)
-{
-}
-
-int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
-{
- abort();
-}
-
-SevAttestationReport *
-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();
-}
diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c
new file mode 100644
index 0000000..7a29295
--- /dev/null
+++ b/target/i386/sev-sysemu-stub.c
@@ -0,0 +1,70 @@
+/*
+ * QEMU SEV system stub
+ *
+ * Copyright Advanced Micro Devices 2018
+ *
+ * Authors:
+ * Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi/error.h"
+#include "sev.h"
+
+SevInfo *qmp_query_sev(Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+SevCapability *qmp_query_sev_capabilities(Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+void qmp_sev_inject_launch_secret(const char *packet_header, const char *secret,
+ bool has_gpa, uint64_t gpa, Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+}
+
+int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
+{
+ g_assert_not_reached();
+}
+
+void sev_es_set_reset_vector(CPUState *cpu)
+{
+}
+
+int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
+{
+ g_assert_not_reached();
+}
+
+SevAttestationReport *qmp_query_sev_attestation_report(const char *mnonce,
+ Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
+
+void hmp_info_sev(Monitor *mon, const QDict *qdict)
+{
+ monitor_printf(mon, "SEV is not available in this QEMU\n");
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index bcd9260..eede07f 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -25,13 +25,16 @@
#include "qemu/uuid.h"
#include "crypto/hash.h"
#include "sysemu/kvm.h"
-#include "sev_i386.h"
+#include "sev.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "trace.h"
#include "migration/blocker.h"
#include "qom/object.h"
#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "qapi/qapi-commands-misc-target.h"
+#include "qapi/qmp/qerror.h"
#include "exec/confidential-guest-support.h"
#include "hw/i386/pc.h"
@@ -65,7 +68,6 @@ struct SevGuestState {
uint8_t api_major;
uint8_t api_minor;
uint8_t build_id;
- uint64_t me_mask;
int sev_fd;
SevState state;
gchar *measurement;
@@ -389,12 +391,6 @@ sev_es_enabled(void)
return sev_enabled() && (sev_guest->policy & SEV_POLICY_ES);
}
-uint64_t
-sev_get_me_mask(void)
-{
- return sev_guest ? sev_guest->me_mask : ~0;
-}
-
uint32_t
sev_get_cbit_position(void)
{
@@ -407,8 +403,7 @@ sev_get_reduced_phys_bits(void)
return sev_guest ? sev_guest->reduced_phys_bits : 0;
}
-SevInfo *
-sev_get_info(void)
+static SevInfo *sev_get_info(void)
{
SevInfo *info;
@@ -427,6 +422,40 @@ sev_get_info(void)
return info;
}
+SevInfo *qmp_query_sev(Error **errp)
+{
+ SevInfo *info;
+
+ info = sev_get_info();
+ if (!info) {
+ error_setg(errp, "SEV feature is not available");
+ return NULL;
+ }
+
+ return info;
+}
+
+void hmp_info_sev(Monitor *mon, const QDict *qdict)
+{
+ SevInfo *info = sev_get_info();
+
+ if (info && info->enabled) {
+ monitor_printf(mon, "handle: %d\n", info->handle);
+ monitor_printf(mon, "state: %s\n", SevState_str(info->state));
+ monitor_printf(mon, "build: %d\n", info->build_id);
+ monitor_printf(mon, "api version: %d.%d\n",
+ info->api_major, info->api_minor);
+ monitor_printf(mon, "debug: %s\n",
+ info->policy & SEV_POLICY_NODBG ? "off" : "on");
+ monitor_printf(mon, "key-sharing: %s\n",
+ info->policy & SEV_POLICY_NOKS ? "off" : "on");
+ } else {
+ monitor_printf(mon, "SEV is not enabled\n");
+ }
+
+ qapi_free_SevInfo(info);
+}
+
static int
sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
size_t *cert_chain_len, Error **errp)
@@ -440,7 +469,8 @@ sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
if (r < 0) {
if (err != SEV_RET_INVALID_LEN) {
- error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
+ error_setg(errp, "SEV: Failed to export PDH cert"
+ " ret=%d fw_err=%d (%s)",
r, err, fw_error_to_str(err));
return 1;
}
@@ -453,7 +483,7 @@ sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
if (r < 0) {
- error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
+ error_setg(errp, "SEV: Failed to export PDH cert ret=%d fw_err=%d (%s)",
r, err, fw_error_to_str(err));
goto e_free;
}
@@ -470,8 +500,7 @@ e_free:
return 1;
}
-SevCapability *
-sev_get_capabilities(Error **errp)
+static SevCapability *sev_get_capabilities(Error **errp)
{
SevCapability *cap = NULL;
guchar *pdh_data = NULL;
@@ -491,7 +520,7 @@ sev_get_capabilities(Error **errp)
fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
if (fd < 0) {
- error_setg_errno(errp, errno, "Failed to open %s",
+ error_setg_errno(errp, errno, "SEV: Failed to open %s",
DEFAULT_SEV_DEVICE);
return NULL;
}
@@ -521,14 +550,19 @@ out:
return cap;
}
-SevAttestationReport *
-sev_get_attestation_report(const char *mnonce, Error **errp)
+SevCapability *qmp_query_sev_capabilities(Error **errp)
+{
+ return sev_get_capabilities(errp);
+}
+
+static SevAttestationReport *sev_get_attestation_report(const char *mnonce,
+ Error **errp)
{
struct kvm_sev_attestation_report input = {};
SevAttestationReport *report = NULL;
SevGuestState *sev = sev_guest;
- guchar *data;
- guchar *buf;
+ g_autofree guchar *data = NULL;
+ g_autofree guchar *buf = NULL;
gsize len;
int err = 0, ret;
@@ -548,7 +582,6 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
if (len != sizeof(input.mnonce)) {
error_setg(errp, "SEV: mnonce must be %zu bytes (got %" G_GSIZE_FORMAT ")",
sizeof(input.mnonce), len);
- g_free(buf);
return NULL;
}
@@ -557,9 +590,9 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
&input, &err);
if (ret < 0) {
if (err != SEV_RET_INVALID_LEN) {
- error_setg(errp, "failed to query the attestation report length "
- "ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
- g_free(buf);
+ error_setg(errp, "SEV: Failed to query the attestation report"
+ " length ret=%d fw_err=%d (%s)",
+ ret, err, fw_error_to_str(err));
return NULL;
}
}
@@ -572,9 +605,9 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
ret = sev_ioctl(sev->sev_fd, KVM_SEV_GET_ATTESTATION_REPORT,
&input, &err);
if (ret) {
- error_setg_errno(errp, errno, "Failed to get attestation report"
+ error_setg_errno(errp, errno, "SEV: Failed to get attestation report"
" ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
- goto e_free_data;
+ return NULL;
}
report = g_new0(SevAttestationReport, 1);
@@ -582,12 +615,15 @@ sev_get_attestation_report(const char *mnonce, Error **errp)
trace_kvm_sev_attestation_report(mnonce, report->data);
-e_free_data:
- g_free(data);
- g_free(buf);
return report;
}
+SevAttestationReport *qmp_query_sev_attestation_report(const char *mnonce,
+ Error **errp)
+{
+ return sev_get_attestation_report(mnonce, errp);
+}
+
static int
sev_read_file_base64(const char *filename, guchar **data, gsize *len)
{
@@ -596,7 +632,7 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len)
GError *error = NULL;
if (!g_file_get_contents(filename, &base64, &sz, &error)) {
- error_report("failed to read '%s' (%s)", filename, error->message);
+ error_report("SEV: Failed to read '%s' (%s)", filename, error->message);
g_error_free(error);
return -1;
}
@@ -611,31 +647,29 @@ sev_launch_start(SevGuestState *sev)
gsize sz;
int ret = 1;
int fw_error, rc;
- struct kvm_sev_launch_start *start;
+ struct kvm_sev_launch_start start = {
+ .handle = sev->handle, .policy = sev->policy
+ };
guchar *session = NULL, *dh_cert = NULL;
- start = g_new0(struct kvm_sev_launch_start, 1);
-
- start->handle = sev->handle;
- start->policy = sev->policy;
if (sev->session_file) {
if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
goto out;
}
- start->session_uaddr = (unsigned long)session;
- start->session_len = sz;
+ start.session_uaddr = (unsigned long)session;
+ start.session_len = sz;
}
if (sev->dh_cert_file) {
if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
goto out;
}
- start->dh_uaddr = (unsigned long)dh_cert;
- start->dh_len = sz;
+ start.dh_uaddr = (unsigned long)dh_cert;
+ start.dh_len = sz;
}
- trace_kvm_sev_launch_start(start->policy, session, dh_cert);
- rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
+ trace_kvm_sev_launch_start(start.policy, session, dh_cert);
+ rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, &start, &fw_error);
if (rc < 0) {
error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
__func__, ret, fw_error, fw_error_to_str(fw_error));
@@ -643,11 +677,10 @@ sev_launch_start(SevGuestState *sev)
}
sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
- sev->handle = start->handle;
+ sev->handle = start.handle;
ret = 0;
out:
- g_free(start);
g_free(session);
g_free(dh_cert);
return ret;
@@ -695,8 +728,8 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
{
SevGuestState *sev = sev_guest;
int ret, error;
- guchar *data;
- struct kvm_sev_launch_measure *measurement;
+ g_autofree guchar *data = NULL;
+ struct kvm_sev_launch_measure measurement = {};
if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
return;
@@ -710,43 +743,35 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
}
}
- measurement = g_new0(struct kvm_sev_launch_measure, 1);
-
/* query the measurement blob length */
ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
- measurement, &error);
- if (!measurement->len) {
+ &measurement, &error);
+ if (!measurement.len) {
error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
__func__, ret, error, fw_error_to_str(errno));
- goto free_measurement;
+ return;
}
- data = g_new0(guchar, measurement->len);
- measurement->uaddr = (unsigned long)data;
+ data = g_new0(guchar, measurement.len);
+ measurement.uaddr = (unsigned long)data;
/* get the measurement blob */
ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
- measurement, &error);
+ &measurement, &error);
if (ret) {
error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
__func__, ret, error, fw_error_to_str(errno));
- goto free_data;
+ return;
}
sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
/* encode the measurement value and emit the event */
- sev->measurement = g_base64_encode(data, measurement->len);
+ sev->measurement = g_base64_encode(data, measurement.len);
trace_kvm_sev_launch_measurement(sev->measurement);
-
-free_data:
- g_free(data);
-free_measurement:
- g_free(measurement);
}
-char *
-sev_get_launch_measurement(void)
+static char *sev_get_launch_measurement(void)
{
if (sev_guest &&
sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
@@ -756,6 +781,23 @@ sev_get_launch_measurement(void)
return NULL;
}
+SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
+{
+ char *data;
+ SevLaunchMeasureInfo *info;
+
+ data = sev_get_launch_measurement();
+ if (!data) {
+ error_setg(errp, "SEV launch measurement is not available");
+ return NULL;
+ }
+
+ info = g_malloc0(sizeof(*info));
+ info->data = data;
+
+ return info;
+}
+
static Notifier sev_machine_done_notify = {
.notify = sev_launch_get_measure,
};
@@ -831,8 +873,6 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
goto err;
}
- sev->me_mask = ~(1UL << sev->cbitpos);
-
devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
sev->sev_fd = open(devname, O_RDWR);
if (sev->sev_fd < 0) {
@@ -911,7 +951,7 @@ sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
int ret = sev_launch_update_data(sev_guest, ptr, len);
if (ret < 0) {
- error_setg(errp, "failed to encrypt pflash rom");
+ error_setg(errp, "SEV: Failed to encrypt pflash rom");
return ret;
}
}
@@ -930,7 +970,7 @@ int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
MemoryRegion *mr = NULL;
if (!sev_guest) {
- error_setg(errp, "SEV: SEV not enabled.");
+ error_setg(errp, "SEV not enabled for guest");
return 1;
}
@@ -982,6 +1022,37 @@ int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
return 0;
}
+#define SEV_SECRET_GUID "4c2eb361-7d9b-4cc3-8081-127c90d3d294"
+struct sev_secret_area {
+ uint32_t base;
+ uint32_t size;
+};
+
+void qmp_sev_inject_launch_secret(const char *packet_hdr,
+ const char *secret,
+ bool has_gpa, uint64_t gpa,
+ Error **errp)
+{
+ if (!sev_enabled()) {
+ error_setg(errp, "SEV not enabled for guest");
+ return;
+ }
+ if (!has_gpa) {
+ uint8_t *data;
+ struct sev_secret_area *area;
+
+ if (!pc_system_ovmf_table_find(SEV_SECRET_GUID, &data, NULL)) {
+ error_setg(errp, "SEV: no secret area found in OVMF,"
+ " gpa must be specified.");
+ return;
+ }
+ area = (struct sev_secret_area *)data;
+ gpa = area->base;
+ }
+
+ sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
+}
+
static int
sev_es_parse_reset_block(SevInfoBlock *info, uint32_t *addr)
{
diff --git a/target/i386/sev_i386.h b/target/i386/sev.h
index 2afe108..83e82aa 100644
--- a/target/i386/sev_i386.h
+++ b/target/i386/sev.h
@@ -14,12 +14,11 @@
#ifndef QEMU_SEV_I386_H
#define QEMU_SEV_I386_H
-#include "qom/object.h"
-#include "qapi/error.h"
-#include "sysemu/kvm.h"
-#include "sysemu/sev.h"
-#include "qemu/error-report.h"
-#include "qapi/qapi-types-misc-target.h"
+#ifndef CONFIG_USER_ONLY
+#include CONFIG_DEVICES /* CONFIG_SEV */
+#endif
+
+#include "exec/confidential-guest-support.h"
#define SEV_POLICY_NODBG 0x1
#define SEV_POLICY_NOKS 0x2
@@ -39,15 +38,25 @@ typedef struct SevKernelLoaderContext {
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);
+#ifdef CONFIG_SEV
+bool sev_enabled(void);
+bool sev_es_enabled(void);
+#else
+#define sev_enabled() 0
+#define sev_es_enabled() 0
+#endif
+
extern uint32_t sev_get_cbit_position(void);
extern uint32_t sev_get_reduced_phys_bits(void);
-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);
+int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
+int sev_inject_launch_secret(const char *hdr, const char *secret,
+ uint64_t gpa, Error **errp);
+
+int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
+void sev_es_set_reset_vector(CPUState *cpu);
+
+int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
+
#endif
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 7bb8961..8434a33 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -150,13 +150,21 @@ check:
ifeq ($(CONFIG_TOOLS)$(CONFIG_POSIX),yy)
check: check-block
export PYTHON
-check-block: $(SRC_PATH)/tests/check-block.sh qemu-img$(EXESUF) \
- qemu-io$(EXESUF) qemu-nbd$(EXESUF) $(QEMU_IOTESTS_HELPERS-y) \
- $(filter qemu-system-%, $(ninja-targets))
+
+ifneq ($(filter check check-block check-build, $(MAKECMDGOALS)),)
+ninja-cmd-goals += \
+ qemu-img$(EXESUF) \
+ qemu-io$(EXESUF) \
+ qemu-nbd$(EXESUF) \
+ storage-daemon/qemu-storage-daemon$(EXESUF) \
+ $(filter qemu-system-%, $(ninja-targets))
+endif
+
+check-block: $(SRC_PATH)/tests/check-block.sh run-ninja
@$<
endif
-check-build: $(QEMU_IOTESTS_HELPERS-y)
+check-build: run-ninja
check-clean:
rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR)
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
index a56b6da..0e29c2f 100644
--- a/tests/qemu-iotests/testrunner.py
+++ b/tests/qemu-iotests/testrunner.py
@@ -341,6 +341,7 @@ class TestRunner(ContextManager['TestRunner']):
elif res.status == 'not run':
notrun.append(name)
+ sys.stdout.flush()
if res.interrupted:
break
diff --git a/tests/tcg/x86_64/system/kernel.ld b/tests/tcg/x86_64/system/kernel.ld
index 49c12b04..ca5d6bd 100644
--- a/tests/tcg/x86_64/system/kernel.ld
+++ b/tests/tcg/x86_64/system/kernel.ld
@@ -16,7 +16,10 @@ SECTIONS {
*(.rodata)
} :text
- /* Keep build ID and PVH notes in same section */
+ /DISCARD/ : {
+ *(.note.gnu*)
+ }
+
.notes : {
*(.note.*)
} :note
diff --git a/util/compatfd.c b/util/compatfd.c
index a8ec525..ab810c4 100644
--- a/util/compatfd.c
+++ b/util/compatfd.c
@@ -17,7 +17,7 @@
#include "qemu/thread.h"
#if defined(CONFIG_SIGNALFD)
-#include <sys/syscall.h>
+#include <sys/signalfd.h>
#endif
struct sigfd_compat_info {
@@ -96,9 +96,8 @@ int qemu_signalfd(const sigset_t *mask)
#if defined(CONFIG_SIGNALFD)
int ret;
- ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
+ ret = signalfd(-1, mask, SFD_CLOEXEC);
if (ret != -1) {
- qemu_set_cloexec(ret);
return ret;
}
#endif