On Mon, 2021-10-11 at 11:59 -0700, Tony Luck wrote: > Add a call inside memory_failure() to call the arch specific code > to check if the address is an SGX EPC page and handle it. > > Note the SGX EPC pages do not have a "struct page" entry, so the hook > goes in at the same point as the device mapping hook. > > Pull the call to acquire the mutex earlier so the SGX errors are also > protected. > > Make set_mce_nospec() skip SGX pages when trying to adjust > the 1:1 map. > > Tested-by: Reinette Chatre <reinette.chatre@xxxxxxxxx> > Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx> > --- > arch/x86/include/asm/processor.h | 8 ++++++++ > arch/x86/include/asm/set_memory.h | 4 ++++ > include/linux/mm.h | 14 ++++++++++++++ > mm/memory-failure.c | 19 +++++++++++++------ > 4 files changed, 39 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h > index 9ad2acaaae9b..4865f2860a4f 100644 > --- a/arch/x86/include/asm/processor.h > +++ b/arch/x86/include/asm/processor.h > @@ -853,4 +853,12 @@ enum mds_mitigations { > MDS_MITIGATION_VMWERV, > }; > > +#ifdef CONFIG_X86_SGX > +int arch_memory_failure(unsigned long pfn, int flags); > +#define arch_memory_failure arch_memory_failure > + > +bool arch_is_platform_page(u64 paddr); > +#define arch_is_platform_page arch_is_platform_page > +#endif > + > #endif /* _ASM_X86_PROCESSOR_H */ > diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h > index 43fa081a1adb..ce8dd215f5b3 100644 > --- a/arch/x86/include/asm/set_memory.h > +++ b/arch/x86/include/asm/set_memory.h > @@ -2,6 +2,7 @@ > #ifndef _ASM_X86_SET_MEMORY_H > #define _ASM_X86_SET_MEMORY_H > > +#include <linux/mm.h> > #include <asm/page.h> > #include <asm-generic/set_memory.h> > > @@ -98,6 +99,9 @@ static inline int set_mce_nospec(unsigned long pfn, bool unmap) > unsigned long decoy_addr; > int rc; > > + /* SGX pages are not in the 1:1 map */ > + if (arch_is_platform_page(pfn << PAGE_SHIFT)) > + return 0; > /* > * We would like to just call: > * set_memory_XX((unsigned long)pfn_to_kaddr(pfn), 1); > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 73a52aba448f..62b199ed5ec6 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -3284,5 +3284,19 @@ static inline int seal_check_future_write(int seals, struct vm_area_struct *vma) > return 0; > } > > +#ifndef arch_memory_failure > +static inline int arch_memory_failure(unsigned long pfn, int flags) > +{ > + return -ENXIO; > +} > +#endif > + > +#ifndef arch_is_platform_page > +static inline bool arch_is_platform_page(u64 paddr) > +{ > + return false; > +} > +#endif > + > #endif /* __KERNEL__ */ > #endif /* _LINUX_MM_H */ > diff --git a/mm/memory-failure.c b/mm/memory-failure.c > index 3e6449f2102a..b1cbf9845c19 100644 > --- a/mm/memory-failure.c > +++ b/mm/memory-failure.c > @@ -1632,21 +1632,28 @@ int memory_failure(unsigned long pfn, int flags) > if (!sysctl_memory_failure_recovery) > panic("Memory failure on page %lx", pfn); > > + mutex_lock(&mf_mutex); > + > p = pfn_to_online_page(pfn); > if (!p) { > + res = arch_memory_failure(pfn, flags); > + if (res == 0) > + goto unlock_mutex; > + > if (pfn_valid(pfn)) { > pgmap = get_dev_pagemap(pfn, NULL); > - if (pgmap) > - return memory_failure_dev_pagemap(pfn, flags, > - pgmap); > + if (pgmap) { > + res = memory_failure_dev_pagemap(pfn, flags, > + pgmap); > + goto unlock_mutex; > + } > } > pr_err("Memory failure: %#lx: memory outside kernel control\n", > pfn); > - return -ENXIO; > + res = -ENXIO; > + goto unlock_mutex; > } > > - mutex_lock(&mf_mutex); > - > try_again: > if (PageHuge(p)) { > res = memory_failure_hugetlb(pfn, flags); Reviewed-by: Jarkko Sakkinen <jarkko@xxxxxxxxxx> /Jarkko