* 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)
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmFmnTwUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroMdTQf+NnPH/6JGYWCm+bx+60qACgEAeLJx
 bcMoBIRjZqSat0wvXdLltHr19OtwkxfwK2Qgxl7nYwa6N09bXUuC4YByHZcd5/5t
 0cnCjp2+8Np0JIbMStSf1AarOhaACQQEEb334DQcgwBHMY80ZsR7ejlbU6jCk+nN
 7vRqHYIKsEW+bNdKnlo2N2dw4Sj9SkvYME8OIEx38+MMU/EEzXhlQ1hPvan74Ck7
 6b/XbZ9JmuEGXCUhBWF4jfWZHebBXgDgnj2tsP6Xgdk7X5KEPoBYPEC6bFC6LAyU
 vrWVrgFm7GEjwDJBUgfJTpbJGDrchIA8RRGmKwitLtUNCIH4hCBxbjvTzQ==
 =Vp1C
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Richard Henderson 2021-10-13 06:56:45 -07:00
commit 946de55835
31 changed files with 392 additions and 619 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -229,6 +229,46 @@
'data': { 'packet-header': 'str', 'secret': 'str', '*gpa': 'uint64' },
'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:
#
@ -297,43 +337,6 @@
'if': 'TARGET_ARM' }
##
# @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:
#

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -341,6 +341,7 @@ class TestRunner(ContextManager['TestRunner']):
elif res.status == 'not run':
notrun.append(name)
sys.stdout.flush()
if res.interrupted:
break

View File

@ -16,7 +16,10 @@ SECTIONS {
*(.rodata)
} :text
/* Keep build ID and PVH notes in same section */
/DISCARD/ : {
*(.note.gnu*)
}
.notes : {
*(.note.*)
} :note

View File

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