summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/i386/cpu.c31
-rw-r--r--target/i386/cpu.h4
-rw-r--r--target/i386/monitor.c7
-rw-r--r--target/i386/sev-stub.c5
-rw-r--r--target/i386/sev.c65
-rw-r--r--target/i386/trace-events1
6 files changed, 112 insertions, 1 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index af48e3f79e..6c11feeb92 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -673,6 +673,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,
@@ -1302,6 +1303,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 {
@@ -1375,6 +1396,10 @@ static FeatureDep feature_dependencies[] = {
.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 },
},
@@ -5756,6 +5781,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;
@@ -6504,7 +6532,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
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 88e8586f8f..c4a49c06a8 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -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 */
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 9f9e1c42f4..1bc91442b1 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -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);
+}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
index 88e3f39a1e..c1fecc2101 100644
--- a/target/i386/sev-stub.c
+++ b/target/i386/sev-stub.c
@@ -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;
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 93c4d60b82..1546606811 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -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)
{
diff --git a/target/i386/trace-events b/target/i386/trace-events
index 789c700d4a..9f299e94a2 100644
--- a/target/i386/trace-events
+++ b/target/i386/trace-events
@@ -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"