All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jarkko Sakkinen <jarkko@kernel.org>
To: linux-sgx@vger.kernel.org
Cc: haitao.huang@intel.com, dan.j.williams@intel.com,
	dave.hansen@linux.intel.com, bp@alien8.de, tglx@linutronix.de,
	linux-kernel@vger.kernel.org, x86@kernel.org,
	Jarkko Sakkinen <jarkko@kernel.org>,
	Ingo Molnar <mingo@redhat.com>, "H. Peter Anvin" <hpa@zytor.com>
Subject: [PATCH 2/3] x86/sgx: Add a version array (VA) structure
Date: Thu, 25 Feb 2021 00:20:48 +0200	[thread overview]
Message-ID: <20210224222049.240754-3-jarkko@kernel.org> (raw)
In-Reply-To: <20210224222049.240754-1-jarkko@kernel.org>

Add a data structure representing an arbitrary size EPC version array (VA),
consisting of a vector of VA EPC pages. Introduce sgx_va_get() and
sgx_va_put() for reserving and releasing VA slots in the version array.

Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
 arch/x86/kernel/cpu/sgx/encl.c | 126 ++++++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/sgx/encl.h |  26 ++++---
 arch/x86/kernel/cpu/sgx/main.c |   1 +
 3 files changed, 144 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
index 42eb879c167a..c8ce3779eaa7 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
@@ -265,7 +265,7 @@ static int sgx_vma_mprotect(struct vm_area_struct *vma, unsigned long start,
 }
 
 static int sgx_encl_debug_read(struct sgx_encl *encl, struct sgx_encl_page *page,
-			       unsigned long addr, void *data)
+				unsigned long addr, void *data)
 {
 	unsigned long offset = addr & ~PAGE_MASK;
 	int ret;
@@ -749,3 +749,127 @@ bool sgx_va_page_full(struct sgx_va_page *va_page)
 
 	return slot == SGX_VA_SLOT_COUNT;
 }
+
+/**
+ * sgx_va_init() - Initialize a version array (VA)
+ * @va:		A version array.
+ *
+ * Initialize the data structure to be ready for sgx_va_get() and sgx_va_put()
+ * operations. The given buffer must be zero initialized.
+ */
+void sgx_va_init(struct sgx_va *va)
+{
+	xa_init(&va->page_array);
+	mutex_init(&va->lock);
+}
+
+/**
+ * sgx_va_destroy() - Destroy a version array (VA)
+ * @va:		A version array.
+ *
+ * Release all the resources reserved by the version array.
+ */
+void sgx_va_destroy(struct sgx_va *va)
+{
+	struct sgx_va_page *entry;
+	unsigned long index;
+
+	/* Delete the VA pages. */
+	xa_for_each(&va->page_array, index, entry) {
+		sgx_free_epc_page(entry->epc_page);
+		kfree(entry);
+	}
+
+	/* Delete the page array structure contents.*/
+	xa_destroy(&va->page_array);
+}
+
+/**
+ * sgx_va_get() - Reserve a slot from a version array (VA)
+ * @va:		A version array.
+ * @index:	The slot index.
+ *
+ * Reserve an arbitrary slot from a version array given by the slot index.
+ *
+ * Return:
+ * - A VA page:		On success.
+ * - ERR_PTR(-errno):	On failure.
+ */
+struct sgx_va_page *sgx_va_get(struct sgx_va *va, int index)
+{
+	int sub_index = index & (SGX_VA_SLOT_COUNT - 1);
+	int page_index = index / SGX_VA_SLOT_COUNT;
+	struct sgx_va_page *page;
+	int ret;
+
+	mutex_lock(&va->lock);
+
+	page = xa_load(&va->page_array, page_index);
+	if (page)
+		goto out;
+
+	page = sgx_alloc_va_page();
+	if (!page) {
+		page = ERR_PTR(-ENOMEM);
+		goto err_lock;
+	}
+
+	ret = xa_insert(&va->page_array, page_index, page, GFP_KERNEL);
+	if (ret) {
+		page = ERR_PTR(ret);
+		goto err_va_page;
+	}
+
+out:
+	WARN_ONCE(test_bit(sub_index, page->slots),
+		  "page_index = %d, sub_index = %d\n", page_index, sub_index);
+
+	set_bit(sub_index, page->slots);
+
+	mutex_unlock(&va->lock);
+
+	return page;
+
+err_va_page:
+	sgx_free_epc_page(page->epc_page);
+	kfree(page);
+
+err_lock:
+	mutex_unlock(&va->lock);
+
+	return page;
+}
+
+/*
+ * sgx_va_put() - Release a slot back to a version array (VA)
+ * @va:		A version array.
+ * @index:	The slot index.
+ *
+ * Release a slot back to a version array (VA). Free the VA page, which contained
+ * the slot, if it becomes empty.
+ */
+void sgx_va_put(struct sgx_va *va, int index)
+{
+	int sub_index = index & (SGX_VA_SLOT_COUNT - 1);
+	int page_index = index / SGX_VA_SLOT_COUNT;
+	struct sgx_va_page *page;
+
+	mutex_lock(&va->lock);
+
+	page = xa_load(&va->page_array, page_index);
+
+	WARN_ONCE(!test_bit(sub_index, page->slots),
+		  "page_index = %d, sub_index = %d\n", page_index, sub_index);
+
+	clear_bit(sub_index, page->slots);
+
+	if (find_first_zero_bit(page->slots, SGX_VA_SLOT_COUNT) == SGX_VA_SLOT_COUNT) {
+		xa_erase(&va->page_array, page_index);
+
+		/* Free the VA page. */
+		sgx_free_epc_page(page->epc_page);
+		kfree(page);
+	}
+
+	mutex_unlock(&va->lock);
+}
diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h
index 315e87fcc142..806cf3ff7391 100644
--- a/arch/x86/kernel/cpu/sgx/encl.h
+++ b/arch/x86/kernel/cpu/sgx/encl.h
@@ -19,6 +19,19 @@
 #include <linux/xarray.h>
 #include "sgx.h"
 
