mirror of https://gitee.com/openkylin/qemu.git
Machine queue, 2020-12-10
Some patches that were queued after 5.2 soft freeze. -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEWjIv1avE09usz9GqKAeTb5hNxaYFAl/SpBkUHGVoYWJrb3N0 QHJlZGhhdC5jb20ACgkQKAeTb5hNxaZIkA/9FtOaj1YXC+3ReLuWwNBCzt7vdh0D 4vDb7EmJ1bTV6G+84BFX8Vnmq7MT6z3m3eJldhDDRSK5vMmUdyCWKcI6krBavNEG rfRVkQNiVVoiK/isXmegvVcmiq6T7bXK/WiTzxV5WwnngkgXArhjQ4itY1UwGAq/ IWXsJjIBSL6KsOzNZnGcYrZCespO6CFqx/w5L5sQo5XsNfZfM7fMx6w0+V1sa7c+ BX3GSmOO3BjdaY2K2lSq6v/jXOHxHIcrHugUm9Z6q8O1JCenmsFTjxnJhwvNraRF RcTcpR/sjFz8QafQJzd8hN86CcRhwnxz8V4lxvnV/EB69V/mU5CKAmQxgB9v8uWt mnx5JI8VHYE71zSY8YTGXIbRrHcoKxlyY2xkYE3TjnN8T0DiBGRRqhadyMNAlp8d Y6EggvuT0g4ciVf6yjBlGhHdiLUFAT5ZbayKCGnDqjXsF6ogTTiJOPe0Wymf4hYf fUFcQXWrfx5qiDCdGhvRgd8vmJ+Y1jsJtd7JtpwvfPN4tGlVoSA1EiRiBOmlmv99 XYVqL3kxbuMR2UgaXSzO1o6ryFNu1qUqwZyr96LEzag3ycTMOkBOyxfV09HyEBs0 crgvsVq4+BHHxS6G2EiYguK1VAEYvTfvRRyrObFgefAPU9lv6l4wwMTgw2Eouhc6 QSDGxjIwoR3+NbE= =oIwH -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging Machine queue, 2020-12-10 Some patches that were queued after 5.2 soft freeze. # gpg: Signature made Thu 10 Dec 2020 22:41:29 GMT # gpg: using RSA key 5A322FD5ABC4D3DBACCFD1AA2807936F984DC5A6 # gpg: issuer "ehabkost@redhat.com" # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full] # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/machine-next-pull-request: i386/cpu: Make the Intel PT LIP feature configurable sev: add sev-inject-launch-secret qom: code hardening - have bound checking while looping with integer value Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
33744604d7
|
@ -4,6 +4,7 @@
|
|||
#include "block/block.h"
|
||||
#include "qapi/qapi-types-misc.h"
|
||||
#include "qemu/readline.h"
|
||||
#include "include/exec/hwaddr.h"
|
||||
|
||||
typedef struct MonitorHMP MonitorHMP;
|
||||
typedef struct MonitorOptions MonitorOptions;
|
||||
|
@ -37,6 +38,8 @@ void monitor_flush(Monitor *mon);
|
|||
int monitor_set_cpu(Monitor *mon, int cpu_index);
|
||||
int monitor_get_cpu_index(Monitor *mon);
|
||||
|
||||
void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
|
||||
|
||||
void monitor_read_command(MonitorHMP *mon, int show_prompt);
|
||||
int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func,
|
||||
void *opaque);
|
||||
|
|
|
@ -18,4 +18,6 @@
|
|||
|
||||
void *sev_guest_init(const char *id);
|
||||
int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
|
||||
int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||
uint64_t gpa, Error **errp);
|
||||
#endif
|
||||
|
|
|
@ -667,10 +667,11 @@ static void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
|
|||
memory_dump(mon, count, format, size, addr, 1);
|
||||
}
|
||||
|
||||
static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
|
||||
void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
|
||||
{
|
||||
Int128 gpa_region_size;
|
||||
MemoryRegionSection mrs = memory_region_find(get_system_memory(),
|
||||
addr, 1);
|
||||
addr, size);
|
||||
|
||||
if (!mrs.mr) {
|
||||
error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
|
||||
|
@ -683,6 +684,14 @@ static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gpa_region_size = int128_make64(size);
|
||||
if (int128_lt(mrs.size, gpa_region_size)) {
|
||||
error_setg(errp, "Size of memory region at 0x%" HWADDR_PRIx
|
||||
" exceeded.", addr);
|
||||
memory_region_unref(mrs.mr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p_mr = mrs.mr;
|
||||
return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
|
||||
}
|
||||
|
@ -694,7 +703,7 @@ static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
|
|||
MemoryRegion *mr = NULL;
|
||||
void *ptr;
|
||||
|
||||
ptr = gpa2hva(&mr, addr, &local_err);
|
||||
ptr = gpa2hva(&mr, addr, 1, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
|
@ -770,7 +779,7 @@ static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
|
|||
void *ptr;
|
||||
uint64_t physaddr;
|
||||
|
||||
ptr = gpa2hva(&mr, addr, &local_err);
|
||||
ptr = gpa2hva(&mr, addr, 1, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
|
|
|
@ -201,6 +201,24 @@
|
|||
{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
|
||||
##
|
||||
# @sev-inject-launch-secret:
|
||||
#
|
||||
# This command injects a secret blob into memory of SEV guest.
|
||||
#
|
||||
# @packet-header: the launch secret packet header encoded in base64
|
||||
#
|
||||
# @secret: the launch secret data to be injected encoded in base64
|
||||
#
|
||||
# @gpa: the guest physical address where secret will be injected.
|
||||
#
|
||||
# Since: 6.0
|
||||
#
|
||||
##
|
||||
{ 'command': 'sev-inject-launch-secret',
|
||||
'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' },
|
||||
'if': 'defined(TARGET_I386)' }
|
||||
|
||||
##
|
||||
# @dump-skeys:
|
||||
#
|
||||
|
|
|
@ -1196,11 +1196,11 @@ object_property_try_add(Object *obj, const char *name, const char *type,
|
|||
|
||||
if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
|
||||
int i;
|
||||
ObjectProperty *ret;
|
||||
ObjectProperty *ret = NULL;
|
||||
char *name_no_array = g_strdup(name);
|
||||
|
||||
name_no_array[name_len - 3] = '\0';
|
||||
for (i = 0; ; ++i) {
|
||||
for (i = 0; i < INT16_MAX; ++i) {
|
||||
char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
|
||||
|
||||
ret = object_property_try_add(obj, full_name, type, get, set,
|
||||
|
@ -1211,6 +1211,7 @@ object_property_try_add(Object *obj, const char *name, const char *type,
|
|||
}
|
||||
}
|
||||
g_free(name_no_array);
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -672,6 +672,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
|
|||
#define TCG_XSAVE_FEATURES (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1)
|
||||
/* missing:
|
||||
CPUID_XSAVE_XSAVEC, CPUID_XSAVE_XSAVES */
|
||||
#define TCG_14_0_ECX_FEATURES 0
|
||||
|
||||
typedef enum FeatureWordType {
|
||||
CPUID_FEATURE_WORD,
|
||||
|
@ -1301,6 +1302,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|||
}
|
||||
},
|
||||
|
||||
[FEAT_14_0_ECX] = {
|
||||
.type = CPUID_FEATURE_WORD,
|
||||
.feat_names = {
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, "intel-pt-lip",
|
||||
},
|
||||
.cpuid = {
|
||||
.eax = 0x14,
|
||||
.needs_ecx = true, .ecx = 0,
|
||||
.reg = R_ECX,
|
||||
},
|
||||
.tcg_features = TCG_14_0_ECX_FEATURES,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
typedef struct FeatureMask {
|
||||
|
@ -1373,6 +1394,10 @@ static FeatureDep feature_dependencies[] = {
|
|||
.from = { FEAT_7_0_EBX, CPUID_7_0_EBX_RDSEED },
|
||||
.to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDSEED_EXITING },
|
||||
},
|
||||
{
|
||||
.from = { FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT },
|
||||
.to = { FEAT_14_0_ECX, ~0ull },
|
||||
},
|
||||
{
|
||||
.from = { FEAT_8000_0001_EDX, CPUID_EXT2_RDTSCP },
|
||||
.to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDTSCP },
|
||||
|
@ -5752,6 +5777,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||
*eax = INTEL_PT_MAX_SUBLEAF;
|
||||
*ebx = INTEL_PT_MINIMAL_EBX;
|
||||
*ecx = INTEL_PT_MINIMAL_ECX;
|
||||
if (env->features[FEAT_14_0_ECX] & CPUID_14_0_ECX_LIP) {
|
||||
*ecx |= CPUID_14_0_ECX_LIP;
|
||||
}
|
||||
} else if (count == 1) {
|
||||
*eax = INTEL_PT_MTC_BITMAP | INTEL_PT_ADDR_RANGES_NUM;
|
||||
*ebx = INTEL_PT_PSB_BITMAP | INTEL_PT_CYCLE_BITMAP;
|
||||
|
@ -6498,7 +6526,8 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose)
|
|||
INTEL_PT_ADDR_RANGES_NUM) ||
|
||||
((ebx_1 & (INTEL_PT_PSB_BITMAP | INTEL_PT_CYCLE_BITMAP)) !=
|
||||
(INTEL_PT_PSB_BITMAP | INTEL_PT_CYCLE_BITMAP)) ||
|
||||
(ecx_0 & INTEL_PT_IP_LIP)) {
|
||||
((ecx_0 & CPUID_14_0_ECX_LIP) !=
|
||||
(env->features[FEAT_14_0_ECX] & CPUID_14_0_ECX_LIP))) {
|
||||
/*
|
||||
* Processor Trace capabilities aren't configurable, so if the
|
||||
* host can't emulate the capabilities we report on
|
||||
|
|
|
@ -541,6 +541,7 @@ typedef enum FeatureWord {
|
|||
FEAT_VMX_EPT_VPID_CAPS,
|
||||
FEAT_VMX_BASIC,
|
||||
FEAT_VMX_VMFUNC,
|
||||
FEAT_14_0_ECX,
|
||||
FEATURE_WORDS,
|
||||
} FeatureWord;
|
||||
|
||||
|
@ -797,6 +798,9 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
|||
/* AVX512 BFloat16 Instruction */
|
||||
#define CPUID_7_1_EAX_AVX512_BF16 (1U << 5)
|
||||
|
||||
/* Packets which contain IP payload have LIP values */
|
||||
#define CPUID_14_0_ECX_LIP (1U << 31)
|
||||
|
||||
/* CLZERO instruction */
|
||||
#define CPUID_8000_0008_EBX_CLZERO (1U << 0)
|
||||
/* Always save/restore FP error pointers */
|
||||
|
|
|
@ -729,3 +729,10 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
|
|||
{
|
||||
return sev_get_capabilities(errp);
|
||||
}
|
||||
|
||||
void qmp_sev_inject_launch_secret(const char *packet_hdr,
|
||||
const char *secret, uint64_t gpa,
|
||||
Error **errp)
|
||||
{
|
||||
sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
|
||||
}
|
||||
|
|
|
@ -49,3 +49,8 @@ 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;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "trace.h"
|
||||
#include "migration/blocker.h"
|
||||
#include "qom/object.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
#define TYPE_SEV_GUEST "sev-guest"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
|
||||
|
@ -785,6 +787,69 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
|
||||
uint64_t gpa, Error **errp)
|
||||
{
|
||||
struct kvm_sev_launch_secret input;
|
||||
g_autofree guchar *data = NULL, *hdr = NULL;
|
||||
int error, ret = 1;
|
||||
void *hva;
|
||||
gsize hdr_sz = 0, data_sz = 0;
|
||||
MemoryRegion *mr = NULL;
|
||||
|
||||
if (!sev_guest) {
|
||||
error_setg(errp, "SEV: SEV not enabled.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* secret can be injected only in this state */
|
||||
if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
|
||||
error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
|
||||
sev_guest->state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hdr = g_base64_decode(packet_hdr, &hdr_sz);
|
||||
if (!hdr || !hdr_sz) {
|
||||
error_setg(errp, "SEV: Failed to decode sequence header");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data = g_base64_decode(secret, &data_sz);
|
||||
if (!data || !data_sz) {
|
||||
error_setg(errp, "SEV: Failed to decode data");
|
||||
return 1;
|
||||
}
|
||||
|
||||
hva = gpa2hva(&mr, gpa, data_sz, errp);
|
||||
if (!hva) {
|
||||
error_prepend(errp, "SEV: Failed to calculate guest address: ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
|
||||
input.hdr_len = hdr_sz;
|
||||
|
||||
input.trans_uaddr = (uint64_t)(unsigned long)data;
|
||||
input.trans_len = data_sz;
|
||||
|
||||
input.guest_uaddr = (uint64_t)(unsigned long)hva;
|
||||
input.guest_len = data_sz;
|
||||
|
||||
trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
|
||||
input.trans_uaddr, input.trans_len);
|
||||
|
||||
ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
|
||||
&input, &error);
|
||||
if (ret) {
|
||||
error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
|
||||
ret, error, fw_error_to_str(error));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sev_register_types(void)
|
||||
{
|
||||
|
|
|
@ -15,3 +15,4 @@ kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session
|
|||
kvm_sev_launch_update_data(void *addr, uint64_t len) "addr %p len 0x%" PRIu64
|
||||
kvm_sev_launch_measurement(const char *value) "data %s"
|
||||
kvm_sev_launch_finish(void) ""
|
||||
kvm_sev_launch_secret(uint64_t hpa, uint64_t hva, uint64_t secret, int len) "hpa 0x%" PRIx64 " hva 0x%" PRIx64 " data 0x%" PRIx64 " len %d"
|
||||
|
|
Loading…
Reference in New Issue