162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * fault.c:  Page fault handlers for the Sparc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
662306a36Sopenharmony_ci * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
762306a36Sopenharmony_ci * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <asm/head.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/string.h>
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/sched.h>
1562306a36Sopenharmony_ci#include <linux/ptrace.h>
1662306a36Sopenharmony_ci#include <linux/mman.h>
1762306a36Sopenharmony_ci#include <linux/threads.h>
1862306a36Sopenharmony_ci#include <linux/kernel.h>
1962306a36Sopenharmony_ci#include <linux/signal.h>
2062306a36Sopenharmony_ci#include <linux/mm.h>
2162306a36Sopenharmony_ci#include <linux/smp.h>
2262306a36Sopenharmony_ci#include <linux/perf_event.h>
2362306a36Sopenharmony_ci#include <linux/interrupt.h>
2462306a36Sopenharmony_ci#include <linux/kdebug.h>
2562306a36Sopenharmony_ci#include <linux/uaccess.h>
2662306a36Sopenharmony_ci#include <linux/extable.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <asm/page.h>
2962306a36Sopenharmony_ci#include <asm/openprom.h>
3062306a36Sopenharmony_ci#include <asm/oplib.h>
3162306a36Sopenharmony_ci#include <asm/setup.h>
3262306a36Sopenharmony_ci#include <asm/smp.h>
3362306a36Sopenharmony_ci#include <asm/traps.h>
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "mm_32.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciint show_unhandled_signals = 1;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic void __noreturn unhandled_fault(unsigned long address,
4062306a36Sopenharmony_ci				       struct task_struct *tsk,
4162306a36Sopenharmony_ci				       struct pt_regs *regs)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	if ((unsigned long) address < PAGE_SIZE) {
4462306a36Sopenharmony_ci		printk(KERN_ALERT
4562306a36Sopenharmony_ci		    "Unable to handle kernel NULL pointer dereference\n");
4662306a36Sopenharmony_ci	} else {
4762306a36Sopenharmony_ci		printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",
4862306a36Sopenharmony_ci		       address);
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci	printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n",
5162306a36Sopenharmony_ci		(tsk->mm ? tsk->mm->context : tsk->active_mm->context));
5262306a36Sopenharmony_ci	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n",
5362306a36Sopenharmony_ci		(tsk->mm ? (unsigned long) tsk->mm->pgd :
5462306a36Sopenharmony_ci			(unsigned long) tsk->active_mm->pgd));
5562306a36Sopenharmony_ci	die_if_kernel("Oops", regs);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline void
5962306a36Sopenharmony_cishow_signal_msg(struct pt_regs *regs, int sig, int code,
6062306a36Sopenharmony_ci		unsigned long address, struct task_struct *tsk)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	if (!unhandled_signal(tsk, sig))
6362306a36Sopenharmony_ci		return;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (!printk_ratelimit())
6662306a36Sopenharmony_ci		return;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x",
6962306a36Sopenharmony_ci	       task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
7062306a36Sopenharmony_ci	       tsk->comm, task_pid_nr(tsk), address,
7162306a36Sopenharmony_ci	       (void *)regs->pc, (void *)regs->u_regs[UREG_I7],
7262306a36Sopenharmony_ci	       (void *)regs->u_regs[UREG_FP], code);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	print_vma_addr(KERN_CONT " in ", regs->pc);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	printk(KERN_CONT "\n");
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void __do_fault_siginfo(int code, int sig, struct pt_regs *regs,
8062306a36Sopenharmony_ci			       unsigned long addr)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	if (unlikely(show_unhandled_signals))
8362306a36Sopenharmony_ci		show_signal_msg(regs, sig, code,
8462306a36Sopenharmony_ci				addr, current);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	force_sig_fault(sig, code, (void __user *) addr);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	unsigned int insn;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if (text_fault)
9462306a36Sopenharmony_ci		return regs->pc;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (regs->psr & PSR_PS)
9762306a36Sopenharmony_ci		insn = *(unsigned int *) regs->pc;
9862306a36Sopenharmony_ci	else
9962306a36Sopenharmony_ci		__get_user(insn, (unsigned int *) regs->pc);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	return safe_compute_effective_address(regs, insn);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
10562306a36Sopenharmony_ci				      int text_fault)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	unsigned long addr = compute_si_addr(regs, text_fault);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	__do_fault_siginfo(code, sig, regs, addr);
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ciasmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
11362306a36Sopenharmony_ci			       unsigned long address)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	struct vm_area_struct *vma;
11662306a36Sopenharmony_ci	struct task_struct *tsk = current;
11762306a36Sopenharmony_ci	struct mm_struct *mm = tsk->mm;
11862306a36Sopenharmony_ci	int from_user = !(regs->psr & PSR_PS);
11962306a36Sopenharmony_ci	int code;
12062306a36Sopenharmony_ci	vm_fault_t fault;
12162306a36Sopenharmony_ci	unsigned int flags = FAULT_FLAG_DEFAULT;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	if (text_fault)
12462306a36Sopenharmony_ci		address = regs->pc;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/*
12762306a36Sopenharmony_ci	 * We fault-in kernel-space virtual memory on-demand. The
12862306a36Sopenharmony_ci	 * 'reference' page table is init_mm.pgd.
12962306a36Sopenharmony_ci	 *
13062306a36Sopenharmony_ci	 * NOTE! We MUST NOT take any locks for this case. We may
13162306a36Sopenharmony_ci	 * be in an interrupt or a critical region, and should
13262306a36Sopenharmony_ci	 * only copy the information from the master page table,
13362306a36Sopenharmony_ci	 * nothing more.
13462306a36Sopenharmony_ci	 */
13562306a36Sopenharmony_ci	code = SEGV_MAPERR;
13662306a36Sopenharmony_ci	if (address >= TASK_SIZE)
13762306a36Sopenharmony_ci		goto vmalloc_fault;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	/*
14062306a36Sopenharmony_ci	 * If we're in an interrupt or have no user
14162306a36Sopenharmony_ci	 * context, we must not take the fault..
14262306a36Sopenharmony_ci	 */
14362306a36Sopenharmony_ci	if (pagefault_disabled() || !mm)
14462306a36Sopenharmony_ci		goto no_context;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (!from_user && address >= PAGE_OFFSET)
14762306a36Sopenharmony_ci		goto no_context;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ciretry:
15262306a36Sopenharmony_ci	vma = lock_mm_and_find_vma(mm, address, regs);
15362306a36Sopenharmony_ci	if (!vma)
15462306a36Sopenharmony_ci		goto bad_area_nosemaphore;
15562306a36Sopenharmony_ci	/*
15662306a36Sopenharmony_ci	 * Ok, we have a good vm_area for this memory access, so
15762306a36Sopenharmony_ci	 * we can handle it..
15862306a36Sopenharmony_ci	 */
15962306a36Sopenharmony_ci	code = SEGV_ACCERR;
16062306a36Sopenharmony_ci	if (write) {
16162306a36Sopenharmony_ci		if (!(vma->vm_flags & VM_WRITE))
16262306a36Sopenharmony_ci			goto bad_area;
16362306a36Sopenharmony_ci	} else {
16462306a36Sopenharmony_ci		/* Allow reads even for write-only mappings */
16562306a36Sopenharmony_ci		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
16662306a36Sopenharmony_ci			goto bad_area;
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	if (from_user)
17062306a36Sopenharmony_ci		flags |= FAULT_FLAG_USER;
17162306a36Sopenharmony_ci	if (write)
17262306a36Sopenharmony_ci		flags |= FAULT_FLAG_WRITE;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/*
17562306a36Sopenharmony_ci	 * If for any reason at all we couldn't handle the fault,
17662306a36Sopenharmony_ci	 * make sure we exit gracefully rather than endlessly redo
17762306a36Sopenharmony_ci	 * the fault.
17862306a36Sopenharmony_ci	 */
17962306a36Sopenharmony_ci	fault = handle_mm_fault(vma, address, flags, regs);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (fault_signal_pending(fault, regs)) {
18262306a36Sopenharmony_ci		if (!from_user)
18362306a36Sopenharmony_ci			goto no_context;
18462306a36Sopenharmony_ci		return;
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* The fault is fully completed (including releasing mmap lock) */
18862306a36Sopenharmony_ci	if (fault & VM_FAULT_COMPLETED)
18962306a36Sopenharmony_ci		return;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if (unlikely(fault & VM_FAULT_ERROR)) {
19262306a36Sopenharmony_ci		if (fault & VM_FAULT_OOM)
19362306a36Sopenharmony_ci			goto out_of_memory;
19462306a36Sopenharmony_ci		else if (fault & VM_FAULT_SIGSEGV)
19562306a36Sopenharmony_ci			goto bad_area;
19662306a36Sopenharmony_ci		else if (fault & VM_FAULT_SIGBUS)
19762306a36Sopenharmony_ci			goto do_sigbus;
19862306a36Sopenharmony_ci		BUG();
19962306a36Sopenharmony_ci	}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	if (fault & VM_FAULT_RETRY) {
20262306a36Sopenharmony_ci		flags |= FAULT_FLAG_TRIED;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci		/* No need to mmap_read_unlock(mm) as we would
20562306a36Sopenharmony_ci		 * have already released it in __lock_page_or_retry
20662306a36Sopenharmony_ci		 * in mm/filemap.c.
20762306a36Sopenharmony_ci		 */
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		goto retry;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	mmap_read_unlock(mm);
21362306a36Sopenharmony_ci	return;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	/*
21662306a36Sopenharmony_ci	 * Something tried to access memory that isn't in our memory map..
21762306a36Sopenharmony_ci	 * Fix it, but check if it's kernel or user first..
21862306a36Sopenharmony_ci	 */
21962306a36Sopenharmony_cibad_area:
22062306a36Sopenharmony_ci	mmap_read_unlock(mm);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cibad_area_nosemaphore:
22362306a36Sopenharmony_ci	/* User mode accesses just cause a SIGSEGV */
22462306a36Sopenharmony_ci	if (from_user) {
22562306a36Sopenharmony_ci		do_fault_siginfo(code, SIGSEGV, regs, text_fault);
22662306a36Sopenharmony_ci		return;
22762306a36Sopenharmony_ci	}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	/* Is this in ex_table? */
23062306a36Sopenharmony_cino_context:
23162306a36Sopenharmony_ci	if (!from_user) {
23262306a36Sopenharmony_ci		const struct exception_table_entry *entry;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		entry = search_exception_tables(regs->pc);
23562306a36Sopenharmony_ci#ifdef DEBUG_EXCEPTIONS
23662306a36Sopenharmony_ci		printk("Exception: PC<%08lx> faddr<%08lx>\n",
23762306a36Sopenharmony_ci		       regs->pc, address);
23862306a36Sopenharmony_ci		printk("EX_TABLE: insn<%08lx> fixup<%08x>\n",
23962306a36Sopenharmony_ci			regs->pc, entry->fixup);
24062306a36Sopenharmony_ci#endif
24162306a36Sopenharmony_ci		regs->pc = entry->fixup;
24262306a36Sopenharmony_ci		regs->npc = regs->pc + 4;
24362306a36Sopenharmony_ci		return;
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	unhandled_fault(address, tsk, regs);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci/*
24962306a36Sopenharmony_ci * We ran out of memory, or some other thing happened to us that made
25062306a36Sopenharmony_ci * us unable to handle the page fault gracefully.
25162306a36Sopenharmony_ci */
25262306a36Sopenharmony_ciout_of_memory:
25362306a36Sopenharmony_ci	mmap_read_unlock(mm);
25462306a36Sopenharmony_ci	if (from_user) {
25562306a36Sopenharmony_ci		pagefault_out_of_memory();
25662306a36Sopenharmony_ci		return;
25762306a36Sopenharmony_ci	}
25862306a36Sopenharmony_ci	goto no_context;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cido_sigbus:
26162306a36Sopenharmony_ci	mmap_read_unlock(mm);
26262306a36Sopenharmony_ci	do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault);
26362306a36Sopenharmony_ci	if (!from_user)
26462306a36Sopenharmony_ci		goto no_context;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_civmalloc_fault:
26762306a36Sopenharmony_ci	{
26862306a36Sopenharmony_ci		/*
26962306a36Sopenharmony_ci		 * Synchronize this task's top level page-table
27062306a36Sopenharmony_ci		 * with the 'reference' page table.
27162306a36Sopenharmony_ci		 */
27262306a36Sopenharmony_ci		int offset = pgd_index(address);
27362306a36Sopenharmony_ci		pgd_t *pgd, *pgd_k;
27462306a36Sopenharmony_ci		p4d_t *p4d, *p4d_k;
27562306a36Sopenharmony_ci		pud_t *pud, *pud_k;
27662306a36Sopenharmony_ci		pmd_t *pmd, *pmd_k;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		pgd = tsk->active_mm->pgd + offset;
27962306a36Sopenharmony_ci		pgd_k = init_mm.pgd + offset;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		if (!pgd_present(*pgd)) {
28262306a36Sopenharmony_ci			if (!pgd_present(*pgd_k))
28362306a36Sopenharmony_ci				goto bad_area_nosemaphore;
28462306a36Sopenharmony_ci			pgd_val(*pgd) = pgd_val(*pgd_k);
28562306a36Sopenharmony_ci			return;
28662306a36Sopenharmony_ci		}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		p4d = p4d_offset(pgd, address);
28962306a36Sopenharmony_ci		pud = pud_offset(p4d, address);
29062306a36Sopenharmony_ci		pmd = pmd_offset(pud, address);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		p4d_k = p4d_offset(pgd_k, address);
29362306a36Sopenharmony_ci		pud_k = pud_offset(p4d_k, address);
29462306a36Sopenharmony_ci		pmd_k = pmd_offset(pud_k, address);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci		if (pmd_present(*pmd) || !pmd_present(*pmd_k))
29762306a36Sopenharmony_ci			goto bad_area_nosemaphore;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci		*pmd = *pmd_k;
30062306a36Sopenharmony_ci		return;
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci/* This always deals with user addresses. */
30562306a36Sopenharmony_cistatic void force_user_fault(unsigned long address, int write)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	struct vm_area_struct *vma;
30862306a36Sopenharmony_ci	struct task_struct *tsk = current;
30962306a36Sopenharmony_ci	struct mm_struct *mm = tsk->mm;
31062306a36Sopenharmony_ci	unsigned int flags = FAULT_FLAG_USER;
31162306a36Sopenharmony_ci	int code;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	code = SEGV_MAPERR;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	vma = lock_mm_and_find_vma(mm, address, NULL);
31662306a36Sopenharmony_ci	if (!vma)
31762306a36Sopenharmony_ci		goto bad_area_nosemaphore;
31862306a36Sopenharmony_ci	code = SEGV_ACCERR;
31962306a36Sopenharmony_ci	if (write) {
32062306a36Sopenharmony_ci		if (!(vma->vm_flags & VM_WRITE))
32162306a36Sopenharmony_ci			goto bad_area;
32262306a36Sopenharmony_ci		flags |= FAULT_FLAG_WRITE;
32362306a36Sopenharmony_ci	} else {
32462306a36Sopenharmony_ci		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
32562306a36Sopenharmony_ci			goto bad_area;
32662306a36Sopenharmony_ci	}
32762306a36Sopenharmony_ci	switch (handle_mm_fault(vma, address, flags, NULL)) {
32862306a36Sopenharmony_ci	case VM_FAULT_SIGBUS:
32962306a36Sopenharmony_ci	case VM_FAULT_OOM:
33062306a36Sopenharmony_ci		goto do_sigbus;
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci	mmap_read_unlock(mm);
33362306a36Sopenharmony_ci	return;
33462306a36Sopenharmony_cibad_area:
33562306a36Sopenharmony_ci	mmap_read_unlock(mm);
33662306a36Sopenharmony_cibad_area_nosemaphore:
33762306a36Sopenharmony_ci	__do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address);
33862306a36Sopenharmony_ci	return;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cido_sigbus:
34162306a36Sopenharmony_ci	mmap_read_unlock(mm);
34262306a36Sopenharmony_ci	__do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address);
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic void check_stack_aligned(unsigned long sp)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	if (sp & 0x7UL)
34862306a36Sopenharmony_ci		force_sig(SIGILL);
34962306a36Sopenharmony_ci}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_civoid window_overflow_fault(void)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	unsigned long sp;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	sp = current_thread_info()->rwbuf_stkptrs[0];
35662306a36Sopenharmony_ci	if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
35762306a36Sopenharmony_ci		force_user_fault(sp + 0x38, 1);
35862306a36Sopenharmony_ci	force_user_fault(sp, 1);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	check_stack_aligned(sp);
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_civoid window_underflow_fault(unsigned long sp)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
36662306a36Sopenharmony_ci		force_user_fault(sp + 0x38, 0);
36762306a36Sopenharmony_ci	force_user_fault(sp, 0);
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	check_stack_aligned(sp);
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_civoid window_ret_fault(struct pt_regs *regs)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	unsigned long sp;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	sp = regs->u_regs[UREG_FP];
37762306a36Sopenharmony_ci	if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
37862306a36Sopenharmony_ci		force_user_fault(sp + 0x38, 0);
37962306a36Sopenharmony_ci	force_user_fault(sp, 0);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	check_stack_aligned(sp);
38262306a36Sopenharmony_ci}
383