Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[XTENSA] Remove non-rt signal handling

The non-rt signal handling was never really used, so we don't break
anything. This patch also cleans up the signal stack-frame to make
it independent from the processor configuration. It also improves
the method used for controlling single-stepping. We now save and
restore the 'icountlevel' register that controls single stepping
and set or clear the saved state to enable or disable it.

Signed-off-by: Chris Zankel <chris@zankel.net>

+361 -535
+1
arch/xtensa/kernel/asm-offsets.c
··· 39 39 DEFINE(PT_LEND, offsetof (struct pt_regs, lend)); 40 40 DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount)); 41 41 DEFINE(PT_SAR, offsetof (struct pt_regs, sar)); 42 + DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); 42 43 DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); 43 44 DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); 44 45 DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
+14 -22
arch/xtensa/kernel/entry.S
··· 125 125 126 126 movi a2, 0 127 127 rsr a3, SAR 128 - wsr a2, ICOUNTLEVEL 128 + xsr a2, ICOUNTLEVEL 129 129 s32i a3, a1, PT_SAR 130 + s32i a2, a1, PT_ICOUNTLEVEL 130 131 131 132 /* Rotate ws so that the current windowbase is at bit0. */ 132 133 /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ ··· 277 276 278 277 movi a2, 0 279 278 rsr a3, SAR 280 - wsr a2, ICOUNTLEVEL 279 + xsr a2, ICOUNTLEVEL 281 280 s32i a3, a1, PT_SAR 281 + s32i a2, a1, PT_ICOUNTLEVEL 282 282 283 283 /* Rotate ws so that the current windowbase is at bit0. */ 284 284 /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ ··· 332 330 333 331 common_exception: 334 332 335 - /* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */ 333 + /* Save some registers, disable loops and clear the syscall flag. */ 336 334 337 335 rsr a2, DEBUGCAUSE 338 336 rsr a3, EPC_1 339 337 s32i a2, a1, PT_DEBUGCAUSE 340 338 s32i a3, a1, PT_PC 341 339 340 + movi a2, -1 342 341 rsr a3, EXCVADDR 342 + s32i a2, a1, PT_SYSCALL 343 343 movi a2, 0 344 344 s32i a3, a1, PT_EXCVADDR 345 345 xsr a2, LCOUNT ··· 454 450 455 451 /* Restore the state of the task and return from the exception. */ 456 452 457 - 458 - /* If we are returning from a user exception, and the process 459 - * to run next has PT_SINGLESTEP set, we want to setup 460 - * ICOUNT and ICOUNTLEVEL to step one instruction. 461 - * PT_SINGLESTEP is set by sys_ptrace (ptrace.c) 462 - */ 463 - 464 453 4: /* a2 holds GET_CURRENT(a2,a1) */ 465 - 466 - l32i a3, a2, TI_TASK 467 - l32i a3, a3, TASK_PTRACE 468 - bbci.l a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set 469 - 470 - movi a3, -2 # PT_SINGLESTEP flag is set, 471 - movi a4, 1 # icountlevel of 1 means it won't 472 - wsr a3, ICOUNT # start counting until after rfe 473 - wsr a4, ICOUNTLEVEL # so setup icount & icountlevel. 474 - isync 475 - 476 - 1: 477 454 478 455 #if XCHAL_EXTRA_SA_SIZE 479 456 ··· 649 664 l32i a2, a1, PT_LCOUNT 650 665 wsr a3, LEND 651 666 wsr a2, LCOUNT 667 + 668 + /* We control single stepping through the ICOUNTLEVEL register. */ 669 + 670 + l32i a2, a1, PT_ICOUNTLEVEL 671 + movi a3, -2 672 + wsr a2, ICOUNTLEVEL 673 + wsr a3, ICOUNT 652 674 653 675 /* Check if it was double exception. */ 654 676
+330 -487
arch/xtensa/kernel/signal.c
··· 1 - // TODO coprocessor stuff 2 1 /* 3 - * linux/arch/xtensa/kernel/signal.c 2 + * arch/xtensa/kernel/signal.c 4 3 * 5 - * Copyright (C) 1991, 1992 Linus Torvalds 6 - * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson 4 + * Default platform functions. 7 5 * 8 - * Joe Taylor <joe@tensilica.com> 9 - * Chris Zankel <chris@zankel.net> 6 + * This file is subject to the terms and conditions of the GNU General Public 7 + * License. See the file "COPYING" in the main directory of this archive 8 + * for more details. 10 9 * 10 + * Copyright (C) 2005, 2006 Tensilica Inc. 11 + * Copyright (C) 1991, 1992 Linus Torvalds 12 + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson 11 13 * 12 - * 14 + * Chris Zankel <chris@zankel.net> 15 + * Joe Taylor <joe@tensilica.com> 13 16 */ 14 17 15 - #include <asm/variant/core.h> 16 - #include <asm/coprocessor.h> 17 - #include <linux/sched.h> 18 - #include <linux/mm.h> 19 - #include <linux/smp.h> 20 - #include <linux/kernel.h> 21 18 #include <linux/signal.h> 22 19 #include <linux/errno.h> 23 - #include <linux/wait.h> 24 20 #include <linux/ptrace.h> 25 - #include <linux/unistd.h> 26 - #include <linux/stddef.h> 27 21 #include <linux/personality.h> 22 + #include <linux/freezer.h> 23 + 28 24 #include <asm/ucontext.h> 29 25 #include <asm/uaccess.h> 30 - #include <asm/pgtable.h> 31 26 #include <asm/cacheflush.h> 27 + #include <asm/coprocessor.h> 28 + #include <asm/unistd.h> 32 29 33 30 #define DEBUG_SIG 0 34 31 35 32 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 36 33 37 - asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, 38 - struct rusage * ru); 39 34 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); 40 35 41 36 extern struct task_struct *coproc_owners[]; 42 37 43 - 44 - /* 45 - * Atomically swap in the new signal mask, and wait for a signal. 46 - */ 47 - 48 - int xtensa_sigsuspend(struct pt_regs *regs) 49 - { 50 - old_sigset_t mask = (old_sigset_t) regs->areg[3]; 51 - sigset_t saveset; 52 - 53 - mask &= _BLOCKABLE; 54 - spin_lock_irq(&current->sighand->siglock); 55 - saveset = current->blocked; 56 - siginitset(&current->blocked, mask); 57 - recalc_sigpending(); 58 - spin_unlock_irq(&current->sighand->siglock); 59 - 60 - regs->areg[2] = -EINTR; 61 - while (1) { 62 - current->state = TASK_INTERRUPTIBLE; 63 - schedule(); 64 - if (do_signal(regs, &saveset)) 65 - return -EINTR; 66 - } 67 - } 68 - 69 - asmlinkage int 70 - xtensa_rt_sigsuspend(struct pt_regs *regs) 71 - { 72 - sigset_t *unewset = (sigset_t *) regs->areg[4]; 73 - size_t sigsetsize = (size_t) regs->areg[3]; 74 - sigset_t saveset, newset; 75 - /* XXX: Don't preclude handling different sized sigset_t's. */ 76 - if (sigsetsize != sizeof(sigset_t)) 77 - return -EINVAL; 78 - 79 - if (copy_from_user(&newset, unewset, sizeof(newset))) 80 - return -EFAULT; 81 - sigdelsetmask(&newset, ~_BLOCKABLE); 82 - spin_lock_irq(&current->sighand->siglock); 83 - saveset = current->blocked; 84 - current->blocked = newset; 85 - recalc_sigpending(); 86 - spin_unlock_irq(&current->sighand->siglock); 87 - 88 - regs->areg[2] = -EINTR; 89 - while (1) { 90 - current->state = TASK_INTERRUPTIBLE; 91 - schedule(); 92 - if (do_signal(regs, &saveset)) 93 - return -EINTR; 94 - } 95 - } 96 - 97 - asmlinkage int 98 - xtensa_sigaction(int sig, const struct old_sigaction *act, 99 - struct old_sigaction *oact) 100 - { 101 - struct k_sigaction new_ka, old_ka; 102 - int ret; 103 - 104 - if (act) { 105 - old_sigset_t mask; 106 - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 107 - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 108 - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) 109 - return -EFAULT; 110 - __get_user(new_ka.sa.sa_flags, &act->sa_flags); 111 - __get_user(mask, &act->sa_mask); 112 - siginitset(&new_ka.sa.sa_mask, mask); 113 - } 114 - 115 - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 116 - 117 - if (!ret && oact) { 118 - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 119 - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 120 - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) 121 - return -EFAULT; 122 - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 123 - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); 124 - } 125 - 126 - return ret; 127 - } 128 - 129 - asmlinkage int 130 - xtensa_sigaltstack(struct pt_regs *regs) 131 - { 132 - const stack_t *uss = (stack_t *) regs->areg[4]; 133 - stack_t *uoss = (stack_t *) regs->areg[3]; 134 - 135 - if (regs->depc > 64) 136 - panic ("Double exception sys_sigreturn\n"); 137 - 138 - 139 - return do_sigaltstack(uss, uoss, regs->areg[1]); 140 - } 141 - 142 - 143 - /* 144 - * Do a signal return; undo the signal stack. 145 - */ 146 - 147 - struct sigframe 148 - { 149 - struct sigcontext sc; 150 - struct _cpstate cpstate; 151 - unsigned long extramask[_NSIG_WORDS-1]; 152 - unsigned char retcode[6]; 153 - unsigned int reserved[4]; /* Reserved area for chaining */ 154 - unsigned int window[4]; /* Window of 4 registers for initial context */ 155 - }; 38 + extern void release_all_cp (struct task_struct *); 156 39 157 40 struct rt_sigframe 158 41 { 159 42 struct siginfo info; 160 43 struct ucontext uc; 161 - struct _cpstate cpstate; 44 + cp_state_t cpstate; 162 45 unsigned char retcode[6]; 163 - unsigned int reserved[4]; /* Reserved area for chaining */ 164 - unsigned int window[4]; /* Window of 4 registers for initial context */ 46 + unsigned int window[4]; 165 47 }; 166 48 167 - extern void release_all_cp (struct task_struct *); 168 - 169 - 170 - // FIXME restore_cpextra 171 - static inline int 172 - restore_cpextra (struct _cpstate *buf) 173 - { 174 - #if 0 175 - /* The signal handler may have used coprocessors in which 176 - * case they are still enabled. We disable them to force a 177 - * reloading of the original task's CP state by the lazy 178 - * context-switching mechanisms of CP exception handling. 179 - * Also, we essentially discard any coprocessor state that the 180 - * signal handler created. */ 181 - 182 - struct task_struct *tsk = current; 183 - release_all_cp(tsk); 184 - return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE); 185 - #endif 186 - return 0; 187 - } 188 - 189 - /* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately... 49 + /* 50 + * Flush register windows stored in pt_regs to stack. 51 + * Returns 1 for errors. 52 + * 53 + * Note that windowbase, windowstart, and wmask are not updated! 190 54 */ 191 55 192 - 193 - static int 194 - restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) 56 + int 57 + flush_window_regs_user(struct pt_regs *regs) 195 58 { 196 - struct thread_struct *thread; 197 - unsigned int err = 0; 198 - unsigned long ps; 199 - struct _cpstate *buf; 59 + const unsigned long ws = regs->windowstart; 60 + const unsigned long wb = regs->windowbase; 61 + unsigned long sp = 0; 62 + unsigned long wm; 63 + int err = 1; 64 + int base; 200 65 201 - #define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) 202 - COPY(pc); 203 - COPY(depc); 204 - COPY(wmask); 205 - COPY(lbeg); 206 - COPY(lend); 207 - COPY(lcount); 208 - COPY(sar); 209 - COPY(windowbase); 210 - COPY(windowstart); 211 - #undef COPY 66 + /* Return if no other frames. */ 212 67 213 - /* For PS, restore only PS.CALLINC. 214 - * Assume that all other bits are either the same as for the signal 215 - * handler, or the user mode value doesn't matter (e.g. PS.OWB). 216 - */ 217 - err |= __get_user(ps, &sc->sc_ps); 218 - regs->ps = (regs->ps & ~PS_CALLINC_MASK) 219 - | (ps & PS_CALLINC_MASK); 68 + if (regs->wmask == 1) 69 + return 0; 220 70 221 - /* Additional corruption checks */ 71 + /* Rotate windowmask and skip empty frames. */ 222 72 223 - if ((regs->windowbase >= (XCHAL_NUM_AREGS/4)) 224 - || ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) ) 225 - err = 1; 226 - if ((regs->lcount > 0) 227 - && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) ) 228 - err = 1; 73 + wm = (ws >> wb) | (ws << (XCHAL_NUM_AREGS / 4 - wb)); 74 + base = (XCHAL_NUM_AREGS / 4) - (regs->wmask >> 4); 75 + 76 + /* For call8 or call12 frames, we need the previous stack pointer. */ 229 77 230 - /* Restore extended register state. 231 - * See struct thread_struct in processor.h. 232 - */ 233 - thread = &current->thread; 78 + if ((regs->wmask & 2) == 0) 79 + if (__get_user(sp, (int*)(regs->areg[base * 4 + 1] - 12))) 80 + goto errout; 234 81 235 - err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4); 236 - err |= __get_user(buf, &sc->sc_cpstate); 237 - if (buf) { 238 - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) 239 - goto badframe; 240 - err |= restore_cpextra(buf); 241 - } 82 + /* Spill frames to stack. */ 242 83 243 - regs->syscall = -1; /* disable syscall checks */ 244 - return err; 84 + while (base < XCHAL_NUM_AREGS / 4) { 245 85 246 - badframe: 247 - return 1; 248 - } 86 + int m = (wm >> base); 87 + int inc = 0; 249 88 250 - static inline void 251 - flush_my_cpstate(struct task_struct *tsk) 252 - { 253 - unsigned long flags; 254 - local_irq_save(flags); 89 + /* Save registers a4..a7 (call8) or a4...a11 (call12) */ 255 90 256 - #if 0 // FIXME 257 - for (i = 0; i < XCHAL_CP_NUM; i++) { 258 - if (tsk == coproc_owners[i]) { 259 - xthal_validate_cp(i); 260 - xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i); 91 + if (m & 2) { /* call4 */ 92 + inc = 1; 261 93 262 - /* Invalidate and "disown" the cp to allow 263 - * callers the chance to reset cp state in the 264 - * task_struct. */ 94 + } else if (m & 4) { /* call8 */ 95 + if (copy_to_user((void*)(sp - 32), 96 + &regs->areg[(base + 1) * 4], 16)) 97 + goto errout; 98 + inc = 2; 265 99 266 - xthal_invalidate_cp(i); 267 - coproc_owners[i] = 0; 100 + } else if (m & 8) { /* call12 */ 101 + if (copy_to_user((void*)(sp - 48), 102 + &regs->areg[(base + 1) * 4], 32)) 103 + goto errout; 104 + inc = 3; 268 105 } 106 + 107 + /* Save current frame a0..a3 under next SP */ 108 + 109 + sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; 110 + if (copy_to_user((void*)(sp - 16), &regs->areg[base * 4], 16)) 111 + goto errout; 112 + 113 + /* Get current stack pointer for next loop iteration. */ 114 + 115 + sp = regs->areg[base * 4 + 1]; 116 + base += inc; 269 117 } 270 - #endif 271 - local_irq_restore(flags); 272 - } 273 118 274 - /* Return codes: 275 - 0: nothing saved 276 - 1: stuff to save, successful 277 - -1: stuff to save, error happened 278 - */ 279 - static int 280 - save_cpextra (struct _cpstate *buf) 281 - { 282 - #if XCHAL_CP_NUM == 0 283 119 return 0; 284 - #else 285 120 286 - /* FIXME: If a task has never used a coprocessor, there is 287 - * no need to save and restore anything. Tracking this 288 - * information would allow us to optimize this section. 289 - * Perhaps we can use current->used_math or (current->flags & 290 - * PF_USEDFPU) or define a new field in the thread 291 - * structure. */ 292 - 293 - /* We flush any live, task-owned cp state to the task_struct, 294 - * then copy it all to the sigframe. Then we clear all 295 - * cp/extra state in the task_struct, effectively 296 - * clearing/resetting all cp/extra state for the signal 297 - * handler (cp-exception handling will load these new values 298 - * into the cp/extra registers.) This step is important for 299 - * things like a floating-point cp, where the OS must reset 300 - * the FCR to the default rounding mode. */ 301 - 302 - int err = 0; 303 - struct task_struct *tsk = current; 304 - 305 - flush_my_cpstate(tsk); 306 - /* Note that we just copy everything: 'extra' and 'cp' state together.*/ 307 - err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE); 308 - memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE); 309 - 310 - #if (XTENSA_CP_EXTRA_SIZE == 0) 311 - #error Sanity check on memset above, cpextra_size should not be zero. 312 - #endif 313 - 314 - return err ? -1 : 1; 315 - #endif 121 + errout: 122 + return err; 316 123 } 317 124 125 + /* 126 + * Note: We don't copy double exception 'regs', we have to finish double exc. 127 + * first before we return to signal handler! This dbl.exc.handler might cause 128 + * another double exception, but I think we are fine as the situation is the 129 + * same as if we had returned to the signal handerl and got an interrupt 130 + * immediately... 131 + */ 132 + 318 133 static int 319 - setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate, 134 + setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate, 320 135 struct pt_regs *regs, unsigned long mask) 321 136 { 322 - struct thread_struct *thread; 323 137 int err = 0; 324 138 325 - //printk("setup_sigcontext\n"); 326 139 #define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) 327 140 COPY(pc); 328 141 COPY(ps); 329 - COPY(depc); 330 - COPY(wmask); 331 142 COPY(lbeg); 332 143 COPY(lend); 333 144 COPY(lcount); 334 145 COPY(sar); 335 - COPY(windowbase); 336 - COPY(windowstart); 337 146 #undef COPY 338 147 339 - /* Save extended register state. 340 - * See struct thread_struct in processor.h. 341 - */ 342 - thread = &current->thread; 343 - err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4); 148 + err |= flush_window_regs_user(regs); 149 + err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4); 150 + 151 + // err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4) 152 + 153 + #if XCHAL_HAVE_CP 154 + # error Coprocessors unsupported 344 155 err |= save_cpextra(cpstate); 345 156 err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate); 157 + #endif 346 158 /* non-iBCS2 extensions.. */ 347 159 err |= __put_user(mask, &sc->oldmask); 348 160 349 161 return err; 350 162 } 351 163 352 - asmlinkage int xtensa_sigreturn(struct pt_regs *regs) 164 + static int 165 + restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 353 166 { 354 - struct sigframe *frame = (struct sigframe *)regs->areg[1]; 355 - sigset_t set; 356 - if (regs->depc > 64) 357 - panic ("Double exception sys_sigreturn\n"); 167 + unsigned int err = 0; 168 + unsigned long ps; 358 169 359 - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 360 - goto badframe; 170 + #define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) 171 + COPY(pc); 172 + COPY(lbeg); 173 + COPY(lend); 174 + COPY(lcount); 175 + COPY(sar); 176 + #undef COPY 361 177 362 - if (__get_user(set.sig[0], &frame->sc.oldmask) 363 - || (_NSIG_WORDS > 1 364 - && __copy_from_user(&set.sig[1], &frame->extramask, 365 - sizeof(frame->extramask)))) 366 - goto badframe; 178 + /* All registers were flushed to stack. Start with a prestine frame. */ 367 179 368 - sigdelsetmask(&set, ~_BLOCKABLE); 180 + regs->wmask = 1; 181 + regs->windowbase = 0; 182 + regs->windowstart = 1; 369 183 370 - spin_lock_irq(&current->sighand->siglock); 371 - current->blocked = set; 372 - recalc_sigpending(); 373 - spin_unlock_irq(&current->sighand->siglock); 184 + /* For PS, restore only PS.CALLINC. 185 + * Assume that all other bits are either the same as for the signal 186 + * handler, or the user mode value doesn't matter (e.g. PS.OWB). 187 + */ 188 + err |= __get_user(ps, &sc->sc_ps); 189 + regs->ps = (regs->ps & ~PS_CALLINC_MASK) | (ps & PS_CALLINC_MASK); 374 190 375 - if (restore_sigcontext(regs, &frame->sc)) 376 - goto badframe; 377 - return regs->areg[2]; 191 + /* Additional corruption checks */ 378 192 379 - badframe: 380 - force_sig(SIGSEGV, current); 381 - return 0; 193 + if ((regs->lcount > 0) 194 + && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) ) 195 + err = 1; 196 + 197 + err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4); 198 + 199 + #if XCHAL_HAVE_CP 200 + # error Coprocessors unsupported 201 + /* The signal handler may have used coprocessors in which 202 + * case they are still enabled. We disable them to force a 203 + * reloading of the original task's CP state by the lazy 204 + * context-switching mechanisms of CP exception handling. 205 + * Also, we essentially discard any coprocessor state that the 206 + * signal handler created. */ 207 + 208 + if (!err) { 209 + struct task_struct *tsk = current; 210 + release_all_cp(tsk); 211 + err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate, 212 + XTENSA_CP_EXTRA_SIZE); 213 + } 214 + #endif 215 + 216 + regs->syscall = -1; /* disable syscall checks */ 217 + return err; 382 218 } 383 219 384 - asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs) 220 + 221 + 222 + /* 223 + * Do a signal return; undo the signal stack. 224 + */ 225 + 226 + asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, 227 + long a4, long a5, struct pt_regs *regs) 385 228 { 386 - struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1]; 229 + struct rt_sigframe __user *frame; 387 230 sigset_t set; 388 - stack_t st; 389 231 int ret; 232 + 390 233 if (regs->depc > 64) 391 - { 392 - printk("!!!!!!! DEPC !!!!!!!\n"); 393 - return 0; 394 - } 234 + panic("rt_sigreturn in double exception!\n"); 235 + 236 + frame = (struct rt_sigframe __user *) regs->areg[1]; 395 237 396 238 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 397 239 goto badframe; ··· 249 407 250 408 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 251 409 goto badframe; 410 + 252 411 ret = regs->areg[2]; 253 412 254 - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) 413 + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->areg[1]) == -EFAULT) 255 414 goto badframe; 256 - /* It is more difficult to avoid calling this function than to 257 - call it and ignore errors. */ 258 - do_sigaltstack(&st, NULL, regs->areg[1]); 259 415 260 416 return ret; 261 417 ··· 262 422 return 0; 263 423 } 264 424 425 + 426 + 265 427 /* 266 428 * Set up a signal frame. 267 429 */ 268 430 269 - /* 270 - * Determine which stack to use.. 271 - */ 272 - static inline void * 273 - get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) 274 - { 275 - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) 276 - sp = current->sas_ss_sp + current->sas_ss_size; 277 - 278 - return (void *)((sp - frame_size) & -16ul); 279 - } 280 - 281 - #define USE_SIGRETURN 0 282 - #define USE_RT_SIGRETURN 1 283 - 284 431 static int 285 - gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn) 432 + gen_return_code(unsigned char *codemem) 286 433 { 287 - unsigned int retcall; 288 434 int err = 0; 289 435 290 - #if 0 291 - /* Ignoring SA_RESTORER for now; it's supposed to be obsolete, 292 - * and the xtensa glibc doesn't use it. 436 + /* 437 + * The 12-bit immediate is really split up within the 24-bit MOVI 438 + * instruction. As long as the above system call numbers fit within 439 + * 8-bits, the following code works fine. See the Xtensa ISA for 440 + * details. 293 441 */ 294 - if (ka->sa.sa_flags & SA_RESTORER) { 295 - regs->pr = (unsigned long) ka->sa.sa_restorer; 296 - } else 297 - #endif /* 0 */ 298 - { 299 442 300 - #if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255) 301 - 302 - /* The 12-bit immediate is really split up within the 24-bit MOVI 303 - * instruction. As long as the above system call numbers fit within 304 - * 8-bits, the following code works fine. See the Xtensa ISA for 305 - * details. 306 - */ 307 - 308 - #error Generating the MOVI instruction below breaks! 443 + #if __NR_rt_sigreturn > 255 444 + # error Generating the MOVI instruction below breaks! 309 445 #endif 310 - 311 - retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn; 312 446 313 447 #ifdef __XTENSA_EB__ /* Big Endian version */ 314 - /* Generate instruction: MOVI a2, retcall */ 315 - err |= __put_user(0x22, &codemem[0]); 316 - err |= __put_user(0x0a, &codemem[1]); 317 - err |= __put_user(retcall, &codemem[2]); 318 - /* Generate instruction: SYSCALL */ 319 - err |= __put_user(0x00, &codemem[3]); 320 - err |= __put_user(0x05, &codemem[4]); 321 - err |= __put_user(0x00, &codemem[5]); 448 + /* Generate instruction: MOVI a2, __NR_rt_sigreturn */ 449 + err |= __put_user(0x22, &codemem[0]); 450 + err |= __put_user(0x0a, &codemem[1]); 451 + err |= __put_user(__NR_rt_sigreturn, &codemem[2]); 452 + /* Generate instruction: SYSCALL */ 453 + err |= __put_user(0x00, &codemem[3]); 454 + err |= __put_user(0x05, &codemem[4]); 455 + err |= __put_user(0x00, &codemem[5]); 322 456 323 457 #elif defined __XTENSA_EL__ /* Little Endian version */ 324 - /* Generate instruction: MOVI a2, retcall */ 325 - err |= __put_user(0x22, &codemem[0]); 326 - err |= __put_user(0xa0, &codemem[1]); 327 - err |= __put_user(retcall, &codemem[2]); 328 - /* Generate instruction: SYSCALL */ 329 - err |= __put_user(0x00, &codemem[3]); 330 - err |= __put_user(0x50, &codemem[4]); 331 - err |= __put_user(0x00, &codemem[5]); 458 + /* Generate instruction: MOVI a2, __NR_rt_sigreturn */ 459 + err |= __put_user(0x22, &codemem[0]); 460 + err |= __put_user(0xa0, &codemem[1]); 461 + err |= __put_user(__NR_rt_sigreturn, &codemem[2]); 462 + /* Generate instruction: SYSCALL */ 463 + err |= __put_user(0x00, &codemem[3]); 464 + err |= __put_user(0x50, &codemem[4]); 465 + err |= __put_user(0x00, &codemem[5]); 332 466 #else 333 - #error Must use compiler for Xtensa processors. 467 + # error Must use compiler for Xtensa processors. 334 468 #endif 335 - } 336 469 337 470 /* Flush generated code out of the data cache */ 338 471 ··· 317 504 return err; 318 505 } 319 506 320 - static void 321 - set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr, 322 - void *handler, unsigned long arg1, void *arg2, void *arg3) 323 - { 324 - /* Set up registers for signal handler */ 325 - start_thread(regs, (unsigned long) handler, (unsigned long) stack); 326 507 327 - /* Set up a stack frame for a call4 328 - * Note: PS.CALLINC is set to one by start_thread 329 - */ 330 - regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000; 331 - regs->areg[6] = arg1; 332 - regs->areg[7] = (unsigned long) arg2; 333 - regs->areg[8] = (unsigned long) arg3; 334 - } 335 - 336 - static void setup_frame(int sig, struct k_sigaction *ka, 508 + static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 337 509 sigset_t *set, struct pt_regs *regs) 338 - { 339 - struct sigframe *frame; 340 - int err = 0; 341 - int signal; 342 - 343 - frame = get_sigframe(ka, regs->areg[1], sizeof(*frame)); 344 - if (regs->depc > 64) 345 - { 346 - printk("!!!!!!! DEPC !!!!!!!\n"); 347 - return; 348 - } 349 - 350 - 351 - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 352 - goto give_sigsegv; 353 - 354 - signal = current_thread_info()->exec_domain 355 - && current_thread_info()->exec_domain->signal_invmap 356 - && sig < 32 357 - ? current_thread_info()->exec_domain->signal_invmap[sig] 358 - : sig; 359 - 360 - err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]); 361 - 362 - if (_NSIG_WORDS > 1) { 363 - err |= __copy_to_user(frame->extramask, &set->sig[1], 364 - sizeof(frame->extramask)); 365 - } 366 - 367 - /* Create sys_sigreturn syscall in stack frame */ 368 - err |= gen_return_code(frame->retcode, USE_SIGRETURN); 369 - 370 - if (err) 371 - goto give_sigsegv; 372 - 373 - /* Create signal handler execution context. 374 - * Return context not modified until this point. 375 - */ 376 - set_thread_state(regs, frame, frame->retcode, 377 - ka->sa.sa_handler, signal, &frame->sc, NULL); 378 - 379 - /* Set access mode to USER_DS. Nomenclature is outdated, but 380 - * functionality is used in uaccess.h 381 - */ 382 - set_fs(USER_DS); 383 - 384 - 385 - #if DEBUG_SIG 386 - printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n", 387 - current->comm, current->pid, signal, frame, regs->pc); 388 - #endif 389 - 390 - return; 391 - 392 - give_sigsegv: 393 - if (sig == SIGSEGV) 394 - ka->sa.sa_handler = SIG_DFL; 395 - force_sig(SIGSEGV, current); 396 - } 397 - 398 - static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 399 - sigset_t *set, struct pt_regs *regs) 400 510 { 401 511 struct rt_sigframe *frame; 402 512 int err = 0; 403 513 int signal; 514 + unsigned long sp, ra; 404 515 405 - frame = get_sigframe(ka, regs->areg[1], sizeof(*frame)); 516 + sp = regs->areg[1]; 517 + 518 + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) { 519 + sp = current->sas_ss_sp + current->sas_ss_size; 520 + } 521 + 522 + frame = (void *)((sp - sizeof(*frame)) & -16ul); 523 + 406 524 if (regs->depc > 64) 407 525 panic ("Double exception sys_sigreturn\n"); 408 526 409 - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 527 + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) { 410 528 goto give_sigsegv; 529 + } 411 530 412 531 signal = current_thread_info()->exec_domain 413 532 && current_thread_info()->exec_domain->signal_invmap ··· 347 602 ? current_thread_info()->exec_domain->signal_invmap[sig] 348 603 : sig; 349 604 350 - err |= copy_siginfo_to_user(&frame->info, info); 605 + if (ka->sa.sa_flags & SA_SIGINFO) { 606 + err |= copy_siginfo_to_user(&frame->info, info); 607 + } 351 608 352 - /* Create the ucontext. */ 609 + /* Create the user context. */ 610 + 353 611 err |= __put_user(0, &frame->uc.uc_flags); 354 612 err |= __put_user(0, &frame->uc.uc_link); 355 613 err |= __put_user((void *)current->sas_ss_sp, ··· 365 617 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 366 618 367 619 /* Create sys_rt_sigreturn syscall in stack frame */ 368 - err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN); 369 620 370 - if (err) 621 + err |= gen_return_code(frame->retcode); 622 + 623 + if (err) { 371 624 goto give_sigsegv; 625 + } 626 + 372 627 373 - /* Create signal handler execution context. 628 + /* 629 + * Create signal handler execution context. 374 630 * Return context not modified until this point. 375 631 */ 376 - set_thread_state(regs, frame, frame->retcode, 377 - ka->sa.sa_handler, signal, &frame->info, &frame->uc); 632 + 633 + /* Set up registers for signal handler */ 634 + start_thread(regs, (unsigned long) ka->sa.sa_handler, 635 + (unsigned long) frame); 636 + 637 + /* Set up a stack frame for a call4 638 + * Note: PS.CALLINC is set to one by start_thread 639 + */ 640 + ra = (unsigned long) frame->retcode; 641 + regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000; 642 + regs->areg[6] = (unsigned long) signal; 643 + regs->areg[7] = (unsigned long) &frame->info; 644 + regs->areg[8] = (unsigned long) &frame->uc; 378 645 379 646 /* Set access mode to USER_DS. Nomenclature is outdated, but 380 647 * functionality is used in uaccess.h ··· 409 646 force_sig(SIGSEGV, current); 410 647 } 411 648 649 + /* 650 + * Atomically swap in the new signal mask, and wait for a signal. 651 + */ 652 + 653 + asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, 654 + size_t sigsetsize, 655 + long a2, long a3, long a4, long a5, 656 + struct pt_regs *regs) 657 + { 658 + sigset_t saveset, newset; 659 + 660 + /* XXX: Don't preclude handling different sized sigset_t's. */ 661 + if (sigsetsize != sizeof(sigset_t)) 662 + return -EINVAL; 663 + 664 + if (copy_from_user(&newset, unewset, sizeof(newset))) 665 + return -EFAULT; 666 + 667 + sigdelsetmask(&newset, ~_BLOCKABLE); 668 + spin_lock_irq(&current->sighand->siglock); 669 + saveset = current->blocked; 670 + current->blocked = newset; 671 + recalc_sigpending(); 672 + spin_unlock_irq(&current->sighand->siglock); 673 + 674 + regs->areg[2] = -EINTR; 675 + while (1) { 676 + current->state = TASK_INTERRUPTIBLE; 677 + schedule(); 678 + if (do_signal(regs, &saveset)) 679 + return -EINTR; 680 + } 681 + } 682 + 683 + asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, 684 + stack_t __user *uoss, 685 + long a2, long a3, long a4, long a5, 686 + struct pt_regs *regs) 687 + { 688 + return do_sigaltstack(uss, uoss, regs->areg[1]); 689 + } 690 + 412 691 413 692 414 693 /* ··· 468 663 int signr; 469 664 struct k_sigaction ka; 470 665 666 + if (!user_mode(regs)) 667 + return 0; 668 + 669 + if (try_to_freeze()) 670 + goto no_signal; 671 + 471 672 if (!oldset) 472 673 oldset = &current->blocked; 473 674 675 + task_pt_regs(current)->icountlevel = 0; 676 + 474 677 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 475 678 476 - /* Are we from a system call? */ 477 - if (regs->syscall >= 0) { 478 - /* If so, check system call restarting.. */ 479 - switch (regs->areg[2]) { 480 - case ERESTARTNOHAND: 481 - case ERESTART_RESTARTBLOCK: 482 - regs->areg[2] = -EINTR; 483 - break; 679 + if (signr > 0) { 484 680 485 - case ERESTARTSYS: 486 - if (!(ka.sa.sa_flags & SA_RESTART)) { 681 + /* Are we from a system call? */ 682 + 683 + if ((signed)regs->syscall >= 0) { 684 + 685 + /* If so, check system call restarting.. */ 686 + 687 + switch (regs->areg[2]) { 688 + case -ERESTARTNOHAND: 689 + case -ERESTART_RESTARTBLOCK: 487 690 regs->areg[2] = -EINTR; 488 691 break; 489 - } 490 - /* fallthrough */ 491 - case ERESTARTNOINTR: 492 - regs->areg[2] = regs->syscall; 493 - regs->pc -= 3; 692 + 693 + case -ERESTARTSYS: 694 + if (!(ka.sa.sa_flags & SA_RESTART)) { 695 + regs->areg[2] = -EINTR; 696 + break; 697 + } 698 + /* fallthrough */ 699 + case -ERESTARTNOINTR: 700 + regs->areg[2] = regs->syscall; 701 + regs->pc -= 3; 702 + break; 703 + 704 + default: 705 + /* nothing to do */ 706 + if (regs->areg[2] != 0) 707 + break; 708 + } 494 709 } 710 + 711 + /* Whee! Actually deliver the signal. */ 712 + /* Set up the stack frame */ 713 + setup_frame(signr, &ka, &info, oldset, regs); 714 + 715 + if (ka.sa.sa_flags & SA_ONESHOT) 716 + ka.sa.sa_handler = SIG_DFL; 717 + 718 + spin_lock_irq(&current->sighand->siglock); 719 + sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask); 720 + if (!(ka.sa.sa_flags & SA_NODEFER)) 721 + sigaddset(&current->blocked, signr); 722 + recalc_sigpending(); 723 + spin_unlock_irq(&current->sighand->siglock); 724 + if (current->ptrace & PT_SINGLESTEP) 725 + task_pt_regs(current)->icountlevel = 1; 726 + 727 + return 1; 495 728 } 496 729 497 - if (signr == 0) 498 - return 0; /* no signals delivered */ 499 - 500 - /* Whee! Actually deliver the signal. */ 501 - 502 - /* Set up the stack frame */ 503 - if (ka.sa.sa_flags & SA_SIGINFO) 504 - setup_rt_frame(signr, &ka, &info, oldset, regs); 505 - else 506 - setup_frame(signr, &ka, oldset, regs); 507 - 508 - if (ka.sa.sa_flags & SA_ONESHOT) 509 - ka.sa.sa_handler = SIG_DFL; 510 - 511 - spin_lock_irq(&current->sighand->siglock); 512 - sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask); 513 - if (!(ka.sa.sa_flags & SA_NODEFER)) 514 - sigaddset(&current->blocked, signr); 515 - recalc_sigpending(); 516 - spin_unlock_irq(&current->sighand->siglock); 517 - return 1; 730 + no_signal: 731 + /* Did we come from a system call? */ 732 + if ((signed) regs->syscall >= 0) { 733 + /* Restart the system call - no handlers present */ 734 + switch (regs->areg[2]) { 735 + case -ERESTARTNOHAND: 736 + case -ERESTARTSYS: 737 + case -ERESTARTNOINTR: 738 + regs->areg[2] = regs->syscall; 739 + regs->pc -= 3; 740 + break; 741 + case -ERESTART_RESTARTBLOCK: 742 + regs->areg[2] = __NR_restart_syscall; 743 + regs->pc -= 3; 744 + break; 745 + } 746 + } 747 + if (current->ptrace & PT_SINGLESTEP) 748 + task_pt_regs(current)->icountlevel = 1; 749 + return 0; 518 750 } 751 +
+6 -2
include/asm-xtensa/coprocessor.h
··· 64 64 # define COPROCESSOR_INFO_SIZE 8 65 65 # endif 66 66 #endif 67 + #endif /* XCHAL_HAVE_CP */ 67 68 68 69 69 70 #ifndef __ASSEMBLY__ ··· 75 74 # else 76 75 # define release_coprocessors(task) 77 76 # endif 78 - #endif 79 77 80 - #endif 78 + typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE] 79 + __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN))); 80 + 81 + #endif /* !__ASSEMBLY__ */ 82 + 81 83 82 84 #endif /* _XTENSA_COPROCESSOR_H */
+1 -2
include/asm-xtensa/elf.h
··· 13 13 #ifndef _XTENSA_ELF_H 14 14 #define _XTENSA_ELF_H 15 15 16 - #include <asm/variant/core.h> 17 16 #include <asm/ptrace.h> 18 17 19 18 /* Xtensa processor ELF architecture-magic number */ ··· 48 49 elf_greg_t lcount; 49 50 elf_greg_t sar; 50 51 elf_greg_t syscall; 51 - elf_greg_t ar[XCHAL_NUM_AREGS]; 52 + elf_greg_t ar[64]; 52 53 } xtensa_gregset_t; 53 54 54 55 #define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
+2 -1
include/asm-xtensa/ptrace.h
··· 99 99 unsigned long windowbase; /* 48 */ 100 100 unsigned long windowstart; /* 52 */ 101 101 unsigned long syscall; /* 56 */ 102 - int reserved[2]; /* 64 */ 102 + unsigned long icountlevel; /* 60 */ 103 + int reserved[1]; /* 64 */ 103 104 104 105 /* Make sure the areg field is 16 bytes aligned. */ 105 106 int align[0] __attribute__ ((aligned(16)));
+5 -19
include/asm-xtensa/sigcontext.h
··· 5 5 * License. See the file "COPYING" in the main directory of this archive 6 6 * for more details. 7 7 * 8 - * Copyright (C) 2001 - 2003 Tensilica Inc. 8 + * Copyright (C) 2001 - 2007 Tensilica Inc. 9 9 */ 10 10 11 11 #ifndef _XTENSA_SIGCONTEXT_H 12 12 #define _XTENSA_SIGCONTEXT_H 13 - 14 - #define _ASMLANGUAGE 15 - #include <asm/processor.h> 16 - #include <asm/coprocessor.h> 17 - 18 - 19 - struct _cpstate { 20 - unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE]; 21 - } __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN))); 22 13 23 14 24 15 struct sigcontext { ··· 18 27 /* CPU registers */ 19 28 unsigned long sc_pc; 20 29 unsigned long sc_ps; 21 - unsigned long sc_wmask; 22 - unsigned long sc_windowbase; 23 - unsigned long sc_windowstart; 24 30 unsigned long sc_lbeg; 25 31 unsigned long sc_lend; 26 32 unsigned long sc_lcount; 27 33 unsigned long sc_sar; 28 - unsigned long sc_depc; 29 - unsigned long sc_dareg0; 30 - unsigned long sc_treg[4]; 31 - unsigned long sc_areg[XCHAL_NUM_AREGS]; 32 - struct _cpstate *sc_cpstate; 34 + unsigned long sc_acclo; 35 + unsigned long sc_acchi; 36 + unsigned long sc_a[16]; 33 37 }; 34 38 35 - #endif /* __ASM_XTENSA_SIGCONTEXT_H */ 39 + #endif /* _XTENSA_SIGCONTEXT_H */
+2 -2
include/asm-xtensa/unistd.h
··· 485 485 __SYSCALL(218, sys_sched_rr_get_interval, 2) 486 486 #define __NR_sched_yield 219 487 487 __SYSCALL(219, sys_sched_yield, 0) 488 - #define __NR_sigreturn 222 489 - __SYSCALL(222, xtensa_sigreturn, 0) 488 + #define __NR_available222 222 489 + __SYSCALL(222, sys_ni_syscall, 0) 490 490 491 491 /* Signal Handling */ 492 492