All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/sgx: Hack in idea for allocating from local EPC node when possible
@ 2020-05-14  4:51 Sean Christopherson
  0 siblings, 0 replies; only message in thread
From: Sean Christopherson @ 2020-05-14  4:51 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-sgx

Allocate EPC from the local node when possible.  Sort EPC sections so
that their index into sgx_epc_sections corresponds with their NUMA node
ID, allowing the NUMA lookup to run in O(1) time.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---

I'm only sending this for completeness, v2 will follow shortly.  v2 is
less hacky and properly handles the scenario of multiple EPC sections in a
single NUMA node.

 arch/x86/kernel/cpu/sgx/main.c | 57 +++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 5ce77e5546766..2aa83e701d3c5 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -12,6 +12,7 @@
 #include "encls.h"
 
 struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS];
+struct sgx_epc_section __initdata unsorted_epc_sections[SGX_MAX_EPC_SECTIONS];
 int sgx_nr_epc_sections;
 
 static struct sgx_epc_page *__sgx_try_alloc_page(struct sgx_epc_section *section)
@@ -43,6 +44,19 @@ struct sgx_epc_page *sgx_try_alloc_page(void)
 	struct sgx_epc_page *page;
 	int i;
 
+#ifdef CONFIG_NUMA
+	i = numa_node_id();
+
+	if (i < sgx_nr_epc_sections) {
+		section = &sgx_epc_sections[i];
+		spin_lock(&section->lock);
+		page = __sgx_try_alloc_page(section);
+		spin_unlock(&section->lock);
+		if (page)
+			return page;
+	}
+#endif
+
 	for (i = 0; i < sgx_nr_epc_sections; i++) {
 		section = &sgx_epc_sections[i];
 		spin_lock(&section->lock);
@@ -195,6 +209,39 @@ static void __init sgx_page_cache_teardown(void)
 		sgx_free_epc_section(&sgx_epc_sections[i]);
 }
 
+static void __init sgx_page_cache_sort(struct sgx_epc_section *sorted,
+				       struct sgx_epc_section *unsorted,
+				       int nr_sections)
+{
+	struct sgx_epc_section *section;
+	unsigned long start, end;
+	pg_data_t *pgdat;
+	int i, nid;
+
+	for (i = 0; i < nr_sections; i++) {
+		section = &unsorted[i];
+		for (nid = 0; nid < nr_node_ids; nid++) {
+			pgdat = NODE_DATA(nid);
+			start = pgdat->node_start_pfn << PAGE_SHIFT;
+			end = start + (pgdat->node_spanned_pages << PAGE_SHIFT);
+
+			if (section->pa >= start && section->pa < end)
+				break;
+		}
+		if (nid >= nr_node_ids || nid >= nr_sections ||
+		    sorted[nid].free_cnt) {
+			for (nid = nr_sections - 1; nid > 0; nid--) {
+				if (!sorted[nid].free_cnt)
+					break;
+			}
+			if (WARN_ON(nid < 0))
+				return;
+		}
+		memcpy(&sorted[nid], &unsorted[i],
+		       sizeof(struct sgx_epc_section));
+	}
+}
+
 /**
  * A section metric is concatenated in a way that @low bits 12-31 define the
  * bits 12-31 of the metric and @high bits 0-19 define the bits 32-51 of the
@@ -235,7 +282,8 @@ static bool __init sgx_page_cache_init(void)
 
 		pr_info("EPC section 0x%llx-0x%llx\n", pa, pa + size - 1);
 
-		if (!sgx_alloc_epc_section(pa, size, i, &sgx_epc_sections[i])) {
+		if (!sgx_alloc_epc_section(pa, size, i,
+					   &unsorted_epc_sections[i])) {
 			pr_err("No free memory for an EPC section\n");
 			break;
 		}
@@ -248,6 +296,13 @@ static bool __init sgx_page_cache_init(void)
 		return false;
 	}
 
+	if (nr_node_ids > 1)
+		sgx_page_cache_sort(sgx_epc_sections, unsorted_epc_sections,
+				    sgx_nr_epc_sections);
+	else
+		memcpy(sgx_epc_section, unsorted_epc_sections,
+		       sizeof(struct sgx_epc_section) * sgx_nr_epc_sections);
+
 	return true;
 }
 
-- 
2.26.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-05-14  4:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-14  4:51 [PATCH] x86/sgx: Hack in idea for allocating from local EPC node when possible Sean Christopherson

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.