You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
4.6 KiB
147 lines
4.6 KiB
2 months ago
|
From 6bb738fb90a3a1221ae35596b3d03a17e0b1c34d Mon Sep 17 00:00:00 2001
|
||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
Date: Tue, 19 Mar 2024 15:30:25 +0100
|
||
|
Subject: [PATCH 023/100] target/i386: SEV: use KVM_SEV_INIT2 if possible
|
||
|
|
||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
RH-MergeRequest: 245: SEV-SNP support
|
||
|
RH-Jira: RHEL-39544
|
||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||
|
RH-Commit: [23/91] 9579d772ae5124a94c6b1e3a4566bf3470d2bc8f (bonzini/rhel-qemu-kvm)
|
||
|
|
||
|
Implement support for the KVM_X86_SEV_VM and KVM_X86_SEV_ES_VM virtual
|
||
|
machine types, and the KVM_SEV_INIT2 function of KVM_MEMORY_ENCRYPT_OP.
|
||
|
|
||
|
These replace the KVM_SEV_INIT and KVM_SEV_ES_INIT functions, and have
|
||
|
several advantages:
|
||
|
|
||
|
- sharing the initialization sequence with SEV-SNP and TDX
|
||
|
|
||
|
- allowing arguments including the set of desired VMSA features
|
||
|
|
||
|
- protection against invalid use of KVM_GET/SET_* ioctls for guests
|
||
|
with encrypted state
|
||
|
|
||
|
If the KVM_X86_SEV_VM and KVM_X86_SEV_ES_VM types are not supported,
|
||
|
fall back to KVM_SEV_INIT and KVM_SEV_ES_INIT (which use the
|
||
|
default x86 VM type).
|
||
|
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
(cherry picked from commit 663e2f443e5722370708ce2f4c27d94a2087d2d3)
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
---
|
||
|
target/i386/kvm/kvm.c | 2 ++
|
||
|
target/i386/sev.c | 41 +++++++++++++++++++++++++++++++++++++----
|
||
|
2 files changed, 39 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||
|
index 1f0ab12c2e..408568d053 100644
|
||
|
--- a/target/i386/kvm/kvm.c
|
||
|
+++ b/target/i386/kvm/kvm.c
|
||
|
@@ -164,6 +164,8 @@ static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value);
|
||
|
|
||
|
static const char *vm_type_name[] = {
|
||
|
[KVM_X86_DEFAULT_VM] = "default",
|
||
|
+ [KVM_X86_SEV_VM] = "SEV",
|
||
|
+ [KVM_X86_SEV_ES_VM] = "SEV-ES",
|
||
|
};
|
||
|
|
||
|
bool kvm_is_vm_type_supported(int type)
|
||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||
|
index ebe36d4c10..9dab4060b8 100644
|
||
|
--- a/target/i386/sev.c
|
||
|
+++ b/target/i386/sev.c
|
||
|
@@ -26,6 +26,7 @@
|
||
|
#include "qemu/error-report.h"
|
||
|
#include "crypto/hash.h"
|
||
|
#include "sysemu/kvm.h"
|
||
|
+#include "kvm/kvm_i386.h"
|
||
|
#include "sev.h"
|
||
|
#include "sysemu/sysemu.h"
|
||
|
#include "sysemu/runstate.h"
|
||
|
@@ -56,6 +57,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
|
||
|
struct SevGuestState {
|
||
|
X86ConfidentialGuest parent_obj;
|
||
|
|
||
|
+ int kvm_type;
|
||
|
+
|
||
|
/* configuration parameters */
|
||
|
char *sev_device;
|
||
|
uint32_t policy;
|
||
|
@@ -850,6 +853,26 @@ sev_vm_state_change(void *opaque, bool running, RunState state)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||
|
+{
|
||
|
+ SevGuestState *sev = SEV_GUEST(cg);
|
||
|
+ int kvm_type;
|
||
|
+
|
||
|
+ if (sev->kvm_type != -1) {
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ kvm_type = (sev->policy & SEV_POLICY_ES) ? KVM_X86_SEV_ES_VM : KVM_X86_SEV_VM;
|
||
|
+ if (kvm_is_vm_type_supported(kvm_type)) {
|
||
|
+ sev->kvm_type = kvm_type;
|
||
|
+ } else {
|
||
|
+ sev->kvm_type = KVM_X86_DEFAULT_VM;
|
||
|
+ }
|
||
|
+
|
||
|
+out:
|
||
|
+ return sev->kvm_type;
|
||
|
+}
|
||
|
+
|
||
|
static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||
|
{
|
||
|
SevGuestState *sev = SEV_GUEST(cgs);
|
||
|
@@ -929,13 +952,19 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||
|
__func__);
|
||
|
goto err;
|
||
|
}
|
||
|
- cmd = KVM_SEV_ES_INIT;
|
||
|
- } else {
|
||
|
- cmd = KVM_SEV_INIT;
|
||
|
}
|
||
|
|
||
|
trace_kvm_sev_init();
|
||
|
- ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
|
||
|
+ if (sev_kvm_type(X86_CONFIDENTIAL_GUEST(sev)) == KVM_X86_DEFAULT_VM) {
|
||
|
+ cmd = sev_es_enabled() ? KVM_SEV_ES_INIT : KVM_SEV_INIT;
|
||
|
+
|
||
|
+ ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
|
||
|
+ } else {
|
||
|
+ struct kvm_sev_init args = { 0 };
|
||
|
+
|
||
|
+ ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT2, &args, &fw_error);
|
||
|
+ }
|
||
|
+
|
||
|
if (ret) {
|
||
|
error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
|
||
|
__func__, ret, fw_error, fw_error_to_str(fw_error));
|
||
|
@@ -1327,8 +1356,10 @@ static void
|
||
|
sev_guest_class_init(ObjectClass *oc, void *data)
|
||
|
{
|
||
|
ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
|
||
|
+ X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||
|
|
||
|
klass->kvm_init = sev_kvm_init;
|
||
|
+ x86_klass->kvm_type = sev_kvm_type;
|
||
|
|
||
|
object_class_property_add_str(oc, "sev-device",
|
||
|
sev_guest_get_sev_device,
|
||
|
@@ -1357,6 +1388,8 @@ sev_guest_instance_init(Object *obj)
|
||
|
{
|
||
|
SevGuestState *sev = SEV_GUEST(obj);
|
||
|
|
||
|
+ sev->kvm_type = -1;
|
||
|
+
|
||
|
sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
|
||
|
sev->policy = DEFAULT_GUEST_POLICY;
|
||
|
object_property_add_uint32_ptr(obj, "policy", &sev->policy,
|
||
|
--
|
||
|
2.39.3
|
||
|
|