To mirror SEV-ES VMs the mirror VM needs to call LAUNCH_UPDATE_VMSA
before the original VM runs LAUNCH_FINISH. This allows the mirror's
vCPUs to be encrypted into the SEV-ES guests context and measured into
the launch digest.
Peter Gonda (2):
KVM: SEV: Update svm_vm_copy_asid_from for SEV-ES
KVM: SEV: Allow launch vmsa from mirror VM
arch/x86/kvm/svm/sev.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
Cc: Marc Orr <[email protected]>
Cc: Nathan Tempelman <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Sean Christopherson <[email protected]>
Cc: Steve Rutherford <[email protected]>
Cc: Brijesh Singh <[email protected]>
Cc: [email protected]
Cc: [email protected]
--
2.33.0.464.g1972c5931b-goog
For mirroring SEV-ES the mirror VM will need more then just the ASID.
The FD and the handle are required to all the mirror to call psp
commands. The mirror VM will need to call KVM_SEV_LAUNCH_UPDATE_VMSA to
setup its vCPUs' VMSAs for SEV-ES.
Signed-off-by: Peter Gonda <[email protected]>
Cc: Marc Orr <[email protected]>
Cc: Nathan Tempelman <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Sean Christopherson <[email protected]>
Cc: Steve Rutherford <[email protected]>
Cc: Brijesh Singh <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
arch/x86/kvm/svm/sev.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 75e0b21ad07c..08c53a4e060e 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1715,8 +1715,7 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
{
struct file *source_kvm_file;
struct kvm *source_kvm;
- struct kvm_sev_info *mirror_sev;
- unsigned int asid;
+ struct kvm_sev_info source_sev, *mirror_sev;
int ret;
source_kvm_file = fget(source_fd);
@@ -1739,7 +1738,8 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
goto e_source_unlock;
}
- asid = to_kvm_svm(source_kvm)->sev_info.asid;
+ memcpy(&source_sev, &to_kvm_svm(source_kvm)->sev_info,
+ sizeof(source_sev));
/*
* The mirror kvm holds an enc_context_owner ref so its asid can't
@@ -1759,8 +1759,16 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
/* Set enc_context_owner and copy its encryption context over */
mirror_sev = &to_kvm_svm(kvm)->sev_info;
mirror_sev->enc_context_owner = source_kvm;
- mirror_sev->asid = asid;
mirror_sev->active = true;
+ mirror_sev->asid = source_sev.asid;
+ mirror_sev->fd = source_sev.fd;
+ mirror_sev->es_active = source_sev.es_active;
+ mirror_sev->handle = source_sev.handle;
+ /*
+ * Do not copy ap_jump_table. Since the mirror does not share the same
+ * KVM contexts as the original, and they may have different
+ * memory-views.
+ */
mutex_unlock(&kvm->lock);
return 0;
--
2.33.0.464.g1972c5931b-goog
A mirrored SEV-ES VM will need to call KVM_SEV_LAUNCH_UPDATE_VMSA to
setup its vCPUs and add them to the SEV-ES VM. Since they need to be
measured and their VMSAs encrypted. Also allow the guest status check
and debugging commands since they do not change any guest state.
Signed-off-by: Peter Gonda <[email protected]>
Cc: Marc Orr <[email protected]>
Cc: Nathan Tempelman <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Sean Christopherson <[email protected]>
Cc: Steve Rutherford <[email protected]>
Cc: Brijesh Singh <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
arch/x86/kvm/svm/sev.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 08c53a4e060e..9cb6e30d6ae4 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1501,6 +1501,20 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
return sev_issue_cmd(kvm, SEV_CMD_RECEIVE_FINISH, &data, &argp->error);
}
+static bool cmd_allowed_from_miror(u32 cmd_id)
+{
+ /*
+ * Allow mirrors VM to call KVM_SEV_LAUNCH_UPDATE_VMSA to enable SEV-ES
+ * active mirror VMs. Also allow the debugging and status commands.
+ */
+ if (cmd_id == KVM_SEV_LAUNCH_UPDATE_VMSA ||
+ cmd_id == KVM_SEV_GUEST_STATUS || cmd_id == KVM_SEV_DBG_DECRYPT ||
+ cmd_id == KVM_SEV_DBG_ENCRYPT)
+ return true;
+
+ return false;
+}
+
int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
{
struct kvm_sev_cmd sev_cmd;
@@ -1517,8 +1531,9 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
mutex_lock(&kvm->lock);
- /* enc_context_owner handles all memory enc operations */
- if (is_mirroring_enc_context(kvm)) {
+ /* Only the enc_context_owner handles some memory enc operations. */
+ if (is_mirroring_enc_context(kvm) &&
+ !cmd_allowed_from_miror(sev_cmd.id)) {
r = -EINVAL;
goto out;
}
--
2.33.0.464.g1972c5931b-goog
On Tue, Sep 21, 2021 at 8:03 AM Peter Gonda <[email protected]> wrote:
>
> For mirroring SEV-ES the mirror VM will need more then just the ASID.
> The FD and the handle are required to all the mirror to call psp
> commands. The mirror VM will need to call KVM_SEV_LAUNCH_UPDATE_VMSA to
> setup its vCPUs' VMSAs for SEV-ES.
>
> Signed-off-by: Peter Gonda <[email protected]>
> Cc: Marc Orr <[email protected]>
> Cc: Nathan Tempelman <[email protected]>
> Cc: Paolo Bonzini <[email protected]>
> Cc: Sean Christopherson <[email protected]>
> Cc: Steve Rutherford <[email protected]>
> Cc: Brijesh Singh <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
> arch/x86/kvm/svm/sev.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 75e0b21ad07c..08c53a4e060e 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -1715,8 +1715,7 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
> {
> struct file *source_kvm_file;
> struct kvm *source_kvm;
> - struct kvm_sev_info *mirror_sev;
> - unsigned int asid;
> + struct kvm_sev_info source_sev, *mirror_sev;
> int ret;
>
> source_kvm_file = fget(source_fd);
> @@ -1739,7 +1738,8 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
> goto e_source_unlock;
> }
>
> - asid = to_kvm_svm(source_kvm)->sev_info.asid;
> + memcpy(&source_sev, &to_kvm_svm(source_kvm)->sev_info,
> + sizeof(source_sev));
>
> /*
> * The mirror kvm holds an enc_context_owner ref so its asid can't
> @@ -1759,8 +1759,16 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
> /* Set enc_context_owner and copy its encryption context over */
> mirror_sev = &to_kvm_svm(kvm)->sev_info;
> mirror_sev->enc_context_owner = source_kvm;
> - mirror_sev->asid = asid;
> mirror_sev->active = true;
> + mirror_sev->asid = source_sev.asid;
> + mirror_sev->fd = source_sev.fd;
> + mirror_sev->es_active = source_sev.es_active;
> + mirror_sev->handle = source_sev.handle;
> + /*
> + * Do not copy ap_jump_table. Since the mirror does not share the same
> + * KVM contexts as the original, and they may have different
> + * memory-views.
> + */
>
> mutex_unlock(&kvm->lock);
> return 0;
> --
> 2.33.0.464.g1972c5931b-goog
>
Looks good. Thanks for doing this Peter.
Reviewed-by: Nathan Tempelman <[email protected]>