[PATCH v3 2/7] x86/sgx: Add infrastructure to identify SGX EPC pages

From: Tony Luck
Date: Wed Jul 28 2021 - 16:47:19 EST


X86 machine check architecture reports a physical address when there
is a memory error. Handling that error requires a method to determine
whether the physical address reported is in any of the areas reserved
for EPC pages by BIOS.

Add an end_phys_addr field to the sgx_epc_section structure and a
new function sgx_paddr_to_page() that searches all such structures
and returns the struct sgx_epc_page pointer if the address is an EPC
page. This function is only intended for use within SGX code.

Export a function sgx_is_epc_page() that simply reports whether an
address is an EPC page for use elsewhere in the kernel.

Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx>
---
arch/x86/kernel/cpu/sgx/main.c | 24 ++++++++++++++++++++++++
arch/x86/kernel/cpu/sgx/sgx.h | 1 +
2 files changed, 25 insertions(+)

diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 17d09186a6c2..ce40c010c9cb 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -649,6 +649,7 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
}

section->phys_addr = phys_addr;
+ section->end_phys_addr = phys_addr + size - 1;

for (i = 0; i < nr_pages; i++) {
section->pages[i].section = index;
@@ -660,6 +661,29 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
return true;
}

+static struct sgx_epc_page *sgx_paddr_to_page(u64 paddr)
+{
+ struct sgx_epc_section *section;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sgx_epc_sections); i++) {
+ section = &sgx_epc_sections[i];
+
+ if (paddr < section->phys_addr || paddr > section->end_phys_addr)
+ continue;
+
+ return &section->pages[PFN_DOWN(paddr - section->phys_addr)];
+ }
+
+ return NULL;
+}
+
+bool sgx_is_epc_page(u64 paddr)
+{
+ return !!sgx_paddr_to_page(paddr);
+}
+EXPORT_SYMBOL_GPL(sgx_is_epc_page);
+
/**
* 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
diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h
index 4e1a410b8a62..226b081a4d05 100644
--- a/arch/x86/kernel/cpu/sgx/sgx.h
+++ b/arch/x86/kernel/cpu/sgx/sgx.h
@@ -50,6 +50,7 @@ struct sgx_numa_node {
*/
struct sgx_epc_section {
unsigned long phys_addr;
+ unsigned long end_phys_addr;
void *virt_addr;
struct sgx_epc_page *pages;
struct sgx_numa_node *node;
--
2.29.2