Skip to content

Commit

Permalink
target/i386: SEV: use KVM_SEV_INIT2 if possible
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bonzini committed Apr 23, 2024
1 parent ee88612 commit 663e2f4
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
2 changes: 2 additions & 0 deletions target/i386/kvm/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
41 changes: 37 additions & 4 deletions target/i386/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 663e2f4

Please sign in to comment.