xref: /openbmc/linux/arch/sparc/mm/fault_32.c (revision 0b26eadb)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2c37ddd93SSam Ravnborg /*
3c37ddd93SSam Ravnborg  * fault.c:  Page fault handlers for the Sparc.
4c37ddd93SSam Ravnborg  *
5c37ddd93SSam Ravnborg  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6c37ddd93SSam Ravnborg  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
7c37ddd93SSam Ravnborg  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
8c37ddd93SSam Ravnborg  */
9c37ddd93SSam Ravnborg 
10c37ddd93SSam Ravnborg #include <asm/head.h>
11c37ddd93SSam Ravnborg 
12c37ddd93SSam Ravnborg #include <linux/string.h>
13c37ddd93SSam Ravnborg #include <linux/types.h>
14c37ddd93SSam Ravnborg #include <linux/sched.h>
15c37ddd93SSam Ravnborg #include <linux/ptrace.h>
16c37ddd93SSam Ravnborg #include <linux/mman.h>
17c37ddd93SSam Ravnborg #include <linux/threads.h>
18c37ddd93SSam Ravnborg #include <linux/kernel.h>
19c37ddd93SSam Ravnborg #include <linux/signal.h>
20c37ddd93SSam Ravnborg #include <linux/mm.h>
21c37ddd93SSam Ravnborg #include <linux/smp.h>
22a084b667SDavid S. Miller #include <linux/perf_event.h>
23c37ddd93SSam Ravnborg #include <linux/interrupt.h>
24c37ddd93SSam Ravnborg #include <linux/kdebug.h>
2570ffdb93SDavid Hildenbrand #include <linux/uaccess.h>
26b4edf06cSAl Viro #include <linux/extable.h>
27c37ddd93SSam Ravnborg 
28c37ddd93SSam Ravnborg #include <asm/page.h>
29c37ddd93SSam Ravnborg #include <asm/openprom.h>
30c37ddd93SSam Ravnborg #include <asm/oplib.h>
319edfae3fSSam Ravnborg #include <asm/setup.h>
32c37ddd93SSam Ravnborg #include <asm/smp.h>
33c37ddd93SSam Ravnborg #include <asm/traps.h>
34c37ddd93SSam Ravnborg 
35e1b2f134SSam Ravnborg #include "mm_32.h"
364b177647SDavid S. Miller 
37e1b2f134SSam Ravnborg int show_unhandled_signals = 1;
38c37ddd93SSam Ravnborg 
unhandled_fault(unsigned long address,struct task_struct * tsk,struct pt_regs * regs)3970168dfaSSam Ravnborg static void __noreturn unhandled_fault(unsigned long address,
4070168dfaSSam Ravnborg 				       struct task_struct *tsk,
41c37ddd93SSam Ravnborg 				       struct pt_regs *regs)
42c37ddd93SSam Ravnborg {
43c37ddd93SSam Ravnborg 	if ((unsigned long) address < PAGE_SIZE) {
44c37ddd93SSam Ravnborg 		printk(KERN_ALERT
45c37ddd93SSam Ravnborg 		    "Unable to handle kernel NULL pointer dereference\n");
46c37ddd93SSam Ravnborg 	} else {
4770168dfaSSam Ravnborg 		printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",
4870168dfaSSam Ravnborg 		       address);
49c37ddd93SSam Ravnborg 	}
50c37ddd93SSam Ravnborg 	printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n",
51c37ddd93SSam Ravnborg 		(tsk->mm ? tsk->mm->context : tsk->active_mm->context));
52c37ddd93SSam Ravnborg 	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n",
53c37ddd93SSam Ravnborg 		(tsk->mm ? (unsigned long) tsk->mm->pgd :
54c37ddd93SSam Ravnborg 			(unsigned long) tsk->active_mm->pgd));
55c37ddd93SSam Ravnborg 	die_if_kernel("Oops", regs);
56c37ddd93SSam Ravnborg }
57c37ddd93SSam Ravnborg 
584b177647SDavid S. Miller static inline void
show_signal_msg(struct pt_regs * regs,int sig,int code,unsigned long address,struct task_struct * tsk)594b177647SDavid S. Miller show_signal_msg(struct pt_regs *regs, int sig, int code,
604b177647SDavid S. Miller 		unsigned long address, struct task_struct *tsk)
614b177647SDavid S. Miller {
624b177647SDavid S. Miller 	if (!unhandled_signal(tsk, sig))
634b177647SDavid S. Miller 		return;
644b177647SDavid S. Miller 
654b177647SDavid S. Miller 	if (!printk_ratelimit())
664b177647SDavid S. Miller 		return;
674b177647SDavid S. Miller 
6810a7e9d8SKees Cook 	printk("%s%s[%d]: segfault at %lx ip %px (rpc %px) sp %px error %x",
694b177647SDavid S. Miller 	       task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
704b177647SDavid S. Miller 	       tsk->comm, task_pid_nr(tsk), address,
714b177647SDavid S. Miller 	       (void *)regs->pc, (void *)regs->u_regs[UREG_I7],
724b177647SDavid S. Miller 	       (void *)regs->u_regs[UREG_FP], code);
734b177647SDavid S. Miller 
744b177647SDavid S. Miller 	print_vma_addr(KERN_CONT " in ", regs->pc);
754b177647SDavid S. Miller 
764b177647SDavid S. Miller 	printk(KERN_CONT "\n");
774b177647SDavid S. Miller }
784b177647SDavid S. Miller 
__do_fault_siginfo(int code,int sig,struct pt_regs * regs,unsigned long addr)794b177647SDavid S. Miller static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs,
804b177647SDavid S. Miller 			       unsigned long addr)
814b177647SDavid S. Miller {
824b177647SDavid S. Miller 	if (unlikely(show_unhandled_signals))
83d1f5bef6SEric W. Biederman 		show_signal_msg(regs, sig, code,
844b177647SDavid S. Miller 				addr, current);
854b177647SDavid S. Miller 
862c9f7eafSEric W. Biederman 	force_sig_fault(sig, code, (void __user *) addr);
874b177647SDavid S. Miller }
884b177647SDavid S. Miller 
compute_si_addr(struct pt_regs * regs,int text_fault)89c37ddd93SSam Ravnborg static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
90c37ddd93SSam Ravnborg {
91c37ddd93SSam Ravnborg 	unsigned int insn;
92c37ddd93SSam Ravnborg 
93c37ddd93SSam Ravnborg 	if (text_fault)
94c37ddd93SSam Ravnborg 		return regs->pc;
95c37ddd93SSam Ravnborg 
9670168dfaSSam Ravnborg 	if (regs->psr & PSR_PS)
97c37ddd93SSam Ravnborg 		insn = *(unsigned int *) regs->pc;
9870168dfaSSam Ravnborg 	else
99c37ddd93SSam Ravnborg 		__get_user(insn, (unsigned int *) regs->pc);
100c37ddd93SSam Ravnborg 
101c37ddd93SSam Ravnborg 	return safe_compute_effective_address(regs, insn);
102c37ddd93SSam Ravnborg }
103c37ddd93SSam Ravnborg 
do_fault_siginfo(int code,int sig,struct pt_regs * regs,int text_fault)1044b177647SDavid S. Miller static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
1054b177647SDavid S. Miller 				      int text_fault)
1064b177647SDavid S. Miller {
1074b177647SDavid S. Miller 	unsigned long addr = compute_si_addr(regs, text_fault);
1084b177647SDavid S. Miller 
1094b177647SDavid S. Miller 	__do_fault_siginfo(code, sig, regs, addr);
1104b177647SDavid S. Miller }
1114b177647SDavid S. Miller 
do_sparc_fault(struct pt_regs * regs,int text_fault,int write,unsigned long address)112c37ddd93SSam Ravnborg asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
113c37ddd93SSam Ravnborg 			       unsigned long address)
114c37ddd93SSam Ravnborg {
115c37ddd93SSam Ravnborg 	struct vm_area_struct *vma;
116c37ddd93SSam Ravnborg 	struct task_struct *tsk = current;
117c37ddd93SSam Ravnborg 	struct mm_struct *mm = tsk->mm;
118c37ddd93SSam Ravnborg 	int from_user = !(regs->psr & PSR_PS);
11950a7ca3cSSouptick Joarder 	int code;
12050a7ca3cSSouptick Joarder 	vm_fault_t fault;
121dde16072SPeter Xu 	unsigned int flags = FAULT_FLAG_DEFAULT;
122c37ddd93SSam Ravnborg 
123c37ddd93SSam Ravnborg 	if (text_fault)
124c37ddd93SSam Ravnborg 		address = regs->pc;
125c37ddd93SSam Ravnborg 
126c37ddd93SSam Ravnborg 	/*
127c37ddd93SSam Ravnborg 	 * We fault-in kernel-space virtual memory on-demand. The
128c37ddd93SSam Ravnborg 	 * 'reference' page table is init_mm.pgd.
129c37ddd93SSam Ravnborg 	 *
130c37ddd93SSam Ravnborg 	 * NOTE! We MUST NOT take any locks for this case. We may
131c37ddd93SSam Ravnborg 	 * be in an interrupt or a critical region, and should
132c37ddd93SSam Ravnborg 	 * only copy the information from the master page table,
133c37ddd93SSam Ravnborg 	 * nothing more.
134c37ddd93SSam Ravnborg 	 */
135c816be7bSDavid S. Miller 	code = SEGV_MAPERR;
136582a0baeSSam Ravnborg 	if (address >= TASK_SIZE)
137c37ddd93SSam Ravnborg 		goto vmalloc_fault;
138c37ddd93SSam Ravnborg 
139c37ddd93SSam Ravnborg 	/*
140c37ddd93SSam Ravnborg 	 * If we're in an interrupt or have no user
141c37ddd93SSam Ravnborg 	 * context, we must not take the fault..
142c37ddd93SSam Ravnborg 	 */
14370ffdb93SDavid Hildenbrand 	if (pagefault_disabled() || !mm)
144c37ddd93SSam Ravnborg 		goto no_context;
145c37ddd93SSam Ravnborg 
146a050ba1eSLinus Torvalds 	if (!from_user && address >= PAGE_OFFSET)
147a050ba1eSLinus Torvalds 		goto no_context;
148a050ba1eSLinus Torvalds 
149a8b0ca17SPeter Zijlstra 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
150a084b667SDavid S. Miller 
151c29554f5SKautuk Consul retry:
152a050ba1eSLinus Torvalds 	vma = lock_mm_and_find_vma(mm, address, regs);
153c37ddd93SSam Ravnborg 	if (!vma)
154a050ba1eSLinus Torvalds 		goto bad_area_nosemaphore;
155c37ddd93SSam Ravnborg 	/*
156c37ddd93SSam Ravnborg 	 * Ok, we have a good vm_area for this memory access, so
157c37ddd93SSam Ravnborg 	 * we can handle it..
158c37ddd93SSam Ravnborg 	 */
1594b177647SDavid S. Miller 	code = SEGV_ACCERR;
160c37ddd93SSam Ravnborg 	if (write) {
161c37ddd93SSam Ravnborg 		if (!(vma->vm_flags & VM_WRITE))
162c37ddd93SSam Ravnborg 			goto bad_area;
163c37ddd93SSam Ravnborg 	} else {
164c37ddd93SSam Ravnborg 		/* Allow reads even for write-only mappings */
165c37ddd93SSam Ravnborg 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
166c37ddd93SSam Ravnborg 			goto bad_area;
167c37ddd93SSam Ravnborg 	}
168c37ddd93SSam Ravnborg 
169759496baSJohannes Weiner 	if (from_user)
170759496baSJohannes Weiner 		flags |= FAULT_FLAG_USER;
171759496baSJohannes Weiner 	if (write)
172759496baSJohannes Weiner 		flags |= FAULT_FLAG_WRITE;
173759496baSJohannes Weiner 
174c37ddd93SSam Ravnborg 	/*
175c37ddd93SSam Ravnborg 	 * If for any reason at all we couldn't handle the fault,
176c37ddd93SSam Ravnborg 	 * make sure we exit gracefully rather than endlessly redo
177c37ddd93SSam Ravnborg 	 * the fault.
178c37ddd93SSam Ravnborg 	 */
17956e10e6aSPeter Xu 	fault = handle_mm_fault(vma, address, flags, regs);
180c29554f5SKautuk Consul 
18179c54c97SAl Viro 	if (fault_signal_pending(fault, regs)) {
18279c54c97SAl Viro 		if (!from_user)
18379c54c97SAl Viro 			goto no_context;
184c29554f5SKautuk Consul 		return;
18579c54c97SAl Viro 	}
186c29554f5SKautuk Consul 
187d9272525SPeter Xu 	/* The fault is fully completed (including releasing mmap lock) */
188d9272525SPeter Xu 	if (fault & VM_FAULT_COMPLETED)
189d9272525SPeter Xu 		return;
190d9272525SPeter Xu 
191c37ddd93SSam Ravnborg 	if (unlikely(fault & VM_FAULT_ERROR)) {
192c37ddd93SSam Ravnborg 		if (fault & VM_FAULT_OOM)
193c37ddd93SSam Ravnborg 			goto out_of_memory;
19433692f27SLinus Torvalds 		else if (fault & VM_FAULT_SIGSEGV)
19533692f27SLinus Torvalds 			goto bad_area;
196c37ddd93SSam Ravnborg 		else if (fault & VM_FAULT_SIGBUS)
197c37ddd93SSam Ravnborg 			goto do_sigbus;
198c37ddd93SSam Ravnborg 		BUG();
199c37ddd93SSam Ravnborg 	}
200c29554f5SKautuk Consul 
201c29554f5SKautuk Consul 	if (fault & VM_FAULT_RETRY) {
20245cac65bSShaohua Li 		flags |= FAULT_FLAG_TRIED;
203c29554f5SKautuk Consul 
2043e4e28c5SMichel Lespinasse 		/* No need to mmap_read_unlock(mm) as we would
205c29554f5SKautuk Consul 		 * have already released it in __lock_page_or_retry
206c29554f5SKautuk Consul 		 * in mm/filemap.c.
207c29554f5SKautuk Consul 		 */
208c29554f5SKautuk Consul 
209c29554f5SKautuk Consul 		goto retry;
210c29554f5SKautuk Consul 	}
211c29554f5SKautuk Consul 
212d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
213c37ddd93SSam Ravnborg 	return;
214c37ddd93SSam Ravnborg 
215c37ddd93SSam Ravnborg 	/*
216c37ddd93SSam Ravnborg 	 * Something tried to access memory that isn't in our memory map..
217c37ddd93SSam Ravnborg 	 * Fix it, but check if it's kernel or user first..
218c37ddd93SSam Ravnborg 	 */
219c37ddd93SSam Ravnborg bad_area:
220d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
221c37ddd93SSam Ravnborg 
222c37ddd93SSam Ravnborg bad_area_nosemaphore:
223c37ddd93SSam Ravnborg 	/* User mode accesses just cause a SIGSEGV */
224c37ddd93SSam Ravnborg 	if (from_user) {
2254b177647SDavid S. Miller 		do_fault_siginfo(code, SIGSEGV, regs, text_fault);
226c37ddd93SSam Ravnborg 		return;
227c37ddd93SSam Ravnborg 	}
228c37ddd93SSam Ravnborg 
229c37ddd93SSam Ravnborg 	/* Is this in ex_table? */
230c37ddd93SSam Ravnborg no_context:
2310157141aSSam Ravnborg 	if (!from_user) {
232b4edf06cSAl Viro 		const struct exception_table_entry *entry;
233b4edf06cSAl Viro 
234b4edf06cSAl Viro 		entry = search_exception_tables(regs->pc);
235c37ddd93SSam Ravnborg #ifdef DEBUG_EXCEPTIONS
23670168dfaSSam Ravnborg 		printk("Exception: PC<%08lx> faddr<%08lx>\n",
23770168dfaSSam Ravnborg 		       regs->pc, address);
238b4edf06cSAl Viro 		printk("EX_TABLE: insn<%08lx> fixup<%08x>\n",
239b4edf06cSAl Viro 			regs->pc, entry->fixup);
240c37ddd93SSam Ravnborg #endif
241b4edf06cSAl Viro 		regs->pc = entry->fixup;
242c37ddd93SSam Ravnborg 		regs->npc = regs->pc + 4;
243c37ddd93SSam Ravnborg 		return;
244c37ddd93SSam Ravnborg 	}
245c37ddd93SSam Ravnborg 
246c37ddd93SSam Ravnborg 	unhandled_fault(address, tsk, regs);
247c37ddd93SSam Ravnborg 
248c37ddd93SSam Ravnborg /*
249c37ddd93SSam Ravnborg  * We ran out of memory, or some other thing happened to us that made
250c37ddd93SSam Ravnborg  * us unable to handle the page fault gracefully.
251c37ddd93SSam Ravnborg  */
252c37ddd93SSam Ravnborg out_of_memory:
253d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
254a923c28fSDavid S. Miller 	if (from_user) {
255a923c28fSDavid S. Miller 		pagefault_out_of_memory();
256a923c28fSDavid S. Miller 		return;
257a923c28fSDavid S. Miller 	}
258c37ddd93SSam Ravnborg 	goto no_context;
259c37ddd93SSam Ravnborg 
260c37ddd93SSam Ravnborg do_sigbus:
261d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
2624b177647SDavid S. Miller 	do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault);
263c37ddd93SSam Ravnborg 	if (!from_user)
264c37ddd93SSam Ravnborg 		goto no_context;
265c37ddd93SSam Ravnborg 
266c37ddd93SSam Ravnborg vmalloc_fault:
267c37ddd93SSam Ravnborg 	{
268c37ddd93SSam Ravnborg 		/*
269c37ddd93SSam Ravnborg 		 * Synchronize this task's top level page-table
270c37ddd93SSam Ravnborg 		 * with the 'reference' page table.
271c37ddd93SSam Ravnborg 		 */
272c37ddd93SSam Ravnborg 		int offset = pgd_index(address);
273c37ddd93SSam Ravnborg 		pgd_t *pgd, *pgd_k;
2747235db26SMike Rapoport 		p4d_t *p4d, *p4d_k;
2757235db26SMike Rapoport 		pud_t *pud, *pud_k;
276c37ddd93SSam Ravnborg 		pmd_t *pmd, *pmd_k;
277c37ddd93SSam Ravnborg 
278c37ddd93SSam Ravnborg 		pgd = tsk->active_mm->pgd + offset;
279c37ddd93SSam Ravnborg 		pgd_k = init_mm.pgd + offset;
280c37ddd93SSam Ravnborg 
281c37ddd93SSam Ravnborg 		if (!pgd_present(*pgd)) {
282c37ddd93SSam Ravnborg 			if (!pgd_present(*pgd_k))
283c37ddd93SSam Ravnborg 				goto bad_area_nosemaphore;
284c37ddd93SSam Ravnborg 			pgd_val(*pgd) = pgd_val(*pgd_k);
285c37ddd93SSam Ravnborg 			return;
286c37ddd93SSam Ravnborg 		}
287c37ddd93SSam Ravnborg 
2887235db26SMike Rapoport 		p4d = p4d_offset(pgd, address);
2897235db26SMike Rapoport 		pud = pud_offset(p4d, address);
2907235db26SMike Rapoport 		pmd = pmd_offset(pud, address);
2917235db26SMike Rapoport 
2927235db26SMike Rapoport 		p4d_k = p4d_offset(pgd_k, address);
2937235db26SMike Rapoport 		pud_k = pud_offset(p4d_k, address);
2947235db26SMike Rapoport 		pmd_k = pmd_offset(pud_k, address);
295c37ddd93SSam Ravnborg 
296c37ddd93SSam Ravnborg 		if (pmd_present(*pmd) || !pmd_present(*pmd_k))
297c37ddd93SSam Ravnborg 			goto bad_area_nosemaphore;
29870168dfaSSam Ravnborg 
299c37ddd93SSam Ravnborg 		*pmd = *pmd_k;
300c37ddd93SSam Ravnborg 		return;
301c37ddd93SSam Ravnborg 	}
302c37ddd93SSam Ravnborg }
303c37ddd93SSam Ravnborg 
304c37ddd93SSam Ravnborg /* This always deals with user addresses. */
force_user_fault(unsigned long address,int write)305c37ddd93SSam Ravnborg static void force_user_fault(unsigned long address, int write)
306c37ddd93SSam Ravnborg {
307c37ddd93SSam Ravnborg 	struct vm_area_struct *vma;
308c37ddd93SSam Ravnborg 	struct task_struct *tsk = current;
309c37ddd93SSam Ravnborg 	struct mm_struct *mm = tsk->mm;
310759496baSJohannes Weiner 	unsigned int flags = FAULT_FLAG_USER;
3114b177647SDavid S. Miller 	int code;
312c37ddd93SSam Ravnborg 
3134b177647SDavid S. Miller 	code = SEGV_MAPERR;
314c37ddd93SSam Ravnborg 
315*0b26eadbSLinus Torvalds 	vma = lock_mm_and_find_vma(mm, address, NULL);
316c37ddd93SSam Ravnborg 	if (!vma)
317a050ba1eSLinus Torvalds 		goto bad_area_nosemaphore;
3184b177647SDavid S. Miller 	code = SEGV_ACCERR;
319c37ddd93SSam Ravnborg 	if (write) {
320c37ddd93SSam Ravnborg 		if (!(vma->vm_flags & VM_WRITE))
321c37ddd93SSam Ravnborg 			goto bad_area;
322759496baSJohannes Weiner 		flags |= FAULT_FLAG_WRITE;
323c37ddd93SSam Ravnborg 	} else {
324c37ddd93SSam Ravnborg 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
325c37ddd93SSam Ravnborg 			goto bad_area;
326c37ddd93SSam Ravnborg 	}
327bce617edSPeter Xu 	switch (handle_mm_fault(vma, address, flags, NULL)) {
328c37ddd93SSam Ravnborg 	case VM_FAULT_SIGBUS:
329c37ddd93SSam Ravnborg 	case VM_FAULT_OOM:
330c37ddd93SSam Ravnborg 		goto do_sigbus;
331c37ddd93SSam Ravnborg 	}
332d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
333c37ddd93SSam Ravnborg 	return;
334c37ddd93SSam Ravnborg bad_area:
335d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
336a050ba1eSLinus Torvalds bad_area_nosemaphore:
3374b177647SDavid S. Miller 	__do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address);
338c37ddd93SSam Ravnborg 	return;
339c37ddd93SSam Ravnborg 
340c37ddd93SSam Ravnborg do_sigbus:
341d8ed45c5SMichel Lespinasse 	mmap_read_unlock(mm);
3424b177647SDavid S. Miller 	__do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address);
343c37ddd93SSam Ravnborg }
344c37ddd93SSam Ravnborg 
check_stack_aligned(unsigned long sp)3459088333eSDavid S. Miller static void check_stack_aligned(unsigned long sp)
3469088333eSDavid S. Miller {
3479088333eSDavid S. Miller 	if (sp & 0x7UL)
3483cf5d076SEric W. Biederman 		force_sig(SIGILL);
3499088333eSDavid S. Miller }
3509088333eSDavid S. Miller 
window_overflow_fault(void)351c37ddd93SSam Ravnborg void window_overflow_fault(void)
352c37ddd93SSam Ravnborg {
353c37ddd93SSam Ravnborg 	unsigned long sp;
354c37ddd93SSam Ravnborg 
355c37ddd93SSam Ravnborg 	sp = current_thread_info()->rwbuf_stkptrs[0];
356c37ddd93SSam Ravnborg 	if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
357c37ddd93SSam Ravnborg 		force_user_fault(sp + 0x38, 1);
358c37ddd93SSam Ravnborg 	force_user_fault(sp, 1);
3599088333eSDavid S. Miller 
3609088333eSDavid S. Miller 	check_stack_aligned(sp);
361c37ddd93SSam Ravnborg }
362c37ddd93SSam Ravnborg 
window_underflow_fault(unsigned long sp)363c37ddd93SSam Ravnborg void window_underflow_fault(unsigned long sp)
364c37ddd93SSam Ravnborg {
365c37ddd93SSam Ravnborg 	if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
366c37ddd93SSam Ravnborg 		force_user_fault(sp + 0x38, 0);
367c37ddd93SSam Ravnborg 	force_user_fault(sp, 0);
3689088333eSDavid S. Miller 
3699088333eSDavid S. Miller 	check_stack_aligned(sp);
370c37ddd93SSam Ravnborg }
371c37ddd93SSam Ravnborg 
window_ret_fault(struct pt_regs * regs)372c37ddd93SSam Ravnborg void window_ret_fault(struct pt_regs *regs)
373c37ddd93SSam Ravnborg {
374c37ddd93SSam Ravnborg 	unsigned long sp;
375c37ddd93SSam Ravnborg 
376c37ddd93SSam Ravnborg 	sp = regs->u_regs[UREG_FP];
377c37ddd93SSam Ravnborg 	if (((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
378c37ddd93SSam Ravnborg 		force_user_fault(sp + 0x38, 0);
379c37ddd93SSam Ravnborg 	force_user_fault(sp, 0);
3809088333eSDavid S. Miller 
3819088333eSDavid S. Miller 	check_stack_aligned(sp);
382c37ddd93SSam Ravnborg }
383