LKML Archive mirror
 help / color / mirror / Atom feed
From: Ashish Kalra <Ashish.Kalra@amd.com>
To: pbonzini@redhat.com
Cc: tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com,
	joro@8bytes.org, bp@suse.de, thomas.lendacky@amd.com,
	x86@kernel.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org, srutherford@google.com,
	seanjc@google.com, venu.busireddy@oracle.com,
	brijesh.singh@amd.com, will@kernel.org, maz@kernel.org,
	qperret@google.com
Subject: [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall
Date: Mon,  5 Apr 2021 14:28:32 +0000	[thread overview]
Message-ID: <4da0d40c309a21ba3952d06f346b6411930729c9.1617302792.git.ashish.kalra@amd.com> (raw)
In-Reply-To: <cover.1617302792.git.ashish.kalra@amd.com>

From: Ashish Kalra <ashish.kalra@amd.com>

This hypercall is used by the SEV guest to notify a change in the page
encryption status to the hypervisor. The hypercall should be invoked
only when the encryption attribute is changed from encrypted -> decrypted
and vice versa. By default all guest pages are considered encrypted.

The hypercall exits to userspace to manage the guest shared regions and
integrate with the userspace VMM's migration code.

The patch integrates and extends DMA_SHARE/UNSHARE hypercall to
userspace exit functionality (arm64-specific) patch from Marc Zyngier,
to avoid arch-specific stuff and have a common interface
from the guest back to the VMM and sharing of the host handling of the
hypercall to support use case for a guest to share memory with a host.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: x86@kernel.org
Cc: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 Documentation/virt/kvm/api.rst        | 18 ++++++++
 Documentation/virt/kvm/hypercalls.rst | 15 +++++++
 arch/x86/include/asm/kvm_host.h       |  2 +
 arch/x86/kvm/svm/sev.c                | 61 +++++++++++++++++++++++++++
 arch/x86/kvm/svm/svm.c                |  2 +
 arch/x86/kvm/svm/svm.h                |  2 +
 arch/x86/kvm/vmx/vmx.c                |  1 +
 arch/x86/kvm/x86.c                    | 12 ++++++
 include/uapi/linux/kvm.h              |  8 ++++
 include/uapi/linux/kvm_para.h         |  1 +
 10 files changed, 122 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 307f2fcf1b02..52bd7e475fd6 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5475,6 +5475,24 @@ Valid values for 'type' are:
     Userspace is expected to place the hypercall result into the appropriate
     field before invoking KVM_RUN again.
 
+::
+
+		/* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */
+		struct {
+			__u64 addr;
+			__u64 len;
+			__u64 ret;
+		} dma_sharing;
+
+This defines a common interface from the guest back to the KVM to support
+use case for a guest to share memory with a host.
+
+The addr and len fields define the starting address and length of the
+shared memory region.
+
+Userspace is expected to place the hypercall result into the "ret" field
+before invoking KVM_RUN again.
+
 ::
 
 		/* Fix the size of the union. */
diff --git a/Documentation/virt/kvm/hypercalls.rst b/Documentation/virt/kvm/hypercalls.rst
index ed4fddd364ea..7aff0cebab7c 100644
--- a/Documentation/virt/kvm/hypercalls.rst
+++ b/Documentation/virt/kvm/hypercalls.rst
@@ -169,3 +169,18 @@ a0: destination APIC ID
 
 :Usage example: When sending a call-function IPI-many to vCPUs, yield if
 	        any of the IPI target vCPUs was preempted.
+
+
+8. KVM_HC_PAGE_ENC_STATUS
+-------------------------
+:Architecture: x86
+:Status: active
+:Purpose: Notify the encryption status changes in guest page table (SEV guest)
+
+a0: the guest physical address of the start page
+a1: the number of pages
+a2: encryption attribute
+
+   Where:
+	* 1: Encryption attribute is set
+	* 0: Encryption attribute is cleared
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 3768819693e5..78284ebbbee7 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1352,6 +1352,8 @@ struct kvm_x86_ops {
 	int (*complete_emulated_msr)(struct kvm_vcpu *vcpu, int err);
 
 	void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu, u8 vector);
+	int (*page_enc_status_hc)(struct kvm_vcpu *vcpu, unsigned long gpa,
+				  unsigned long sz, unsigned long mode);
 };
 
 struct kvm_x86_nested_ops {
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index c9795a22e502..fb3a315e5827 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1544,6 +1544,67 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
 	return ret;
 }
 
