--- zzzz-none-000/linux-4.4.60/arch/arm/mm/fault.c 2017-04-08 07:53:53.000000000 +0000 +++ scorpion-7490-727/linux-4.4.60/arch/arm/mm/fault.c 2021-02-04 17:41:59.000000000 +0000 @@ -25,9 +25,21 @@ #include #include #include +#if defined(CONFIG_AVM_SIMPLE_PROFILING) +#include +#endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ +#if defined(CONFIG_AVM_POWER) +#include +#endif /*--- #if defined(CONFIG_AVM_POWER) ---*/ + +#if defined(CONFIG_AVM_FASTIRQ) +#include +#endif/*--- #if defined(CONFIG_AVM_FASTIRQ) ---*/ #include "fault.h" +#include + #ifdef CONFIG_MMU #ifdef CONFIG_KPROBES @@ -132,6 +144,9 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct pt_regs *regs) { +#if defined(CONFIG_AVM_FASTIRQ) + struct pt_regs fregs; +#endif /* * Are we prepared to handle this kernel fault? */ @@ -141,6 +156,10 @@ /* * No handler, we'll have to terminate things with extreme prejudice. */ +#if defined(CONFIG_AVM_FASTIRQ) + prepare_register_for_trap(&fregs, ®s); + set_exc_regs(regs); +#endif bust_spinlocks(1); pr_alert("Unable to handle kernel %s at virtual address %08lx\n", (addr < PAGE_SIZE) ? "NULL pointer dereference" : @@ -163,6 +182,8 @@ { struct siginfo si; + trace_user_fault(tsk, addr, fsr); + #ifdef CONFIG_DEBUG_USER if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) || ((user_debug & UDBG_BUS) && (sig == SIGBUS))) { @@ -243,7 +264,18 @@ goto out; } - return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); + /* + * If for any reason at all we couldn't handle the fault, make + * sure we exit gracefully rather than endlessly redo the fault. + */ +#if defined(CONFIG_AVM_POWER) + avm_page_statistic_fault_get(); +#endif/*--- #if defined(CONFIG_AVM_POWER) ---*/ + fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); +#if defined(CONFIG_AVM_POWER) + avm_page_statistic_fault_put(); +#endif/*--- #if defined(CONFIG_AVM_POWER) ---*/ + return fault; check_stack: /* Don't allow expansion below FIRST_USER_ADDRESS */ @@ -262,6 +294,10 @@ int fault, sig, code; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; +#if defined(CONFIG_AVM_SIMPLE_PROFILING) + avm_simple_profiling_enter_irq_context(regs->ARM_pc, regs->ARM_lr); +#endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ + if (notify_page_fault(regs, fsr)) return 0; @@ -308,7 +344,13 @@ #endif } +#if defined(CONFIG_AVM_SIMPLE_PROFILING) + avm_simple_profiling_log(avm_profile_data_type_hw_irq_begin, (unsigned int)regs->ARM_pc, AVM_PROFILE_PAGE_FAULT_ID); +#endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ fault = __do_page_fault(mm, addr, fsr, flags, tsk); +#if defined(CONFIG_AVM_SIMPLE_PROFILING) + avm_simple_profiling_log(avm_profile_data_type_hw_irq_end, (unsigned int)regs->ARM_pc, AVM_PROFILE_PAGE_FAULT_ID); +#endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ /* If we need to retry but a fatal signal is pending, handle the * signal first. We do not need to release the mmap_sem because @@ -430,6 +472,10 @@ if (addr < TASK_SIZE) return do_page_fault(addr, fsr, regs); +#if defined(CONFIG_AVM_SIMPLE_PROFILING) + avm_simple_profiling_enter_irq_context(regs->ARM_pc, regs->ARM_lr); +#endif/*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ + if (user_mode(regs)) goto bad_area; @@ -547,11 +593,22 @@ const struct fsr_info *inf = fsr_info + fsr_fs(fsr); struct siginfo info; +#if defined(CONFIG_AVM_FASTIRQ) + struct pt_regs fregs; +#endif if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs)) return; pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); + +#if defined(CONFIG_AVM_FASTIRQ) + if (!user_mode(regs)) { + prepare_register_for_trap(&fregs, ®s); + set_exc_regs(regs); + } +#endif + show_pte(current->mm, addr); info.si_signo = inf->sig; @@ -580,12 +637,22 @@ const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); struct siginfo info; +#if defined(CONFIG_AVM_FASTIRQ) + struct pt_regs fregs; +#endif if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) return; pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n", inf->name, ifsr, addr); +#if defined(CONFIG_AVM_FASTIRQ) + if (!user_mode(regs)) { + prepare_register_for_trap(&fregs, ®s); + set_exc_regs(regs); + } +#endif + info.si_signo = inf->sig; info.si_errno = 0; info.si_code = inf->code;