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:
Peter Maydell 2020-12-11 12:16:33 +00:00
commit 33744604d7
11 changed files with 151 additions and 7 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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