+#define SGX_VA_SLOT_COUNT 512
+
+struct sgx_va_page {
+	struct sgx_epc_page *epc_page;
+	DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT);
+	struct list_head list;
+};
+
+struct sgx_va {
+	struct xarray page_array;
+	struct mutex lock;
+};
+
 /* 'desc' bits holding the offset in the VA (version array) page. */
 #define SGX_ENCL_PAGE_VA_OFFSET_MASK	GENMASK_ULL(11, 3)
 
@@ -69,14 +82,6 @@ struct sgx_encl {
 	struct srcu_struct srcu;
 };
 
-#define SGX_VA_SLOT_COUNT 512
-
-struct sgx_va_page {
-	struct sgx_epc_page *epc_page;
-	DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT);
-	struct list_head list;
-};
-
 struct sgx_backing {
 	pgoff_t page_index;
 	struct page *contents;
@@ -116,4 +121,9 @@ unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page);
 void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset);
 bool sgx_va_page_full(struct sgx_va_page *va_page);
 
+void sgx_va_init(struct sgx_va *va);
+void sgx_va_destroy(struct sgx_va *va);
+struct sgx_va_page *sgx_va_get(struct sgx_va *va, int index);
+void sgx_va_put(struct sgx_va *va, int index);
+
 #endif /* _X86_ENCL_H */
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 8df81a3ed945..26dfe6aecd72 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -617,6 +617,7 @@ void sgx_free_epc_page(struct sgx_epc_page *page)
 	spin_unlock(&section->lock);
 }
 
+
 static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
 					 unsigned long index,
 					 struct sgx_epc_section *section)
-- 
2.30.1


  parent reply	other threads:[~2021-02-24 22:22 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-24 22:20 [PATCH 0/3] Introduce version array structure: sgx_va Jarkko Sakkinen
2021-02-24 22:20 ` [PATCH 1/3] x86/sgx: Move struct sgx_va_page creation to sgx_alloc_va_page() Jarkko Sakkinen
2021-02-24 22:20 ` Jarkko Sakkinen [this message]
2021-02-24 22:20 ` [PATCH 3/3] x86/sgx: Use sgx_va for the enclave's version array Jarkko Sakkinen
2021-02-24 23:48 ` [PATCH 0/3] Introduce version array structure: sgx_va Dave Hansen
2021-02-25  1:01   ` Jarkko Sakkinen
2021-02-25  7:34 ` Jarkko Sakkinen

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=20210224222049.240754-3-jarkko@kernel.org \
    --to=jarkko@kernel.org \
    --cc=bp@alien8.de \
    --cc=dan.j.williams@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=haitao.huang@intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sgx@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    --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.