aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/main.c12
-rw-r--r--arch/um/os-Linux/process.c30
-rw-r--r--arch/um/os-Linux/signal.c203
-rw-r--r--arch/um/os-Linux/skas/process.c29
-rw-r--r--arch/um/os-Linux/trap.c3
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/util.c1
7 files changed, 164 insertions, 118 deletions
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 98becd18f211..2878e89a674f 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -81,20 +81,8 @@ extern void scan_elf_aux( char **envp);
81int main(int argc, char **argv, char **envp) 81int main(int argc, char **argv, char **envp)
82{ 82{
83 char **new_argv; 83 char **new_argv;
84 sigset_t mask;
85 int ret, i, err; 84 int ret, i, err;
86 85
87 /* Enable all signals except SIGIO - in some environments, we can
88 * enter with some signals blocked
89 */
90
91 sigemptyset(&mask);
92 sigaddset(&mask, SIGIO);
93 if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
94 perror("sigprocmask");
95 exit(1);
96 }
97
98#ifdef UML_CONFIG_CMDLINE_ON_HOST 86#ifdef UML_CONFIG_CMDLINE_ON_HOST
99 /* Allocate memory for thread command lines */ 87 /* Allocate memory for thread command lines */
100 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ 88 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 39815c6b5e45..7f5e2dac2a35 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -18,6 +18,7 @@
18#include "process.h" 18#include "process.h"
19#include "irq_user.h" 19#include "irq_user.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "longjmp.h"
21 22
22#define ARBITRARY_ADDR -1 23#define ARBITRARY_ADDR -1
23#define FAILURE_PID -1 24#define FAILURE_PID -1
@@ -205,24 +206,13 @@ void init_new_thread_signals(int altstack)
205 206
206int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) 207int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
207{ 208{
208 sigjmp_buf buf; 209 sigjmp_buf buf;
209 int n; 210 int n, enable;
210 211
211 *jmp_ptr = &buf; 212 *jmp_ptr = &buf;
212 n = sigsetjmp(buf, 1); 213 n = UML_SIGSETJMP(&buf, enable);
213 if(n != 0) 214 if(n != 0)
214 return(n); 215 return(n);
215 (*fn)(arg); 216 (*fn)(arg);
216 return(0); 217 return(0);
217} 218}
218
219/*
220 * Overrides for Emacs so that we follow Linus's tabbing style.
221 * Emacs will notice this stuff at the end of the file and automatically
222 * adjust the settings for this buffer only. This must remain at the end
223 * of the file.
224 * ---------------------------------------------------------------------------
225 * Local variables:
226 * c-file-style: "linux"
227 * End:
228 */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 56ca95931b41..f11b3124a0c8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -20,23 +20,58 @@
20#include "mode.h" 20#include "mode.h"
21#include "os.h" 21#include "os.h"
22 22
23/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
24 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
25 * be able to profile all of UML, not just the non-critical sections. If
26 * profiling is not thread-safe, then that is not my problem. We can disable
27 * profiling when SMP is enabled in that case.
28 */
29#define SIGIO_BIT 0
30#define SIGIO_MASK (1 << SIGIO_BIT)
31
32#define SIGVTALRM_BIT 1
33#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
34
35#define SIGALRM_BIT 2
36#define SIGALRM_MASK (1 << SIGALRM_BIT)
37
38static int signals_enabled = 1;
39static int pending = 0;
40
23void sig_handler(ARCH_SIGHDLR_PARAM) 41void sig_handler(ARCH_SIGHDLR_PARAM)
24{ 42{
25 struct sigcontext *sc; 43 struct sigcontext *sc;
44 int enabled;
45
46 /* Must be the first thing that this handler does - x86_64 stores
47 * the sigcontext in %rdx, and we need to save it before it has a
48 * chance to get trashed.
49 */
26 50
27 ARCH_GET_SIGCONTEXT(sc, sig); 51 ARCH_GET_SIGCONTEXT(sc, sig);
52
53 enabled = signals_enabled;
54 if(!enabled && (sig == SIGIO)){
55 pending |= SIGIO_MASK;
56 return;
57 }
58
59 block_signals();
60
28 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 61 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
29 sig, sc); 62 sig, sc);
63
64 set_signals(enabled);
30} 65}
31 66
32extern int timer_irq_inited; 67extern int timer_irq_inited;
33 68
34void alarm_handler(ARCH_SIGHDLR_PARAM) 69static void real_alarm_handler(int sig, struct sigcontext *sc)
35{ 70{
36 struct sigcontext *sc; 71 if(!timer_irq_inited){
37 72 signals_enabled = 1;
38 ARCH_GET_SIGCONTEXT(sc, sig); 73 return;
39 if(!timer_irq_inited) return; 74 }
40 75
41 if(sig == SIGALRM) 76 if(sig == SIGALRM)
42 switch_timers(0); 77 switch_timers(0);
@@ -46,6 +81,29 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
46 81
47 if(sig == SIGALRM) 82 if(sig == SIGALRM)
48 switch_timers(1); 83 switch_timers(1);
84
85}
86
87void alarm_handler(ARCH_SIGHDLR_PARAM)
88{
89 struct sigcontext *sc;
90 int enabled;
91
92 ARCH_GET_SIGCONTEXT(sc, sig);
93
94 enabled = signals_enabled;
95 if(!signals_enabled){
96 if(sig == SIGVTALRM)
97 pending |= SIGVTALRM_MASK;
98 else pending |= SIGALRM_MASK;
99
100 return;
101 }
102
103 block_signals();
104
105 real_alarm_handler(sig, sc);
106 set_signals(enabled);
49} 107}
50 108
51extern void do_boot_timer_handler(struct sigcontext * sc); 109extern void do_boot_timer_handler(struct sigcontext * sc);
@@ -53,10 +111,22 @@ extern void do_boot_timer_handler(struct sigcontext * sc);
53void boot_timer_handler(ARCH_SIGHDLR_PARAM) 111void boot_timer_handler(ARCH_SIGHDLR_PARAM)
54{ 112{
55 struct sigcontext *sc; 113 struct sigcontext *sc;
114 int enabled;
56 115
57 ARCH_GET_SIGCONTEXT(sc, sig); 116 ARCH_GET_SIGCONTEXT(sc, sig);
58 117
118 enabled = signals_enabled;
119 if(!enabled){
120 if(sig == SIGVTALRM)
121 pending |= SIGVTALRM_MASK;
122 else pending |= SIGALRM_MASK;
123 return;
124 }
125
126 block_signals();
127
59 do_boot_timer_handler(sc); 128 do_boot_timer_handler(sc);
129 set_signals(enabled);
60} 130}
61 131
62void set_sigstack(void *sig_stack, int size) 132void set_sigstack(void *sig_stack, int size)
@@ -83,6 +153,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
83{ 153{
84 struct sigaction action; 154 struct sigaction action;
85 va_list ap; 155 va_list ap;
156 sigset_t sig_mask;
86 int mask; 157 int mask;
87 158
88 va_start(ap, flags); 159 va_start(ap, flags);
@@ -95,7 +166,12 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
95 action.sa_flags = flags; 166 action.sa_flags = flags;
96 action.sa_restorer = NULL; 167 action.sa_restorer = NULL;
97 if(sigaction(sig, &action, NULL) < 0) 168 if(sigaction(sig, &action, NULL) < 0)
98 panic("sigaction failed"); 169 panic("sigaction failed - errno = %d\n", errno);
170
171 sigemptyset(&sig_mask);
172 sigaddset(&sig_mask, sig);
173 if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
174 panic("sigprocmask failed - errno = %d\n", errno);
99} 175}
100 176
101int change_sig(int signal, int on) 177int change_sig(int signal, int on)
@@ -108,91 +184,74 @@ int change_sig(int signal, int on)
108 return(!sigismember(&old, signal)); 184 return(!sigismember(&old, signal));
109} 185}
110 186
111/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
112 * disable profiling; it's safe because the profiling code does not interact
113 * with the kernel code at all.*/
114
115static void change_signals(int type)
116{
117 sigset_t mask;
118
119 sigemptyset(&mask);
120 sigaddset(&mask, SIGVTALRM);
121 sigaddset(&mask, SIGALRM);
122 sigaddset(&mask, SIGIO);
123 if(sigprocmask(type, &mask, NULL) < 0)
124 panic("Failed to change signal mask - errno = %d", errno);
125}
126
127void block_signals(void) 187void block_signals(void)
128{ 188{
129 change_signals(SIG_BLOCK); 189 signals_enabled = 0;
130} 190}
131 191
132void unblock_signals(void) 192void unblock_signals(void)
133{ 193{
134 change_signals(SIG_UNBLOCK); 194 int save_pending;
135}
136 195
137/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled 196 if(signals_enabled == 1)
138 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to 197 return;
139 * be able to profile all of UML, not just the non-critical sections. If
140 * profiling is not thread-safe, then that is not my problem. We can disable
141 * profiling when SMP is enabled in that case.
142 */
143#define SIGIO_BIT 0
144#define SIGVTALRM_BIT 1
145
146static int enable_mask(sigset_t *mask)
147{
148 int sigs;
149 198
150 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; 199 /* We loop because the IRQ handler returns with interrupts off. So,
151 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; 200 * interrupts may have arrived and we need to re-enable them and
152 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; 201 * recheck pending.
153 return(sigs); 202 */
203 while(1){
204 /* Save and reset save_pending after enabling signals. This
205 * way, pending won't be changed while we're reading it.
206 */
207 signals_enabled = 1;
208
209 save_pending = pending;
210 if(save_pending == 0)
211 return;
212
213 pending = 0;
214
215 /* We have pending interrupts, so disable signals, as the
216 * handlers expect them off when they are called. They will
217 * be enabled again above.
218 */
219
220 signals_enabled = 0;
221
222 /* Deal with SIGIO first because the alarm handler might
223 * schedule, leaving the pending SIGIO stranded until we come
224 * back here.
225 */
226 if(save_pending & SIGIO_MASK)
227 CHOOSE_MODE_PROC(sig_handler_common_tt,
228 sig_handler_common_skas, SIGIO, NULL);
229
230 if(save_pending & SIGALRM_MASK)
231 real_alarm_handler(SIGALRM, NULL);
232
233 if(save_pending & SIGVTALRM_MASK)
234 real_alarm_handler(SIGVTALRM, NULL);
235 }
154} 236}
155 237
156int get_signals(void) 238int get_signals(void)
157{ 239{
158 sigset_t mask; 240 return signals_enabled;
159
160 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
161 panic("Failed to get signal mask");
162 return(enable_mask(&mask));
163} 241}
164 242
165int set_signals(int enable) 243int set_signals(int enable)
166{ 244{
167 sigset_t mask;
168 int ret; 245 int ret;
246 if(signals_enabled == enable)
247 return enable;
169 248
170 sigemptyset(&mask); 249 ret = signals_enabled;
171 if(enable & (1 << SIGIO_BIT)) 250 if(enable)
172 sigaddset(&mask, SIGIO); 251 unblock_signals();
173 if(enable & (1 << SIGVTALRM_BIT)){ 252 else block_signals();
174 sigaddset(&mask, SIGVTALRM);
175 sigaddset(&mask, SIGALRM);
176 }
177
178 /* This is safe - sigprocmask is guaranteed to copy locally the
179 * value of new_set, do his work and then, at the end, write to
180 * old_set.
181 */
182 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
183 panic("Failed to enable signals");
184 ret = enable_mask(&mask);
185 sigemptyset(&mask);
186 if((enable & (1 << SIGIO_BIT)) == 0)
187 sigaddset(&mask, SIGIO);
188 if((enable & (1 << SIGVTALRM_BIT)) == 0){
189 sigaddset(&mask, SIGVTALRM);
190 sigaddset(&mask, SIGALRM);
191 }
192 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
193 panic("Failed to block signals");
194 253
195 return(ret); 254 return ret;
196} 255}
197 256
198void os_usr1_signal(int on) 257void os_usr1_signal(int on)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index b959b2618b7f..120a21c5883f 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -34,6 +34,7 @@
34#include "mem.h" 34#include "mem.h"
35#include "uml-config.h" 35#include "uml-config.h"
36#include "process.h" 36#include "process.h"
37#include "longjmp.h"
37 38
38int is_skas_winch(int pid, int fd, void *data) 39int is_skas_winch(int pid, int fd, void *data)
39{ 40{
@@ -433,6 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
433{ 434{
434 unsigned long flags; 435 unsigned long flags;
435 sigjmp_buf switch_buf, fork_buf; 436 sigjmp_buf switch_buf, fork_buf;
437 int enable;
436 438
437 *switch_buf_ptr = &switch_buf; 439 *switch_buf_ptr = &switch_buf;
438 *fork_buf_ptr = &fork_buf; 440 *fork_buf_ptr = &fork_buf;
@@ -447,7 +449,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
447 */ 449 */
448 flags = get_signals(); 450 flags = get_signals();
449 block_signals(); 451 block_signals();
450 if(sigsetjmp(fork_buf, 1) == 0) 452 if(UML_SIGSETJMP(&fork_buf, enable) == 0)
451 new_thread_proc(stack, handler); 453 new_thread_proc(stack, handler);
452 454
453 remove_sigstack(); 455 remove_sigstack();
@@ -458,20 +460,22 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
458void thread_wait(void *sw, void *fb) 460void thread_wait(void *sw, void *fb)
459{ 461{
460 sigjmp_buf buf, **switch_buf = sw, *fork_buf; 462 sigjmp_buf buf, **switch_buf = sw, *fork_buf;
463 int enable;
461 464
462 *switch_buf = &buf; 465 *switch_buf = &buf;
463 fork_buf = fb; 466 fork_buf = fb;
464 if(sigsetjmp(buf, 1) == 0) 467 if(UML_SIGSETJMP(&buf, enable) == 0)
465 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); 468 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
466} 469}
467 470
468void switch_threads(void *me, void *next) 471void switch_threads(void *me, void *next)
469{ 472{
470 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; 473 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
474 int enable;
471 475
472 *me_ptr = &my_buf; 476 *me_ptr = &my_buf;
473 if(sigsetjmp(my_buf, 1) == 0) 477 if(UML_SIGSETJMP(&my_buf, enable) == 0)
474 siglongjmp(*next_buf, 1); 478 UML_SIGLONGJMP(next_buf, 1);
475} 479}
476 480
477static sigjmp_buf initial_jmpbuf; 481static sigjmp_buf initial_jmpbuf;
@@ -484,14 +488,14 @@ static sigjmp_buf *cb_back;
484int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) 488int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
485{ 489{
486 sigjmp_buf **switch_buf = switch_buf_ptr; 490 sigjmp_buf **switch_buf = switch_buf_ptr;
487 int n; 491 int n, enable;
488 492
489 set_handler(SIGWINCH, (__sighandler_t) sig_handler, 493 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
490 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 494 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
491 SIGVTALRM, -1); 495 SIGVTALRM, -1);
492 496
493 *fork_buf_ptr = &initial_jmpbuf; 497 *fork_buf_ptr = &initial_jmpbuf;
494 n = sigsetjmp(initial_jmpbuf, 1); 498 n = UML_SIGSETJMP(&initial_jmpbuf, enable);
495 switch(n){ 499 switch(n){
496 case INIT_JMP_NEW_THREAD: 500 case INIT_JMP_NEW_THREAD:
497 new_thread_proc((void *) stack, new_thread_handler); 501 new_thread_proc((void *) stack, new_thread_handler);
@@ -501,7 +505,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
501 break; 505 break;
502 case INIT_JMP_CALLBACK: 506 case INIT_JMP_CALLBACK:
503 (*cb_proc)(cb_arg); 507 (*cb_proc)(cb_arg);
504 siglongjmp(*cb_back, 1); 508 UML_SIGLONGJMP(cb_back, 1);
505 break; 509 break;
506 case INIT_JMP_HALT: 510 case INIT_JMP_HALT:
507 kmalloc_ok = 0; 511 kmalloc_ok = 0;
@@ -512,20 +516,21 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
512 default: 516 default:
513 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 517 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
514 } 518 }
515 siglongjmp(**switch_buf, 1); 519 UML_SIGLONGJMP(*switch_buf, 1);
516} 520}
517 521
518void initial_thread_cb_skas(void (*proc)(void *), void *arg) 522void initial_thread_cb_skas(void (*proc)(void *), void *arg)
519{ 523{
520 sigjmp_buf here; 524 sigjmp_buf here;
525 int enable;
521 526
522 cb_proc = proc; 527 cb_proc = proc;
523 cb_arg = arg; 528 cb_arg = arg;
524 cb_back = &here; 529 cb_back = &here;
525 530
526 block_signals(); 531 block_signals();
527 if(sigsetjmp(here, 1) == 0) 532 if(UML_SIGSETJMP(&here, enable) == 0)
528 siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK); 533 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
529 unblock_signals(); 534 unblock_signals();
530 535
531 cb_proc = NULL; 536 cb_proc = NULL;
@@ -536,13 +541,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
536void halt_skas(void) 541void halt_skas(void)
537{ 542{
538 block_signals(); 543 block_signals();
539 siglongjmp(initial_jmpbuf, INIT_JMP_HALT); 544 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
540} 545}
541 546
542void reboot_skas(void) 547void reboot_skas(void)
543{ 548{
544 block_signals(); 549 block_signals();
545 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); 550 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
546} 551}
547 552
548void switch_mm_skas(struct mm_id *mm_idp) 553void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 321e1c8e227d..a9f6b26f9828 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -10,6 +10,7 @@
10#include "user_util.h" 10#include "user_util.h"
11#include "os.h" 11#include "os.h"
12#include "mode.h" 12#include "mode.h"
13#include "longjmp.h"
13 14
14void usr2_handler(int sig, union uml_pt_regs *regs) 15void usr2_handler(int sig, union uml_pt_regs *regs)
15{ 16{
@@ -36,5 +37,5 @@ void do_longjmp(void *b, int val)
36{ 37{
37 sigjmp_buf *buf = b; 38 sigjmp_buf *buf = b;
38 39
39 siglongjmp(*buf, val); 40 UML_SIGLONGJMP(buf, val);
40} 41}
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 38d710158c3d..166fb66995df 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -6,6 +6,7 @@
6 6
7#include <setjmp.h> 7#include <setjmp.h>
8#include <string.h> 8#include <string.h>
9#include "longjmp.h"
9 10
10unsigned long __do_user_copy(void *to, const void *from, int n, 11unsigned long __do_user_copy(void *to, const void *from, int n,
11 void **fault_addr, void **fault_catcher, 12 void **fault_addr, void **fault_catcher,
@@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
13 int n), int *faulted_out) 14 int n), int *faulted_out)
14{ 15{
15 unsigned long *faddrp = (unsigned long *) fault_addr, ret; 16 unsigned long *faddrp = (unsigned long *) fault_addr, ret;
17 int enable;
16 18
17 sigjmp_buf jbuf; 19 sigjmp_buf jbuf;
18 *fault_catcher = &jbuf; 20 *fault_catcher = &jbuf;
19 if(sigsetjmp(jbuf, 1) == 0){ 21 if(UML_SIGSETJMP(&jbuf, enable) == 0){
20 (*op)(to, from, n); 22 (*op)(to, from, n);
21 ret = 0; 23 ret = 0;
22 *faulted_out = 0; 24 *faulted_out = 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index d224434d5610..e32065e2fdc8 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -30,6 +30,7 @@
30#include "ptrace_user.h" 30#include "ptrace_user.h"
31#include "uml-config.h" 31#include "uml-config.h"
32#include "os.h" 32#include "os.h"
33#include "longjmp.h"
33 34
34void stack_protections(unsigned long address) 35void stack_protections(unsigned long address)
35{ 36{