When VM guest access a SGX EPC page with memory failure, current behavior will kill the guest, expected only kill the SGX application inside it. To fix it we send SIGBUS with code BUS_MCEERR_AR and some extra information for hypervisor to inject #MC information to guest, which is helpful in SGX case. Signed-off-by: Zhiquan Li <zhiquan1.li@xxxxxxxxx> --- arch/x86/kernel/cpu/sgx/main.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index 8e4bc6453d26..81801ab0009e 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -710,6 +710,8 @@ int arch_memory_failure(unsigned long pfn, int flags) struct sgx_epc_page *page = sgx_paddr_to_page(pfn << PAGE_SHIFT); struct sgx_epc_section *section; struct sgx_numa_node *node; + struct sgx_vepc_page *owner; + int ret = 0; /* * mm/memory-failure.c calls this routine for all errors @@ -726,8 +728,22 @@ int arch_memory_failure(unsigned long pfn, int flags) * error. The signal may help the task understand why the * enclave is broken. */ - if (flags & MF_ACTION_REQUIRED) - force_sig(SIGBUS); + if (flags & MF_ACTION_REQUIRED) { + /* + * In case the error memory is accessed by VM guest, provide + * extra info for hypervisor to make further decision but not + * simply kill it. + */ + if (page->flags & SGX_EPC_PAGE_IS_VEPC) { + owner = (struct sgx_vepc_page *)page->owner; + ret = force_sig_mceerr(BUS_MCEERR_AR, (void __user *)owner->vaddr, + PAGE_SHIFT); + if (ret < 0) + pr_err("Memory failure: Error sending signal to %s:%d: %d\n", + current->comm, current->pid, ret); + } else + force_sig(SIGBUS); + } section = &sgx_epc_sections[page->section]; node = section->node; -- 2.25.1