diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-07 20:10:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-07 20:10:19 -0400 |
commit | c8d8170feb824875baf68f8aaecb181a6500ce81 (patch) | |
tree | fc215c0776597015cd7e02ef12e24fe60e74961e | |
parent | 34750bb15687fa03ba95a0ccb1307b0727bc308b (diff) | |
parent | df5e38703d647b160d7ba300b3d2fcb64a48549a (diff) |
Merge git://git.linux-xtensa.org/kernel/xtensa-feed
* git://git.linux-xtensa.org/kernel/xtensa-feed:
Xtensa: use asm-generic/fcntl.h
[XTENSA] Remove non-rt signal handling
[XTENSA] Move common sections into bss sections
[XTENSA] clean-up header files
[XTENSA] Use generic 64-bit division
[XTENSA] Remove multi-exported symbols from xtensa_ksyms.c
[XTENSA] fix sources using deprecated assembler directive
[XTENSA] Spelling fixes in arch/xtensa
[XTENSA] fix bit operations in bitops.h
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 | ||