All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brijesh Singh <brijesh.singh@amd.com>
To: linux-kernel@vger.kernel.org, x86@kernel.org, kvm@vger.kernel.org
Cc: "Thomas Gleixner" <tglx@linutronix.de>,
	"Borislav Petkov" <bp@suse.de>, "Joerg Roedel" <joro@8bytes.org>,
	"Michael S . Tsirkin" <mst@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"\\\"Radim Krčmář\\\"" <rkrcmar@redhat.com>,
	"Tom Lendacky" <thomas.lendacky@amd.com>,
	"Brijesh Singh" <brijesh.singh@amd.com>
Subject: [RFC Part2 PATCH v3 22/26] KVM: SVM: Pin guest memory when SEV is active
Date: Mon, 24 Jul 2017 15:02:59 -0500	[thread overview]
Message-ID: <20170724200303.12197-23-brijesh.singh@amd.com> (raw)
In-Reply-To: <20170724200303.12197-1-brijesh.singh@amd.com>

The SEV memory encryption engine uses a tweak such that two identical
plaintexts at different location will have a different ciphertexts.
So swapping or moving ciphertexts of two pages will not result in
plaintexts being swapped. Relocating (or migrating) a physical backing
pages for SEV guest will require some additional steps. The current SEV
key management spec does not provide commands to swap or migrate (move)
ciphertexts. For now, we pin the guest memory registered through
KVM_MEMORY_ENCRYPT_REGISTER_RAM ioctl.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/include/asm/kvm_host.h |   1 +
 arch/x86/kvm/svm.c              | 113 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 150177e..a91aadf 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -747,6 +747,7 @@ struct kvm_sev_info {
 	unsigned int handle;	/* firmware handle */
 	unsigned int asid;	/* asid for this guest */
 	int sev_fd;		/* SEV device fd */
+	struct list_head ram_list; /* list of registered ram */
 };
 
 struct kvm_arch {
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 75dcaa9..cdb1cf3 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -333,8 +333,19 @@ static int sev_asid_new(void);
 static void sev_asid_free(int asid);
 static void sev_deactivate_handle(struct kvm *kvm, int *error);
 static void sev_decommission_handle(struct kvm *kvm, int *error);
+static void sev_unpin_memory(struct page **pages, unsigned long npages);
+
 #define __sme_page_pa(x) __sme_set(page_to_pfn(x) << PAGE_SHIFT)
 
+struct kvm_sev_pin_ram {
+	struct list_head list;
+	unsigned long npages;
+	struct page **pages;
+	struct kvm_memory_encrypt_ram userspace;
+};
+
+static void __mem_encrypt_unregister_ram(struct kvm_sev_pin_ram *ram);
+
 static bool svm_sev_enabled(void)
 {
 	return !!max_sev_asid;
@@ -385,6 +396,11 @@ static inline void sev_set_fd(struct kvm *kvm, int fd)
 	to_sev_info(kvm)->sev_fd = fd;
 }
 
+static inline struct list_head *sev_get_ram_list(struct kvm *kvm)
+{
+	return &to_sev_info(kvm)->ram_list;
+}
+
 static inline void mark_all_dirty(struct vmcb *vmcb)
 {
 	vmcb->control.clean = 0;
@@ -1566,10 +1582,24 @@ static void sev_firmware_uninit(void)
 static void sev_vm_destroy(struct kvm *kvm)
 {
 	int state, error;
+	struct list_head *pos, *q;
+	struct kvm_sev_pin_ram *ram;
+	struct list_head *head = sev_get_ram_list(kvm);
 
 	if (!sev_guest(kvm))
 		return;
 
+	/*
+	 * if userspace was terminated before unregistering the memory region
+	 * then lets unpin all the registered memory.
+	 */
+	if (!list_empty(head)) {
+		list_for_each_safe(pos, q, head) {
+			ram = list_entry(pos, struct kvm_sev_pin_ram, list);
+			__mem_encrypt_unregister_ram(ram);
+		}
+	}
+
 	/* release the firmware resources for this guest */
 	if (sev_get_handle(kvm)) {
 		sev_deactivate_handle(kvm, &error);
@@ -5640,6 +5670,7 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
 	sev_set_active(kvm);
 	sev_set_asid(kvm, asid);
 	sev_set_fd(kvm, argp->sev_fd);
+	INIT_LIST_HEAD(sev_get_ram_list(kvm));
 	ret = 0;
 e_err:
 	fdput(f);
@@ -6437,6 +6468,86 @@ static int svm_memory_encryption_op(struct kvm *kvm, void __user *argp)
 	return r;
 }
 
+static int mem_encrypt_register_ram(struct kvm *kvm,
+				    struct kvm_memory_encrypt_ram *ram)
+{
+	struct list_head *head = sev_get_ram_list(kvm);
+	struct kvm_sev_pin_ram *pin_ram;
+
+	if (!sev_guest(kvm))
+		return -ENOTTY;
+
+	pin_ram = kzalloc(sizeof(*pin_ram), GFP_KERNEL);
+	if (!pin_ram)
+		return -ENOMEM;
+
+	pin_ram->pages = sev_pin_memory(ram->address, ram->size,
+					&pin_ram->npages, 1);
+	if (!pin_ram->pages)
+		goto e_free;
+
+	/*
+	 * Guest may change the memory encryption attribute from C=0 -> C=1
+	 * for this memory range. Lets make sure caches are flushed to ensure
+	 * that guest data gets written into memory with correct C-bit.
+	 */
+	sev_clflush_pages(pin_ram->pages, pin_ram->npages);
+
+	pin_ram->userspace.address = ram->address;
+	pin_ram->userspace.size = ram->size;
+	list_add_tail(&pin_ram->list, head);
+	return 0;
+e_free:
+	kfree(pin_ram);
+	return 1;
+}
+
+static struct kvm_sev_pin_ram *sev_find_pinned_ram(struct kvm *kvm,
+					struct kvm_memory_encrypt_ram *ram)
+{
+	struct list_head *head = sev_get_ram_list(kvm);
+	struct kvm_sev_pin_ram *i;
+
+	list_for_each_entry(i, head, list) {
+		if (i->userspace.address == ram->address &&
+			i->userspace.size == ram->size)
+			return i;
+	}
+
+	return NULL;
+}
+
+static void __mem_encrypt_unregister_ram(struct kvm_sev_pin_ram *ram)
+{
+	/*
+	 * Guest may have changed the memory encryption attribute from
+	 * C=0 -> C=1. Lets make sure caches are flushed to ensure in data
+	 * gets written into memory with correct C-bit.
+	 */
+	sev_clflush_pages(ram->pages, ram->npages);
+
+	sev_unpin_memory(ram->pages, ram->npages);
+	list_del(&ram->list);
+	kfree(ram);
+}
+
+static int mem_encrypt_unregister_ram(struct kvm *kvm,
+				      struct kvm_memory_encrypt_ram *ram)
+{
+	struct kvm_sev_pin_ram *pinned_ram;
+
+	if (!sev_guest(kvm))
+		return -ENOTTY;
+
+	pinned_ram = sev_find_pinned_ram(kvm, ram);
+	if (!pinned_ram)
+		return -EINVAL;
+
+	__mem_encrypt_unregister_ram(pinned_ram);
+
+	return 0;
+}
+
 static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 	.cpu_has_kvm_support = has_svm,
 	.disabled_by_bios = is_disabled,
@@ -6551,6 +6662,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
 	.setup_mce = svm_setup_mce,
 
 	.memory_encryption_op = svm_memory_encryption_op,
+	.memory_encryption_register_ram = mem_encrypt_register_ram,
+	.memory_encryption_unregister_ram = mem_encrypt_unregister_ram,
 };
 
 static int __init svm_init(void)
-- 
2.9.4

  parent reply	other threads:[~2017-07-24 20:11 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-24 20:02 [RFC Part2 PATCH v3 00/26] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-07-24 20:02 ` [RFC Part2 PATCH v3 01/26] Documentation/virtual/kvm: Add AMD Secure Encrypted Virtualization (SEV) Brijesh Singh
2017-09-05 17:21   ` Borislav Petkov
2017-09-05 21:39     ` Brijesh Singh
2017-09-05 22:06       ` Borislav Petkov
2017-09-06 16:41       ` Borislav Petkov
2017-09-06 20:54         ` Brijesh Singh
2017-07-24 20:02 ` [RFC Part2 PATCH v3 02/26] crypto: ccp: Add Platform Security Processor (PSP) device support Brijesh Singh
2017-07-25  8:29   ` Kamil Konieczny
2017-07-25 15:00     ` Brijesh Singh
2017-09-06 17:00   ` Borislav Petkov
2017-09-06 20:38     ` Brijesh Singh
2017-09-06 20:46       ` Borislav Petkov
2017-09-06 21:26         ` Gary R Hook
2017-09-07 10:34           ` Borislav Petkov
2017-09-07 14:27   ` Borislav Petkov
2017-09-07 22:19     ` Brijesh Singh
2017-09-07 23:15       ` Gary R Hook
2017-09-08  8:22         ` Borislav Petkov
2017-09-08  8:40       ` Borislav Petkov
2017-09-08 13:54         ` Brijesh Singh
2017-09-08 16:06         ` Brijesh Singh
2017-07-24 20:02 ` [RFC Part2 PATCH v3 03/26] crypto: ccp: Add Secure Encrypted Virtualization (SEV) " Brijesh Singh
2017-09-12 14:02   ` Borislav Petkov
2017-09-12 15:32     ` Brijesh Singh
2017-09-12 16:29       ` Borislav Petkov
2017-09-13 14:17   ` Borislav Petkov
2017-09-13 15:18     ` Brijesh Singh
2017-07-24 20:02 ` [RFC Part2 PATCH v3 04/26] KVM: SVM: Prepare to reserve asid for SEV guest Brijesh Singh
2017-09-12 19:54   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 05/26] KVM: SVM: Reserve ASID range " Brijesh Singh
2017-09-12 20:04   ` Borislav Petkov
2017-09-12 20:24     ` Brijesh Singh
2017-09-12 20:28       ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 06/26] KVM: SVM: Prepare for new bit definition in nested_ctl Brijesh Singh
2017-09-12 20:06   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 07/26] KVM: SVM: Add SEV feature definitions to KVM Brijesh Singh
2017-09-12 20:08   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 08/26] KVM: X86: Extend CPUID range to include new leaf Brijesh Singh
2017-09-12 20:12   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 09/26] KVM: Introduce KVM_MEMORY_ENCRYPT_OP ioctl Brijesh Singh
2017-09-12 20:19   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 10/26] KVM: Introduce KVM_MEMORY_ENCRYPT_REGISTER/UNREGISTER_RAM ioctl Brijesh Singh
2017-09-12 20:29   ` Borislav Petkov
2017-09-12 20:50     ` Brijesh Singh
2017-09-12 21:08       ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 11/26] KVM: X86: Extend struct kvm_arch to include SEV information Brijesh Singh
2017-09-13 13:37   ` Borislav Petkov
2017-09-13 15:14     ` Brijesh Singh
2017-09-13 15:21       ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 12/26] KVM: Define SEV key management command id Brijesh Singh
2017-09-13 13:45   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 13/26] KVM: SVM: Add KVM_SEV_INIT command Brijesh Singh
2017-09-13 15:06   ` Borislav Petkov
2017-09-13 16:23     ` Brijesh Singh
2017-09-13 16:37       ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 14/26] KVM: SVM: VMRUN should use assosiated ASID when SEV is enabled Brijesh Singh
2017-09-13 15:37   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 15/26] KVM: SVM: Add support for SEV LAUNCH_START command Brijesh Singh
2017-09-13 17:25   ` Borislav Petkov
2017-09-13 18:23     ` Brijesh Singh
2017-09-13 18:37       ` Borislav Petkov
2017-09-13 18:58         ` Brijesh Singh
2017-09-13 21:02           ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 16/26] KVM: SVM: Add support for SEV LAUNCH_UPDATE_DATA command Brijesh Singh
2017-09-13 17:55   ` Borislav Petkov
2017-09-13 19:45     ` Brijesh Singh
2017-09-13 21:07       ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 17/26] KVM: SVM: Add support for SEV LAUNCH_MEASURE command Brijesh Singh
2017-09-14 10:20   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 18/26] KVM: SVM: Add support for SEV LAUNCH_FINISH command Brijesh Singh
2017-09-14 10:24   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 19/26] KVM: svm: Add support for SEV GUEST_STATUS command Brijesh Singh
2017-09-14 10:35   ` Borislav Petkov
2017-09-14 11:25     ` Brijesh Singh
2017-07-24 20:02 ` [RFC Part2 PATCH v3 20/26] KVM: SVM: Add support for SEV DEBUG_DECRYPT command Brijesh Singh
2017-09-14 11:08   ` Borislav Petkov
2017-07-24 20:02 ` [RFC Part2 PATCH v3 21/26] KVM: SVM: Add support for SEV DEBUG_ENCRYPT command Brijesh Singh
2017-09-14 13:32   ` Borislav Petkov
2017-07-24 20:02 ` Brijesh Singh [this message]
2017-09-14 14:00   ` [RFC Part2 PATCH v3 22/26] KVM: SVM: Pin guest memory when SEV is active Borislav Petkov
2017-07-24 20:03 ` [RFC Part2 PATCH v3 23/26] KVM: X86: Add memory encryption enabled ops Brijesh Singh
2017-09-14 14:09   ` Borislav Petkov
2017-07-24 20:03 ` [RFC Part2 PATCH v3 24/26] KVM: SVM: Clear C-bit from the page fault address Brijesh Singh
2017-09-14 14:35   ` Borislav Petkov
2017-07-24 20:03 ` [RFC Part2 PATCH v3 25/26] KVM: SVM: Do not install #UD intercept when SEV is enabled Brijesh Singh
2017-09-14 14:56   ` Borislav Petkov
2017-07-24 20:03 ` [RFC Part2 PATCH v3 26/26] KVM: X86: Restart the guest when insn_len is zero and " Brijesh Singh
2017-09-14 15:40   ` Borislav Petkov

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=20170724200303.12197-23-brijesh.singh@amd.com \
    --to=brijesh.singh@amd.com \
    --cc=bp@suse.de \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.