From: Jarkko Sakkinen <jarkko@kernel.org>
To: linux-sgx@vger.kernel.org
Cc: Jarkko Sakkinen <jarkko@kernel.org>,
Dave Hansen <dave.hansen@linux.intel.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH v4 2/3] x86/sgx: Replace section local dirty page lists with a global list
Date: Sat, 13 Mar 2021 18:01:18 +0200 [thread overview]
Message-ID: <20210313160119.1318533-3-jarkko@kernel.org> (raw)
In-Reply-To: <20210313160119.1318533-1-jarkko@kernel.org>
Reset initialized EPC pages in sgx_dirty_page_list to uninitialized state,
and free them using sgx_free_epc_page(). Do two passes, as for SECS pages
the first round can fail, if all child pages have not yet been removed.
The driver puts all pages on startup first to sgx_dirty_page_list, as the
initialization could be triggered by kexec(), meaning that pages have been
reserved for active enclaves before the operation.
The section local lists are redundant, as sgx_free_epc_page() figures
out the correction by using epc_page->section.
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
v4:
* Open coded sgx_santize_section() to ksgxd().
* Rewrote the commit message.
arch/x86/kernel/cpu/sgx/main.c | 81 ++++++++++++++++------------------
arch/x86/kernel/cpu/sgx/sgx.h | 7 ---
2 files changed, 37 insertions(+), 51 deletions(-)
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 65004fb8a91f..cb4561444b96 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -27,39 +27,10 @@ static LIST_HEAD(sgx_active_page_list);
static DEFINE_SPINLOCK(sgx_reclaimer_lock);
/*
- * Reset dirty EPC pages to uninitialized state. Laundry can be left with SECS
- * pages whose child pages blocked EREMOVE.
+ * When the driver initialized, EPC pages go first here, as they could be
+ * initialized to an active enclave, on kexec entry.
*/
-static void sgx_sanitize_section(struct sgx_epc_section *section)
-{
- struct sgx_epc_page *page;
- LIST_HEAD(dirty);
- int ret;
-
- /* init_laundry_list is thread-local, no need for a lock: */
- while (!list_empty(§ion->init_laundry_list)) {
- if (kthread_should_stop())
- return;
-
- /* needed for access to ->page_list: */
- spin_lock(§ion->lock);
-
- page = list_first_entry(§ion->init_laundry_list,
- struct sgx_epc_page, list);
-
- ret = __eremove(sgx_get_epc_virt_addr(page));
- if (!ret)
- list_move(&page->list, §ion->page_list);
- else
- list_move_tail(&page->list, &dirty);
-
- spin_unlock(§ion->lock);
-
- cond_resched();
- }
-
- list_splice(&dirty, §ion->init_laundry_list);
-}
+static LIST_HEAD(sgx_dirty_page_list);
static bool sgx_reclaimer_age(struct sgx_epc_page *epc_page)
{
@@ -400,25 +371,48 @@ static bool sgx_should_reclaim(unsigned long watermark)
static int ksgxd(void *p)
{
- int i;
+ struct sgx_epc_page *page;
+ LIST_HEAD(dirty);
+ int i, ret;
set_freezable();
/*
- * Sanitize pages in order to recover from kexec(). The 2nd pass is
- * required for SECS pages, whose child pages blocked EREMOVE.
+ * Reset initialized EPC pages in sgx_dirty_page_list to uninitialized state,
+ * and free them using sgx_free_epc_page(). Do two passes, as for SECS pages the
+ * first round can fail, if all child pages have not yet been removed. The
+ * driver puts all pages on startup first to sgx_dirty_page_list, as the
+ * initialization could be triggered by kexec(), meaning that pages have been
+ * reserved for active enclaves before the operation.
*/
- for (i = 0; i < sgx_nr_epc_sections; i++)
- sgx_sanitize_section(&sgx_epc_sections[i]);
- for (i = 0; i < sgx_nr_epc_sections; i++) {
- sgx_sanitize_section(&sgx_epc_sections[i]);
+ /* sgx_dirty_page_list is thread-local to ksgxd, no need for a lock: */
+ for (i = 0; i < 2 && !list_empty(&sgx_dirty_page_list); i++) {
+ while (!list_empty(&sgx_dirty_page_list)) {
+ if (kthread_should_stop())
+ return 0;
+
+ page = list_first_entry(&sgx_dirty_page_list, struct sgx_epc_page, list);
+
+ ret = __eremove(sgx_get_epc_virt_addr(page));
+ if (!ret) {
+ /* The page is clean - move to the free list. */
+ list_del(&page->list);
+ sgx_free_epc_page(page);
+ } else {
+ /* The page is not yet clean - move to the dirty list. */
+ list_move_tail(&page->list, &dirty);
+ }
+
+ cond_resched();
+ }
- /* Should never happen. */
- if (!list_empty(&sgx_epc_sections[i].init_laundry_list))
- WARN(1, "EPC section %d has unsanitized pages.\n", i);
+ list_splice(&dirty, &sgx_dirty_page_list);
}
+ if (!list_empty(&sgx_dirty_page_list))
+ WARN(1, "EPC section %d has unsanitized pages.\n", i);
+
while (!kthread_should_stop()) {
if (try_to_freeze())
continue;
@@ -632,13 +626,12 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
section->phys_addr = phys_addr;
spin_lock_init(§ion->lock);
INIT_LIST_HEAD(§ion->page_list);
- INIT_LIST_HEAD(§ion->init_laundry_list);
for (i = 0; i < nr_pages; i++) {
section->pages[i].section = index;
section->pages[i].flags = 0;
section->pages[i].owner = NULL;
- list_add_tail(§ion->pages[i].list, §ion->init_laundry_list);
+ list_add_tail(§ion->pages[i].list, &sgx_dirty_page_list);
}
section->free_cnt = nr_pages;
diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h
index 5fa42d143feb..bc8af0428640 100644
--- a/arch/x86/kernel/cpu/sgx/sgx.h
+++ b/arch/x86/kernel/cpu/sgx/sgx.h
@@ -45,13 +45,6 @@ struct sgx_epc_section {
spinlock_t lock;
struct list_head page_list;
unsigned long free_cnt;
-
- /*
- * Pages which need EREMOVE run on them before they can be
- * used. Only safe to be accessed in ksgxd and init code.
- * Not protected by locks.
- */
- struct list_head init_laundry_list;
};
extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS];
--
2.30.2
next prev parent reply other threads:[~2021-03-13 16:02 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-13 16:01 [PATCH v4 0/3] x86/sgx: NUMA Jarkko Sakkinen
2021-03-13 16:01 ` [PATCH v4 1/3] x86/sgx: Use sgx_free_epc_page() in sgx_reclaim_pages() Jarkko Sakkinen
2021-03-15 15:32 ` Dave Hansen
2021-03-15 19:06 ` Jarkko Sakkinen
2021-03-15 19:27 ` Jarkko Sakkinen
2021-03-16 12:50 ` Jarkko Sakkinen
2021-03-13 16:01 ` Jarkko Sakkinen [this message]
2021-03-15 16:03 ` [PATCH v4 2/3] x86/sgx: Replace section local dirty page lists with a global list Dave Hansen
2021-03-15 19:14 ` Jarkko Sakkinen
2021-03-15 19:47 ` Dave Hansen
2021-03-13 16:01 ` [PATCH v4 3/3] x86/sgx: Add a basic NUMA allocation scheme to sgx_alloc_epc_page() Jarkko Sakkinen
2021-03-14 11:56 ` Jarkko Sakkinen
2021-03-15 16:35 ` Dave Hansen
2021-03-15 19:23 ` 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=20210313160119.1318533-3-jarkko@kernel.org \
--to=jarkko@kernel.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.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.