1867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
2867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright (C) 1991, 1992  Linus Torvalds
3867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Copyright 2010 Tilera Corporation. All Rights Reserved.
4867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
5867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   This program is free software; you can redistribute it and/or
6867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   modify it under the terms of the GNU General Public License
7867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   as published by the Free Software Foundation, version 2.
8867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *
9867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   This program is distributed in the hope that it will be useful, but
10867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   WITHOUT ANY WARRANTY; without even the implied warranty of
11867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   NON INFRINGEMENT.  See the GNU General Public License for
13867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf *   more details.
14867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
15867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
16867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/sched.h>
17867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/mm.h>
18867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/smp.h>
19867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/kernel.h>
20867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/signal.h>
21867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/errno.h>
22867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/wait.h>
23867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/unistd.h>
24867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/stddef.h>
25867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/personality.h>
26867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/suspend.h>
27867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/ptrace.h>
28867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/elf.h>
29867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/compat.h>
30867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/syscalls.h>
31867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <linux/uaccess.h>
32867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/processor.h>
33867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/ucontext.h>
34867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <asm/sigframe.h>
350707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf#include <asm/syscalls.h>
36867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#include <arch/interrupts.h>
37867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
38867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define DEBUG_SIG 0
39867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
40867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
41867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
42d929b6aeaacbe78cbfef4a80e3eed1bf0464d984Chris MetcalfSYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
43d929b6aeaacbe78cbfef4a80e3eed1bf0464d984Chris Metcalf		stack_t __user *, uoss, struct pt_regs *, regs)
44867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
45867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return do_sigaltstack(uss, uoss, regs->sp);
46867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
47867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
48867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
49867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
50867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Do a signal return; undo the signal stack.
51867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
52867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
53867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfint restore_sigcontext(struct pt_regs *regs,
5481711cee933599fa114abb0d258d8bbabef8adfbChris Metcalf		       struct sigcontext __user *sc)
55867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
56867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int err = 0;
57867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int i;
58867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
59867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Always make any pending restarted system calls return -EINTR */
60867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	current_thread_info()->restart_block.fn = do_no_restart_syscall;
61867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
6274fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	/*
6374fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	 * Enforce that sigcontext is like pt_regs, and doesn't mess
6474fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	 * up our stack alignment rules.
6574fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	 */
6674fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs));
6774fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0);
6874fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf
69867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
7074fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf		err |= __get_user(regs->regs[i], &sc->gregs[i]);
71867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
721deb9c5dfb179819ecdbf80a1d121e26c63caab3Chris Metcalf	/* Ensure that the PL is always set to USER_PL. */
731deb9c5dfb179819ecdbf80a1d121e26c63caab3Chris Metcalf	regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1));
741deb9c5dfb179819ecdbf80a1d121e26c63caab3Chris Metcalf
75867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	regs->faultnum = INT_SWINT_1_SIGRETURN;
76867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
77867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return err;
78867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
79867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
80571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalfvoid signal_fault(const char *type, struct pt_regs *regs,
81571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		  void __user *frame, int sig)
82571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf{
83571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	trace_unhandled_signal(type, regs, (unsigned long)frame, SIGSEGV);
84571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	force_sigsegv(sig, current);
85571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf}
86571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
8781711cee933599fa114abb0d258d8bbabef8adfbChris Metcalf/* The assembly shim for this function arranges to ignore the return value. */
88d929b6aeaacbe78cbfef4a80e3eed1bf0464d984Chris MetcalfSYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
89867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
90867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	struct rt_sigframe __user *frame =
91867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		(struct rt_sigframe __user *)(regs->sp);
92867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	sigset_t set;
93867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
94867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
95867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		goto badframe;
96867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
97867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		goto badframe;
98867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
99867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	sigdelsetmask(&set, ~_BLOCKABLE);
100ad092338350e517608a41341095b6b1e312c4eb1Matt Fleming	set_current_blocked(&set);
101867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
10281711cee933599fa114abb0d258d8bbabef8adfbChris Metcalf	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
103867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		goto badframe;
104867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
105867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
106867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		goto badframe;
107867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
10881711cee933599fa114abb0d258d8bbabef8adfbChris Metcalf	return 0;
109867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
110867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfbadframe:
111571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	signal_fault("bad sigreturn frame", regs, frame, 0);
112867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return 0;
113867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
114867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
115867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
116867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Set up a signal frame.
117867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
118867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
119867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfint setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
120867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
121867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int i, err = 0;
122867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
123867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i)
12474fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf		err |= __put_user(regs->regs[i], &sc->gregs[i]);
125867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
126867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return err;
127867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
128867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
129867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
130867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Determine which stack to use..
131867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
132867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic inline void __user *get_sigframe(struct k_sigaction *ka,
133867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf					struct pt_regs *regs,
134867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf					size_t frame_size)
135867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
136867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned long sp;
137867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
138867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Default to using normal stack */
139867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	sp = regs->sp;
140867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
141867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
142867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * If we are on the alternate signal stack and would overflow
143867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * it, don't.  Return an always-bogus address instead so we
144867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * will die with SIGSEGV.
145867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
146867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
1470707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf		return (void __user __force *)-1UL;
148867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
149867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* This is the X/Open sanctioned signal stack switching.  */
150867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (ka->sa.sa_flags & SA_ONSTACK) {
151867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		if (sas_ss_flags(sp) == 0)
152867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			sp = current->sas_ss_sp + current->sas_ss_size;
153867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
154867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
155867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	sp -= frame_size;
156867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
157867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Align the stack pointer according to the TILE ABI,
158867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * i.e. so that on function entry (sp & 15) == 0.
159867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
160867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	sp &= -16UL;
161867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return (void __user *) sp;
162867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
163867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
164867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
165867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			   sigset_t *set, struct pt_regs *regs)
166867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
167867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	unsigned long restorer;
168867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	struct rt_sigframe __user *frame;
169867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int err = 0;
170867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int usig;
171867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
172867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	frame = get_sigframe(ka, regs, sizeof(*frame));
173867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
174867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
175867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		goto give_sigsegv;
176867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
177867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	usig = current_thread_info()->exec_domain
178867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		&& current_thread_info()->exec_domain->signal_invmap
179867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		&& sig < 32
180867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		? current_thread_info()->exec_domain->signal_invmap[sig]
181867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		: sig;
182867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
183867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Always write at least the signal number for the stack backtracer. */
184867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (ka->sa.sa_flags & SA_SIGINFO) {
185867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		/* At sigreturn time, restore the callee-save registers too. */
186867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		err |= copy_siginfo_to_user(&frame->info, info);
187867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		regs->flags |= PT_FLAGS_RESTORE_REGS;
188867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	} else {
189867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		err |= __put_user(info->si_signo, &frame->info.si_signo);
190867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
191867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
192867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Create the ucontext.  */
193867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
194867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	err |= __put_user(0, &frame->uc.uc_flags);
1950707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf	err |= __put_user(NULL, &frame->uc.uc_link);
1960707ad30d10110aebc01a5a64fb63f4b32d20b73Chris Metcalf	err |= __put_user((void __user *)(current->sas_ss_sp),
197867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			  &frame->uc.uc_stack.ss_sp);
198867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	err |= __put_user(sas_ss_flags(regs->sp),
199867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			  &frame->uc.uc_stack.ss_flags);
200867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
201867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
202867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
203867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (err)
204867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		goto give_sigsegv;
205867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
206867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	restorer = VDSO_BASE;
207867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (ka->sa.sa_flags & SA_RESTORER)
208867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		restorer = (unsigned long) ka->sa.sa_restorer;
209867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
210867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
211867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Set up registers for signal handler.
212867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Registers that we don't modify keep the value they had from
213867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * user-space at the time we took the signal.
21474fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
21574fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	 * since some things rely on this (e.g. glibc's debug/segfault.c).
216867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
217867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	regs->pc = (unsigned long) ka->sa.sa_handler;
218867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
219867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	regs->sp = (unsigned long) frame;
220867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	regs->lr = restorer;
221867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	regs->regs[0] = (unsigned long) usig;
22274fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	regs->regs[1] = (unsigned long) &frame->info;
22374fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	regs->regs[2] = (unsigned long) &frame->uc;
22474fca9da097b74117ae2cef9e5f0d9b0e28ccbb7Chris Metcalf	regs->flags |= PT_FLAGS_CALLER_SAVES;
225867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
226867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
227867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * Notify any tracer that was single-stepping it.
228867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * The tracer may want to single-step inside the
229867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * handler too.
230867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
231867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (test_thread_flag(TIF_SINGLESTEP))
232867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		ptrace_notify(SIGTRAP);
233867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
234867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return 0;
235867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
236867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfgive_sigsegv:
237571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	signal_fault("bad setup frame", regs, frame, sig);
238867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return -EFAULT;
239867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
240867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
241867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
242867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * OK, we're invoking a handler
243867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
244867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
245867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfstatic int handle_signal(unsigned long sig, siginfo_t *info,
246867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 struct k_sigaction *ka, sigset_t *oldset,
247867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 struct pt_regs *regs)
248867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
249867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int ret;
250867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
251867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Are we from a system call? */
252867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (regs->faultnum == INT_SWINT_1) {
253867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		/* If so, check system call restarting.. */
254867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		switch (regs->regs[0]) {
255867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTART_RESTARTBLOCK:
256867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTARTNOHAND:
257867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->regs[0] = -EINTR;
258867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			break;
259867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
260867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTARTSYS:
261867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			if (!(ka->sa.sa_flags & SA_RESTART)) {
262867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				regs->regs[0] = -EINTR;
263867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf				break;
264867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			}
265867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			/* fallthrough */
266867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTARTNOINTR:
267867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			/* Reload caller-saves to restore r0..r5 and r10. */
268867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->flags |= PT_FLAGS_CALLER_SAVES;
269867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->regs[0] = regs->orig_r0;
270867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->pc -= 8;
271867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		}
272867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
273867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
274867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Set up the stack frame */
275867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#ifdef CONFIG_COMPAT
276867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (is_compat_task())
277867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		ret = compat_setup_rt_frame(sig, ka, info, oldset, regs);
278867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	else
279867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf#endif
280867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		ret = setup_rt_frame(sig, ka, info, oldset, regs);
281867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (ret == 0) {
282867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		/* This code is only called from system calls or from
283867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		 * the work_pending path in the return-to-user code, and
284867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		 * either way we can re-enable interrupts unconditionally.
285867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		 */
286ad092338350e517608a41341095b6b1e312c4eb1Matt Fleming		block_sigmask(ka, sig);
287867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
288867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
289867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	return ret;
290867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
291867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
292867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf/*
293867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * Note that 'init' is a special process: it doesn't get signals it doesn't
294867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * want to handle. Thus you cannot kill init even with a SIGKILL even by
295867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf * mistake.
296867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf */
297867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalfvoid do_signal(struct pt_regs *regs)
298867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf{
299867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	siginfo_t info;
300867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	int signr;
301867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	struct k_sigaction ka;
302867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	sigset_t *oldset;
303867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
304867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/*
305867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * i386 will check if we're coming from kernel mode and bail out
306867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * here.  In my experience this just turns weird crashes into
307867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * weird spin-hangs.  But if we find a case where this seems
308867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 * helpful, we can reinstate the check on "!user_mode(regs)".
309867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	 */
310867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
311867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
312867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		oldset = &current->saved_sigmask;
313867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	else
314867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		oldset = &current->blocked;
315867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
316867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
317867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (signr > 0) {
318867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		/* Whee! Actually deliver the signal.  */
319867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
320867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			/*
321867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 * A signal was successfully delivered; the saved
322867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 * sigmask will have been stored in the signal frame,
323867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 * and will be restored by sigreturn, so we can simply
324867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 * clear the TS_RESTORE_SIGMASK flag.
325867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			 */
326867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
327867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		}
328867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
32934a89d26bdc4ba46a406fa3842239e921c493d44Chris Metcalf		goto done;
330867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
331867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
332867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* Did we come from a system call? */
333867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (regs->faultnum == INT_SWINT_1) {
334867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		/* Restart the system call - no handlers present */
335867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		switch (regs->regs[0]) {
336867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTARTNOHAND:
337867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTARTSYS:
338867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTARTNOINTR:
339867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->flags |= PT_FLAGS_CALLER_SAVES;
340867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->regs[0] = regs->orig_r0;
341867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->pc -= 8;
342867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			break;
343867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
344867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		case -ERESTART_RESTARTBLOCK:
345867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->flags |= PT_FLAGS_CALLER_SAVES;
346867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->regs[TREG_SYSCALL_NR] = __NR_restart_syscall;
347867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			regs->pc -= 8;
348867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf			break;
349867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		}
350867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
351867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf
352867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	/* If there's no signal to deliver, just put the saved sigmask back. */
353867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
354867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
355867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
356867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf	}
35734a89d26bdc4ba46a406fa3842239e921c493d44Chris Metcalf
35834a89d26bdc4ba46a406fa3842239e921c493d44Chris Metcalfdone:
35934a89d26bdc4ba46a406fa3842239e921c493d44Chris Metcalf	/* Avoid double syscall restart if there are nested signals. */
36034a89d26bdc4ba46a406fa3842239e921c493d44Chris Metcalf	regs->faultnum = INT_SWINT_1_SIGRETURN;
361867e359b97c970a60626d5d76bbe2a8fadbf38fbChris Metcalf}
362571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
363571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalfint show_unhandled_signals = 1;
364571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
365571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalfstatic int __init crashinfo(char *str)
366571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf{
367571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	unsigned long val;
368571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	const char *word;
369571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
370571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (*str == '\0')
371571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		val = 2;
372571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	else if (*str != '=' || strict_strtoul(++str, 0, &val) != 0)
373571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		return 0;
374571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	show_unhandled_signals = val;
375571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	switch (show_unhandled_signals) {
376571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	case 0:
377571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		word = "No";
378571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		break;
379571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	case 1:
380571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		word = "One-line";
381571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		break;
382571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	default:
383571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		word = "Detailed";
384571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		break;
385571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	}
386571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	pr_info("%s crash reports will be generated on the console\n", word);
387571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	return 1;
388571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf}
389571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf__setup("crashinfo", crashinfo);
390571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
391571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalfstatic void dump_mem(void __user *address)
392571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf{
393571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	void __user *addr;
394571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	enum { region_size = 256, bytes_per_line = 16 };
395571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	int i, j, k;
396571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	int found_readable_mem = 0;
397571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
398571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	pr_err("\n");
399571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (!access_ok(VERIFY_READ, address, 1)) {
400571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		pr_err("Not dumping at address 0x%lx (kernel address)\n",
401571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		       (unsigned long)address);
402571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		return;
403571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	}
404571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
405571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	addr = (void __user *)
406571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		(((unsigned long)address & -bytes_per_line) - region_size/2);
407571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (addr > address)
408571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		addr = NULL;
409571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	for (i = 0; i < region_size;
410571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	     addr += bytes_per_line, i += bytes_per_line) {
411571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		unsigned char buf[bytes_per_line];
412571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		char line[100];
413571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		if (copy_from_user(buf, addr, bytes_per_line))
414571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			continue;
415571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		if (!found_readable_mem) {
416571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			pr_err("Dumping memory around address 0x%lx:\n",
417571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			       (unsigned long)address);
418571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			found_readable_mem = 1;
419571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		}
420571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		j = sprintf(line, REGFMT":", (unsigned long)addr);
421571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		for (k = 0; k < bytes_per_line; ++k)
422571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			j += sprintf(&line[j], " %02x", buf[k]);
423571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		pr_err("%s\n", line);
424571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	}
425571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (!found_readable_mem)
426571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		pr_err("No readable memory around address 0x%lx\n",
427571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		       (unsigned long)address);
428571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf}
429571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
430571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalfvoid trace_unhandled_signal(const char *type, struct pt_regs *regs,
431571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			    unsigned long address, int sig)
432571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf{
433571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	struct task_struct *tsk = current;
434571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
435571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (show_unhandled_signals == 0)
436571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		return;
437571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
438571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	/* If the signal is handled, don't show it here. */
439571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (!is_global_init(tsk)) {
440571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		void __user *handler =
441571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			tsk->sighand->action[sig-1].sa.sa_handler;
442571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		if (handler != SIG_IGN && handler != SIG_DFL)
443571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			return;
444571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	}
445571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
446571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	/* Rate-limit the one-line output, not the detailed output. */
447571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (show_unhandled_signals <= 1 && !printk_ratelimit())
448571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		return;
449571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
450571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	printk("%s%s[%d]: %s at %lx pc "REGFMT" signal %d",
451571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	       task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
452571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	       tsk->comm, task_pid_nr(tsk), type, address, regs->pc, sig);
453571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
454571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	print_vma_addr(KERN_CONT " in ", regs->pc);
455571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
456571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	printk(KERN_CONT "\n");
457571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf
458571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	if (show_unhandled_signals > 1) {
459571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		switch (sig) {
460571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		case SIGILL:
461571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		case SIGFPE:
462571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		case SIGSEGV:
463571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		case SIGBUS:
464571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			pr_err("User crash: signal %d,"
465571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			       " trap %ld, address 0x%lx\n",
466571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			       sig, regs->faultnum, address);
467571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			show_regs(regs);
468571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			dump_mem((void __user *)address);
469571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			break;
470571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		default:
471571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			pr_err("User crash: signal %d, trap %ld\n",
472571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			       sig, regs->faultnum);
473571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf			break;
474571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf		}
475571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf	}
476571d76acdab95876aeff869ab6449f826c23aa43Chris Metcalf}
477