+static int sev_complete_userspace_page_enc_status_hc(struct kvm_vcpu *vcpu)
+{
+	vcpu->run->exit_reason = 0;
+	kvm_rax_write(vcpu, vcpu->run->dma_sharing.ret);
+	++vcpu->stat.hypercalls;
+	return kvm_skip_emulated_instruction(vcpu);
+}
+
+int svm_page_enc_status_hc(struct kvm_vcpu *vcpu, unsigned long gpa,
+			   unsigned long npages, unsigned long enc)
+{
+	kvm_pfn_t pfn_start, pfn_end;
+	struct kvm *kvm = vcpu->kvm;
+	gfn_t gfn_start, gfn_end;
+
+	if (!sev_guest(kvm))
+		return -EINVAL;
+
+	if (!npages)
+		return 0;
+
+	gfn_start = gpa_to_gfn(gpa);
+	gfn_end = gfn_start + npages;
+
+	/* out of bound access error check */
+	if (gfn_end <= gfn_start)
+		return -EINVAL;
+
+	/* lets make sure that gpa exist in our memslot */
+	pfn_start = gfn_to_pfn(kvm, gfn_start);
+	pfn_end = gfn_to_pfn(kvm, gfn_end);
+
+	if (is_error_noslot_pfn(pfn_start) && !is_noslot_pfn(pfn_start)) {
+		/*
+		 * Allow guest MMIO range(s) to be added
+		 * to the shared pages list.
+		 */
+		return -EINVAL;
+	}
+
+	if (is_error_noslot_pfn(pfn_end) && !is_noslot_pfn(pfn_end)) {
+		/*
+		 * Allow guest MMIO range(s) to be added
+		 * to the shared pages list.
+		 */
+		return -EINVAL;
+	}
+
+	if (enc)
+		vcpu->run->exit_reason = KVM_EXIT_DMA_UNSHARE;
+	else
+		vcpu->run->exit_reason = KVM_EXIT_DMA_SHARE;
+
+	vcpu->run->dma_sharing.addr = gfn_start;
+	vcpu->run->dma_sharing.len = npages * PAGE_SIZE;
+	vcpu->arch.complete_userspace_io =
+		sev_complete_userspace_page_enc_status_hc;
+
+	return 0;
+}
+
 int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 {
 	struct kvm_sev_cmd sev_cmd;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 58a45bb139f8..3cbf000beff1 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -4620,6 +4620,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
 	.complete_emulated_msr = svm_complete_emulated_msr,
 
 	.vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector,
+
+	.page_enc_status_hc = svm_page_enc_status_hc,
 };
 
 static struct kvm_x86_init_ops svm_init_ops __initdata = {
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 39e071fdab0c..9cc16d2c0b8f 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -451,6 +451,8 @@ int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
 			       bool has_error_code, u32 error_code);
 int nested_svm_exit_special(struct vcpu_svm *svm);
 void sync_nested_vmcb_control(struct vcpu_svm *svm);
+int svm_page_enc_status_hc(struct kvm_vcpu *vcpu, unsigned long gpa,
+			   unsigned long npages, unsigned long enc);
 
 extern struct kvm_x86_nested_ops svm_nested_ops;
 
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 32cf8287d4a7..2c98a5ed554b 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7748,6 +7748,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
 	.can_emulate_instruction = vmx_can_emulate_instruction,
 	.apic_init_signal_blocked = vmx_apic_init_signal_blocked,
 	.migrate_timers = vmx_migrate_timers,
+	.page_enc_status_hc = NULL,
 
 	.msr_filter_changed = vmx_msr_filter_changed,
 	.complete_emulated_msr = kvm_complete_insn_gp,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f7d12fca397b..ef5c77d59651 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -8273,6 +8273,18 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 		kvm_sched_yield(vcpu->kvm, a0);
 		ret = 0;
 		break;
+	case KVM_HC_PAGE_ENC_STATUS: {
+		int r;
+
+		ret = -KVM_ENOSYS;
+		if (kvm_x86_ops.page_enc_status_hc) {
+			r = kvm_x86_ops.page_enc_status_hc(vcpu, a0, a1, a2);
+			if (r >= 0)
+				return r;
+			ret = r;
+		}
+		break;
+	}
 	default:
 		ret = -KVM_ENOSYS;
 		break;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 3a656d43fc6c..4174925aa5fc 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -268,6 +268,8 @@ struct kvm_xen_exit {
 #define KVM_EXIT_AP_RESET_HOLD    32
 #define KVM_EXIT_X86_BUS_LOCK     33
 #define KVM_EXIT_XEN              34
+#define KVM_EXIT_DMA_SHARE        35
+#define KVM_EXIT_DMA_UNSHARE      36
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -446,6 +448,12 @@ struct kvm_run {
 		} msr;
 		/* KVM_EXIT_XEN */
 		struct kvm_xen_exit xen;
+		/* KVM_EXIT_DMA_SHARE / KVM_EXIT_DMA_UNSHARE */
+		struct {
+			__u64 addr;
+			__u64 len;
+			__u64 ret;
+		} dma_sharing;
 		/* Fix the size of the union. */
 		char padding[256];
 	};
diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h
index 8b86609849b9..847b83b75dc8 100644
--- a/include/uapi/linux/kvm_para.h
+++ b/include/uapi/linux/kvm_para.h
@@ -29,6 +29,7 @@
 #define KVM_HC_CLOCK_PAIRING		9
 #define KVM_HC_SEND_IPI		10
 #define KVM_HC_SCHED_YIELD		11
+#define KVM_HC_PAGE_ENC_STATUS		12
 
 /*
  * hypercalls use architecture specific
-- 
2.17.1


  parent reply	other threads:[~2021-04-05 14:28 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-05 14:20 [PATCH v11 00/13] Add AMD SEV guest live migration support Ashish Kalra
2021-04-05 14:21 ` [PATCH v11 01/13] KVM: SVM: Add KVM_SEV SEND_START command Ashish Kalra
2021-04-05 14:23 ` [PATCH v11 02/13] KVM: SVM: Add KVM_SEND_UPDATE_DATA command Ashish Kalra
2021-04-05 14:23 ` [PATCH v11 03/13] KVM: SVM: Add KVM_SEV_SEND_FINISH command Ashish Kalra
2021-04-05 14:24 ` [PATCH v11 04/13] KVM: SVM: Add support for KVM_SEV_RECEIVE_START command Ashish Kalra
2021-04-05 14:24 ` [PATCH v11 05/13] KVM: SVM: Add KVM_SEV_RECEIVE_UPDATE_DATA command Ashish Kalra
2021-04-05 14:25 ` [PATCH v11 06/13] KVM: SVM: Add KVM_SEV_RECEIVE_FINISH command Ashish Kalra
2021-04-05 14:26 ` [PATCH v11 07/13] KVM: x86: Add AMD SEV specific Hypercall3 Ashish Kalra
2021-04-05 14:28 ` Ashish Kalra [this message]
2021-04-05 20:42   ` [PATCH v11 08/13] KVM: X86: Introduce KVM_HC_PAGE_ENC_STATUS hypercall Steve Rutherford
2021-04-06  6:22     ` Ashish Kalra
2021-04-06 15:11       ` Sean Christopherson
2021-04-06 15:20         ` Sean Christopherson
2021-04-06 18:14       ` Ashish Kalra
2021-04-06 15:48   ` Sean Christopherson
2021-04-06 16:07     ` Ashish Kalra
2021-04-06 20:14       ` Steve Rutherford
2021-04-06 20:27         ` Sean Christopherson
2021-04-07 14:01     ` Ashish Kalra
2021-04-05 14:29 ` [PATCH v11 09/13] mm: x86: Invoke hypercall when page encryption status is changed Ashish Kalra
2021-04-05 14:30 ` [PATCH v11 10/13] KVM: x86: Introduce new KVM_FEATURE_SEV_LIVE_MIGRATION feature & Custom MSR Ashish Kalra
2021-04-06  1:39   ` Steve Rutherford
2021-04-06 13:26     ` Ashish Kalra
2021-04-06 13:47       ` Paolo Bonzini
2021-04-06 13:59         ` Ashish Kalra
2021-04-06 19:41           ` Steve Rutherford
2021-04-05 14:30 ` [PATCH v11 11/13] EFI: Introduce the new AMD Memory Encryption GUID Ashish Kalra
2021-04-05 14:31 ` [PATCH v11 12/13] x86/kvm: Add guest support for detecting and enabling SEV Live Migration feature Ashish Kalra
2021-04-05 14:35 ` [PATCH v11 13/13] x86/kvm: Add kexec support for SEV Live Migration Ashish Kalra
2021-04-05 15:17 ` [PATCH v11 00/13] Add AMD SEV guest live migration support Peter Gonda
2021-04-05 18:27   ` Steve Rutherford
2021-04-06 13:48     ` Paolo Bonzini
2021-04-06  1:43 ` Steve Rutherford

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4da0d40c309a21ba3952d06f346b6411930729c9.1617302792.git.ashish.kalra@amd.com \
    --to=ashish.kalra@amd.com \
    --cc=bp@suse.de \
    --cc=brijesh.singh@amd.com \
    --cc=hpa@zytor.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qperret@google.com \
    --cc=seanjc@google.com \
    --cc=srutherford@google.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=venu.busireddy@oracle.com \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).