diff options
author | David S. Miller <davem@davemloft.net> | 2008-04-27 05:26:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-27 05:26:36 -0400 |
commit | 5526b7e4513c66bc1c91f661dcd518d5199f8934 (patch) | |
tree | 658de7d323dc5aa5c13d7c9545820b5911d758dc /arch | |
parent | 7cf069955f2f0b95fed6a8b1a61ef598a3df0f4e (diff) |
sparc: Remove old style signal frame support.
Back around the same time we were bootstrapping the first 32-bit sparc
Linux kernel with a SunOS userland, we made the signal frame match
that of SunOS.
By the time we even started putting together a native Linux userland
for 32-bit Sparc we realized this layout wasn't sufficient for Linux's
needs.
Therefore we changed the layout, yet kept support for the old style
signal frame layout in there. The detection mechanism is that we had
sys_sigaction() start passing in a negative signal number to indicate
"new style signal frames please".
Anyways, no binaries exist in the world that use the old stuff. In
fact, I bet Jakub Jelinek and myself are the only two people who ever
had such binaries to be honest.
So let's get rid of this stuff.
I added an assertion using WARN_ON_ONCE() that makes sure 32-bit
applications are passing in that negative signal number still.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/signal.c | 260 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc.c | 14 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/signal32.c | 272 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc32.c | 11 |
6 files changed, 44 insertions, 521 deletions
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 70c0dd22491d..e7f35198ae34 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c | |||
@@ -357,8 +357,6 @@ void flush_thread(void) | |||
357 | { | 357 | { |
358 | current_thread_info()->w_saved = 0; | 358 | current_thread_info()->w_saved = 0; |
359 | 359 | ||
360 | /* No new signal delivery by default */ | ||
361 | current->thread.new_signal = 0; | ||
362 | #ifndef CONFIG_SMP | 360 | #ifndef CONFIG_SMP |
363 | if(last_task_used_math == current) { | 361 | if(last_task_used_math == current) { |
364 | #else | 362 | #else |
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 3e849e8e3480..3c312290c3c2 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: signal.c,v 1.110 2002/02/08 03:57:14 davem Exp $ | 1 | /* linux/arch/sparc/kernel/signal.c |
2 | * linux/arch/sparc/kernel/signal.c | ||
3 | * | 2 | * |
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | 4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) |
@@ -32,37 +31,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, | |||
32 | void *fpqueue, unsigned long *fpqdepth); | 31 | void *fpqueue, unsigned long *fpqdepth); |
33 | extern void fpload(unsigned long *fpregs, unsigned long *fsr); | 32 | extern void fpload(unsigned long *fpregs, unsigned long *fsr); |
34 | 33 | ||
35 | /* Signal frames: the original one (compatible with SunOS): | 34 | struct signal_frame { |
36 | * | ||
37 | * Set up a signal frame... Make the stack look the way SunOS | ||
38 | * expects it to look which is basically: | ||
39 | * | ||
40 | * ---------------------------------- <-- %sp at signal time | ||
41 | * Struct sigcontext | ||
42 | * Signal address | ||
43 | * Ptr to sigcontext area above | ||
44 | * Signal code | ||
45 | * The signal number itself | ||
46 | * One register window | ||
47 | * ---------------------------------- <-- New %sp | ||
48 | */ | ||
49 | struct signal_sframe { | ||
50 | struct reg_window sig_window; | ||
51 | int sig_num; | ||
52 | int sig_code; | ||
53 | struct sigcontext __user *sig_scptr; | ||
54 | int sig_address; | ||
55 | struct sigcontext sig_context; | ||
56 | unsigned int extramask[_NSIG_WORDS - 1]; | ||
57 | }; | ||
58 | |||
59 | /* | ||
60 | * And the new one, intended to be used for Linux applications only | ||
61 | * (we have enough in there to work with clone). | ||
62 | * All the interesting bits are in the info field. | ||
63 | */ | ||
64 | |||
65 | struct new_signal_frame { | ||
66 | struct sparc_stackf ss; | 35 | struct sparc_stackf ss; |
67 | __siginfo_t info; | 36 | __siginfo_t info; |
68 | __siginfo_fpu_t __user *fpu_save; | 37 | __siginfo_fpu_t __user *fpu_save; |
@@ -85,8 +54,7 @@ struct rt_signal_frame { | |||
85 | }; | 54 | }; |
86 | 55 | ||
87 | /* Align macros */ | 56 | /* Align macros */ |
88 | #define SF_ALIGNEDSZ (((sizeof(struct signal_sframe) + 7) & (~7))) | 57 | #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) |
89 | #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) | ||
90 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) | 58 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) |
91 | 59 | ||
92 | static int _sigpause_common(old_sigset_t set) | 60 | static int _sigpause_common(old_sigset_t set) |
@@ -141,15 +109,20 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | |||
141 | return err; | 109 | return err; |
142 | } | 110 | } |
143 | 111 | ||
144 | static inline void do_new_sigreturn (struct pt_regs *regs) | 112 | asmlinkage void do_sigreturn(struct pt_regs *regs) |
145 | { | 113 | { |
146 | struct new_signal_frame __user *sf; | 114 | struct signal_frame __user *sf; |
147 | unsigned long up_psr, pc, npc; | 115 | unsigned long up_psr, pc, npc; |
148 | sigset_t set; | 116 | sigset_t set; |
149 | __siginfo_fpu_t __user *fpu_save; | 117 | __siginfo_fpu_t __user *fpu_save; |
150 | int err; | 118 | int err; |
151 | 119 | ||
152 | sf = (struct new_signal_frame __user *) regs->u_regs[UREG_FP]; | 120 | /* Always make any pending restarted system calls return -EINTR */ |
121 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
122 | |||
123 | synchronize_user_stack(); | ||
124 | |||
125 | sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; | ||
153 | 126 | ||
154 | /* 1. Make sure we are not getting garbage from the user */ | 127 | /* 1. Make sure we are not getting garbage from the user */ |
155 | if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) | 128 | if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) |
@@ -198,73 +171,6 @@ segv_and_exit: | |||
198 | force_sig(SIGSEGV, current); | 171 | force_sig(SIGSEGV, current); |
199 | } | 172 | } |
200 | 173 | ||
201 | asmlinkage void do_sigreturn(struct pt_regs *regs) | ||
202 | { | ||
203 | struct sigcontext __user *scptr; | ||
204 | unsigned long pc, npc, psr; | ||
205 | sigset_t set; | ||
206 | int err; | ||
207 | |||
208 | /* Always make any pending restarted system calls return -EINTR */ | ||
209 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
210 | |||
211 | synchronize_user_stack(); | ||
212 | |||
213 | if (current->thread.new_signal) { | ||
214 | do_new_sigreturn(regs); | ||
215 | return; | ||
216 | } | ||
217 | |||
218 | scptr = (struct sigcontext __user *) regs->u_regs[UREG_I0]; | ||
219 | |||
220 | /* Check sanity of the user arg. */ | ||
221 | if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext)) || | ||
222 | (((unsigned long) scptr) & 3)) | ||
223 | goto segv_and_exit; | ||
224 | |||
225 | err = __get_user(pc, &scptr->sigc_pc); | ||
226 | err |= __get_user(npc, &scptr->sigc_npc); | ||
227 | |||
228 | if ((pc | npc) & 3) | ||
229 | goto segv_and_exit; | ||
230 | |||
231 | /* This is pretty much atomic, no amount locking would prevent | ||
232 | * the races which exist anyways. | ||
233 | */ | ||
234 | err |= __get_user(set.sig[0], &scptr->sigc_mask); | ||
235 | /* Note that scptr + 1 points to extramask */ | ||
236 | err |= __copy_from_user(&set.sig[1], scptr + 1, | ||
237 | (_NSIG_WORDS - 1) * sizeof(unsigned int)); | ||
238 | |||
239 | if (err) | ||
240 | goto segv_and_exit; | ||
241 | |||
242 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
243 | spin_lock_irq(¤t->sighand->siglock); | ||
244 | current->blocked = set; | ||
245 | recalc_sigpending(); | ||
246 | spin_unlock_irq(¤t->sighand->siglock); | ||
247 | |||
248 | regs->pc = pc; | ||
249 | regs->npc = npc; | ||
250 | |||
251 | err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp); | ||
252 | err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0); | ||
253 | err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1); | ||
254 | |||
255 | /* User can only change condition codes in %psr. */ | ||
256 | err |= __get_user(psr, &scptr->sigc_psr); | ||
257 | if (err) | ||
258 | goto segv_and_exit; | ||
259 | |||
260 | regs->psr &= ~(PSR_ICC); | ||
261 | regs->psr |= (psr & PSR_ICC); | ||
262 | return; | ||
263 | |||
264 | segv_and_exit: | ||
265 | force_sig(SIGSEGV, current); | ||
266 | } | ||
267 | |||
268 | asmlinkage void do_rt_sigreturn(struct pt_regs *regs) | 174 | asmlinkage void do_rt_sigreturn(struct pt_regs *regs) |
269 | { | 175 | { |
270 | struct rt_signal_frame __user *sf; | 176 | struct rt_signal_frame __user *sf; |
@@ -351,128 +257,6 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re | |||
351 | return (void __user *)(sp - framesize); | 257 | return (void __user *)(sp - framesize); |
352 | } | 258 | } |
353 | 259 | ||
354 | static inline void | ||
355 | setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info) | ||
356 | { | ||
357 | struct signal_sframe __user *sframep; | ||
358 | struct sigcontext __user *sc; | ||
359 | int window = 0, err; | ||
360 | unsigned long pc = regs->pc; | ||
361 | unsigned long npc = regs->npc; | ||
362 | struct thread_info *tp = current_thread_info(); | ||
363 | void __user *sig_address; | ||
364 | int sig_code; | ||
365 | |||
366 | synchronize_user_stack(); | ||
367 | sframep = (struct signal_sframe __user *) | ||
368 | get_sigframe(sa, regs, SF_ALIGNEDSZ); | ||
369 | if (invalid_frame_pointer(sframep, sizeof(*sframep))){ | ||
370 | /* Don't change signal code and address, so that | ||
371 | * post mortem debuggers can have a look. | ||
372 | */ | ||
373 | goto sigill_and_return; | ||
374 | } | ||
375 | |||
376 | sc = &sframep->sig_context; | ||
377 | |||
378 | /* We've already made sure frame pointer isn't in kernel space... */ | ||
379 | err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), | ||
380 | &sc->sigc_onstack); | ||
381 | err |= __put_user(oldset->sig[0], &sc->sigc_mask); | ||
382 | err |= __copy_to_user(sframep->extramask, &oldset->sig[1], | ||
383 | (_NSIG_WORDS - 1) * sizeof(unsigned int)); | ||
384 | err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); | ||
385 | err |= __put_user(pc, &sc->sigc_pc); | ||
386 | err |= __put_user(npc, &sc->sigc_npc); | ||
387 | err |= __put_user(regs->psr, &sc->sigc_psr); | ||
388 | err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); | ||
389 | err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); | ||
390 | err |= __put_user(tp->w_saved, &sc->sigc_oswins); | ||
391 | if (tp->w_saved) | ||
392 | for (window = 0; window < tp->w_saved; window++) { | ||
393 | put_user((char *)tp->rwbuf_stkptrs[window], | ||
394 | &sc->sigc_spbuf[window]); | ||
395 | err |= __copy_to_user(&sc->sigc_wbuf[window], | ||
396 | &tp->reg_window[window], | ||
397 | sizeof(struct reg_window)); | ||
398 | } | ||
399 | else | ||
400 | err |= __copy_to_user(sframep, (char *) regs->u_regs[UREG_FP], | ||
401 | sizeof(struct reg_window)); | ||
402 | |||
403 | tp->w_saved = 0; /* So process is allowed to execute. */ | ||
404 | |||
405 | err |= __put_user(signr, &sframep->sig_num); | ||
406 | sig_address = NULL; | ||
407 | sig_code = 0; | ||
408 | if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) { | ||
409 | sig_address = info->si_addr; | ||
410 | switch (signr) { | ||
411 | case SIGSEGV: | ||
412 | switch (info->si_code) { | ||
413 | case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break; | ||
414 | default: sig_code = SUBSIG_PROTECTION; break; | ||
415 | } | ||
416 | break; | ||
417 | case SIGILL: | ||
418 | switch (info->si_code) { | ||
419 | case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break; | ||
420 | case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break; | ||
421 | case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break; | ||
422 | default: sig_code = SUBSIG_STACK; break; | ||
423 | } | ||
424 | break; | ||
425 | case SIGFPE: | ||
426 | switch (info->si_code) { | ||
427 | case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break; | ||
428 | case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break; | ||
429 | case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break; | ||
430 | case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break; | ||
431 | case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break; | ||
432 | case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break; | ||
433 | case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break; | ||
434 | default: sig_code = SUBSIG_FPERROR; break; | ||
435 | } | ||
436 | break; | ||
437 | case SIGBUS: | ||
438 | switch (info->si_code) { | ||
439 | case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break; | ||
440 | case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break; | ||
441 | default: sig_code = SUBSIG_BUSTIMEOUT; break; | ||
442 | } | ||
443 | break; | ||
444 | case SIGEMT: | ||
445 | switch (info->si_code) { | ||
446 | case EMT_TAGOVF: sig_code = SUBSIG_TAG; break; | ||
447 | } | ||
448 | break; | ||
449 | case SIGSYS: | ||
450 | if (info->si_code == (__SI_FAULT|0x100)) { | ||
451 | sig_code = info->si_trapno; | ||
452 | break; | ||
453 | } | ||
454 | default: | ||
455 | sig_address = NULL; | ||
456 | } | ||
457 | } | ||
458 | err |= __put_user((unsigned long)sig_address, &sframep->sig_address); | ||
459 | err |= __put_user(sig_code, &sframep->sig_code); | ||
460 | err |= __put_user(sc, &sframep->sig_scptr); | ||
461 | if (err) | ||
462 | goto sigsegv; | ||
463 | |||
464 | regs->u_regs[UREG_FP] = (unsigned long) sframep; | ||
465 | regs->pc = (unsigned long) sa->sa_handler; | ||
466 | regs->npc = (regs->pc + 4); | ||
467 | return; | ||
468 | |||
469 | sigill_and_return: | ||
470 | do_exit(SIGILL); | ||
471 | sigsegv: | ||
472 | force_sigsegv(signr, current); | ||
473 | } | ||
474 | |||
475 | |||
476 | static inline int | 260 | static inline int |
477 | save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | 261 | save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) |
478 | { | 262 | { |
@@ -508,21 +292,20 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | |||
508 | return err; | 292 | return err; |
509 | } | 293 | } |
510 | 294 | ||
511 | static inline void | 295 | static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, |
512 | new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, | 296 | int signo, sigset_t *oldset) |
513 | int signo, sigset_t *oldset) | ||
514 | { | 297 | { |
515 | struct new_signal_frame __user *sf; | 298 | struct signal_frame __user *sf; |
516 | int sigframe_size, err; | 299 | int sigframe_size, err; |
517 | 300 | ||
518 | /* 1. Make sure everything is clean */ | 301 | /* 1. Make sure everything is clean */ |
519 | synchronize_user_stack(); | 302 | synchronize_user_stack(); |
520 | 303 | ||
521 | sigframe_size = NF_ALIGNEDSZ; | 304 | sigframe_size = SF_ALIGNEDSZ; |
522 | if (!used_math()) | 305 | if (!used_math()) |
523 | sigframe_size -= sizeof(__siginfo_fpu_t); | 306 | sigframe_size -= sizeof(__siginfo_fpu_t); |
524 | 307 | ||
525 | sf = (struct new_signal_frame __user *) | 308 | sf = (struct signal_frame __user *) |
526 | get_sigframe(&ka->sa, regs, sigframe_size); | 309 | get_sigframe(&ka->sa, regs, sigframe_size); |
527 | 310 | ||
528 | if (invalid_frame_pointer(sf, sigframe_size)) | 311 | if (invalid_frame_pointer(sf, sigframe_size)) |
@@ -586,9 +369,8 @@ sigsegv: | |||
586 | force_sigsegv(signo, current); | 369 | force_sigsegv(signo, current); |
587 | } | 370 | } |
588 | 371 | ||
589 | static inline void | 372 | static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, |
590 | new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | 373 | int signo, sigset_t *oldset, siginfo_t *info) |
591 | int signo, sigset_t *oldset, siginfo_t *info) | ||
592 | { | 374 | { |
593 | struct rt_signal_frame __user *sf; | 375 | struct rt_signal_frame __user *sf; |
594 | int sigframe_size; | 376 | int sigframe_size; |
@@ -674,11 +456,9 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, | |||
674 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | 456 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
675 | { | 457 | { |
676 | if (ka->sa.sa_flags & SA_SIGINFO) | 458 | if (ka->sa.sa_flags & SA_SIGINFO) |
677 | new_setup_rt_frame(ka, regs, signr, oldset, info); | 459 | setup_rt_frame(ka, regs, signr, oldset, info); |
678 | else if (current->thread.new_signal) | ||
679 | new_setup_frame(ka, regs, signr, oldset); | ||
680 | else | 460 | else |
681 | setup_frame(&ka->sa, regs, signr, oldset, info); | 461 | setup_frame(ka, regs, signr, oldset); |
682 | 462 | ||
683 | spin_lock_irq(¤t->sighand->siglock); | 463 | spin_lock_irq(¤t->sighand->siglock); |
684 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 464 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 42bf09db9a81..f188b5dc9fd0 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $ | 1 | /* linux/arch/sparc/kernel/sys_sparc.c |
2 | * linux/arch/sparc/kernel/sys_sparc.c | ||
3 | * | 2 | * |
4 | * This file contains various random system calls that | 3 | * This file contains various random system calls that |
5 | * have a non-standard calling sequence on the Linux/sparc | 4 | * have a non-standard calling sequence on the Linux/sparc |
@@ -395,10 +394,8 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act, | |||
395 | struct k_sigaction new_ka, old_ka; | 394 | struct k_sigaction new_ka, old_ka; |
396 | int ret; | 395 | int ret; |
397 | 396 | ||
398 | if (sig < 0) { | 397 | WARN_ON_ONCE(sig >= 0); |
399 | current->thread.new_signal = 1; | 398 | sig = -sig; |
400 | sig = -sig; | ||
401 | } | ||
402 | 399 | ||
403 | if (act) { | 400 | if (act) { |
404 | unsigned long mask; | 401 | unsigned long mask; |
@@ -446,11 +443,6 @@ sys_rt_sigaction(int sig, | |||
446 | if (sigsetsize != sizeof(sigset_t)) | 443 | if (sigsetsize != sizeof(sigset_t)) |
447 | return -EINVAL; | 444 | return -EINVAL; |
448 | 445 | ||
449 | /* All tasks which use RT signals (effectively) use | ||
450 | * new style signals. | ||
451 | */ | ||
452 | current->thread.new_signal = 1; | ||
453 | |||
454 | if (act) { | 446 | if (act) { |
455 | new_ka.ka_restorer = restorer; | 447 | new_ka.ka_restorer = restorer; |
456 | if (copy_from_user(&new_ka.sa, act, sizeof(*act))) | 448 | if (copy_from_user(&new_ka.sa, act, sizeof(*act))) |
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index acf8c5250aa9..500ac6d483a0 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $ | 1 | /* arch/sparc64/kernel/process.c |
2 | * arch/sparc64/kernel/process.c | ||
3 | * | 2 | * |
4 | * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) | 3 | * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) |
5 | * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) | 4 | * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) |
@@ -368,9 +367,6 @@ void flush_thread(void) | |||
368 | 367 | ||
369 | if (get_thread_current_ds() != ASI_AIUS) | 368 | if (get_thread_current_ds() != ASI_AIUS) |
370 | set_fs(USER_DS); | 369 | set_fs(USER_DS); |
371 | |||
372 | /* Init new signal delivery disposition. */ | ||
373 | clear_thread_flag(TIF_NEWSIGNALS); | ||
374 | } | 370 | } |
375 | 371 | ||
376 | /* It's a bit more tricky when 64-bit tasks are involved... */ | 372 | /* It's a bit more tricky when 64-bit tasks are involved... */ |
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 43cdec64d9c9..91f8d0826db1 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: signal32.c,v 1.74 2002/02/09 19:49:30 davem Exp $ | 1 | /* arch/sparc64/kernel/signal32.c |
2 | * arch/sparc64/kernel/signal32.c | ||
3 | * | 2 | * |
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | 4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) |
@@ -31,30 +30,6 @@ | |||
31 | 30 | ||
32 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
33 | 32 | ||
34 | /* Signal frames: the original one (compatible with SunOS): | ||
35 | * | ||
36 | * Set up a signal frame... Make the stack look the way SunOS | ||
37 | * expects it to look which is basically: | ||
38 | * | ||
39 | * ---------------------------------- <-- %sp at signal time | ||
40 | * Struct sigcontext | ||
41 | * Signal address | ||
42 | * Ptr to sigcontext area above | ||
43 | * Signal code | ||
44 | * The signal number itself | ||
45 | * One register window | ||
46 | * ---------------------------------- <-- New %sp | ||
47 | */ | ||
48 | struct signal_sframe32 { | ||
49 | struct reg_window32 sig_window; | ||
50 | int sig_num; | ||
51 | int sig_code; | ||
52 | /* struct sigcontext32 * */ u32 sig_scptr; | ||
53 | int sig_address; | ||
54 | struct sigcontext32 sig_context; | ||
55 | unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; | ||
56 | }; | ||
57 | |||
58 | /* This magic should be in g_upper[0] for all upper parts | 33 | /* This magic should be in g_upper[0] for all upper parts |
59 | * to be valid. | 34 | * to be valid. |
60 | */ | 35 | */ |
@@ -65,12 +40,7 @@ typedef struct { | |||
65 | unsigned int asi; | 40 | unsigned int asi; |
66 | } siginfo_extra_v8plus_t; | 41 | } siginfo_extra_v8plus_t; |
67 | 42 | ||
68 | /* | 43 | struct signal_frame32 { |
69 | * And the new one, intended to be used for Linux applications only | ||
70 | * (we have enough in there to work with clone). | ||
71 | * All the interesting bits are in the info field. | ||
72 | */ | ||
73 | struct new_signal_frame32 { | ||
74 | struct sparc_stackf32 ss; | 44 | struct sparc_stackf32 ss; |
75 | __siginfo32_t info; | 45 | __siginfo32_t info; |
76 | /* __siginfo_fpu32_t * */ u32 fpu_save; | 46 | /* __siginfo_fpu32_t * */ u32 fpu_save; |
@@ -149,8 +119,7 @@ struct rt_signal_frame32 { | |||
149 | }; | 119 | }; |
150 | 120 | ||
151 | /* Align macros */ | 121 | /* Align macros */ |
152 | #define SF_ALIGNEDSZ (((sizeof(struct signal_sframe32) + 7) & (~7))) | 122 | #define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 7) & (~7))) |
153 | #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7))) | ||
154 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) | 123 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) |
155 | 124 | ||
156 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | 125 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
@@ -241,17 +210,22 @@ static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu | |||
241 | return err; | 210 | return err; |
242 | } | 211 | } |
243 | 212 | ||
244 | void do_new_sigreturn32(struct pt_regs *regs) | 213 | void do_sigreturn32(struct pt_regs *regs) |
245 | { | 214 | { |
246 | struct new_signal_frame32 __user *sf; | 215 | struct signal_frame32 __user *sf; |
247 | unsigned int psr; | 216 | unsigned int psr; |
248 | unsigned pc, npc, fpu_save; | 217 | unsigned pc, npc, fpu_save; |
249 | sigset_t set; | 218 | sigset_t set; |
250 | unsigned seta[_COMPAT_NSIG_WORDS]; | 219 | unsigned seta[_COMPAT_NSIG_WORDS]; |
251 | int err, i; | 220 | int err, i; |
252 | 221 | ||
222 | /* Always make any pending restarted system calls return -EINTR */ | ||
223 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
224 | |||
225 | synchronize_user_stack(); | ||
226 | |||
253 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; | 227 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; |
254 | sf = (struct new_signal_frame32 __user *) regs->u_regs[UREG_FP]; | 228 | sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP]; |
255 | 229 | ||
256 | /* 1. Make sure we are not getting garbage from the user */ | 230 | /* 1. Make sure we are not getting garbage from the user */ |
257 | if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || | 231 | if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || |
@@ -319,76 +293,6 @@ segv: | |||
319 | force_sig(SIGSEGV, current); | 293 | force_sig(SIGSEGV, current); |
320 | } | 294 | } |
321 | 295 | ||
322 | asmlinkage void do_sigreturn32(struct pt_regs *regs) | ||
323 | { | ||
324 | struct sigcontext32 __user *scptr; | ||
325 | unsigned int pc, npc, psr; | ||
326 | sigset_t set; | ||
327 | unsigned int seta[_COMPAT_NSIG_WORDS]; | ||
328 | int err; | ||
329 | |||
330 | /* Always make any pending restarted system calls return -EINTR */ | ||
331 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
332 | |||
333 | synchronize_user_stack(); | ||
334 | if (test_thread_flag(TIF_NEWSIGNALS)) { | ||
335 | do_new_sigreturn32(regs); | ||
336 | return; | ||
337 | } | ||
338 | |||
339 | scptr = (struct sigcontext32 __user *) | ||
340 | (regs->u_regs[UREG_I0] & 0x00000000ffffffffUL); | ||
341 | /* Check sanity of the user arg. */ | ||
342 | if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext32)) || | ||
343 | (((unsigned long) scptr) & 3)) | ||
344 | goto segv; | ||
345 | |||
346 | err = __get_user(pc, &scptr->sigc_pc); | ||
347 | err |= __get_user(npc, &scptr->sigc_npc); | ||
348 | |||
349 | if ((pc | npc) & 3) | ||
350 | goto segv; /* Nice try. */ | ||
351 | |||
352 | err |= __get_user(seta[0], &scptr->sigc_mask); | ||
353 | /* Note that scptr + 1 points to extramask */ | ||
354 | err |= copy_from_user(seta+1, scptr + 1, | ||
355 | (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); | ||
356 | if (err) | ||
357 | goto segv; | ||
358 | switch (_NSIG_WORDS) { | ||
359 | case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32); | ||
360 | case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32); | ||
361 | case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); | ||
362 | case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); | ||
363 | } | ||
364 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
365 | spin_lock_irq(¤t->sighand->siglock); | ||
366 | current->blocked = set; | ||
367 | recalc_sigpending(); | ||
368 | spin_unlock_irq(¤t->sighand->siglock); | ||
369 | |||
370 | if (test_thread_flag(TIF_32BIT)) { | ||
371 | pc &= 0xffffffff; | ||
372 | npc &= 0xffffffff; | ||
373 | } | ||
374 | regs->tpc = pc; | ||
375 | regs->tnpc = npc; | ||
376 | err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp); | ||
377 | err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0); | ||
378 | err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1); | ||
379 | |||
380 | /* User can only change condition codes in %tstate. */ | ||
381 | err |= __get_user(psr, &scptr->sigc_psr); | ||
382 | if (err) | ||
383 | goto segv; | ||
384 | regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); | ||
385 | regs->tstate |= psr_to_tstate_icc(psr); | ||
386 | return; | ||
387 | |||
388 | segv: | ||
389 | force_sig(SIGSEGV, current); | ||
390 | } | ||
391 | |||
392 | asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) | 296 | asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) |
393 | { | 297 | { |
394 | struct rt_signal_frame32 __user *sf; | 298 | struct rt_signal_frame32 __user *sf; |
@@ -504,145 +408,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns | |||
504 | return (void __user *)(sp - framesize); | 408 | return (void __user *)(sp - framesize); |
505 | } | 409 | } |
506 | 410 | ||
507 | static void | ||
508 | setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info) | ||
509 | { | ||
510 | struct signal_sframe32 __user *sframep; | ||
511 | struct sigcontext32 __user *sc; | ||
512 | unsigned int seta[_COMPAT_NSIG_WORDS]; | ||
513 | int err = 0; | ||
514 | void __user *sig_address; | ||
515 | int sig_code; | ||
516 | unsigned long pc = regs->tpc; | ||
517 | unsigned long npc = regs->tnpc; | ||
518 | unsigned int psr; | ||
519 | |||
520 | if (test_thread_flag(TIF_32BIT)) { | ||
521 | pc &= 0xffffffff; | ||
522 | npc &= 0xffffffff; | ||
523 | } | ||
524 | |||
525 | synchronize_user_stack(); | ||
526 | save_and_clear_fpu(); | ||
527 | |||
528 | sframep = (struct signal_sframe32 __user *) | ||
529 | get_sigframe(sa, regs, SF_ALIGNEDSZ); | ||
530 | if (invalid_frame_pointer(sframep, sizeof(*sframep))){ | ||
531 | /* Don't change signal code and address, so that | ||
532 | * post mortem debuggers can have a look. | ||
533 | */ | ||
534 | do_exit(SIGILL); | ||
535 | } | ||
536 | |||
537 | sc = &sframep->sig_context; | ||
538 | |||
539 | /* We've already made sure frame pointer isn't in kernel space... */ | ||
540 | err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), | ||
541 | &sc->sigc_onstack); | ||
542 | |||
543 | switch (_NSIG_WORDS) { | ||
544 | case 4: seta[7] = (oldset->sig[3] >> 32); | ||
545 | seta[6] = oldset->sig[3]; | ||
546 | case 3: seta[5] = (oldset->sig[2] >> 32); | ||
547 | seta[4] = oldset->sig[2]; | ||
548 | case 2: seta[3] = (oldset->sig[1] >> 32); | ||
549 | seta[2] = oldset->sig[1]; | ||
550 | case 1: seta[1] = (oldset->sig[0] >> 32); | ||
551 | seta[0] = oldset->sig[0]; | ||
552 | } | ||
553 | err |= __put_user(seta[0], &sc->sigc_mask); | ||
554 | err |= __copy_to_user(sframep->extramask, seta + 1, | ||
555 | (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); | ||
556 | err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); | ||
557 | err |= __put_user(pc, &sc->sigc_pc); | ||
558 | err |= __put_user(npc, &sc->sigc_npc); | ||
559 | psr = tstate_to_psr(regs->tstate); | ||
560 | if (current_thread_info()->fpsaved[0] & FPRS_FEF) | ||
561 | psr |= PSR_EF; | ||
562 | err |= __put_user(psr, &sc->sigc_psr); | ||
563 | err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); | ||
564 | err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); | ||
565 | err |= __put_user(get_thread_wsaved(), &sc->sigc_oswins); | ||
566 | |||
567 | err |= copy_in_user((u32 __user *)sframep, | ||
568 | (u32 __user *)(regs->u_regs[UREG_FP]), | ||
569 | sizeof(struct reg_window32)); | ||
570 | |||
571 | set_thread_wsaved(0); /* So process is allowed to execute. */ | ||
572 | err |= __put_user(signr, &sframep->sig_num); | ||
573 | sig_address = NULL; | ||
574 | sig_code = 0; | ||
575 | if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) { | ||
576 | sig_address = info->si_addr; | ||
577 | switch (signr) { | ||
578 | case SIGSEGV: | ||
579 | switch (info->si_code) { | ||
580 | case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break; | ||
581 | default: sig_code = SUBSIG_PROTECTION; break; | ||
582 | } | ||
583 | break; | ||
584 | case SIGILL: | ||
585 | switch (info->si_code) { | ||
586 | case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break; | ||
587 | case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break; | ||
588 | case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break; | ||
589 | default: sig_code = SUBSIG_STACK; break; | ||
590 | } | ||
591 | break; | ||
592 | case SIGFPE: | ||
593 | switch (info->si_code) { | ||
594 | case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break; | ||
595 | case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break; | ||
596 | case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break; | ||
597 | case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break; | ||
598 | case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break; | ||
599 | case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break; | ||
600 | case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break; | ||
601 | default: sig_code = SUBSIG_FPERROR; break; | ||
602 | } | ||
603 | break; | ||
604 | case SIGBUS: | ||
605 | switch (info->si_code) { | ||
606 | case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break; | ||
607 | case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break; | ||
608 | default: sig_code = SUBSIG_BUSTIMEOUT; break; | ||
609 | } | ||
610 | break; | ||
611 | case SIGEMT: | ||
612 | switch (info->si_code) { | ||
613 | case EMT_TAGOVF: sig_code = SUBSIG_TAG; break; | ||
614 | } | ||
615 | break; | ||
616 | case SIGSYS: | ||
617 | if (info->si_code == (__SI_FAULT|0x100)) { | ||
618 | /* See sys_sunos32.c */ | ||
619 | sig_code = info->si_trapno; | ||
620 | break; | ||
621 | } | ||
622 | default: | ||
623 | sig_address = NULL; | ||
624 | } | ||
625 | } | ||
626 | err |= __put_user(ptr_to_compat(sig_address), &sframep->sig_address); | ||
627 | err |= __put_user(sig_code, &sframep->sig_code); | ||
628 | err |= __put_user(ptr_to_compat(sc), &sframep->sig_scptr); | ||
629 | if (err) | ||
630 | goto sigsegv; | ||
631 | |||
632 | regs->u_regs[UREG_FP] = (unsigned long) sframep; | ||
633 | regs->tpc = (unsigned long) sa->sa_handler; | ||
634 | regs->tnpc = (regs->tpc + 4); | ||
635 | if (test_thread_flag(TIF_32BIT)) { | ||
636 | regs->tpc &= 0xffffffff; | ||
637 | regs->tnpc &= 0xffffffff; | ||
638 | } | ||
639 | return; | ||
640 | |||
641 | sigsegv: | ||
642 | force_sigsegv(signr, current); | ||
643 | } | ||
644 | |||
645 | |||
646 | static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | 411 | static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) |
647 | { | 412 | { |
648 | unsigned long *fpregs = current_thread_info()->fpregs; | 413 | unsigned long *fpregs = current_thread_info()->fpregs; |
@@ -663,10 +428,10 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | |||
663 | return err; | 428 | return err; |
664 | } | 429 | } |
665 | 430 | ||
666 | static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, | 431 | static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, |
667 | int signo, sigset_t *oldset) | 432 | int signo, sigset_t *oldset) |
668 | { | 433 | { |
669 | struct new_signal_frame32 __user *sf; | 434 | struct signal_frame32 __user *sf; |
670 | int sigframe_size; | 435 | int sigframe_size; |
671 | u32 psr; | 436 | u32 psr; |
672 | int i, err; | 437 | int i, err; |
@@ -676,11 +441,11 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, | |||
676 | synchronize_user_stack(); | 441 | synchronize_user_stack(); |
677 | save_and_clear_fpu(); | 442 | save_and_clear_fpu(); |
678 | 443 | ||
679 | sigframe_size = NF_ALIGNEDSZ; | 444 | sigframe_size = SF_ALIGNEDSZ; |
680 | if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) | 445 | if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) |
681 | sigframe_size -= sizeof(__siginfo_fpu_t); | 446 | sigframe_size -= sizeof(__siginfo_fpu_t); |
682 | 447 | ||
683 | sf = (struct new_signal_frame32 __user *) | 448 | sf = (struct signal_frame32 __user *) |
684 | get_sigframe(&ka->sa, regs, sigframe_size); | 449 | get_sigframe(&ka->sa, regs, sigframe_size); |
685 | 450 | ||
686 | if (invalid_frame_pointer(sf, sigframe_size)) | 451 | if (invalid_frame_pointer(sf, sigframe_size)) |
@@ -944,10 +709,9 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, | |||
944 | { | 709 | { |
945 | if (ka->sa.sa_flags & SA_SIGINFO) | 710 | if (ka->sa.sa_flags & SA_SIGINFO) |
946 | setup_rt_frame32(ka, regs, signr, oldset, info); | 711 | setup_rt_frame32(ka, regs, signr, oldset, info); |
947 | else if (test_thread_flag(TIF_NEWSIGNALS)) | ||
948 | new_setup_frame32(ka, regs, signr, oldset); | ||
949 | else | 712 | else |
950 | setup_frame32(&ka->sa, regs, signr, oldset, info); | 713 | setup_frame32(ka, regs, signr, oldset); |
714 | |||
951 | spin_lock_irq(¤t->sighand->siglock); | 715 | spin_lock_irq(¤t->sighand->siglock); |
952 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 716 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
953 | if (!(ka->sa.sa_flags & SA_NOMASK)) | 717 | if (!(ka->sa.sa_flags & SA_NOMASK)) |
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index c1a61e98899a..161ce4710fe7 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c | |||
@@ -554,10 +554,8 @@ asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act | |||
554 | struct k_sigaction new_ka, old_ka; | 554 | struct k_sigaction new_ka, old_ka; |
555 | int ret; | 555 | int ret; |
556 | 556 | ||
557 | if (sig < 0) { | 557 | WARN_ON_ONCE(sig >= 0); |
558 | set_thread_flag(TIF_NEWSIGNALS); | 558 | sig = -sig; |
559 | sig = -sig; | ||
560 | } | ||
561 | 559 | ||
562 | if (act) { | 560 | if (act) { |
563 | compat_old_sigset_t mask; | 561 | compat_old_sigset_t mask; |
@@ -601,11 +599,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig, | |||
601 | if (sigsetsize != sizeof(compat_sigset_t)) | 599 | if (sigsetsize != sizeof(compat_sigset_t)) |
602 | return -EINVAL; | 600 | return -EINVAL; |
603 | 601 | ||
604 | /* All tasks which use RT signals (effectively) use | ||
605 | * new style signals. | ||
606 | */ | ||
607 | set_thread_flag(TIF_NEWSIGNALS); | ||
608 | |||
609 | if (act) { | 602 | if (act) { |
610 | u32 u_handler, u_restorer; | 603 | u32 u_handler, u_restorer; |
611 | 604 | ||