18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
68c2ecf20Sopenharmony_ci * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <asm/head.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/string.h>
128c2ecf20Sopenharmony_ci#include <linux/types.h>
138c2ecf20Sopenharmony_ci#include <linux/sched.h>
148c2ecf20Sopenharmony_ci#include <linux/sched/debug.h>
158c2ecf20Sopenharmony_ci#include <linux/ptrace.h>
168c2ecf20Sopenharmony_ci#include <linux/mman.h>
178c2ecf20Sopenharmony_ci#include <linux/signal.h>
188c2ecf20Sopenharmony_ci#include <linux/mm.h>
198c2ecf20Sopenharmony_ci#include <linux/extable.h>
208c2ecf20Sopenharmony_ci#include <linux/init.h>
218c2ecf20Sopenharmony_ci#include <linux/perf_event.h>
228c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
238c2ecf20Sopenharmony_ci#include <linux/kprobes.h>
248c2ecf20Sopenharmony_ci#include <linux/kdebug.h>
258c2ecf20Sopenharmony_ci#include <linux/percpu.h>
268c2ecf20Sopenharmony_ci#include <linux/context_tracking.h>
278c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include <asm/page.h>
308c2ecf20Sopenharmony_ci#include <asm/openprom.h>
318c2ecf20Sopenharmony_ci#include <asm/oplib.h>
328c2ecf20Sopenharmony_ci#include <asm/asi.h>
338c2ecf20Sopenharmony_ci#include <asm/lsu.h>
348c2ecf20Sopenharmony_ci#include <asm/sections.h>
358c2ecf20Sopenharmony_ci#include <asm/mmu_context.h>
368c2ecf20Sopenharmony_ci#include <asm/setup.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ciint show_unhandled_signals = 1;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic void __kprobes unhandled_fault(unsigned long address,
418c2ecf20Sopenharmony_ci				      struct task_struct *tsk,
428c2ecf20Sopenharmony_ci				      struct pt_regs *regs)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	if ((unsigned long) address < PAGE_SIZE) {
458c2ecf20Sopenharmony_ci		printk(KERN_ALERT "Unable to handle kernel NULL "
468c2ecf20Sopenharmony_ci		       "pointer dereference\n");
478c2ecf20Sopenharmony_ci	} else {
488c2ecf20Sopenharmony_ci		printk(KERN_ALERT "Unable to handle kernel paging request "
498c2ecf20Sopenharmony_ci		       "at virtual address %016lx\n", (unsigned long)address);
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci	printk(KERN_ALERT "tsk->{mm,active_mm}->context = %016lx\n",
528c2ecf20Sopenharmony_ci	       (tsk->mm ?
538c2ecf20Sopenharmony_ci		CTX_HWBITS(tsk->mm->context) :
548c2ecf20Sopenharmony_ci		CTX_HWBITS(tsk->active_mm->context)));
558c2ecf20Sopenharmony_ci	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
568c2ecf20Sopenharmony_ci	       (tsk->mm ? (unsigned long) tsk->mm->pgd :
578c2ecf20Sopenharmony_ci		          (unsigned long) tsk->active_mm->pgd));
588c2ecf20Sopenharmony_ci	die_if_kernel("Oops", regs);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic void __kprobes bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
648c2ecf20Sopenharmony_ci	       regs->tpc);
658c2ecf20Sopenharmony_ci	printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]);
668c2ecf20Sopenharmony_ci	printk("OOPS: RPC <%pS>\n", (void *) regs->u_regs[15]);
678c2ecf20Sopenharmony_ci	printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr);
688c2ecf20Sopenharmony_ci	dump_stack();
698c2ecf20Sopenharmony_ci	unhandled_fault(regs->tpc, current, regs);
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/*
738c2ecf20Sopenharmony_ci * We now make sure that mmap_lock is held in all paths that call
748c2ecf20Sopenharmony_ci * this. Additionally, to prevent kswapd from ripping ptes from
758c2ecf20Sopenharmony_ci * under us, raise interrupts around the time that we look at the
768c2ecf20Sopenharmony_ci * pte, kswapd will have to wait to get his smp ipi response from
778c2ecf20Sopenharmony_ci * us. vmtruncate likewise. This saves us having to get pte lock.
788c2ecf20Sopenharmony_ci */
798c2ecf20Sopenharmony_cistatic unsigned int get_user_insn(unsigned long tpc)
808c2ecf20Sopenharmony_ci{
818c2ecf20Sopenharmony_ci	pgd_t *pgdp = pgd_offset(current->mm, tpc);
828c2ecf20Sopenharmony_ci	p4d_t *p4dp;
838c2ecf20Sopenharmony_ci	pud_t *pudp;
848c2ecf20Sopenharmony_ci	pmd_t *pmdp;
858c2ecf20Sopenharmony_ci	pte_t *ptep, pte;
868c2ecf20Sopenharmony_ci	unsigned long pa;
878c2ecf20Sopenharmony_ci	u32 insn = 0;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp)))
908c2ecf20Sopenharmony_ci		goto out;
918c2ecf20Sopenharmony_ci	p4dp = p4d_offset(pgdp, tpc);
928c2ecf20Sopenharmony_ci	if (p4d_none(*p4dp) || unlikely(p4d_bad(*p4dp)))
938c2ecf20Sopenharmony_ci		goto out;
948c2ecf20Sopenharmony_ci	pudp = pud_offset(p4dp, tpc);
958c2ecf20Sopenharmony_ci	if (pud_none(*pudp) || unlikely(pud_bad(*pudp)))
968c2ecf20Sopenharmony_ci		goto out;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	/* This disables preemption for us as well. */
998c2ecf20Sopenharmony_ci	local_irq_disable();
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	pmdp = pmd_offset(pudp, tpc);
1028c2ecf20Sopenharmony_ci	if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp)))
1038c2ecf20Sopenharmony_ci		goto out_irq_enable;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
1068c2ecf20Sopenharmony_ci	if (is_hugetlb_pmd(*pmdp)) {
1078c2ecf20Sopenharmony_ci		pa  = pmd_pfn(*pmdp) << PAGE_SHIFT;
1088c2ecf20Sopenharmony_ci		pa += tpc & ~HPAGE_MASK;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci		/* Use phys bypass so we don't pollute dtlb/dcache. */
1118c2ecf20Sopenharmony_ci		__asm__ __volatile__("lduwa [%1] %2, %0"
1128c2ecf20Sopenharmony_ci				     : "=r" (insn)
1138c2ecf20Sopenharmony_ci				     : "r" (pa), "i" (ASI_PHYS_USE_EC));
1148c2ecf20Sopenharmony_ci	} else
1158c2ecf20Sopenharmony_ci#endif
1168c2ecf20Sopenharmony_ci	{
1178c2ecf20Sopenharmony_ci		ptep = pte_offset_map(pmdp, tpc);
1188c2ecf20Sopenharmony_ci		pte = *ptep;
1198c2ecf20Sopenharmony_ci		if (pte_present(pte)) {
1208c2ecf20Sopenharmony_ci			pa  = (pte_pfn(pte) << PAGE_SHIFT);
1218c2ecf20Sopenharmony_ci			pa += (tpc & ~PAGE_MASK);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci			/* Use phys bypass so we don't pollute dtlb/dcache. */
1248c2ecf20Sopenharmony_ci			__asm__ __volatile__("lduwa [%1] %2, %0"
1258c2ecf20Sopenharmony_ci					     : "=r" (insn)
1268c2ecf20Sopenharmony_ci					     : "r" (pa), "i" (ASI_PHYS_USE_EC));
1278c2ecf20Sopenharmony_ci		}
1288c2ecf20Sopenharmony_ci		pte_unmap(ptep);
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ciout_irq_enable:
1318c2ecf20Sopenharmony_ci	local_irq_enable();
1328c2ecf20Sopenharmony_ciout:
1338c2ecf20Sopenharmony_ci	return insn;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic inline void
1378c2ecf20Sopenharmony_cishow_signal_msg(struct pt_regs *regs, int sig, int code,
1388c2ecf20Sopenharmony_ci		unsigned long address, struct task_struct *tsk)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	if (!unhandled_signal(tsk, sig))
1418c2ecf20Sopenharmony_ci		return;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (!printk_ratelimit())
1448c2ecf20Sopenharmony_ci		return;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x",
1478c2ecf20Sopenharmony_ci	       task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
1488c2ecf20Sopenharmony_ci	       tsk->comm, task_pid_nr(tsk), address,
1498c2ecf20Sopenharmony_ci	       (void *)regs->tpc, (void *)regs->u_regs[UREG_I7],
1508c2ecf20Sopenharmony_ci	       (void *)regs->u_regs[UREG_FP], code);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	print_vma_addr(KERN_CONT " in ", regs->tpc);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	printk(KERN_CONT "\n");
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistatic void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
1588c2ecf20Sopenharmony_ci			     unsigned long fault_addr, unsigned int insn,
1598c2ecf20Sopenharmony_ci			     int fault_code)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	unsigned long addr;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	if (fault_code & FAULT_CODE_ITLB) {
1648c2ecf20Sopenharmony_ci		addr = regs->tpc;
1658c2ecf20Sopenharmony_ci	} else {
1668c2ecf20Sopenharmony_ci		/* If we were able to probe the faulting instruction, use it
1678c2ecf20Sopenharmony_ci		 * to compute a precise fault address.  Otherwise use the fault
1688c2ecf20Sopenharmony_ci		 * time provided address which may only have page granularity.
1698c2ecf20Sopenharmony_ci		 */
1708c2ecf20Sopenharmony_ci		if (insn)
1718c2ecf20Sopenharmony_ci			addr = compute_effective_address(regs, insn, 0);
1728c2ecf20Sopenharmony_ci		else
1738c2ecf20Sopenharmony_ci			addr = fault_addr;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (unlikely(show_unhandled_signals))
1778c2ecf20Sopenharmony_ci		show_signal_msg(regs, sig, code, addr, current);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	force_sig_fault(sig, code, (void __user *) addr, 0);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	if (!insn) {
1858c2ecf20Sopenharmony_ci		if (!regs->tpc || (regs->tpc & 0x3))
1868c2ecf20Sopenharmony_ci			return 0;
1878c2ecf20Sopenharmony_ci		if (regs->tstate & TSTATE_PRIV) {
1888c2ecf20Sopenharmony_ci			insn = *(unsigned int *) regs->tpc;
1898c2ecf20Sopenharmony_ci		} else {
1908c2ecf20Sopenharmony_ci			insn = get_user_insn(regs->tpc);
1918c2ecf20Sopenharmony_ci		}
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci	return insn;
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic void __kprobes do_kernel_fault(struct pt_regs *regs, int si_code,
1978c2ecf20Sopenharmony_ci				      int fault_code, unsigned int insn,
1988c2ecf20Sopenharmony_ci				      unsigned long address)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	unsigned char asi = ASI_P;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	if ((!insn) && (regs->tstate & TSTATE_PRIV))
2038c2ecf20Sopenharmony_ci		goto cannot_handle;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	/* If user insn could be read (thus insn is zero), that
2068c2ecf20Sopenharmony_ci	 * is fine.  We will just gun down the process with a signal
2078c2ecf20Sopenharmony_ci	 * in that case.
2088c2ecf20Sopenharmony_ci	 */
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if (!(fault_code & (FAULT_CODE_WRITE|FAULT_CODE_ITLB)) &&
2118c2ecf20Sopenharmony_ci	    (insn & 0xc0800000) == 0xc0800000) {
2128c2ecf20Sopenharmony_ci		if (insn & 0x2000)
2138c2ecf20Sopenharmony_ci			asi = (regs->tstate >> 24);
2148c2ecf20Sopenharmony_ci		else
2158c2ecf20Sopenharmony_ci			asi = (insn >> 5);
2168c2ecf20Sopenharmony_ci		if ((asi & 0xf2) == 0x82) {
2178c2ecf20Sopenharmony_ci			if (insn & 0x1000000) {
2188c2ecf20Sopenharmony_ci				handle_ldf_stq(insn, regs);
2198c2ecf20Sopenharmony_ci			} else {
2208c2ecf20Sopenharmony_ci				/* This was a non-faulting load. Just clear the
2218c2ecf20Sopenharmony_ci				 * destination register(s) and continue with the next
2228c2ecf20Sopenharmony_ci				 * instruction. -jj
2238c2ecf20Sopenharmony_ci				 */
2248c2ecf20Sopenharmony_ci				handle_ld_nf(insn, regs);
2258c2ecf20Sopenharmony_ci			}
2268c2ecf20Sopenharmony_ci			return;
2278c2ecf20Sopenharmony_ci		}
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Is this in ex_table? */
2318c2ecf20Sopenharmony_ci	if (regs->tstate & TSTATE_PRIV) {
2328c2ecf20Sopenharmony_ci		const struct exception_table_entry *entry;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci		entry = search_exception_tables(regs->tpc);
2358c2ecf20Sopenharmony_ci		if (entry) {
2368c2ecf20Sopenharmony_ci			regs->tpc = entry->fixup;
2378c2ecf20Sopenharmony_ci			regs->tnpc = regs->tpc + 4;
2388c2ecf20Sopenharmony_ci			return;
2398c2ecf20Sopenharmony_ci		}
2408c2ecf20Sopenharmony_ci	} else {
2418c2ecf20Sopenharmony_ci		/* The si_code was set to make clear whether
2428c2ecf20Sopenharmony_ci		 * this was a SEGV_MAPERR or SEGV_ACCERR fault.
2438c2ecf20Sopenharmony_ci		 */
2448c2ecf20Sopenharmony_ci		do_fault_siginfo(si_code, SIGSEGV, regs, address, insn, fault_code);
2458c2ecf20Sopenharmony_ci		return;
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cicannot_handle:
2498c2ecf20Sopenharmony_ci	unhandled_fault (address, current, regs);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	static int times;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (times++ < 10)
2578c2ecf20Sopenharmony_ci		printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports "
2588c2ecf20Sopenharmony_ci		       "64-bit TPC [%lx]\n",
2598c2ecf20Sopenharmony_ci		       current->comm, current->pid,
2608c2ecf20Sopenharmony_ci		       regs->tpc);
2618c2ecf20Sopenharmony_ci	show_regs(regs);
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ciasmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	enum ctx_state prev_state = exception_enter();
2678c2ecf20Sopenharmony_ci	struct mm_struct *mm = current->mm;
2688c2ecf20Sopenharmony_ci	struct vm_area_struct *vma;
2698c2ecf20Sopenharmony_ci	unsigned int insn = 0;
2708c2ecf20Sopenharmony_ci	int si_code, fault_code;
2718c2ecf20Sopenharmony_ci	vm_fault_t fault;
2728c2ecf20Sopenharmony_ci	unsigned long address, mm_rss;
2738c2ecf20Sopenharmony_ci	unsigned int flags = FAULT_FLAG_DEFAULT;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	fault_code = get_thread_fault_code();
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	if (kprobe_page_fault(regs, 0))
2788c2ecf20Sopenharmony_ci		goto exit_exception;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	si_code = SEGV_MAPERR;
2818c2ecf20Sopenharmony_ci	address = current_thread_info()->fault_address;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if ((fault_code & FAULT_CODE_ITLB) &&
2848c2ecf20Sopenharmony_ci	    (fault_code & FAULT_CODE_DTLB))
2858c2ecf20Sopenharmony_ci		BUG();
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (test_thread_flag(TIF_32BIT)) {
2888c2ecf20Sopenharmony_ci		if (!(regs->tstate & TSTATE_PRIV)) {
2898c2ecf20Sopenharmony_ci			if (unlikely((regs->tpc >> 32) != 0)) {
2908c2ecf20Sopenharmony_ci				bogus_32bit_fault_tpc(regs);
2918c2ecf20Sopenharmony_ci				goto intr_or_no_mm;
2928c2ecf20Sopenharmony_ci			}
2938c2ecf20Sopenharmony_ci		}
2948c2ecf20Sopenharmony_ci		if (unlikely((address >> 32) != 0))
2958c2ecf20Sopenharmony_ci			goto intr_or_no_mm;
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	if (regs->tstate & TSTATE_PRIV) {
2998c2ecf20Sopenharmony_ci		unsigned long tpc = regs->tpc;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		/* Sanity check the PC. */
3028c2ecf20Sopenharmony_ci		if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) ||
3038c2ecf20Sopenharmony_ci		    (tpc >= MODULES_VADDR && tpc < MODULES_END)) {
3048c2ecf20Sopenharmony_ci			/* Valid, no problems... */
3058c2ecf20Sopenharmony_ci		} else {
3068c2ecf20Sopenharmony_ci			bad_kernel_pc(regs, address);
3078c2ecf20Sopenharmony_ci			goto exit_exception;
3088c2ecf20Sopenharmony_ci		}
3098c2ecf20Sopenharmony_ci	} else
3108c2ecf20Sopenharmony_ci		flags |= FAULT_FLAG_USER;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/*
3138c2ecf20Sopenharmony_ci	 * If we're in an interrupt or have no user
3148c2ecf20Sopenharmony_ci	 * context, we must not take the fault..
3158c2ecf20Sopenharmony_ci	 */
3168c2ecf20Sopenharmony_ci	if (faulthandler_disabled() || !mm)
3178c2ecf20Sopenharmony_ci		goto intr_or_no_mm;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (!mmap_read_trylock(mm)) {
3228c2ecf20Sopenharmony_ci		if ((regs->tstate & TSTATE_PRIV) &&
3238c2ecf20Sopenharmony_ci		    !search_exception_tables(regs->tpc)) {
3248c2ecf20Sopenharmony_ci			insn = get_fault_insn(regs, insn);
3258c2ecf20Sopenharmony_ci			goto handle_kernel_fault;
3268c2ecf20Sopenharmony_ci		}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ciretry:
3298c2ecf20Sopenharmony_ci		mmap_read_lock(mm);
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (fault_code & FAULT_CODE_BAD_RA)
3338c2ecf20Sopenharmony_ci		goto do_sigbus;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	vma = find_vma(mm, address);
3368c2ecf20Sopenharmony_ci	if (!vma)
3378c2ecf20Sopenharmony_ci		goto bad_area;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	/* Pure DTLB misses do not tell us whether the fault causing
3408c2ecf20Sopenharmony_ci	 * load/store/atomic was a write or not, it only says that there
3418c2ecf20Sopenharmony_ci	 * was no match.  So in such a case we (carefully) read the
3428c2ecf20Sopenharmony_ci	 * instruction to try and figure this out.  It's an optimization
3438c2ecf20Sopenharmony_ci	 * so it's ok if we can't do this.
3448c2ecf20Sopenharmony_ci	 *
3458c2ecf20Sopenharmony_ci	 * Special hack, window spill/fill knows the exact fault type.
3468c2ecf20Sopenharmony_ci	 */
3478c2ecf20Sopenharmony_ci	if (((fault_code &
3488c2ecf20Sopenharmony_ci	      (FAULT_CODE_DTLB | FAULT_CODE_WRITE | FAULT_CODE_WINFIXUP)) == FAULT_CODE_DTLB) &&
3498c2ecf20Sopenharmony_ci	    (vma->vm_flags & VM_WRITE) != 0) {
3508c2ecf20Sopenharmony_ci		insn = get_fault_insn(regs, 0);
3518c2ecf20Sopenharmony_ci		if (!insn)
3528c2ecf20Sopenharmony_ci			goto continue_fault;
3538c2ecf20Sopenharmony_ci		/* All loads, stores and atomics have bits 30 and 31 both set
3548c2ecf20Sopenharmony_ci		 * in the instruction.  Bit 21 is set in all stores, but we
3558c2ecf20Sopenharmony_ci		 * have to avoid prefetches which also have bit 21 set.
3568c2ecf20Sopenharmony_ci		 */
3578c2ecf20Sopenharmony_ci		if ((insn & 0xc0200000) == 0xc0200000 &&
3588c2ecf20Sopenharmony_ci		    (insn & 0x01780000) != 0x01680000) {
3598c2ecf20Sopenharmony_ci			/* Don't bother updating thread struct value,
3608c2ecf20Sopenharmony_ci			 * because update_mmu_cache only cares which tlb
3618c2ecf20Sopenharmony_ci			 * the access came from.
3628c2ecf20Sopenharmony_ci			 */
3638c2ecf20Sopenharmony_ci			fault_code |= FAULT_CODE_WRITE;
3648c2ecf20Sopenharmony_ci		}
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_cicontinue_fault:
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	if (vma->vm_start <= address)
3698c2ecf20Sopenharmony_ci		goto good_area;
3708c2ecf20Sopenharmony_ci	if (!(vma->vm_flags & VM_GROWSDOWN))
3718c2ecf20Sopenharmony_ci		goto bad_area;
3728c2ecf20Sopenharmony_ci	if (!(fault_code & FAULT_CODE_WRITE)) {
3738c2ecf20Sopenharmony_ci		/* Non-faulting loads shouldn't expand stack. */
3748c2ecf20Sopenharmony_ci		insn = get_fault_insn(regs, insn);
3758c2ecf20Sopenharmony_ci		if ((insn & 0xc0800000) == 0xc0800000) {
3768c2ecf20Sopenharmony_ci			unsigned char asi;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci			if (insn & 0x2000)
3798c2ecf20Sopenharmony_ci				asi = (regs->tstate >> 24);
3808c2ecf20Sopenharmony_ci			else
3818c2ecf20Sopenharmony_ci				asi = (insn >> 5);
3828c2ecf20Sopenharmony_ci			if ((asi & 0xf2) == 0x82)
3838c2ecf20Sopenharmony_ci				goto bad_area;
3848c2ecf20Sopenharmony_ci		}
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci	if (expand_stack(vma, address))
3878c2ecf20Sopenharmony_ci		goto bad_area;
3888c2ecf20Sopenharmony_ci	/*
3898c2ecf20Sopenharmony_ci	 * Ok, we have a good vm_area for this memory access, so
3908c2ecf20Sopenharmony_ci	 * we can handle it..
3918c2ecf20Sopenharmony_ci	 */
3928c2ecf20Sopenharmony_cigood_area:
3938c2ecf20Sopenharmony_ci	si_code = SEGV_ACCERR;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	/* If we took a ITLB miss on a non-executable page, catch
3968c2ecf20Sopenharmony_ci	 * that here.
3978c2ecf20Sopenharmony_ci	 */
3988c2ecf20Sopenharmony_ci	if ((fault_code & FAULT_CODE_ITLB) && !(vma->vm_flags & VM_EXEC)) {
3998c2ecf20Sopenharmony_ci		WARN(address != regs->tpc,
4008c2ecf20Sopenharmony_ci		     "address (%lx) != regs->tpc (%lx)\n", address, regs->tpc);
4018c2ecf20Sopenharmony_ci		WARN_ON(regs->tstate & TSTATE_PRIV);
4028c2ecf20Sopenharmony_ci		goto bad_area;
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	if (fault_code & FAULT_CODE_WRITE) {
4068c2ecf20Sopenharmony_ci		if (!(vma->vm_flags & VM_WRITE))
4078c2ecf20Sopenharmony_ci			goto bad_area;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci		/* Spitfire has an icache which does not snoop
4108c2ecf20Sopenharmony_ci		 * processor stores.  Later processors do...
4118c2ecf20Sopenharmony_ci		 */
4128c2ecf20Sopenharmony_ci		if (tlb_type == spitfire &&
4138c2ecf20Sopenharmony_ci		    (vma->vm_flags & VM_EXEC) != 0 &&
4148c2ecf20Sopenharmony_ci		    vma->vm_file != NULL)
4158c2ecf20Sopenharmony_ci			set_thread_fault_code(fault_code |
4168c2ecf20Sopenharmony_ci					      FAULT_CODE_BLKCOMMIT);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci		flags |= FAULT_FLAG_WRITE;
4198c2ecf20Sopenharmony_ci	} else {
4208c2ecf20Sopenharmony_ci		/* Allow reads even for write-only mappings */
4218c2ecf20Sopenharmony_ci		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
4228c2ecf20Sopenharmony_ci			goto bad_area;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	fault = handle_mm_fault(vma, address, flags, regs);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	if (fault_signal_pending(fault, regs))
4288c2ecf20Sopenharmony_ci		goto exit_exception;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	if (unlikely(fault & VM_FAULT_ERROR)) {
4318c2ecf20Sopenharmony_ci		if (fault & VM_FAULT_OOM)
4328c2ecf20Sopenharmony_ci			goto out_of_memory;
4338c2ecf20Sopenharmony_ci		else if (fault & VM_FAULT_SIGSEGV)
4348c2ecf20Sopenharmony_ci			goto bad_area;
4358c2ecf20Sopenharmony_ci		else if (fault & VM_FAULT_SIGBUS)
4368c2ecf20Sopenharmony_ci			goto do_sigbus;
4378c2ecf20Sopenharmony_ci		BUG();
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	if (flags & FAULT_FLAG_ALLOW_RETRY) {
4418c2ecf20Sopenharmony_ci		if (fault & VM_FAULT_RETRY) {
4428c2ecf20Sopenharmony_ci			flags |= FAULT_FLAG_TRIED;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci			/* No need to mmap_read_unlock(mm) as we would
4458c2ecf20Sopenharmony_ci			 * have already released it in __lock_page_or_retry
4468c2ecf20Sopenharmony_ci			 * in mm/filemap.c.
4478c2ecf20Sopenharmony_ci			 */
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci			goto retry;
4508c2ecf20Sopenharmony_ci		}
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci	mmap_read_unlock(mm);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	mm_rss = get_mm_rss(mm);
4558c2ecf20Sopenharmony_ci#if defined(CONFIG_TRANSPARENT_HUGEPAGE)
4568c2ecf20Sopenharmony_ci	mm_rss -= (mm->context.thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
4578c2ecf20Sopenharmony_ci#endif
4588c2ecf20Sopenharmony_ci	if (unlikely(mm_rss >
4598c2ecf20Sopenharmony_ci		     mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit))
4608c2ecf20Sopenharmony_ci		tsb_grow(mm, MM_TSB_BASE, mm_rss);
4618c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
4628c2ecf20Sopenharmony_ci	mm_rss = mm->context.hugetlb_pte_count + mm->context.thp_pte_count;
4638c2ecf20Sopenharmony_ci	mm_rss *= REAL_HPAGE_PER_HPAGE;
4648c2ecf20Sopenharmony_ci	if (unlikely(mm_rss >
4658c2ecf20Sopenharmony_ci		     mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) {
4668c2ecf20Sopenharmony_ci		if (mm->context.tsb_block[MM_TSB_HUGE].tsb)
4678c2ecf20Sopenharmony_ci			tsb_grow(mm, MM_TSB_HUGE, mm_rss);
4688c2ecf20Sopenharmony_ci		else
4698c2ecf20Sopenharmony_ci			hugetlb_setup(regs);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	}
4728c2ecf20Sopenharmony_ci#endif
4738c2ecf20Sopenharmony_ciexit_exception:
4748c2ecf20Sopenharmony_ci	exception_exit(prev_state);
4758c2ecf20Sopenharmony_ci	return;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	/*
4788c2ecf20Sopenharmony_ci	 * Something tried to access memory that isn't in our memory map..
4798c2ecf20Sopenharmony_ci	 * Fix it, but check if it's kernel or user first..
4808c2ecf20Sopenharmony_ci	 */
4818c2ecf20Sopenharmony_cibad_area:
4828c2ecf20Sopenharmony_ci	insn = get_fault_insn(regs, insn);
4838c2ecf20Sopenharmony_ci	mmap_read_unlock(mm);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cihandle_kernel_fault:
4868c2ecf20Sopenharmony_ci	do_kernel_fault(regs, si_code, fault_code, insn, address);
4878c2ecf20Sopenharmony_ci	goto exit_exception;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci/*
4908c2ecf20Sopenharmony_ci * We ran out of memory, or some other thing happened to us that made
4918c2ecf20Sopenharmony_ci * us unable to handle the page fault gracefully.
4928c2ecf20Sopenharmony_ci */
4938c2ecf20Sopenharmony_ciout_of_memory:
4948c2ecf20Sopenharmony_ci	insn = get_fault_insn(regs, insn);
4958c2ecf20Sopenharmony_ci	mmap_read_unlock(mm);
4968c2ecf20Sopenharmony_ci	if (!(regs->tstate & TSTATE_PRIV)) {
4978c2ecf20Sopenharmony_ci		pagefault_out_of_memory();
4988c2ecf20Sopenharmony_ci		goto exit_exception;
4998c2ecf20Sopenharmony_ci	}
5008c2ecf20Sopenharmony_ci	goto handle_kernel_fault;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ciintr_or_no_mm:
5038c2ecf20Sopenharmony_ci	insn = get_fault_insn(regs, 0);
5048c2ecf20Sopenharmony_ci	goto handle_kernel_fault;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_cido_sigbus:
5078c2ecf20Sopenharmony_ci	insn = get_fault_insn(regs, insn);
5088c2ecf20Sopenharmony_ci	mmap_read_unlock(mm);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	/*
5118c2ecf20Sopenharmony_ci	 * Send a sigbus, regardless of whether we were in kernel
5128c2ecf20Sopenharmony_ci	 * or user mode.
5138c2ecf20Sopenharmony_ci	 */
5148c2ecf20Sopenharmony_ci	do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, address, insn, fault_code);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	/* Kernel mode? Handle exceptions or die */
5178c2ecf20Sopenharmony_ci	if (regs->tstate & TSTATE_PRIV)
5188c2ecf20Sopenharmony_ci		goto handle_kernel_fault;
5198c2ecf20Sopenharmony_ci}
520