diff options
Diffstat (limited to 'arch/um/os-Linux/signal.c')
-rw-r--r-- | arch/um/os-Linux/signal.c | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 6ae180703a63..2d22f1fcd8e2 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c | |||
@@ -12,13 +12,7 @@ | |||
12 | #include "as-layout.h" | 12 | #include "as-layout.h" |
13 | #include "kern_util.h" | 13 | #include "kern_util.h" |
14 | #include "os.h" | 14 | #include "os.h" |
15 | #include "process.h" | 15 | #include "sysdep/mcontext.h" |
16 | #include "sysdep/barrier.h" | ||
17 | #include "sysdep/sigcontext.h" | ||
18 | #include "user.h" | ||
19 | |||
20 | /* Copied from linux/compiler-gcc.h since we can't include it directly */ | ||
21 | #define barrier() __asm__ __volatile__("": : :"memory") | ||
22 | 16 | ||
23 | void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { | 17 | void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { |
24 | [SIGTRAP] = relay_signal, | 18 | [SIGTRAP] = relay_signal, |
@@ -30,7 +24,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { | |||
30 | [SIGIO] = sigio_handler, | 24 | [SIGIO] = sigio_handler, |
31 | [SIGVTALRM] = timer_handler }; | 25 | [SIGVTALRM] = timer_handler }; |
32 | 26 | ||
33 | static void sig_handler_common(int sig, struct sigcontext *sc) | 27 | static void sig_handler_common(int sig, mcontext_t *mc) |
34 | { | 28 | { |
35 | struct uml_pt_regs r; | 29 | struct uml_pt_regs r; |
36 | int save_errno = errno; | 30 | int save_errno = errno; |
@@ -38,8 +32,8 @@ static void sig_handler_common(int sig, struct sigcontext *sc) | |||
38 | r.is_user = 0; | 32 | r.is_user = 0; |
39 | if (sig == SIGSEGV) { | 33 | if (sig == SIGSEGV) { |
40 | /* For segfaults, we want the data from the sigcontext. */ | 34 | /* For segfaults, we want the data from the sigcontext. */ |
41 | copy_sc(&r, sc); | 35 | get_regs_from_mc(&r, mc); |
42 | GET_FAULTINFO_FROM_SC(r.faultinfo, sc); | 36 | GET_FAULTINFO_FROM_MC(r.faultinfo, mc); |
43 | } | 37 | } |
44 | 38 | ||
45 | /* enable signals if sig isn't IRQ signal */ | 39 | /* enable signals if sig isn't IRQ signal */ |
@@ -66,7 +60,7 @@ static void sig_handler_common(int sig, struct sigcontext *sc) | |||
66 | static int signals_enabled; | 60 | static int signals_enabled; |
67 | static unsigned int signals_pending; | 61 | static unsigned int signals_pending; |
68 | 62 | ||
69 | void sig_handler(int sig, struct sigcontext *sc) | 63 | void sig_handler(int sig, mcontext_t *mc) |
70 | { | 64 | { |
71 | int enabled; | 65 | int enabled; |
72 | 66 | ||
@@ -78,23 +72,23 @@ void sig_handler(int sig, struct sigcontext *sc) | |||
78 | 72 | ||
79 | block_signals(); | 73 | block_signals(); |
80 | 74 | ||
81 | sig_handler_common(sig, sc); | 75 | sig_handler_common(sig, mc); |
82 | 76 | ||
83 | set_signals(enabled); | 77 | set_signals(enabled); |
84 | } | 78 | } |
85 | 79 | ||
86 | static void real_alarm_handler(struct sigcontext *sc) | 80 | static void real_alarm_handler(mcontext_t *mc) |
87 | { | 81 | { |
88 | struct uml_pt_regs regs; | 82 | struct uml_pt_regs regs; |
89 | 83 | ||
90 | if (sc != NULL) | 84 | if (mc != NULL) |
91 | copy_sc(®s, sc); | 85 | get_regs_from_mc(®s, mc); |
92 | regs.is_user = 0; | 86 | regs.is_user = 0; |
93 | unblock_signals(); | 87 | unblock_signals(); |
94 | timer_handler(SIGVTALRM, ®s); | 88 | timer_handler(SIGVTALRM, ®s); |
95 | } | 89 | } |
96 | 90 | ||
97 | void alarm_handler(int sig, struct sigcontext *sc) | 91 | void alarm_handler(int sig, mcontext_t *mc) |
98 | { | 92 | { |
99 | int enabled; | 93 | int enabled; |
100 | 94 | ||
@@ -106,14 +100,13 @@ void alarm_handler(int sig, struct sigcontext *sc) | |||
106 | 100 | ||
107 | block_signals(); | 101 | block_signals(); |
108 | 102 | ||
109 | real_alarm_handler(sc); | 103 | real_alarm_handler(mc); |
110 | set_signals(enabled); | 104 | set_signals(enabled); |
111 | } | 105 | } |
112 | 106 | ||
113 | void timer_init(void) | 107 | void timer_init(void) |
114 | { | 108 | { |
115 | set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, | 109 | set_handler(SIGVTALRM); |
116 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); | ||
117 | } | 110 | } |
118 | 111 | ||
119 | void set_sigstack(void *sig_stack, int size) | 112 | void set_sigstack(void *sig_stack, int size) |
@@ -126,10 +119,23 @@ void set_sigstack(void *sig_stack, int size) | |||
126 | panic("enabling signal stack failed, errno = %d\n", errno); | 119 | panic("enabling signal stack failed, errno = %d\n", errno); |
127 | } | 120 | } |
128 | 121 | ||
129 | static void (*handlers[_NSIG])(int sig, struct sigcontext *sc); | 122 | static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { |
123 | [SIGSEGV] = sig_handler, | ||
124 | [SIGBUS] = sig_handler, | ||
125 | [SIGILL] = sig_handler, | ||
126 | [SIGFPE] = sig_handler, | ||
127 | [SIGTRAP] = sig_handler, | ||
128 | |||
129 | [SIGIO] = sig_handler, | ||
130 | [SIGWINCH] = sig_handler, | ||
131 | [SIGVTALRM] = alarm_handler | ||
132 | }; | ||
133 | |||
130 | 134 | ||
131 | void handle_signal(int sig, struct sigcontext *sc) | 135 | static void hard_handler(int sig, siginfo_t *info, void *p) |
132 | { | 136 | { |
137 | struct ucontext *uc = p; | ||
138 | mcontext_t *mc = &uc->uc_mcontext; | ||
133 | unsigned long pending = 1UL << sig; | 139 | unsigned long pending = 1UL << sig; |
134 | 140 | ||
135 | do { | 141 | do { |
@@ -155,7 +161,7 @@ void handle_signal(int sig, struct sigcontext *sc) | |||
155 | while ((sig = ffs(pending)) != 0){ | 161 | while ((sig = ffs(pending)) != 0){ |
156 | sig--; | 162 | sig--; |
157 | pending &= ~(1 << sig); | 163 | pending &= ~(1 << sig); |
158 | (*handlers[sig])(sig, sc); | 164 | (*handlers[sig])(sig, mc); |
159 | } | 165 | } |
160 | 166 | ||
161 | /* | 167 | /* |
@@ -169,28 +175,26 @@ void handle_signal(int sig, struct sigcontext *sc) | |||
169 | } while (pending); | 175 | } while (pending); |
170 | } | 176 | } |
171 | 177 | ||
172 | extern void hard_handler(int sig); | 178 | void set_handler(int sig) |
173 | |||
174 | void set_handler(int sig, void (*handler)(int), int flags, ...) | ||
175 | { | 179 | { |
176 | struct sigaction action; | 180 | struct sigaction action; |
177 | va_list ap; | 181 | int flags = SA_SIGINFO | SA_ONSTACK; |
178 | sigset_t sig_mask; | 182 | sigset_t sig_mask; |
179 | int mask; | ||
180 | 183 | ||
181 | handlers[sig] = (void (*)(int, struct sigcontext *)) handler; | 184 | action.sa_sigaction = hard_handler; |
182 | action.sa_handler = hard_handler; | ||
183 | 185 | ||
186 | /* block irq ones */ | ||
184 | sigemptyset(&action.sa_mask); | 187 | sigemptyset(&action.sa_mask); |
185 | 188 | sigaddset(&action.sa_mask, SIGVTALRM); | |
186 | va_start(ap, flags); | 189 | sigaddset(&action.sa_mask, SIGIO); |
187 | while ((mask = va_arg(ap, int)) != -1) | 190 | sigaddset(&action.sa_mask, SIGWINCH); |
188 | sigaddset(&action.sa_mask, mask); | ||
189 | va_end(ap); | ||
190 | 191 | ||
191 | if (sig == SIGSEGV) | 192 | if (sig == SIGSEGV) |
192 | flags |= SA_NODEFER; | 193 | flags |= SA_NODEFER; |
193 | 194 | ||
195 | if (sigismember(&action.sa_mask, sig)) | ||
196 | flags |= SA_RESTART; /* if it's an irq signal */ | ||
197 | |||
194 | action.sa_flags = flags; | 198 | action.sa_flags = flags; |
195 | action.sa_restorer = NULL; | 199 | action.sa_restorer = NULL; |
196 | if (sigaction(sig, &action, NULL) < 0) | 200 | if (sigaction(sig, &action, NULL) < 0) |