diff options
26 files changed, 475 insertions, 783 deletions
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index 698079b3a336..d0323cd6a2ea 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c | |||
| @@ -39,6 +39,7 @@ int main(void) | |||
| 39 | DEFINE(PT_LEND, offsetof (struct pt_regs, lend)); | 39 | DEFINE(PT_LEND, offsetof (struct pt_regs, lend)); |
| 40 | DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount)); | 40 | DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount)); |
| 41 | DEFINE(PT_SAR, offsetof (struct pt_regs, sar)); | 41 | DEFINE(PT_SAR, offsetof (struct pt_regs, sar)); |
| 42 | DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel)); | ||
| 42 | DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); | 43 | DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall)); |
| 43 | DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); | 44 | DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0])); |
| 44 | DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); | 45 | DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0])); |
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 9e271ba009bf..8dc7a2c26ff9 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
| @@ -125,8 +125,9 @@ _user_exception: | |||
| 125 | 125 | ||
| 126 | movi a2, 0 | 126 | movi a2, 0 |
| 127 | rsr a3, SAR | 127 | rsr a3, SAR |
| 128 | wsr a2, ICOUNTLEVEL | 128 | xsr a2, ICOUNTLEVEL |
| 129 | s32i a3, a1, PT_SAR | 129 | s32i a3, a1, PT_SAR |
| 130 | s32i a2, a1, PT_ICOUNTLEVEL | ||
| 130 | 131 | ||
| 131 | /* Rotate ws so that the current windowbase is at bit0. */ | 132 | /* Rotate ws so that the current windowbase is at bit0. */ |
| 132 | /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ | 133 | /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ |
| @@ -276,8 +277,9 @@ _kernel_exception: | |||
| 276 | 277 | ||
| 277 | movi a2, 0 | 278 | movi a2, 0 |
| 278 | rsr a3, SAR | 279 | rsr a3, SAR |
| 279 | wsr a2, ICOUNTLEVEL | 280 | xsr a2, ICOUNTLEVEL |
| 280 | s32i a3, a1, PT_SAR | 281 | s32i a3, a1, PT_SAR |
| 282 | s32i a2, a1, PT_ICOUNTLEVEL | ||
| 281 | 283 | ||
| 282 | /* Rotate ws so that the current windowbase is at bit0. */ | 284 | /* Rotate ws so that the current windowbase is at bit0. */ |
| 283 | /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ | 285 | /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ |
| @@ -330,14 +332,16 @@ _kernel_exception: | |||
| 330 | 332 | ||
| 331 | common_exception: | 333 | common_exception: |
| 332 | 334 | ||
| 333 | /* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */ | 335 | /* Save some registers, disable loops and clear the syscall flag. */ |
| 334 | 336 | ||
| 335 | rsr a2, DEBUGCAUSE | 337 | rsr a2, DEBUGCAUSE |
| 336 | rsr a3, EPC_1 | 338 | rsr a3, EPC_1 |
| 337 | s32i a2, a1, PT_DEBUGCAUSE | 339 | s32i a2, a1, PT_DEBUGCAUSE |
| 338 | s32i a3, a1, PT_PC | 340 | s32i a3, a1, PT_PC |
| 339 | 341 | ||
| 342 | movi a2, -1 | ||
| 340 | rsr a3, EXCVADDR | 343 | rsr a3, EXCVADDR |
| 344 | s32i a2, a1, PT_SYSCALL | ||
| 341 | movi a2, 0 | 345 | movi a2, 0 |
| 342 | s32i a3, a1, PT_EXCVADDR | 346 | s32i a3, a1, PT_EXCVADDR |
| 343 | xsr a2, LCOUNT | 347 | xsr a2, LCOUNT |
| @@ -450,27 +454,8 @@ common_exception_return: | |||
| 450 | 454 | ||
| 451 | /* Restore the state of the task and return from the exception. */ | 455 | /* Restore the state of the task and return from the exception. */ |
| 452 | 456 | ||
| 453 | |||
| 454 | /* If we are returning from a user exception, and the process | ||
| 455 | * to run next has PT_SINGLESTEP set, we want to setup | ||
| 456 | * ICOUNT and ICOUNTLEVEL to step one instruction. | ||
| 457 | * PT_SINGLESTEP is set by sys_ptrace (ptrace.c) | ||
| 458 | */ | ||
| 459 | |||
| 460 | 4: /* a2 holds GET_CURRENT(a2,a1) */ | 457 | 4: /* a2 holds GET_CURRENT(a2,a1) */ |
| 461 | 458 | ||
| 462 | l32i a3, a2, TI_TASK | ||
| 463 | l32i a3, a3, TASK_PTRACE | ||
| 464 | bbci.l a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set | ||
| 465 | |||
| 466 | movi a3, -2 # PT_SINGLESTEP flag is set, | ||
| 467 | movi a4, 1 # icountlevel of 1 means it won't | ||
| 468 | wsr a3, ICOUNT # start counting until after rfe | ||
| 469 | wsr a4, ICOUNTLEVEL # so setup icount & icountlevel. | ||
| 470 | isync | ||
| 471 | |||
| 472 | 1: | ||
| 473 | |||
| 474 | #if XCHAL_EXTRA_SA_SIZE | 459 | #if XCHAL_EXTRA_SA_SIZE |
| 475 | 460 | ||
| 476 | /* For user exceptions, restore the extra state from the user's TCB. */ | 461 | /* For user exceptions, restore the extra state from the user's TCB. */ |
| @@ -665,6 +650,13 @@ common_exception_exit: | |||
| 665 | wsr a3, LEND | 650 | wsr a3, LEND |
| 666 | wsr a2, LCOUNT | 651 | wsr a2, LCOUNT |
| 667 | 652 | ||
| 653 | /* We control single stepping through the ICOUNTLEVEL register. */ | ||
| 654 | |||
| 655 | l32i a2, a1, PT_ICOUNTLEVEL | ||
| 656 | movi a3, -2 | ||
| 657 | wsr a2, ICOUNTLEVEL | ||
| 658 | wsr a3, ICOUNT | ||
| 659 | |||
| 668 | /* Check if it was double exception. */ | 660 | /* Check if it was double exception. */ |
| 669 | 661 | ||
| 670 | l32i a0, a1, PT_DEPC | 662 | l32i a0, a1, PT_DEPC |
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index ea89910efa44..67e69139520b 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <asm/page.h> | 19 | #include <asm/page.h> |
| 20 | #include <asm/cacheasm.h> | 20 | #include <asm/cacheasm.h> |
| 21 | 21 | ||
| 22 | #include <linux/linkage.h> | ||
| 23 | |||
| 22 | /* | 24 | /* |
| 23 | * This module contains the entry code for kernel images. It performs the | 25 | * This module contains the entry code for kernel images. It performs the |
| 24 | * minimal setup needed to call the generic C routines. | 26 | * minimal setup needed to call the generic C routines. |
| @@ -227,13 +229,14 @@ _startup: | |||
| 227 | should_never_return: | 229 | should_never_return: |
| 228 | j should_never_return | 230 | j should_never_return |
| 229 | 231 | ||
| 230 | /* Define some common data structures here. We define them | ||
| 231 | * here in this assembly file due to their unusual alignment | ||
| 232 | * requirements. | ||
| 233 | */ | ||
| 234 | 232 | ||
| 235 | .comm swapper_pg_dir,PAGE_SIZE,PAGE_SIZE | 233 | /* |
| 236 | .comm empty_bad_page_table,PAGE_SIZE,PAGE_SIZE | 234 | * BSS section |
| 237 | .comm empty_bad_page,PAGE_SIZE,PAGE_SIZE | 235 | */ |
| 238 | .comm empty_zero_page,PAGE_SIZE,PAGE_SIZE | 236 | |
| 237 | .section ".bss.page_aligned", "w" | ||
| 238 | ENTRY(swapper_pg_dir) | ||
| 239 | .fill PAGE_SIZE, 1, 0 | ||
| 240 | ENTRY(empty_zero_page) | ||
| 241 | .fill PAGE_SIZE, 1, 0 | ||
| 239 | 242 | ||
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 45571ccb72d6..77deae5290f0 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c | |||
| @@ -401,7 +401,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
| 401 | * Also, think for a moment about likes of floppy.c that | 401 | * Also, think for a moment about likes of floppy.c that |
| 402 | * include architecture specific parts. They may want to redefine ins/outs. | 402 | * include architecture specific parts. They may want to redefine ins/outs. |
| 403 | * | 403 | * |
| 404 | * We do not use horroble macroses here because we want to | 404 | * We do not use horrible macros here because we want to |
| 405 | * advance pointer by sizeof(size). | 405 | * advance pointer by sizeof(size). |
| 406 | */ | 406 | */ |
| 407 | void outsb(unsigned long addr, const void *src, unsigned long count) { | 407 | void outsb(unsigned long addr, const void *src, unsigned long count) { |
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 1ecf6716c327..2e8d398cf196 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <asm/platform.h> | 41 | #include <asm/platform.h> |
| 42 | #include <asm/page.h> | 42 | #include <asm/page.h> |
| 43 | #include <asm/setup.h> | 43 | #include <asm/setup.h> |
| 44 | #include <asm/param.h> | ||
| 44 | 45 | ||
| 45 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) | 46 | #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) |
| 46 | struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16}; | 47 | struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16}; |
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 58107672a619..033aae0336d2 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c | |||
| @@ -1,397 +1,239 @@ | |||
| 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 | 4 | * Default platform functions. |
| 6 | * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson | ||
| 7 | * | ||
| 8 | * Joe Taylor <joe@tensilica.com> | ||
| 9 | * Chris Zankel <chris@zankel.net> | ||
| 10 | * | 5 | * |
| 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. | ||
| 11 | * | 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 | ||
| 12 | * | 13 | * |
| 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 | #include <linux/signal.h> | 18 | #include <linux/signal.h> |
| 22 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
| 23 | #include <linux/wait.h> | ||
| 24 | #include <linux/ptrace.h> | 20 | #include <linux/ptrace.h> |
| 25 | #include <linux/unistd.h> | ||
| 26 | #include <linux/stddef.h> | ||
| 27 | #include <linux/personality.h> | 21 | #include <linux/personality.h> |
| 22 | #include <linux/freezer.h> | ||
| 23 | |||
| 28 | #include <asm/ucontext.h> | 24 | #include <asm/ucontext.h> |
| 29 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
| 30 | #include <asm/pgtable.h> | ||
| 31 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
| 27 | #include <asm/coprocessor.h> | ||
| 28 | #include <asm/unistd.h> | ||
| 32 | 29 | ||
| 33 | #define DEBUG_SIG 0 | 30 | #define DEBUG_SIG 0 |
| 34 | 31 | ||
| 35 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 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 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | 34 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); |
| 40 | 35 | ||
| 41 | extern struct task_struct *coproc_owners[]; | 36 | extern struct task_struct *coproc_owners[]; |
| 42 | 37 | ||
| 38 | extern void release_all_cp (struct task_struct *); | ||
| 43 | 39 | ||
| 44 | /* | 40 | struct rt_sigframe |
| 45 | * Atomically swap in the new signal mask, and wait for a signal. | 41 | { |
| 42 | struct siginfo info; | ||
| 43 | struct ucontext uc; | ||
| 44 | cp_state_t cpstate; | ||
| 45 | unsigned char retcode[6]; | ||
| 46 | unsigned int window[4]; | ||
| 47 | }; | ||
| 48 | |||
| 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! | ||
| 46 | */ | 54 | */ |
| 47 | 55 | ||
| 48 | int xtensa_sigsuspend(struct pt_regs *regs) | 56 | int |
| 57 | flush_window_regs_user(struct pt_regs *regs) | ||
| 49 | { | 58 | { |
| 50 | old_sigset_t mask = (old_sigset_t) regs->areg[3]; | 59 | const unsigned long ws = regs->windowstart; |
| 51 | sigset_t saveset; | 60 | const unsigned long wb = regs->windowbase; |
| 61 | unsigned long sp = 0; | ||
| 62 | unsigned long wm; | ||
| 63 | int err = 1; | ||
| 64 | int base; | ||
| 52 | 65 | ||
| 53 | mask &= _BLOCKABLE; | 66 | /* Return if no other frames. */ |
| 54 | spin_lock_irq(¤t->sighand->siglock); | ||
| 55 | saveset = current->blocked; | ||
| 56 | siginitset(¤t->blocked, mask); | ||
| 57 | recalc_sigpending(); | ||
| 58 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 59 | 67 | ||
| 60 | regs->areg[2] = -EINTR; | 68 | if (regs->wmask == 1) |
| 61 | while (1) { | 69 | return 0; |
| 62 | current->state = TASK_INTERRUPTIBLE; | ||
| 63 | schedule(); | ||
| 64 | if (do_signal(regs, &saveset)) | ||
| 65 | return -EINTR; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | 70 | ||
| 69 | asmlinkage int | 71 | /* Rotate windowmask and skip empty frames. */ |
| 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 | 72 | ||
| 79 | if (copy_from_user(&newset, unewset, sizeof(newset))) | 73 | wm = (ws >> wb) | (ws << (XCHAL_NUM_AREGS / 4 - wb)); |
| 80 | return -EFAULT; | 74 | base = (XCHAL_NUM_AREGS / 4) - (regs->wmask >> 4); |
| 81 | sigdelsetmask(&newset, ~_BLOCKABLE); | 75 | |
| 82 | spin_lock_irq(¤t->sighand->siglock); | 76 | /* For call8 or call12 frames, we need the previous stack pointer. */ |
| 83 | saveset = current->blocked; | ||
| 84 | current->blocked = newset; | ||
| 85 | recalc_sigpending(); | ||
| 86 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 87 | 77 | ||
| 88 | regs->areg[2] = -EINTR; | 78 | if ((regs->wmask & 2) == 0) |
| 89 | while (1) { | 79 | if (__get_user(sp, (int*)(regs->areg[base * 4 + 1] - 12))) |
| 90 | current->state = TASK_INTERRUPTIBLE; | 80 | goto errout; |
| 91 | schedule(); | ||
| 92 | if (do_signal(regs, &saveset)) | ||
| 93 | return -EINTR; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | 81 | ||
| 97 | asmlinkage int | 82 | /* Spill frames to stack. */ |
| 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 | 83 | ||
| 104 | if (act) { | 84 | while (base < XCHAL_NUM_AREGS / 4) { |
| 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 | 85 | ||
| 115 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | 86 | int m = (wm >> base); |
| 87 | int inc = 0; | ||
| 116 | 88 | ||
| 117 | if (!ret && oact) { | 89 | /* Save registers a4..a7 (call8) or a4...a11 (call12) */ |
| 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 | 90 | ||
| 126 | return ret; | 91 | if (m & 2) { /* call4 */ |
| 127 | } | 92 | inc = 1; |
| 128 | 93 | ||
| 129 | asmlinkage int | 94 | } else if (m & 4) { /* call8 */ |
| 130 | xtensa_sigaltstack(struct pt_regs *regs) | 95 | if (copy_to_user((void*)(sp - 32), |
| 131 | { | 96 | ®s->areg[(base + 1) * 4], 16)) |
| 132 | const stack_t *uss = (stack_t *) regs->areg[4]; | 97 | goto errout; |
| 133 | stack_t *uoss = (stack_t *) regs->areg[3]; | 98 | inc = 2; |
| 134 | 99 | ||
| 135 | if (regs->depc > 64) | 100 | } else if (m & 8) { /* call12 */ |
| 136 | panic ("Double exception sys_sigreturn\n"); | 101 | if (copy_to_user((void*)(sp - 48), |
| 102 | ®s->areg[(base + 1) * 4], 32)) | ||
| 103 | goto errout; | ||
| 104 | inc = 3; | ||
| 105 | } | ||
| 137 | 106 | ||
| 107 | /* Save current frame a0..a3 under next SP */ | ||
| 138 | 108 | ||
| 139 | return do_sigaltstack(uss, uoss, regs->areg[1]); | 109 | sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; |
| 140 | } | 110 | if (copy_to_user((void*)(sp - 16), ®s->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; | ||
| 117 | } | ||
| 118 | |||
| 119 | return 0; | ||
| 141 | 120 | ||
| 121 | errout: | ||
| 122 | return err; | ||
| 123 | } | ||
| 142 | 124 | ||
| 143 | /* | 125 | /* |
| 144 | * Do a signal return; undo the signal stack. | 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... | ||
| 145 | */ | 131 | */ |
| 146 | 132 | ||
| 147 | struct sigframe | 133 | static int |
| 148 | { | 134 | setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate, |
| 149 | struct sigcontext sc; | 135 | struct pt_regs *regs, unsigned long mask) |
| 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 | }; | ||
| 156 | |||
| 157 | struct rt_sigframe | ||
| 158 | { | 136 | { |
| 159 | struct siginfo info; | 137 | int err = 0; |
| 160 | struct ucontext uc; | ||
| 161 | struct _cpstate cpstate; | ||
| 162 | 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 */ | ||
| 165 | }; | ||
| 166 | 138 | ||
| 167 | extern void release_all_cp (struct task_struct *); | 139 | #define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) |
| 140 | COPY(pc); | ||
| 141 | COPY(ps); | ||
| 142 | COPY(lbeg); | ||
| 143 | COPY(lend); | ||
| 144 | COPY(lcount); | ||
| 145 | COPY(sar); | ||
| 146 | #undef COPY | ||
| 168 | 147 | ||
| 148 | err |= flush_window_regs_user(regs); | ||
| 149 | err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4); | ||
| 169 | 150 | ||
| 170 | // FIXME restore_cpextra | 151 | // err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4) |
| 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 | 152 | ||
| 182 | struct task_struct *tsk = current; | 153 | #if XCHAL_HAVE_CP |
| 183 | release_all_cp(tsk); | 154 | # error Coprocessors unsupported |
| 184 | return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE); | 155 | err |= save_cpextra(cpstate); |
| 156 | err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate); | ||
| 185 | #endif | 157 | #endif |
| 186 | return 0; | 158 | /* non-iBCS2 extensions.. */ |
| 187 | } | 159 | err |= __put_user(mask, &sc->oldmask); |
| 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... | ||
| 190 | */ | ||
| 191 | 160 | ||
| 161 | return err; | ||
| 162 | } | ||
| 192 | 163 | ||
| 193 | static int | 164 | static int |
| 194 | restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) | 165 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
| 195 | { | 166 | { |
| 196 | struct thread_struct *thread; | ||
| 197 | unsigned int err = 0; | 167 | unsigned int err = 0; |
| 198 | unsigned long ps; | 168 | unsigned long ps; |
| 199 | struct _cpstate *buf; | ||
| 200 | 169 | ||
| 201 | #define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) | 170 | #define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) |
| 202 | COPY(pc); | 171 | COPY(pc); |
| 203 | COPY(depc); | ||
| 204 | COPY(wmask); | ||
| 205 | COPY(lbeg); | 172 | COPY(lbeg); |
| 206 | COPY(lend); | 173 | COPY(lend); |
| 207 | COPY(lcount); | 174 | COPY(lcount); |
| 208 | COPY(sar); | 175 | COPY(sar); |
| 209 | COPY(windowbase); | ||
| 210 | COPY(windowstart); | ||
| 211 | #undef COPY | 176 | #undef COPY |
| 212 | 177 | ||
| 178 | /* All registers were flushed to stack. Start with a prestine frame. */ | ||
| 179 | |||
| 180 | regs->wmask = 1; | ||
| 181 | regs->windowbase = 0; | ||
| 182 | regs->windowstart = 1; | ||
| 183 | |||
| 213 | /* For PS, restore only PS.CALLINC. | 184 | /* For PS, restore only PS.CALLINC. |
| 214 | * Assume that all other bits are either the same as for the signal | 185 | * 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). | 186 | * handler, or the user mode value doesn't matter (e.g. PS.OWB). |
| 216 | */ | 187 | */ |
| 217 | err |= __get_user(ps, &sc->sc_ps); | 188 | err |= __get_user(ps, &sc->sc_ps); |
| 218 | regs->ps = (regs->ps & ~PS_CALLINC_MASK) | 189 | regs->ps = (regs->ps & ~PS_CALLINC_MASK) | (ps & PS_CALLINC_MASK); |
| 219 | | (ps & PS_CALLINC_MASK); | ||
| 220 | 190 | ||
| 221 | /* Additional corruption checks */ | 191 | /* Additional corruption checks */ |
| 222 | 192 | ||
| 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) | 193 | if ((regs->lcount > 0) |
| 227 | && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) ) | 194 | && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) ) |
| 228 | err = 1; | 195 | err = 1; |
| 229 | 196 | ||
| 230 | /* Restore extended register state. | 197 | err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4); |
| 231 | * See struct thread_struct in processor.h. | ||
| 232 | */ | ||
| 233 | thread = ¤t->thread; | ||
| 234 | |||
| 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 | } | ||
| 242 | |||
| 243 | regs->syscall = -1; /* disable syscall checks */ | ||
| 244 | return err; | ||
| 245 | |||
| 246 | badframe: | ||
| 247 | return 1; | ||
| 248 | } | ||
| 249 | |||
| 250 | static inline void | ||
| 251 | flush_my_cpstate(struct task_struct *tsk) | ||
| 252 | { | ||
| 253 | unsigned long flags; | ||
| 254 | local_irq_save(flags); | ||
| 255 | |||
| 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); | ||
| 261 | 198 | ||
| 262 | /* Invalidate and "disown" the cp to allow | 199 | #if XCHAL_HAVE_CP |
| 263 | * callers the chance to reset cp state in the | 200 | # error Coprocessors unsupported |
| 264 | * task_struct. */ | 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. */ | ||
| 265 | 207 | ||
| 266 | xthal_invalidate_cp(i); | 208 | if (!err) { |
| 267 | coproc_owners[i] = 0; | 209 | struct task_struct *tsk = current; |
| 268 | } | 210 | release_all_cp(tsk); |
| 211 | err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate, | ||
| 212 | XTENSA_CP_EXTRA_SIZE); | ||
| 269 | } | 213 | } |
| 270 | #endif | 214 | #endif |
| 271 | local_irq_restore(flags); | ||
| 272 | } | ||
| 273 | |||
| 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 | return 0; | ||
| 284 | #else | ||
| 285 | |||
| 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 | ||
| 316 | } | ||
| 317 | |||
| 318 | static int | ||
| 319 | setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate, | ||
| 320 | struct pt_regs *regs, unsigned long mask) | ||
| 321 | { | ||
| 322 | struct thread_struct *thread; | ||
| 323 | int err = 0; | ||
| 324 | |||
| 325 | //printk("setup_sigcontext\n"); | ||
| 326 | #define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) | ||
| 327 | COPY(pc); | ||
| 328 | COPY(ps); | ||
| 329 | COPY(depc); | ||
| 330 | COPY(wmask); | ||
| 331 | COPY(lbeg); | ||
| 332 | COPY(lend); | ||
| 333 | COPY(lcount); | ||
| 334 | COPY(sar); | ||
| 335 | COPY(windowbase); | ||
| 336 | COPY(windowstart); | ||
| 337 | #undef COPY | ||
| 338 | |||
| 339 | /* Save extended register state. | ||
| 340 | * See struct thread_struct in processor.h. | ||
| 341 | */ | ||
| 342 | thread = ¤t->thread; | ||
| 343 | err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4); | ||
| 344 | err |= save_cpextra(cpstate); | ||
| 345 | err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate); | ||
| 346 | /* non-iBCS2 extensions.. */ | ||
| 347 | err |= __put_user(mask, &sc->oldmask); | ||
| 348 | 215 | ||
| 216 | regs->syscall = -1; /* disable syscall checks */ | ||
| 349 | return err; | 217 | return err; |
| 350 | } | 218 | } |
| 351 | 219 | ||
| 352 | asmlinkage int xtensa_sigreturn(struct pt_regs *regs) | ||
| 353 | { | ||
| 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"); | ||
| 358 | |||
| 359 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
| 360 | goto badframe; | ||
| 361 | |||
| 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; | ||
| 367 | |||
| 368 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
| 369 | |||
| 370 | spin_lock_irq(¤t->sighand->siglock); | ||
| 371 | current->blocked = set; | ||
| 372 | recalc_sigpending(); | ||
| 373 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 374 | 220 | ||
| 375 | if (restore_sigcontext(regs, &frame->sc)) | ||
| 376 | goto badframe; | ||
| 377 | return regs->areg[2]; | ||
| 378 | 221 | ||
| 379 | badframe: | 222 | /* |
| 380 | force_sig(SIGSEGV, current); | 223 | * Do a signal return; undo the signal stack. |
| 381 | return 0; | 224 | */ |
| 382 | } | ||
| 383 | 225 | ||
| 384 | asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs) | 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 | sigset_t set; | 230 | sigset_t set; |
| 388 | stack_t st; | ||
| 389 | int ret; | 231 | int ret; |
| 232 | |||
| 390 | if (regs->depc > 64) | 233 | if (regs->depc > 64) |
| 391 | { | 234 | panic("rt_sigreturn in double exception!\n"); |
| 392 | printk("!!!!!!! DEPC !!!!!!!\n"); | 235 | |
| 393 | return 0; | 236 | frame = (struct rt_sigframe __user *) regs->areg[1]; |
| 394 | } | ||
| 395 | 237 | ||
| 396 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 238 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 397 | goto badframe; | 239 | goto badframe; |
| @@ -407,13 +249,11 @@ asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs) | |||
| 407 | 249 | ||
| 408 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) | 250 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
| 409 | goto badframe; | 251 | goto badframe; |
| 252 | |||
| 410 | ret = regs->areg[2]; | 253 | ret = regs->areg[2]; |
| 411 | 254 | ||
| 412 | if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) | 255 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->areg[1]) == -EFAULT) |
| 413 | goto badframe; | 256 | goto badframe; |
| 414 | /* It is more difficult to avoid calling this function than to | ||
| 415 | call it and ignore errors. */ | ||
| 416 | do_sigaltstack(&st, NULL, regs->areg[1]); | ||
| 417 | 257 | ||
| 418 | return ret; | 258 | return ret; |
| 419 | 259 | ||
| @@ -422,77 +262,50 @@ badframe: | |||
| 422 | return 0; | 262 | return 0; |
| 423 | } | 263 | } |
| 424 | 264 | ||
| 425 | /* | 265 | |
| 426 | * Set up a signal frame. | ||
| 427 | */ | ||
| 428 | 266 | ||
| 429 | /* | 267 | /* |
| 430 | * Determine which stack to use.. | 268 | * Set up a signal frame. |
| 431 | */ | 269 | */ |
| 432 | static inline void * | ||
| 433 | get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | ||
| 434 | { | ||
| 435 | if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) | ||
| 436 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
| 437 | |||
| 438 | return (void *)((sp - frame_size) & -16ul); | ||
| 439 | } | ||
| 440 | |||
| 441 | #define USE_SIGRETURN 0 | ||
| 442 | #define USE_RT_SIGRETURN 1 | ||
| 443 | 270 | ||
| 444 | static int | 271 | static int |
| 445 | gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn) | 272 | gen_return_code(unsigned char *codemem) |
| 446 | { | 273 | { |
| 447 | unsigned int retcall; | ||
| 448 | int err = 0; | 274 | int err = 0; |
| 449 | 275 | ||
| 450 | #if 0 | 276 | /* |
| 451 | /* Ignoring SA_RESTORER for now; it's supposed to be obsolete, | 277 | * The 12-bit immediate is really split up within the 24-bit MOVI |
| 452 | * and the xtensa glibc doesn't use it. | 278 | * instruction. As long as the above system call numbers fit within |
| 279 | * 8-bits, the following code works fine. See the Xtensa ISA for | ||
| 280 | * details. | ||
| 453 | */ | 281 | */ |
| 454 | if (ka->sa.sa_flags & SA_RESTORER) { | ||
| 455 | regs->pr = (unsigned long) ka->sa.sa_restorer; | ||
| 456 | } else | ||
| 457 | #endif /* 0 */ | ||
| 458 | { | ||
| 459 | |||
| 460 | #if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255) | ||
| 461 | |||
| 462 | /* The 12-bit immediate is really split up within the 24-bit MOVI | ||
| 463 | * instruction. As long as the above system call numbers fit within | ||
| 464 | * 8-bits, the following code works fine. See the Xtensa ISA for | ||
| 465 | * details. | ||
| 466 | */ | ||
| 467 | 282 | ||
| 468 | #error Generating the MOVI instruction below breaks! | 283 | #if __NR_rt_sigreturn > 255 |
| 284 | # error Generating the MOVI instruction below breaks! | ||
| 469 | #endif | 285 | #endif |
| 470 | 286 | ||
| 471 | retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn; | ||
| 472 | |||
| 473 | #ifdef __XTENSA_EB__ /* Big Endian version */ | 287 | #ifdef __XTENSA_EB__ /* Big Endian version */ |
| 474 | /* Generate instruction: MOVI a2, retcall */ | 288 | /* Generate instruction: MOVI a2, __NR_rt_sigreturn */ |
| 475 | err |= __put_user(0x22, &codemem[0]); | 289 | err |= __put_user(0x22, &codemem[0]); |
| 476 | err |= __put_user(0x0a, &codemem[1]); | 290 | err |= __put_user(0x0a, &codemem[1]); |
| 477 | err |= __put_user(retcall, &codemem[2]); | 291 | err |= __put_user(__NR_rt_sigreturn, &codemem[2]); |
| 478 | /* Generate instruction: SYSCALL */ | 292 | /* Generate instruction: SYSCALL */ |
| 479 | err |= __put_user(0x00, &codemem[3]); | 293 | err |= __put_user(0x00, &codemem[3]); |
| 480 | err |= __put_user(0x05, &codemem[4]); | 294 | err |= __put_user(0x05, &codemem[4]); |
| 481 | err |= __put_user(0x00, &codemem[5]); | 295 | err |= __put_user(0x00, &codemem[5]); |
| 482 | 296 | ||
| 483 | #elif defined __XTENSA_EL__ /* Little Endian version */ | 297 | #elif defined __XTENSA_EL__ /* Little Endian version */ |
| 484 | /* Generate instruction: MOVI a2, retcall */ | 298 | /* Generate instruction: MOVI a2, __NR_rt_sigreturn */ |
| 485 | err |= __put_user(0x22, &codemem[0]); | 299 | err |= __put_user(0x22, &codemem[0]); |
| 486 | err |= __put_user(0xa0, &codemem[1]); | 300 | err |= __put_user(0xa0, &codemem[1]); |
| 487 | err |= __put_user(retcall, &codemem[2]); | 301 | err |= __put_user(__NR_rt_sigreturn, &codemem[2]); |
| 488 | /* Generate instruction: SYSCALL */ | 302 | /* Generate instruction: SYSCALL */ |
| 489 | err |= __put_user(0x00, &codemem[3]); | 303 | err |= __put_user(0x00, &codemem[3]); |
| 490 | err |= __put_user(0x50, &codemem[4]); | 304 | err |= __put_user(0x50, &codemem[4]); |
| 491 | err |= __put_user(0x00, &codemem[5]); | 305 | err |= __put_user(0x00, &codemem[5]); |
| 492 | #else | 306 | #else |
| 493 | #error Must use compiler for Xtensa processors. | 307 | # error Must use compiler for Xtensa processors. |
| 494 | #endif | 308 | #endif |
| 495 | } | ||
| 496 | 309 | ||
| 497 | /* Flush generated code out of the data cache */ | 310 | /* Flush generated code out of the data cache */ |
| 498 | 311 | ||
| @@ -504,97 +317,29 @@ gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn) | |||
| 504 | return err; | 317 | return err; |
| 505 | } | 318 | } |
| 506 | 319 | ||
| 507 | static void | ||
| 508 | set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr, | ||
| 509 | void *handler, unsigned long arg1, void *arg2, void *arg3) | ||
| 510 | { | ||
| 511 | /* Set up registers for signal handler */ | ||
| 512 | start_thread(regs, (unsigned long) handler, (unsigned long) stack); | ||
| 513 | |||
| 514 | /* Set up a stack frame for a call4 | ||
| 515 | * Note: PS.CALLINC is set to one by start_thread | ||
| 516 | */ | ||
| 517 | regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000; | ||
| 518 | regs->areg[6] = arg1; | ||
| 519 | regs->areg[7] = (unsigned long) arg2; | ||
| 520 | regs->areg[8] = (unsigned long) arg3; | ||
| 521 | } | ||
| 522 | 320 | ||
| 523 | static void setup_frame(int sig, struct k_sigaction *ka, | 321 | static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 524 | sigset_t *set, struct pt_regs *regs) | 322 | sigset_t *set, struct pt_regs *regs) |
| 525 | { | 323 | { |
| 526 | struct sigframe *frame; | 324 | struct rt_sigframe *frame; |
| 527 | int err = 0; | 325 | int err = 0; |
| 528 | int signal; | 326 | int signal; |
| 327 | unsigned long sp, ra; | ||
| 529 | 328 | ||
| 530 | frame = get_sigframe(ka, regs->areg[1], sizeof(*frame)); | 329 | sp = regs->areg[1]; |
| 531 | if (regs->depc > 64) | ||
| 532 | { | ||
| 533 | printk("!!!!!!! DEPC !!!!!!!\n"); | ||
| 534 | return; | ||
| 535 | } | ||
| 536 | |||
| 537 | |||
| 538 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
| 539 | goto give_sigsegv; | ||
| 540 | |||
| 541 | signal = current_thread_info()->exec_domain | ||
| 542 | && current_thread_info()->exec_domain->signal_invmap | ||
| 543 | && sig < 32 | ||
| 544 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
| 545 | : sig; | ||
| 546 | |||
| 547 | err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]); | ||
| 548 | 330 | ||
| 549 | if (_NSIG_WORDS > 1) { | 331 | if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) { |
| 550 | err |= __copy_to_user(frame->extramask, &set->sig[1], | 332 | sp = current->sas_ss_sp + current->sas_ss_size; |
| 551 | sizeof(frame->extramask)); | ||
| 552 | } | 333 | } |
| 553 | 334 | ||
| 554 | /* Create sys_sigreturn syscall in stack frame */ | 335 | frame = (void *)((sp - sizeof(*frame)) & -16ul); |
| 555 | err |= gen_return_code(frame->retcode, USE_SIGRETURN); | ||
| 556 | |||
| 557 | if (err) | ||
| 558 | goto give_sigsegv; | ||
| 559 | |||
| 560 | /* Create signal handler execution context. | ||
| 561 | * Return context not modified until this point. | ||
| 562 | */ | ||
| 563 | set_thread_state(regs, frame, frame->retcode, | ||
| 564 | ka->sa.sa_handler, signal, &frame->sc, NULL); | ||
| 565 | |||
| 566 | /* Set access mode to USER_DS. Nomenclature is outdated, but | ||
| 567 | * functionality is used in uaccess.h | ||
| 568 | */ | ||
| 569 | set_fs(USER_DS); | ||
| 570 | |||
| 571 | |||
| 572 | #if DEBUG_SIG | ||
| 573 | printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n", | ||
| 574 | current->comm, current->pid, signal, frame, regs->pc); | ||
| 575 | #endif | ||
| 576 | |||
| 577 | return; | ||
| 578 | |||
| 579 | give_sigsegv: | ||
| 580 | if (sig == SIGSEGV) | ||
| 581 | ka->sa.sa_handler = SIG_DFL; | ||
| 582 | force_sig(SIGSEGV, current); | ||
| 583 | } | ||
| 584 | |||
| 585 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
| 586 | sigset_t *set, struct pt_regs *regs) | ||
| 587 | { | ||
| 588 | struct rt_sigframe *frame; | ||
| 589 | int err = 0; | ||
| 590 | int signal; | ||
| 591 | 336 | ||
| 592 | frame = get_sigframe(ka, regs->areg[1], sizeof(*frame)); | ||
| 593 | if (regs->depc > 64) | 337 | if (regs->depc > 64) |
| 594 | panic ("Double exception sys_sigreturn\n"); | 338 | panic ("Double exception sys_sigreturn\n"); |
| 595 | 339 | ||
| 596 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 340 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) { |
| 597 | goto give_sigsegv; | 341 | goto give_sigsegv; |
| 342 | } | ||
| 598 | 343 | ||
| 599 | signal = current_thread_info()->exec_domain | 344 | signal = current_thread_info()->exec_domain |
| 600 | && current_thread_info()->exec_domain->signal_invmap | 345 | && current_thread_info()->exec_domain->signal_invmap |
| @@ -602,9 +347,12 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 602 | ? current_thread_info()->exec_domain->signal_invmap[sig] | 347 | ? current_thread_info()->exec_domain->signal_invmap[sig] |
| 603 | : sig; | 348 | : sig; |
| 604 | 349 | ||
| 605 | err |= copy_siginfo_to_user(&frame->info, info); | 350 | if (ka->sa.sa_flags & SA_SIGINFO) { |
| 351 | err |= copy_siginfo_to_user(&frame->info, info); | ||
| 352 | } | ||
| 353 | |||
| 354 | /* Create the user context. */ | ||
| 606 | 355 | ||
| 607 | /* Create the ucontext. */ | ||
| 608 | err |= __put_user(0, &frame->uc.uc_flags); | 356 | err |= __put_user(0, &frame->uc.uc_flags); |
| 609 | err |= __put_user(0, &frame->uc.uc_link); | 357 | err |= __put_user(0, &frame->uc.uc_link); |
| 610 | err |= __put_user((void *)current->sas_ss_sp, | 358 | err |= __put_user((void *)current->sas_ss_sp, |
| @@ -617,16 +365,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 617 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 365 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 618 | 366 | ||
| 619 | /* Create sys_rt_sigreturn syscall in stack frame */ | 367 | /* Create sys_rt_sigreturn syscall in stack frame */ |
| 620 | err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN); | ||
| 621 | 368 | ||
| 622 | if (err) | 369 | err |= gen_return_code(frame->retcode); |
| 370 | |||
| 371 | if (err) { | ||
| 623 | goto give_sigsegv; | 372 | goto give_sigsegv; |
| 373 | } | ||
| 374 | |||
| 624 | 375 | ||
| 625 | /* Create signal handler execution context. | 376 | /* |
| 377 | * Create signal handler execution context. | ||
| 626 | * Return context not modified until this point. | 378 | * Return context not modified until this point. |
| 627 | */ | 379 | */ |
| 628 | set_thread_state(regs, frame, frame->retcode, | 380 | |
| 629 | ka->sa.sa_handler, signal, &frame->info, &frame->uc); | 381 | /* Set up registers for signal handler */ |
| 382 | start_thread(regs, (unsigned long) ka->sa.sa_handler, | ||
| 383 | (unsigned long) frame); | ||
| 384 | |||
| 385 | /* Set up a stack frame for a call4 | ||
| 386 | * Note: PS.CALLINC is set to one by start_thread | ||
| 387 | */ | ||
| 388 | ra = (unsigned long) frame->retcode; | ||
| 389 | regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000; | ||
| 390 | regs->areg[6] = (unsigned long) signal; | ||
| 391 | regs->areg[7] = (unsigned long) &frame->info; | ||
| 392 | regs->areg[8] = (unsigned long) &frame->uc; | ||
| 630 | 393 | ||
| 631 | /* Set access mode to USER_DS. Nomenclature is outdated, but | 394 | /* Set access mode to USER_DS. Nomenclature is outdated, but |
| 632 | * functionality is used in uaccess.h | 395 | * functionality is used in uaccess.h |
| @@ -646,6 +409,48 @@ give_sigsegv: | |||
| 646 | force_sig(SIGSEGV, current); | 409 | force_sig(SIGSEGV, current); |
| 647 | } | 410 | } |
| 648 | 411 | ||
| 412 | /* | ||
| 413 | * Atomically swap in the new signal mask, and wait for a signal. | ||
| 414 | */ | ||
| 415 | |||
| 416 | asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, | ||
| 417 | size_t sigsetsize, | ||
| 418 | long a2, long a3, long a4, long a5, | ||
| 419 | struct pt_regs *regs) | ||
| 420 | { | ||
| 421 | sigset_t saveset, newset; | ||
| 422 | |||
| 423 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
| 424 | if (sigsetsize != sizeof(sigset_t)) | ||
| 425 | return -EINVAL; | ||
| 426 | |||
| 427 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
| 428 | return -EFAULT; | ||
| 429 | |||
| 430 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
| 431 | spin_lock_irq(¤t->sighand->siglock); | ||
| 432 | saveset = current->blocked; | ||
| 433 | current->blocked = newset; | ||
| 434 | recalc_sigpending(); | ||
| 435 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 436 | |||
| 437 | regs->areg[2] = -EINTR; | ||
| 438 | while (1) { | ||
| 439 | current->state = TASK_INTERRUPTIBLE; | ||
| 440 | schedule(); | ||
| 441 | if (do_signal(regs, &saveset)) | ||
| 442 | return -EINTR; | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 446 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, | ||
| 447 | stack_t __user *uoss, | ||
| 448 | long a2, long a3, long a4, long a5, | ||
| 449 | struct pt_regs *regs) | ||
| 450 | { | ||
| 451 | return do_sigaltstack(uss, uoss, regs->areg[1]); | ||
| 452 | } | ||
| 453 | |||
| 649 | 454 | ||
| 650 | 455 | ||
| 651 | /* | 456 | /* |
| @@ -663,51 +468,89 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
| 663 | int signr; | 468 | int signr; |
| 664 | struct k_sigaction ka; | 469 | struct k_sigaction ka; |
| 665 | 470 | ||
| 471 | if (!user_mode(regs)) | ||
| 472 | return 0; | ||
| 473 | |||
| 474 | if (try_to_freeze()) | ||
| 475 | goto no_signal; | ||
| 476 | |||
| 666 | if (!oldset) | 477 | if (!oldset) |
| 667 | oldset = ¤t->blocked; | 478 | oldset = ¤t->blocked; |
| 668 | 479 | ||
| 480 | task_pt_regs(current)->icountlevel = 0; | ||
| 481 | |||
| 669 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 482 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| 670 | 483 | ||
| 671 | /* Are we from a system call? */ | 484 | if (signr > 0) { |
| 672 | if (regs->syscall >= 0) { | 485 | |
| 673 | /* If so, check system call restarting.. */ | 486 | /* Are we from a system call? */ |
| 674 | switch (regs->areg[2]) { | 487 | |
| 675 | case ERESTARTNOHAND: | 488 | if ((signed)regs->syscall >= 0) { |
| 676 | case ERESTART_RESTARTBLOCK: | ||
| 677 | regs->areg[2] = -EINTR; | ||
| 678 | break; | ||
| 679 | 489 | ||
| 680 | case ERESTARTSYS: | 490 | /* If so, check system call restarting.. */ |
| 681 | if (!(ka.sa.sa_flags & SA_RESTART)) { | 491 | |
| 492 | switch (regs->areg[2]) { | ||
| 493 | case -ERESTARTNOHAND: | ||
| 494 | case -ERESTART_RESTARTBLOCK: | ||
| 682 | regs->areg[2] = -EINTR; | 495 | regs->areg[2] = -EINTR; |
| 683 | break; | 496 | break; |
| 684 | } | 497 | |
| 685 | /* fallthrough */ | 498 | case -ERESTARTSYS: |
| 686 | case ERESTARTNOINTR: | 499 | if (!(ka.sa.sa_flags & SA_RESTART)) { |
| 687 | regs->areg[2] = regs->syscall; | 500 | regs->areg[2] = -EINTR; |
| 688 | regs->pc -= 3; | 501 | break; |
| 502 | } | ||
| 503 | /* fallthrough */ | ||
| 504 | case -ERESTARTNOINTR: | ||
| 505 | regs->areg[2] = regs->syscall; | ||
| 506 | regs->pc -= 3; | ||
| 507 | break; | ||
| 508 | |||
| 509 | default: | ||
| 510 | /* nothing to do */ | ||
| 511 | if (regs->areg[2] != 0) | ||
| 512 | break; | ||
| 513 | } | ||
| 689 | } | 514 | } |
| 690 | } | ||
| 691 | 515 | ||
| 692 | if (signr == 0) | 516 | /* Whee! Actually deliver the signal. */ |
| 693 | return 0; /* no signals delivered */ | 517 | /* Set up the stack frame */ |
| 518 | setup_frame(signr, &ka, &info, oldset, regs); | ||
| 694 | 519 | ||
| 695 | /* Whee! Actually deliver the signal. */ | 520 | if (ka.sa.sa_flags & SA_ONESHOT) |
| 521 | ka.sa.sa_handler = SIG_DFL; | ||
| 696 | 522 | ||
| 697 | /* Set up the stack frame */ | 523 | spin_lock_irq(¤t->sighand->siglock); |
| 698 | if (ka.sa.sa_flags & SA_SIGINFO) | 524 | sigorsets(¤t->blocked, ¤t->blocked, &ka.sa.sa_mask); |
| 699 | setup_rt_frame(signr, &ka, &info, oldset, regs); | 525 | if (!(ka.sa.sa_flags & SA_NODEFER)) |
| 700 | else | 526 | sigaddset(¤t->blocked, signr); |
| 701 | setup_frame(signr, &ka, oldset, regs); | 527 | recalc_sigpending(); |
| 528 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 529 | if (current->ptrace & PT_SINGLESTEP) | ||
| 530 | task_pt_regs(current)->icountlevel = 1; | ||
| 702 | 531 | ||
| 703 | if (ka.sa.sa_flags & SA_ONESHOT) | 532 | return 1; |
| 704 | ka.sa.sa_handler = SIG_DFL; | 533 | } |
| 705 | 534 | ||
| 706 | spin_lock_irq(¤t->sighand->siglock); | 535 | no_signal: |
| 707 | sigorsets(¤t->blocked, ¤t->blocked, &ka.sa.sa_mask); | 536 | /* Did we come from a system call? */ |
| 708 | if (!(ka.sa.sa_flags & SA_NODEFER)) | 537 | if ((signed) regs->syscall >= 0) { |
| 709 | sigaddset(¤t->blocked, signr); | 538 | /* Restart the system call - no handlers present */ |
| 710 | recalc_sigpending(); | 539 | switch (regs->areg[2]) { |
| 711 | spin_unlock_irq(¤t->sighand->siglock); | 540 | case -ERESTARTNOHAND: |
| 712 | return 1; | 541 | case -ERESTARTSYS: |
| 542 | case -ERESTARTNOINTR: | ||
| 543 | regs->areg[2] = regs->syscall; | ||
| 544 | regs->pc -= 3; | ||
| 545 | break; | ||
| 546 | case -ERESTART_RESTARTBLOCK: | ||
| 547 | regs->areg[2] = __NR_restart_syscall; | ||
| 548 | regs->pc -= 3; | ||
| 549 | break; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | if (current->ptrace & PT_SINGLESTEP) | ||
| 553 | task_pt_regs(current)->icountlevel = 1; | ||
| 554 | return 0; | ||
| 713 | } | 555 | } |
| 556 | |||
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index 4b7b4ff79973..b0582c3c5f8d 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S | |||
| @@ -84,9 +84,7 @@ SECTIONS | |||
| 84 | { | 84 | { |
| 85 | /* The .head.text section must be the first section! */ | 85 | /* The .head.text section must be the first section! */ |
| 86 | *(.head.text) | 86 | *(.head.text) |
| 87 | *(.literal) | 87 | *(.literal .text) |
| 88 | TEXT_TEXT | ||
| 89 | *(.srom.text) | ||
| 90 | VMLINUX_SYMBOL(__sched_text_start) = .; | 88 | VMLINUX_SYMBOL(__sched_text_start) = .; |
| 91 | *(.sched.literal .sched.text) | 89 | *(.sched.literal .sched.text) |
| 92 | VMLINUX_SYMBOL(__sched_text_end) = .; | 90 | VMLINUX_SYMBOL(__sched_text_end) = .; |
| @@ -96,6 +94,7 @@ SECTIONS | |||
| 96 | 94 | ||
| 97 | } | 95 | } |
| 98 | _etext = .; | 96 | _etext = .; |
| 97 | PROVIDE (etext = .); | ||
| 99 | 98 | ||
| 100 | . = ALIGN(16); | 99 | . = ALIGN(16); |
| 101 | 100 | ||
| @@ -103,32 +102,6 @@ SECTIONS | |||
| 103 | 102 | ||
| 104 | /* Relocation table */ | 103 | /* Relocation table */ |
| 105 | 104 | ||
| 106 | . = ALIGN(16); | ||
| 107 | __boot_reloc_table_start = ABSOLUTE(.); | ||
| 108 | |||
| 109 | __relocate : { | ||
| 110 | |||
| 111 | RELOCATE_ENTRY(_WindowVectors_text, | ||
| 112 | .WindowVectors.text); | ||
| 113 | #if 0 | ||
| 114 | RELOCATE_ENTRY(_KernelExceptionVector_literal, | ||
| 115 | .KernelExceptionVector.literal); | ||
| 116 | #endif | ||
| 117 | RELOCATE_ENTRY(_KernelExceptionVector_text, | ||
| 118 | .KernelExceptionVector.text); | ||
| 119 | #if 0 | ||
| 120 | RELOCATE_ENTRY(_UserExceptionVector_literal, | ||
| 121 | .UserExceptionVector.literal); | ||
| 122 | #endif | ||
| 123 | RELOCATE_ENTRY(_UserExceptionVector_text, | ||
| 124 | .UserExceptionVector.text); | ||
| 125 | RELOCATE_ENTRY(_DoubleExceptionVector_literal, | ||
| 126 | .DoubleExceptionVector.literal); | ||
| 127 | RELOCATE_ENTRY(_DoubleExceptionVector_text, | ||
| 128 | .DoubleExceptionVector.text); | ||
| 129 | } | ||
| 130 | __boot_reloc_table_end = ABSOLUTE(.) ; | ||
| 131 | |||
| 132 | .fixup : { *(.fixup) } | 105 | .fixup : { *(.fixup) } |
| 133 | 106 | ||
| 134 | . = ALIGN(16); | 107 | . = ALIGN(16); |
| @@ -145,8 +118,7 @@ SECTIONS | |||
| 145 | _fdata = .; | 118 | _fdata = .; |
| 146 | .data : | 119 | .data : |
| 147 | { | 120 | { |
| 148 | DATA_DATA | 121 | *(.data) CONSTRUCTORS |
| 149 | CONSTRUCTORS | ||
| 150 | . = ALIGN(XCHAL_ICACHE_LINESIZE); | 122 | . = ALIGN(XCHAL_ICACHE_LINESIZE); |
| 151 | *(.data.cacheline_aligned) | 123 | *(.data.cacheline_aligned) |
| 152 | } | 124 | } |
| @@ -174,6 +146,22 @@ SECTIONS | |||
| 174 | __tagtable_begin = .; | 146 | __tagtable_begin = .; |
| 175 | *(.taglist) | 147 | *(.taglist) |
| 176 | __tagtable_end = .; | 148 | __tagtable_end = .; |
| 149 | |||
| 150 | . = ALIGN(16); | ||
| 151 | __boot_reloc_table_start = ABSOLUTE(.); | ||
| 152 | |||
| 153 | RELOCATE_ENTRY(_WindowVectors_text, | ||
| 154 | .WindowVectors.text); | ||
| 155 | RELOCATE_ENTRY(_KernelExceptionVector_text, | ||
| 156 | .KernelExceptionVector.text); | ||
| 157 | RELOCATE_ENTRY(_UserExceptionVector_text, | ||
| 158 | .UserExceptionVector.text); | ||
| 159 | RELOCATE_ENTRY(_DoubleExceptionVector_literal, | ||
| 160 | .DoubleExceptionVector.literal); | ||
| 161 | RELOCATE_ENTRY(_DoubleExceptionVector_text, | ||
| 162 | .DoubleExceptionVector.text); | ||
| 163 | |||
| 164 | __boot_reloc_table_end = ABSOLUTE(.) ; | ||
| 177 | } | 165 | } |
| 178 | 166 | ||
| 179 | . = ALIGN(XCHAL_ICACHE_LINESIZE); | 167 | . = ALIGN(XCHAL_ICACHE_LINESIZE); |
| @@ -194,16 +182,6 @@ SECTIONS | |||
| 194 | 182 | ||
| 195 | SECURITY_INIT | 183 | SECURITY_INIT |
| 196 | 184 | ||
| 197 | . = ALIGN(4); | ||
| 198 | |||
| 199 | __start___ftr_fixup = .; | ||
| 200 | __ftr_fixup : { *(__ftr_fixup) } | ||
| 201 | __stop___ftr_fixup = .; | ||
| 202 | |||
| 203 | . = ALIGN(4096); | ||
| 204 | __per_cpu_start = .; | ||
| 205 | .data.percpu : { *(.data.percpu) } | ||
| 206 | __per_cpu_end = .; | ||
| 207 | 185 | ||
| 208 | #ifdef CONFIG_BLK_DEV_INITRD | 186 | #ifdef CONFIG_BLK_DEV_INITRD |
| 209 | . = ALIGN(4096); | 187 | . = ALIGN(4096); |
| @@ -212,6 +190,12 @@ SECTIONS | |||
| 212 | __initramfs_end = .; | 190 | __initramfs_end = .; |
| 213 | #endif | 191 | #endif |
| 214 | 192 | ||
| 193 | . = ALIGN(4096); | ||
| 194 | __per_cpu_start = .; | ||
| 195 | .data.percpu : { *(.data.percpu) } | ||
| 196 | __per_cpu_end = .; | ||
| 197 | |||
| 198 | |||
| 215 | /* We need this dummy segment here */ | 199 | /* We need this dummy segment here */ |
| 216 | 200 | ||
| 217 | . = ALIGN(4); | 201 | . = ALIGN(4); |
| @@ -273,9 +257,9 @@ SECTIONS | |||
| 273 | 257 | ||
| 274 | /* BSS section */ | 258 | /* BSS section */ |
| 275 | _bss_start = .; | 259 | _bss_start = .; |
| 276 | .sbss : { *(.sbss) *(.scommon) } | 260 | .bss : { *(.bss.page_aligned) *(.bss) } |
| 277 | .bss : { *(COMMON) *(.bss) } | ||
| 278 | _bss_end = .; | 261 | _bss_end = .; |
| 262 | |||
| 279 | _end = .; | 263 | _end = .; |
| 280 | 264 | ||
| 281 | /* only used by the boot loader */ | 265 | /* only used by the boot loader */ |
| @@ -293,16 +277,16 @@ SECTIONS | |||
| 293 | *(.ResetVector.text) | 277 | *(.ResetVector.text) |
| 294 | } | 278 | } |
| 295 | 279 | ||
| 296 | |||
| 297 | /* Sections to be discarded */ | 280 | /* Sections to be discarded */ |
| 298 | /DISCARD/ : | 281 | /DISCARD/ : |
| 299 | { | 282 | { |
| 300 | *(.text.exit) | 283 | *(.exit.literal .exit.text) |
| 301 | *(.text.exit.literal) | 284 | *(.exit.data) |
| 302 | *(.data.exit) | ||
| 303 | *(.exitcall.exit) | 285 | *(.exitcall.exit) |
| 304 | } | 286 | } |
| 305 | 287 | ||
| 288 | .xt.lit : { *(.xt.lit) } | ||
| 289 | .xt.prop : { *(.xt.prop) } | ||
| 306 | 290 | ||
| 307 | .debug 0 : { *(.debug) } | 291 | .debug 0 : { *(.debug) } |
| 308 | .line 0 : { *(.line) } | 292 | .line 0 : { *(.line) } |
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index cd7e6a020602..60dbdb43fb4c 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c | |||
| @@ -38,21 +38,10 @@ | |||
| 38 | /* | 38 | /* |
| 39 | * String functions | 39 | * String functions |
| 40 | */ | 40 | */ |
| 41 | EXPORT_SYMBOL(memcmp); | ||
| 42 | EXPORT_SYMBOL(memset); | 41 | EXPORT_SYMBOL(memset); |
| 43 | EXPORT_SYMBOL(memcpy); | 42 | EXPORT_SYMBOL(memcpy); |
| 44 | EXPORT_SYMBOL(memmove); | 43 | EXPORT_SYMBOL(memmove); |
| 45 | EXPORT_SYMBOL(memchr); | ||
| 46 | EXPORT_SYMBOL(strcat); | ||
| 47 | EXPORT_SYMBOL(strchr); | ||
| 48 | EXPORT_SYMBOL(strlen); | ||
| 49 | EXPORT_SYMBOL(strncat); | ||
| 50 | EXPORT_SYMBOL(strnlen); | ||
| 51 | EXPORT_SYMBOL(strrchr); | ||
| 52 | EXPORT_SYMBOL(strstr); | ||
| 53 | 44 | ||
| 54 | EXPORT_SYMBOL(enable_irq); | ||
| 55 | EXPORT_SYMBOL(disable_irq); | ||
| 56 | EXPORT_SYMBOL(kernel_thread); | 45 | EXPORT_SYMBOL(kernel_thread); |
| 57 | 46 | ||
| 58 | /* | 47 | /* |
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S index a834057bda6b..b2655d94558d 100644 --- a/arch/xtensa/lib/strncpy_user.S +++ b/arch/xtensa/lib/strncpy_user.S | |||
| @@ -25,18 +25,18 @@ | |||
| 25 | /* | 25 | /* |
| 26 | * char *__strncpy_user(char *dst, const char *src, size_t len) | 26 | * char *__strncpy_user(char *dst, const char *src, size_t len) |
| 27 | */ | 27 | */ |
| 28 | .text | 28 | |
| 29 | .begin literal | 29 | #ifdef __XTENSA_EB__ |
| 30 | .align 4 | 30 | # define MASK0 0xff000000 |
| 31 | .Lmask0: | 31 | # define MASK1 0x00ff0000 |
| 32 | .byte 0xff, 0x00, 0x00, 0x00 | 32 | # define MASK2 0x0000ff00 |
| 33 | .Lmask1: | 33 | # define MASK3 0x000000ff |
| 34 | .byte 0x00, 0xff, 0x00, 0x00 | 34 | #else |
| 35 | .Lmask2: | 35 | # define MASK0 0x000000ff |
| 36 | .byte 0x00, 0x00, 0xff, 0x00 | 36 | # define MASK1 0x0000ff00 |
| 37 | .Lmask3: | 37 | # define MASK2 0x00ff0000 |
| 38 | .byte 0x00, 0x00, 0x00, 0xff | 38 | # define MASK3 0xff000000 |
| 39 | .end literal | 39 | #endif |
| 40 | 40 | ||
| 41 | # Register use | 41 | # Register use |
| 42 | # a0/ return address | 42 | # a0/ return address |
| @@ -53,6 +53,7 @@ | |||
| 53 | # a11/ dst | 53 | # a11/ dst |
| 54 | # a12/ tmp | 54 | # a12/ tmp |
| 55 | 55 | ||
| 56 | .text | ||
| 56 | .align 4 | 57 | .align 4 |
| 57 | .global __strncpy_user | 58 | .global __strncpy_user |
| 58 | .type __strncpy_user,@function | 59 | .type __strncpy_user,@function |
| @@ -61,10 +62,10 @@ __strncpy_user: | |||
| 61 | # a2/ dst, a3/ src, a4/ len | 62 | # a2/ dst, a3/ src, a4/ len |
| 62 | mov a11, a2 # leave dst in return value register | 63 | mov a11, a2 # leave dst in return value register |
| 63 | beqz a4, .Lret # if len is zero | 64 | beqz a4, .Lret # if len is zero |
| 64 | l32r a5, .Lmask0 # mask for byte 0 | 65 | movi a5, MASK0 # mask for byte 0 |
| 65 | l32r a6, .Lmask1 # mask for byte 1 | 66 | movi a6, MASK1 # mask for byte 1 |
| 66 | l32r a7, .Lmask2 # mask for byte 2 | 67 | movi a7, MASK2 # mask for byte 2 |
| 67 | l32r a8, .Lmask3 # mask for byte 3 | 68 | movi a8, MASK3 # mask for byte 3 |
| 68 | bbsi.l a3, 0, .Lsrc1mod2 # if only 8-bit aligned | 69 | bbsi.l a3, 0, .Lsrc1mod2 # if only 8-bit aligned |
| 69 | bbsi.l a3, 1, .Lsrc2mod4 # if only 16-bit aligned | 70 | bbsi.l a3, 1, .Lsrc2mod4 # if only 16-bit aligned |
| 70 | .Lsrcaligned: # return here when src is word-aligned | 71 | .Lsrcaligned: # return here when src is word-aligned |
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S index 5e9c1e709b2e..ad3f616322ca 100644 --- a/arch/xtensa/lib/strnlen_user.S +++ b/arch/xtensa/lib/strnlen_user.S | |||
| @@ -24,18 +24,18 @@ | |||
| 24 | /* | 24 | /* |
| 25 | * size_t __strnlen_user(const char *s, size_t len) | 25 | * size_t __strnlen_user(const char *s, size_t len) |
| 26 | */ | 26 | */ |
| 27 | .text | 27 | |
| 28 | .begin literal | 28 | #ifdef __XTENSA_EB__ |
| 29 | .align 4 | 29 | # define MASK0 0xff000000 |
| 30 | .Lmask0: | 30 | # define MASK1 0x00ff0000 |
| 31 | .byte 0xff, 0x00, 0x00, 0x00 | 31 | # define MASK2 0x0000ff00 |
| 32 | .Lmask1: | 32 | # define MASK3 0x000000ff |
| 33 | .byte 0x00, 0xff, 0x00, 0x00 | 33 | #else |
| 34 | .Lmask2: | 34 | # define MASK0 0x000000ff |
| 35 | .byte 0x00, 0x00, 0xff, 0x00 | 35 | # define MASK1 0x0000ff00 |
| 36 | .Lmask3: | 36 | # define MASK2 0x00ff0000 |
| 37 | .byte 0x00, 0x00, 0x00, 0xff | 37 | # define MASK3 0xff000000 |
| 38 | .end literal | 38 | #endif |
| 39 | 39 | ||
| 40 | # Register use: | 40 | # Register use: |
| 41 | # a2/ src | 41 | # a2/ src |
| @@ -48,6 +48,7 @@ | |||
| 48 | # a9/ tmp | 48 | # a9/ tmp |
| 49 | # a10/ tmp | 49 | # a10/ tmp |
| 50 | 50 | ||
| 51 | .text | ||
| 51 | .align 4 | 52 | .align 4 |
| 52 | .global __strnlen_user | 53 | .global __strnlen_user |
| 53 | .type __strnlen_user,@function | 54 | .type __strnlen_user,@function |
| @@ -56,10 +57,10 @@ __strnlen_user: | |||
| 56 | # a2/ s, a3/ len | 57 | # a2/ s, a3/ len |
| 57 | addi a4, a2, -4 # because we overincrement at the end; | 58 | addi a4, a2, -4 # because we overincrement at the end; |
| 58 | # we compensate with load offsets of 4 | 59 | # we compensate with load offsets of 4 |
| 59 | l32r a5, .Lmask0 # mask for byte 0 | 60 | movi a5, MASK0 # mask for byte 0 |
| 60 | l32r a6, .Lmask1 # mask for byte 1 | 61 | movi a6, MASK1 # mask for byte 1 |
| 61 | l32r a7, .Lmask2 # mask for byte 2 | 62 | movi a7, MASK2 # mask for byte 2 |
| 62 | l32r a8, .Lmask3 # mask for byte 3 | 63 | movi a8, MASK3 # mask for byte 3 |
| 63 | bbsi.l a2, 0, .L1mod2 # if only 8-bit aligned | 64 | bbsi.l a2, 0, .L1mod2 # if only 8-bit aligned |
| 64 | bbsi.l a2, 1, .L2mod4 # if only 16-bit aligned | 65 | bbsi.l a2, 1, .L2mod4 # if only 16-bit aligned |
| 65 | 66 | ||
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index e1ec2d1e8189..8415c76f11c2 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
| @@ -205,7 +205,7 @@ void __init init_mmu (void) | |||
| 205 | /* Writing zeros to the <t>TLBCFG special registers ensure | 205 | /* Writing zeros to the <t>TLBCFG special registers ensure |
| 206 | * that valid values exist in the register. For existing | 206 | * that valid values exist in the register. For existing |
| 207 | * PGSZID<w> fields, zero selects the first element of the | 207 | * PGSZID<w> fields, zero selects the first element of the |
| 208 | * page-size array. For nonexistant PGSZID<w> fields, zero is | 208 | * page-size array. For nonexistent PGSZID<w> fields, zero is |
| 209 | * the best value to write. Also, when changing PGSZID<w> | 209 | * the best value to write. Also, when changing PGSZID<w> |
| 210 | * fields, the corresponding TLB must be flushed. | 210 | * fields, the corresponding TLB must be flushed. |
| 211 | */ | 211 | */ |
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c index 4bfe333be229..f09962fa98c0 100644 --- a/arch/xtensa/platform-iss/network.c +++ b/arch/xtensa/platform-iss/network.c | |||
| @@ -473,7 +473,7 @@ static int iss_net_open(struct net_device *dev) | |||
| 473 | netif_start_queue(dev); | 473 | netif_start_queue(dev); |
| 474 | 474 | ||
| 475 | /* clear buffer - it can happen that the host side of the interface | 475 | /* clear buffer - it can happen that the host side of the interface |
| 476 | * is full when we gethere. In this case, new data is never queued, | 476 | * is full when we get here. In this case, new data is never queued, |
| 477 | * SIGIOs never arrive, and the net never works. | 477 | * SIGIOs never arrive, and the net never works. |
| 478 | */ | 478 | */ |
| 479 | while ((err = iss_net_rx(dev)) > 0) | 479 | while ((err = iss_net_rx(dev)) > 0) |
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h index d815649617aa..1c1e0d933eea 100644 --- a/include/asm-xtensa/bitops.h +++ b/include/asm-xtensa/bitops.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * License. See the file "COPYING" in the main directory of this archive | 7 | * License. See the file "COPYING" in the main directory of this archive |
| 8 | * for more details. | 8 | * for more details. |
| 9 | * | 9 | * |
| 10 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 10 | * Copyright (C) 2001 - 2007 Tensilica Inc. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #ifndef _XTENSA_BITOPS_H | 13 | #ifndef _XTENSA_BITOPS_H |
| @@ -31,53 +31,30 @@ | |||
| 31 | 31 | ||
| 32 | #if XCHAL_HAVE_NSA | 32 | #if XCHAL_HAVE_NSA |
| 33 | 33 | ||
| 34 | static __inline__ int __cntlz (unsigned long x) | 34 | static inline unsigned long __cntlz (unsigned long x) |
| 35 | { | 35 | { |
| 36 | int lz; | 36 | int lz; |
| 37 | asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); | 37 | asm ("nsau %0, %1" : "=r" (lz) : "r" (x)); |
| 38 | return 31 - lz; | 38 | return lz; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | #else | ||
| 42 | |||
| 43 | static __inline__ int __cntlz (unsigned long x) | ||
| 44 | { | ||
| 45 | unsigned long sum, x1, x2, x4, x8, x16; | ||
| 46 | x1 = x & 0xAAAAAAAA; | ||
| 47 | x2 = x & 0xCCCCCCCC; | ||
| 48 | x4 = x & 0xF0F0F0F0; | ||
| 49 | x8 = x & 0xFF00FF00; | ||
| 50 | x16 = x & 0xFFFF0000; | ||
| 51 | sum = x2 ? 2 : 0; | ||
| 52 | sum += (x16 != 0) * 16; | ||
| 53 | sum += (x8 != 0) * 8; | ||
| 54 | sum += (x4 != 0) * 4; | ||
| 55 | sum += (x1 != 0); | ||
| 56 | |||
| 57 | return sum; | ||
| 58 | } | ||
| 59 | |||
| 60 | #endif | ||
| 61 | |||
| 62 | /* | 41 | /* |
| 63 | * ffz: Find first zero in word. Undefined if no zero exists. | 42 | * ffz: Find first zero in word. Undefined if no zero exists. |
| 64 | * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). | 43 | * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). |
| 65 | */ | 44 | */ |
| 66 | 45 | ||
| 67 | static __inline__ int ffz(unsigned long x) | 46 | static inline int ffz(unsigned long x) |
| 68 | { | 47 | { |
| 69 | if ((x = ~x) == 0) | 48 | return 31 - __cntlz(~x & -~x); |
| 70 | return 32; | ||
| 71 | return __cntlz(x & -x); | ||
| 72 | } | 49 | } |
| 73 | 50 | ||
| 74 | /* | 51 | /* |
| 75 | * __ffs: Find first bit set in word. Return 0 for bit 0 | 52 | * __ffs: Find first bit set in word. Return 0 for bit 0 |
| 76 | */ | 53 | */ |
| 77 | 54 | ||
| 78 | static __inline__ int __ffs(unsigned long x) | 55 | static inline int __ffs(unsigned long x) |
| 79 | { | 56 | { |
| 80 | return __cntlz(x & -x); | 57 | return 31 - __cntlz(x & -x); |
| 81 | } | 58 | } |
| 82 | 59 | ||
| 83 | /* | 60 | /* |
| @@ -86,9 +63,9 @@ static __inline__ int __ffs(unsigned long x) | |||
| 86 | * differs in spirit from the above ffz (man ffs). | 63 | * differs in spirit from the above ffz (man ffs). |
| 87 | */ | 64 | */ |
| 88 | 65 | ||
| 89 | static __inline__ int ffs(unsigned long x) | 66 | static inline int ffs(unsigned long x) |
| 90 | { | 67 | { |
| 91 | return __cntlz(x & -x) + 1; | 68 | return 32 - __cntlz(x & -x); |
| 92 | } | 69 | } |
| 93 | 70 | ||
| 94 | /* | 71 | /* |
| @@ -96,20 +73,36 @@ static __inline__ int ffs(unsigned long x) | |||
| 96 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. | 73 | * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. |
| 97 | */ | 74 | */ |
| 98 | 75 | ||
| 99 | static __inline__ int fls (unsigned int x) | 76 | static inline int fls (unsigned int x) |
| 100 | { | 77 | { |
| 101 | return __cntlz(x); | 78 | return 32 - __cntlz(x); |
| 102 | } | 79 | } |
| 80 | |||
| 81 | #else | ||
| 82 | |||
| 83 | /* Use the generic implementation if we don't have the nsa/nsau instructions. */ | ||
| 84 | |||
| 85 | # include <asm-generic/bitops/ffs.h> | ||
| 86 | # include <asm-generic/bitops/__ffs.h> | ||
| 87 | # include <asm-generic/bitops/ffz.h> | ||
| 88 | # include <asm-generic/bitops/fls.h> | ||
| 89 | |||
| 90 | #endif | ||
| 91 | |||
| 103 | #include <asm-generic/bitops/fls64.h> | 92 | #include <asm-generic/bitops/fls64.h> |
| 104 | #include <asm-generic/bitops/find.h> | 93 | #include <asm-generic/bitops/find.h> |
| 105 | #include <asm-generic/bitops/ext2-non-atomic.h> | 94 | #include <asm-generic/bitops/ext2-non-atomic.h> |
| 106 | 95 | ||
| 107 | #ifdef __XTENSA_EL__ | 96 | #ifdef __XTENSA_EL__ |
| 108 | # define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr)) | 97 | # define ext2_set_bit_atomic(lock,nr,addr) \ |
| 109 | # define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr)) | 98 | test_and_set_bit((nr), (unsigned long*)(addr)) |
| 99 | # define ext2_clear_bit_atomic(lock,nr,addr) \ | ||
| 100 | test_and_clear_bit((nr), (unsigned long*)(addr)) | ||
| 110 | #elif defined(__XTENSA_EB__) | 101 | #elif defined(__XTENSA_EB__) |
| 111 | # define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr)) | 102 | # define ext2_set_bit_atomic(lock,nr,addr) \ |
| 112 | # define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr)) | 103 | test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr)) |
| 104 | # define ext2_clear_bit_atomic(lock,nr,addr) \ | ||
| 105 | test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr)) | ||
| 113 | #else | 106 | #else |
| 114 | # error processor byte order undefined! | 107 | # error processor byte order undefined! |
| 115 | #endif | 108 | #endif |
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h index 0f540a5f4c01..765edf17a9a4 100644 --- a/include/asm-xtensa/byteorder.h +++ b/include/asm-xtensa/byteorder.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #define _XTENSA_BYTEORDER_H | 12 | #define _XTENSA_BYTEORDER_H |
| 13 | 13 | ||
| 14 | #include <asm/types.h> | 14 | #include <asm/types.h> |
| 15 | #include <linux/compiler.h> | ||
| 15 | 16 | ||
| 16 | static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) | 17 | static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) |
| 17 | { | 18 | { |
| @@ -78,4 +79,4 @@ static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) | |||
| 78 | # error processor byte order undefined! | 79 | # error processor byte order undefined! |
| 79 | #endif | 80 | #endif |
| 80 | 81 | ||
| 81 | #endif /* __ASM_XTENSA_BYTEORDER_H */ | 82 | #endif /* _XTENSA_BYTEORDER_H */ |
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h index bd09ec02d57f..aa2121034558 100644 --- a/include/asm-xtensa/coprocessor.h +++ b/include/asm-xtensa/coprocessor.h | |||
| @@ -64,6 +64,7 @@ typedef struct { | |||
| 64 | # define COPROCESSOR_INFO_SIZE 8 | 64 | # define COPROCESSOR_INFO_SIZE 8 |
| 65 | # endif | 65 | # endif |
| 66 | #endif | 66 | #endif |
| 67 | #endif /* XCHAL_HAVE_CP */ | ||
| 67 | 68 | ||
| 68 | 69 | ||
| 69 | #ifndef __ASSEMBLY__ | 70 | #ifndef __ASSEMBLY__ |
| @@ -74,8 +75,11 @@ extern void save_coprocessor_registers(void*, int); | |||
| 74 | # else | 75 | # else |
| 75 | # define release_coprocessors(task) | 76 | # define release_coprocessors(task) |
| 76 | # endif | 77 | # endif |
| 77 | #endif | ||
| 78 | 78 | ||
| 79 | #endif | 79 | typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE] |
| 80 | __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN))); | ||
| 81 | |||
| 82 | #endif /* !__ASSEMBLY__ */ | ||
| 83 | |||
| 80 | 84 | ||
| 81 | #endif /* _XTENSA_COPROCESSOR_H */ | 85 | #endif /* _XTENSA_COPROCESSOR_H */ |
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h index 20965e3af1dd..f35678cb0a9b 100644 --- a/include/asm-xtensa/div64.h +++ b/include/asm-xtensa/div64.h | |||
| @@ -5,21 +5,12 @@ | |||
| 5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
| 6 | * for more details. | 6 | * for more details. |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 8 | * Copyright (C) 2001 - 2007 Tensilica Inc. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #ifndef _XTENSA_DIV64_H | 11 | #ifndef _XTENSA_DIV64_H |
| 12 | #define _XTENSA_DIV64_H | 12 | #define _XTENSA_DIV64_H |
| 13 | 13 | ||
| 14 | #include <linux/types.h> | 14 | #include <asm-generic/div64.h> |
| 15 | 15 | ||
| 16 | #define do_div(n,base) ({ \ | 16 | #endif /* _XTENSA_DIV64_H */ |
| 17 | int __res = n % ((unsigned int) base); \ | ||
| 18 | n /= (unsigned int) base; \ | ||
| 19 | __res; }) | ||
| 20 | |||
| 21 | static inline uint64_t div64_64(uint64_t dividend, uint64_t divisor) | ||
| 22 | { | ||
| 23 | return dividend / divisor; | ||
| 24 | } | ||
| 25 | #endif | ||
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h index f0f9fd8560a5..1569b53cec91 100644 --- a/include/asm-xtensa/elf.h +++ b/include/asm-xtensa/elf.h | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #ifndef _XTENSA_ELF_H | 13 | #ifndef _XTENSA_ELF_H |
| 14 | #define _XTENSA_ELF_H | 14 | #define _XTENSA_ELF_H |
| 15 | 15 | ||
| 16 | #include <asm/variant/core.h> | ||
| 17 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
| 18 | 17 | ||
| 19 | /* Xtensa processor ELF architecture-magic number */ | 18 | /* Xtensa processor ELF architecture-magic number */ |
| @@ -49,7 +48,7 @@ typedef struct { | |||
| 49 | elf_greg_t lcount; | 48 | elf_greg_t lcount; |
| 50 | elf_greg_t sar; | 49 | elf_greg_t sar; |
| 51 | elf_greg_t syscall; | 50 | elf_greg_t syscall; |
| 52 | elf_greg_t ar[XCHAL_NUM_AREGS]; | 51 | elf_greg_t ar[64]; |
| 53 | } xtensa_gregset_t; | 52 | } xtensa_gregset_t; |
| 54 | 53 | ||
| 55 | #define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t)) | 54 | #define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t)) |
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h index 0609fc691b72..46ab12db5739 100644 --- a/include/asm-xtensa/fcntl.h +++ b/include/asm-xtensa/fcntl.h | |||
| @@ -1,99 +1 @@ | |||
| 1 | /* | #include <asm-generic/fcntl.h> | |
| 2 | * include/asm-xtensa/fcntl.h | ||
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | * | ||
| 8 | * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle | ||
| 9 | * Copyright (C) 2001 - 2005 Tensilica Inc. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _XTENSA_FCNTL_H | ||
| 13 | #define _XTENSA_FCNTL_H | ||
| 14 | |||
| 15 | /* open/fcntl - O_SYNC is only implemented on blocks devices and on files | ||
| 16 | located on an ext2 file system */ | ||
| 17 | #define O_ACCMODE 0003 | ||
| 18 | #define O_RDONLY 00 | ||
| 19 | #define O_WRONLY 01 | ||
| 20 | #define O_RDWR 02 | ||
| 21 | #define O_CREAT 0100 /* not fcntl */ | ||
| 22 | #define O_EXCL 0200 /* not fcntl */ | ||
| 23 | #define O_NOCTTY 0400 /* not fcntl */ | ||
| 24 | #define O_TRUNC 01000 /* not fcntl */ | ||
| 25 | #define O_APPEND 02000 | ||
| 26 | #define O_NONBLOCK 04000 | ||
| 27 | #define O_NDELAY O_NONBLOCK | ||
| 28 | #define O_SYNC 010000 | ||
| 29 | #define FASYNC 020000 /* fcntl, for BSD compatibility */ | ||
| 30 | #define O_DIRECT 040000 /* direct disk access hint */ | ||
| 31 | #define O_LARGEFILE 0100000 | ||
| 32 | #define O_DIRECTORY 0200000 /* must be a directory */ | ||
| 33 | #define O_NOFOLLOW 0400000 /* don't follow links */ | ||
| 34 | #define O_NOATIME 01000000 | ||
| 35 | |||
| 36 | #define F_DUPFD 0 /* dup */ | ||
| 37 | #define F_GETFD 1 /* get close_on_exec */ | ||
| 38 | #define F_SETFD 2 /* set/clear close_on_exec */ | ||
| 39 | #define F_GETFL 3 /* get file->f_flags */ | ||
| 40 | #define F_SETFL 4 /* set file->f_flags */ | ||
| 41 | #define F_GETLK 5 | ||
| 42 | #define F_SETLK 6 | ||
| 43 | #define F_SETLKW 7 | ||
| 44 | |||
| 45 | #define F_SETOWN 8 /* for sockets. */ | ||
| 46 | #define F_GETOWN 9 /* for sockets. */ | ||
| 47 | #define F_SETSIG 10 /* for sockets. */ | ||
| 48 | #define F_GETSIG 11 /* for sockets. */ | ||
| 49 | |||
| 50 | #define F_GETLK64 12 /* using 'struct flock64' */ | ||
| 51 | #define F_SETLK64 13 | ||
| 52 | #define F_SETLKW64 14 | ||
| 53 | |||
| 54 | /* for F_[GET|SET]FL */ | ||
| 55 | #define FD_CLOEXEC 1 /* actually anything with low bit set goes */ | ||
| 56 | |||
| 57 | /* for posix fcntl() and lockf() */ | ||
| 58 | #define F_RDLCK 0 | ||
| 59 | #define F_WRLCK 1 | ||
| 60 | #define F_UNLCK 2 | ||
| 61 | |||
| 62 | /* for old implementation of bsd flock () */ | ||
| 63 | #define F_EXLCK 4 /* or 3 */ | ||
| 64 | #define F_SHLCK 8 /* or 4 */ | ||
| 65 | |||
| 66 | /* for leases */ | ||
| 67 | #define F_INPROGRESS 16 | ||
| 68 | |||
| 69 | /* operations for bsd flock(), also used by the kernel implementation */ | ||
| 70 | #define LOCK_SH 1 /* shared lock */ | ||
| 71 | #define LOCK_EX 2 /* exclusive lock */ | ||
| 72 | #define LOCK_NB 4 /* or'd with one of the above to prevent | ||
| 73 | blocking */ | ||
| 74 | #define LOCK_UN 8 /* remove lock */ | ||
| 75 | |||
| 76 | #define LOCK_MAND 32 /* This is a mandatory flock */ | ||
| 77 | #define LOCK_READ 64 /* ... Which allows concurrent read operations */ | ||
| 78 | #define LOCK_WRITE 128 /* ... Which allows concurrent write operations */ | ||
| 79 | #define LOCK_RW 192 /* ... Which allows concurrent read & write ops */ | ||
| 80 | |||
| 81 | struct flock { | ||
| 82 | short l_type; | ||
| 83 | short l_whence; | ||
| 84 | off_t l_start; | ||
| 85 | off_t l_len; | ||
| 86 | pid_t l_pid; | ||
| 87 | }; | ||
| 88 | |||
| 89 | struct flock64 { | ||
| 90 | short l_type; | ||
| 91 | short l_whence; | ||
| 92 | loff_t l_start; | ||
| 93 | loff_t l_len; | ||
| 94 | pid_t l_pid; | ||
| 95 | }; | ||
| 96 | |||
| 97 | #define F_LINUX_SPECIFIC_BASE 1024 | ||
| 98 | |||
| 99 | #endif /* _XTENSA_FCNTL_H */ | ||
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h index 92f948392ebc..c0fd8e5b4513 100644 --- a/include/asm-xtensa/mmu_context.h +++ b/include/asm-xtensa/mmu_context.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #define _XTENSA_MMU_CONTEXT_H | 14 | #define _XTENSA_MMU_CONTEXT_H |
| 15 | 15 | ||
| 16 | #include <linux/stringify.h> | 16 | #include <linux/stringify.h> |
| 17 | #include <linux/sched.h> | ||
| 17 | 18 | ||
| 18 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
| 19 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h index c631d006194b..1213cde75438 100644 --- a/include/asm-xtensa/page.h +++ b/include/asm-xtensa/page.h | |||
| @@ -131,6 +131,6 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page); | |||
| 131 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ | 131 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ |
| 132 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | 132 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
| 133 | 133 | ||
| 134 | #endif /* __KERNEL__ */ | ||
| 135 | #include <asm-generic/memory_model.h> | 134 | #include <asm-generic/memory_model.h> |
| 135 | #endif /* __KERNEL__ */ | ||
| 136 | #endif /* _XTENSA_PAGE_H */ | 136 | #endif /* _XTENSA_PAGE_H */ |
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h index 6f281392e3f8..ce3a336cad07 100644 --- a/include/asm-xtensa/param.h +++ b/include/asm-xtensa/param.h | |||
| @@ -11,15 +11,13 @@ | |||
| 11 | #ifndef _XTENSA_PARAM_H | 11 | #ifndef _XTENSA_PARAM_H |
| 12 | #define _XTENSA_PARAM_H | 12 | #define _XTENSA_PARAM_H |
| 13 | 13 | ||
| 14 | #include <asm/variant/core.h> | ||
| 15 | |||
| 16 | #ifdef __KERNEL__ | 14 | #ifdef __KERNEL__ |
| 17 | # define HZ 100 /* internal timer frequency */ | 15 | # define HZ 100 /* internal timer frequency */ |
| 18 | # define USER_HZ 100 /* for user interfaces in "ticks" */ | 16 | # define USER_HZ 100 /* for user interfaces in "ticks" */ |
| 19 | # define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */ | 17 | # define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */ |
| 20 | #endif | 18 | #endif |
| 21 | 19 | ||
| 22 | #define EXEC_PAGESIZE (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE) | 20 | #define EXEC_PAGESIZE 4096 |
| 23 | 21 | ||
| 24 | #ifndef NGROUPS | 22 | #ifndef NGROUPS |
| 25 | #define NGROUPS 32 | 23 | #define NGROUPS 32 |
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h index 1b7fe363fad1..77ff02d307bb 100644 --- a/include/asm-xtensa/ptrace.h +++ b/include/asm-xtensa/ptrace.h | |||
| @@ -11,8 +11,6 @@ | |||
| 11 | #ifndef _XTENSA_PTRACE_H | 11 | #ifndef _XTENSA_PTRACE_H |
| 12 | #define _XTENSA_PTRACE_H | 12 | #define _XTENSA_PTRACE_H |
| 13 | 13 | ||
| 14 | #include <asm/variant/core.h> | ||
| 15 | |||
| 16 | /* | 14 | /* |
| 17 | * Kernel stack | 15 | * Kernel stack |
| 18 | * | 16 | * |
| @@ -101,7 +99,8 @@ struct pt_regs { | |||
| 101 | unsigned long windowbase; /* 48 */ | 99 | unsigned long windowbase; /* 48 */ |
| 102 | unsigned long windowstart; /* 52 */ | 100 | unsigned long windowstart; /* 52 */ |
| 103 | unsigned long syscall; /* 56 */ | 101 | unsigned long syscall; /* 56 */ |
| 104 | int reserved[2]; /* 64 */ | 102 | unsigned long icountlevel; /* 60 */ |
| 103 | int reserved[1]; /* 64 */ | ||
| 105 | 104 | ||
| 106 | /* Make sure the areg field is 16 bytes aligned. */ | 105 | /* Make sure the areg field is 16 bytes aligned. */ |
| 107 | int align[0] __attribute__ ((aligned(16))); | 106 | int align[0] __attribute__ ((aligned(16))); |
| @@ -113,6 +112,9 @@ struct pt_regs { | |||
| 113 | }; | 112 | }; |
| 114 | 113 | ||
| 115 | #ifdef __KERNEL__ | 114 | #ifdef __KERNEL__ |
| 115 | |||
| 116 | #include <asm/variant/core.h> | ||
| 117 | |||
| 116 | # define task_pt_regs(tsk) ((struct pt_regs*) \ | 118 | # define task_pt_regs(tsk) ((struct pt_regs*) \ |
| 117 | (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) | 119 | (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1) |
| 118 | # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) | 120 | # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) |
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h index d3b65bfa71c3..c8cc16c3da9e 100644 --- a/include/asm-xtensa/shmparam.h +++ b/include/asm-xtensa/shmparam.h | |||
| @@ -9,8 +9,6 @@ | |||
| 9 | #ifndef _XTENSA_SHMPARAM_H | 9 | #ifndef _XTENSA_SHMPARAM_H |
| 10 | #define _XTENSA_SHMPARAM_H | 10 | #define _XTENSA_SHMPARAM_H |
| 11 | 11 | ||
| 12 | #include <asm/processor.h> | ||
| 13 | |||
| 14 | /* | 12 | /* |
| 15 | * Xtensa can have variable size caches, and if | 13 | * Xtensa can have variable size caches, and if |
| 16 | * the size of single way is larger than the page size, | 14 | * the size of single way is larger than the page size, |
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h index a75177291418..e3381cee5059 100644 --- a/include/asm-xtensa/sigcontext.h +++ b/include/asm-xtensa/sigcontext.h | |||
| @@ -5,21 +5,12 @@ | |||
| 5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
| 6 | * for more details. | 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 | #ifndef _XTENSA_SIGCONTEXT_H | 11 | #ifndef _XTENSA_SIGCONTEXT_H |
| 12 | #define _XTENSA_SIGCONTEXT_H | 12 | #define _XTENSA_SIGCONTEXT_H |
| 13 | 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 | |||
| 23 | 14 | ||
| 24 | struct sigcontext { | 15 | struct sigcontext { |
| 25 | unsigned long oldmask; | 16 | unsigned long oldmask; |
| @@ -27,18 +18,13 @@ struct sigcontext { | |||
| 27 | /* CPU registers */ | 18 | /* CPU registers */ |
| 28 | unsigned long sc_pc; | 19 | unsigned long sc_pc; |
| 29 | unsigned long sc_ps; | 20 | unsigned long sc_ps; |
| 30 | unsigned long sc_wmask; | ||
| 31 | unsigned long sc_windowbase; | ||
| 32 | unsigned long sc_windowstart; | ||
| 33 | unsigned long sc_lbeg; | 21 | unsigned long sc_lbeg; |
| 34 | unsigned long sc_lend; | 22 | unsigned long sc_lend; |
| 35 | unsigned long sc_lcount; | 23 | unsigned long sc_lcount; |
| 36 | unsigned long sc_sar; | 24 | unsigned long sc_sar; |
| 37 | unsigned long sc_depc; | 25 | unsigned long sc_acclo; |
| 38 | unsigned long sc_dareg0; | 26 | unsigned long sc_acchi; |
| 39 | unsigned long sc_treg[4]; | 27 | unsigned long sc_a[16]; |
| 40 | unsigned long sc_areg[XCHAL_NUM_AREGS]; | ||
| 41 | struct _cpstate *sc_cpstate; | ||
| 42 | }; | 28 | }; |
| 43 | 29 | ||
| 44 | #endif /* __ASM_XTENSA_SIGCONTEXT_H */ | 30 | #endif /* _XTENSA_SIGCONTEXT_H */ |
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h index 5ae34ab71597..3fa29799b435 100644 --- a/include/asm-xtensa/thread_info.h +++ b/include/asm-xtensa/thread_info.h | |||
| @@ -116,6 +116,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 116 | #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ | 116 | #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ |
| 117 | #define TIF_IRET 5 /* return with iret */ | 117 | #define TIF_IRET 5 /* return with iret */ |
| 118 | #define TIF_MEMDIE 6 | 118 | #define TIF_MEMDIE 6 |
| 119 | #define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal() */ | ||
| 119 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 120 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
| 120 | 121 | ||
| 121 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 122 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
| @@ -125,6 +126,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 125 | #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) | 126 | #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) |
| 126 | #define _TIF_IRET (1<<TIF_IRET) | 127 | #define _TIF_IRET (1<<TIF_IRET) |
| 127 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 128 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
| 129 | #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) | ||
| 128 | 130 | ||
| 129 | #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ | 131 | #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ |
| 130 | #define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ | 132 | #define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ |
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h index 8a7fb6964ce1..9bd34024431c 100644 --- a/include/asm-xtensa/unistd.h +++ b/include/asm-xtensa/unistd.h | |||
| @@ -485,8 +485,8 @@ __SYSCALL(217, sys_sched_get_priority_min, 1) | |||
| 485 | __SYSCALL(218, sys_sched_rr_get_interval, 2) | 485 | __SYSCALL(218, sys_sched_rr_get_interval, 2) |
| 486 | #define __NR_sched_yield 219 | 486 | #define __NR_sched_yield 219 |
| 487 | __SYSCALL(219, sys_sched_yield, 0) | 487 | __SYSCALL(219, sys_sched_yield, 0) |
| 488 | #define __NR_sigreturn 222 | 488 | #define __NR_available222 222 |
| 489 | __SYSCALL(222, xtensa_sigreturn, 0) | 489 | __SYSCALL(222, sys_ni_syscall, 0) |
| 490 | 490 | ||
| 491 | /* Signal Handling */ | 491 | /* Signal Handling */ |
| 492 | 492 | ||
