On Mon, 2021-09-27 at 14:34 -0700, Tony Luck wrote: > 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. > > SGX EPC pages do not have Linux "struct page" associated with them. > > Keep track of the mapping from ranges of EPC pages to the sections > that contain them using an xarray. > > Create a function arch_is_platform_page() that simply reports whether an address > is an EPC page for use elsewhere in the kernel. The ACPI error injection > code needs this function and is typically built as a module, so export it. > > Note that arch_is_platform_page() will be slower than other similar "what type > is this page" functions that can simply check bits in the "struct page". > If there is some future performance critical user of this function it > may need to be implemented in a more efficient way. > > Note also that the current implementation of xarray allocates a few > hundred kilobytes for this usage on a system with 4GB of SGX EPC memory > configured. This isn't ideal, but worth it for the code simplicity. > > Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx> > --- > arch/x86/kernel/cpu/sgx/main.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c > index d18988a46c13..09fa42690ff2 100644 > --- a/arch/x86/kernel/cpu/sgx/main.c > +++ b/arch/x86/kernel/cpu/sgx/main.c > @@ -20,6 +20,7 @@ struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; > static int sgx_nr_epc_sections; > static struct task_struct *ksgxd_tsk; > static DECLARE_WAIT_QUEUE_HEAD(ksgxd_waitq); > +static DEFINE_XARRAY(sgx_epc_address_space); > > /* > * These variables are part of the state of the reclaimer, and must be accessed > @@ -650,6 +651,8 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, > } > > section->phys_addr = phys_addr; > + xa_store_range(&sgx_epc_address_space, section->phys_addr, > + phys_addr + size - 1, section, GFP_KERNEL); > > for (i = 0; i < nr_pages; i++) { > section->pages[i].section = index; > @@ -661,6 +664,12 @@ static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, > return true; > } > > +bool arch_is_platform_page(u64 paddr) > +{ > + return !!xa_load(&sgx_epc_address_space, paddr); > +} > +EXPORT_SYMBOL_GPL(arch_is_platform_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 Reviewed-by: Jarkko Sakkinen <jarkko@xxxxxxxxxx> /Jarkko