diff options
Diffstat (limited to 'arch/mips/kernel')
29 files changed, 616 insertions, 719 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 1bf2c8448912..49246264cc7c 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -53,9 +53,9 @@ obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o | |||
53 | obj-$(CONFIG_32BIT) += scall32-o32.o | 53 | obj-$(CONFIG_32BIT) += scall32-o32.o |
54 | obj-$(CONFIG_64BIT) += scall64-64.o | 54 | obj-$(CONFIG_64BIT) += scall64-64.o |
55 | obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o | 55 | obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o |
56 | obj-$(CONFIG_MIPS32_COMPAT) += linux32.o signal32.o | 56 | obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o |
57 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o | 57 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o |
58 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o | 58 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o |
59 | 59 | ||
60 | obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o | 60 | obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o |
61 | obj-$(CONFIG_PROC_FS) += proc.o | 61 | obj-$(CONFIG_PROC_FS) += proc.o |
@@ -65,7 +65,6 @@ obj-$(CONFIG_64BIT) += cpu-bugs64.o | |||
65 | obj-$(CONFIG_I8253) += i8253.o | 65 | obj-$(CONFIG_I8253) += i8253.o |
66 | 66 | ||
67 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 67 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
68 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | ||
68 | 69 | ||
69 | CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) | 70 | CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) |
70 | |||
71 | EXTRA_AFLAGS := $(CFLAGS) | ||
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index c0b089d47181..761a779d5c4f 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c | |||
@@ -64,6 +64,9 @@ void output_ptreg_defines(void) | |||
64 | offset("#define PT_R31 ", struct pt_regs, regs[31]); | 64 | offset("#define PT_R31 ", struct pt_regs, regs[31]); |
65 | offset("#define PT_LO ", struct pt_regs, lo); | 65 | offset("#define PT_LO ", struct pt_regs, lo); |
66 | offset("#define PT_HI ", struct pt_regs, hi); | 66 | offset("#define PT_HI ", struct pt_regs, hi); |
67 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | ||
68 | offset("#define PT_ACX ", struct pt_regs, acx); | ||
69 | #endif | ||
67 | offset("#define PT_EPC ", struct pt_regs, cp0_epc); | 70 | offset("#define PT_EPC ", struct pt_regs, cp0_epc); |
68 | offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); | 71 | offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); |
69 | offset("#define PT_STATUS ", struct pt_regs, cp0_status); | 72 | offset("#define PT_STATUS ", struct pt_regs, cp0_status); |
@@ -99,7 +102,6 @@ void output_thread_info_defines(void) | |||
99 | offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); | 102 | offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); |
100 | offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); | 103 | offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); |
101 | offset("#define TI_REGS ", struct thread_info, regs); | 104 | offset("#define TI_REGS ", struct thread_info, regs); |
102 | constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER); | ||
103 | constant("#define _THREAD_SIZE ", THREAD_SIZE); | 105 | constant("#define _THREAD_SIZE ", THREAD_SIZE); |
104 | constant("#define _THREAD_MASK ", THREAD_MASK); | 106 | constant("#define _THREAD_MASK ", THREAD_MASK); |
105 | linefeed; | 107 | linefeed; |
@@ -246,6 +248,7 @@ void output_sc_defines(void) | |||
246 | text("/* Linux sigcontext offsets. */"); | 248 | text("/* Linux sigcontext offsets. */"); |
247 | offset("#define SC_REGS ", struct sigcontext, sc_regs); | 249 | offset("#define SC_REGS ", struct sigcontext, sc_regs); |
248 | offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); | 250 | offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); |
251 | offset("#define SC_ACX ", struct sigcontext, sc_acx); | ||
249 | offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); | 252 | offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); |
250 | offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); | 253 | offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); |
251 | offset("#define SC_PC ", struct sigcontext, sc_pc); | 254 | offset("#define SC_PC ", struct sigcontext, sc_pc); |
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f59ef271d247..ab755ea26c6a 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/ptrace.h> | 16 | #include <linux/ptrace.h> |
17 | #include <linux/stddef.h> | 17 | #include <linux/stddef.h> |
18 | 18 | ||
19 | #include <asm/bugs.h> | ||
19 | #include <asm/cpu.h> | 20 | #include <asm/cpu.h> |
20 | #include <asm/fpu.h> | 21 | #include <asm/fpu.h> |
21 | #include <asm/mipsregs.h> | 22 | #include <asm/mipsregs.h> |
@@ -97,7 +98,7 @@ static void au1k_wait(void) | |||
97 | 98 | ||
98 | static int __initdata nowait = 0; | 99 | static int __initdata nowait = 0; |
99 | 100 | ||
100 | int __init wait_disable(char *s) | 101 | static int __init wait_disable(char *s) |
101 | { | 102 | { |
102 | nowait = 1; | 103 | nowait = 1; |
103 | 104 | ||
diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c new file mode 100644 index 000000000000..304efdc5682f --- /dev/null +++ b/arch/mips/kernel/early_printk.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2002, 2003, 06, 07 Ralf Baechle (ralf@linux-mips.org) | ||
7 | * Copyright (C) 2007 MIPS Technologies, Inc. | ||
8 | * written by Ralf Baechle (ralf@linux-mips.org) | ||
9 | */ | ||
10 | #include <linux/console.h> | ||
11 | #include <linux/init.h> | ||
12 | |||
13 | extern void prom_putchar(char); | ||
14 | |||
15 | static void early_console_write(struct console *con, const char *s, unsigned n) | ||
16 | { | ||
17 | while (n-- && *s) { | ||
18 | if (*s == '\n') | ||
19 | prom_putchar('\r'); | ||
20 | prom_putchar(*s); | ||
21 | s++; | ||
22 | } | ||
23 | } | ||
24 | |||
25 | static struct console early_console = { | ||
26 | .name = "early", | ||
27 | .write = early_console_write, | ||
28 | .flags = CON_PRINTBUFFER | CON_BOOT, | ||
29 | .index = -1 | ||
30 | }; | ||
31 | |||
32 | void __init setup_early_printk(void) | ||
33 | { | ||
34 | register_console(&early_console); | ||
35 | } | ||
36 | |||
37 | void __init disable_early_printk(void) | ||
38 | { | ||
39 | unregister_console(&early_console); | ||
40 | } | ||
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 0b78fcbf044a..686249c5c328 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S | |||
@@ -121,7 +121,11 @@ FEXPORT(restore_partial) # restore partial frame | |||
121 | SAVE_AT | 121 | SAVE_AT |
122 | SAVE_TEMP | 122 | SAVE_TEMP |
123 | LONG_L v0, PT_STATUS(sp) | 123 | LONG_L v0, PT_STATUS(sp) |
124 | and v0, 1 | 124 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
125 | and v0, ST0_IEP | ||
126 | #else | ||
127 | and v0, ST0_IE | ||
128 | #endif | ||
125 | beqz v0, 1f | 129 | beqz v0, 1f |
126 | jal trace_hardirqs_on | 130 | jal trace_hardirqs_on |
127 | b 2f | 131 | b 2f |
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index aacd4a005c5f..297bd56c2347 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S | |||
@@ -128,6 +128,37 @@ handle_vcei: | |||
128 | 128 | ||
129 | .align 5 | 129 | .align 5 |
130 | NESTED(handle_int, PT_SIZE, sp) | 130 | NESTED(handle_int, PT_SIZE, sp) |
131 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
132 | /* | ||
133 | * Check to see if the interrupted code has just disabled | ||
134 | * interrupts and ignore this interrupt for now if so. | ||
135 | * | ||
136 | * local_irq_disable() disables interrupts and then calls | ||
137 | * trace_hardirqs_off() to track the state. If an interrupt is taken | ||
138 | * after interrupts are disabled but before the state is updated | ||
139 | * it will appear to restore_all that it is incorrectly returning with | ||
140 | * interrupts disabled | ||
141 | */ | ||
142 | .set push | ||
143 | .set noat | ||
144 | mfc0 k0, CP0_STATUS | ||
145 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | ||
146 | and k0, ST0_IEP | ||
147 | bnez k0, 1f | ||
148 | |||
149 | mfc0 k0, EP0_EPC | ||
150 | .set noreorder | ||
151 | j k0 | ||
152 | rfe | ||
153 | #else | ||
154 | and k0, ST0_IE | ||
155 | bnez k0, 1f | ||
156 | |||
157 | eret | ||
158 | #endif | ||
159 | 1: | ||
160 | .set pop | ||
161 | #endif | ||
131 | SAVE_ALL | 162 | SAVE_ALL |
132 | CLI | 163 | CLI |
133 | TRACE_IRQS_OFF | 164 | TRACE_IRQS_OFF |
@@ -181,13 +212,13 @@ NESTED(except_vec_vi, 0, sp) | |||
181 | * during service by SMTC kernel, we also want to | 212 | * during service by SMTC kernel, we also want to |
182 | * pass the IM value to be cleared. | 213 | * pass the IM value to be cleared. |
183 | */ | 214 | */ |
184 | EXPORT(except_vec_vi_mori) | 215 | FEXPORT(except_vec_vi_mori) |
185 | ori a0, $0, 0 | 216 | ori a0, $0, 0 |
186 | #endif /* CONFIG_MIPS_MT_SMTC */ | 217 | #endif /* CONFIG_MIPS_MT_SMTC */ |
187 | EXPORT(except_vec_vi_lui) | 218 | FEXPORT(except_vec_vi_lui) |
188 | lui v0, 0 /* Patched */ | 219 | lui v0, 0 /* Patched */ |
189 | j except_vec_vi_handler | 220 | j except_vec_vi_handler |
190 | EXPORT(except_vec_vi_ori) | 221 | FEXPORT(except_vec_vi_ori) |
191 | ori v0, 0 /* Patched */ | 222 | ori v0, 0 /* Patched */ |
192 | .set pop | 223 | .set pop |
193 | END(except_vec_vi) | 224 | END(except_vec_vi) |
@@ -220,7 +251,17 @@ NESTED(except_vec_vi_handler, 0, sp) | |||
220 | _ehb | 251 | _ehb |
221 | #endif /* CONFIG_MIPS_MT_SMTC */ | 252 | #endif /* CONFIG_MIPS_MT_SMTC */ |
222 | CLI | 253 | CLI |
254 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
255 | move s0, v0 | ||
256 | #ifdef CONFIG_MIPS_MT_SMTC | ||
257 | move s1, a0 | ||
258 | #endif | ||
223 | TRACE_IRQS_OFF | 259 | TRACE_IRQS_OFF |
260 | #ifdef CONFIG_MIPS_MT_SMTC | ||
261 | move a0, s1 | ||
262 | #endif | ||
263 | move v0, s0 | ||
264 | #endif | ||
224 | 265 | ||
225 | LONG_L s0, TI_REGS($28) | 266 | LONG_L s0, TI_REGS($28) |
226 | LONG_S sp, TI_REGS($28) | 267 | LONG_S sp, TI_REGS($28) |
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index b33ba6cd7f5b..2345160e63fc 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c | |||
@@ -28,7 +28,7 @@ | |||
28 | * moves to arch independent land | 28 | * moves to arch independent land |
29 | */ | 29 | */ |
30 | 30 | ||
31 | static int i8259A_auto_eoi; | 31 | static int i8259A_auto_eoi = -1; |
32 | DEFINE_SPINLOCK(i8259A_lock); | 32 | DEFINE_SPINLOCK(i8259A_lock); |
33 | /* some platforms call this... */ | 33 | /* some platforms call this... */ |
34 | void mask_and_ack_8259A(unsigned int); | 34 | void mask_and_ack_8259A(unsigned int); |
@@ -216,7 +216,8 @@ spurious_8259A_irq: | |||
216 | 216 | ||
217 | static int i8259A_resume(struct sys_device *dev) | 217 | static int i8259A_resume(struct sys_device *dev) |
218 | { | 218 | { |
219 | init_8259A(i8259A_auto_eoi); | 219 | if (i8259A_auto_eoi >= 0) |
220 | init_8259A(i8259A_auto_eoi); | ||
220 | return 0; | 221 | return 0; |
221 | } | 222 | } |
222 | 223 | ||
@@ -226,8 +227,10 @@ static int i8259A_shutdown(struct sys_device *dev) | |||
226 | * the kernel initialization code can get it | 227 | * the kernel initialization code can get it |
227 | * out of. | 228 | * out of. |
228 | */ | 229 | */ |
229 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 230 | if (i8259A_auto_eoi >= 0) { |
230 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ | 231 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
232 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ | ||
233 | } | ||
231 | return 0; | 234 | return 0; |
232 | } | 235 | } |
233 | 236 | ||
@@ -252,7 +255,7 @@ static int __init i8259A_init_sysfs(void) | |||
252 | 255 | ||
253 | device_initcall(i8259A_init_sysfs); | 256 | device_initcall(i8259A_init_sysfs); |
254 | 257 | ||
255 | void __init init_8259A(int auto_eoi) | 258 | void init_8259A(int auto_eoi) |
256 | { | 259 | { |
257 | unsigned long flags; | 260 | unsigned long flags; |
258 | 261 | ||
@@ -325,8 +328,8 @@ void __init init_i8259_irqs (void) | |||
325 | { | 328 | { |
326 | int i; | 329 | int i; |
327 | 330 | ||
328 | request_resource(&ioport_resource, &pic1_io_resource); | 331 | insert_resource(&ioport_resource, &pic1_io_resource); |
329 | request_resource(&ioport_resource, &pic2_io_resource); | 332 | insert_resource(&ioport_resource, &pic2_io_resource); |
330 | 333 | ||
331 | init_8259A(0); | 334 | init_8259A(0); |
332 | 335 | ||
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 5929f883e46b..c6580018c94b 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/sched.h> | ||
20 | #include <linux/unistd.h> | 21 | #include <linux/unistd.h> |
21 | #include <linux/file.h> | 22 | #include <linux/file.h> |
22 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
@@ -70,6 +71,7 @@ static int sp_stopping = 0; | |||
70 | #define MTSP_SYSCALL_GETTIME (MTSP_SYSCALL_BASE + 7) | 71 | #define MTSP_SYSCALL_GETTIME (MTSP_SYSCALL_BASE + 7) |
71 | #define MTSP_SYSCALL_PIPEFREQ (MTSP_SYSCALL_BASE + 8) | 72 | #define MTSP_SYSCALL_PIPEFREQ (MTSP_SYSCALL_BASE + 8) |
72 | #define MTSP_SYSCALL_GETTOD (MTSP_SYSCALL_BASE + 9) | 73 | #define MTSP_SYSCALL_GETTOD (MTSP_SYSCALL_BASE + 9) |
74 | #define MTSP_SYSCALL_IOCTL (MTSP_SYSCALL_BASE + 10) | ||
73 | 75 | ||
74 | #define MTSP_O_RDONLY 0x0000 | 76 | #define MTSP_O_RDONLY 0x0000 |
75 | #define MTSP_O_WRONLY 0x0001 | 77 | #define MTSP_O_WRONLY 0x0001 |
@@ -110,7 +112,8 @@ struct apsp_table syscall_command_table[] = { | |||
110 | { MTSP_SYSCALL_CLOSE, __NR_close }, | 112 | { MTSP_SYSCALL_CLOSE, __NR_close }, |
111 | { MTSP_SYSCALL_READ, __NR_read }, | 113 | { MTSP_SYSCALL_READ, __NR_read }, |
112 | { MTSP_SYSCALL_WRITE, __NR_write }, | 114 | { MTSP_SYSCALL_WRITE, __NR_write }, |
113 | { MTSP_SYSCALL_LSEEK32, __NR_lseek } | 115 | { MTSP_SYSCALL_LSEEK32, __NR_lseek }, |
116 | { MTSP_SYSCALL_IOCTL, __NR_ioctl } | ||
114 | }; | 117 | }; |
115 | 118 | ||
116 | static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3) | 119 | static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3) |
@@ -189,17 +192,22 @@ void sp_work_handle_request(void) | |||
189 | struct mtsp_syscall_generic generic; | 192 | struct mtsp_syscall_generic generic; |
190 | struct mtsp_syscall_ret ret; | 193 | struct mtsp_syscall_ret ret; |
191 | struct kspd_notifications *n; | 194 | struct kspd_notifications *n; |
195 | unsigned long written; | ||
196 | mm_segment_t old_fs; | ||
192 | struct timeval tv; | 197 | struct timeval tv; |
193 | struct timezone tz; | 198 | struct timezone tz; |
194 | int cmd; | 199 | int cmd; |
195 | 200 | ||
196 | char *vcwd; | 201 | char *vcwd; |
197 | mm_segment_t old_fs; | ||
198 | int size; | 202 | int size; |
199 | 203 | ||
200 | ret.retval = -1; | 204 | ret.retval = -1; |
201 | 205 | ||
202 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) { | 206 | old_fs = get_fs(); |
207 | set_fs(KERNEL_DS); | ||
208 | |||
209 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall))) { | ||
210 | set_fs(old_fs); | ||
203 | printk(KERN_ERR "Expected request but nothing to read\n"); | 211 | printk(KERN_ERR "Expected request but nothing to read\n"); |
204 | return; | 212 | return; |
205 | } | 213 | } |
@@ -207,7 +215,8 @@ void sp_work_handle_request(void) | |||
207 | size = sc.size; | 215 | size = sc.size; |
208 | 216 | ||
209 | if (size) { | 217 | if (size) { |
210 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) { | 218 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size)) { |
219 | set_fs(old_fs); | ||
211 | printk(KERN_ERR "Expected request but nothing to read\n"); | 220 | printk(KERN_ERR "Expected request but nothing to read\n"); |
212 | return; | 221 | return; |
213 | } | 222 | } |
@@ -232,8 +241,6 @@ void sp_work_handle_request(void) | |||
232 | if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv, | 241 | if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv, |
233 | (int)&tz, 0,0)) == 0) | 242 | (int)&tz, 0,0)) == 0) |
234 | ret.retval = tv.tv_sec; | 243 | ret.retval = tv.tv_sec; |
235 | |||
236 | ret.errno = errno; | ||
237 | break; | 244 | break; |
238 | 245 | ||
239 | case MTSP_SYSCALL_EXIT: | 246 | case MTSP_SYSCALL_EXIT: |
@@ -270,7 +277,6 @@ void sp_work_handle_request(void) | |||
270 | if (cmd >= 0) { | 277 | if (cmd >= 0) { |
271 | ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1, | 278 | ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1, |
272 | generic.arg2, generic.arg3); | 279 | generic.arg2, generic.arg3); |
273 | ret.errno = errno; | ||
274 | } else | 280 | } else |
275 | printk(KERN_WARNING | 281 | printk(KERN_WARNING |
276 | "KSPD: Unknown SP syscall number %d\n", sc.cmd); | 282 | "KSPD: Unknown SP syscall number %d\n", sc.cmd); |
@@ -280,8 +286,11 @@ void sp_work_handle_request(void) | |||
280 | if (vpe_getuid(SP_VPE)) | 286 | if (vpe_getuid(SP_VPE)) |
281 | sp_setfsuidgid( 0, 0); | 287 | sp_setfsuidgid( 0, 0); |
282 | 288 | ||
283 | if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0)) | 289 | old_fs = get_fs(); |
284 | < sizeof(struct mtsp_syscall_ret)) | 290 | set_fs(KERNEL_DS); |
291 | written = rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(ret)); | ||
292 | set_fs(old_fs); | ||
293 | if (written < sizeof(ret)) | ||
285 | printk("KSPD: sp_work_handle_request failed to send to SP\n"); | 294 | printk("KSPD: sp_work_handle_request failed to send to SP\n"); |
286 | } | 295 | } |
287 | 296 | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index fc4dd6c9dd80..37849edd0645 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -166,34 +166,6 @@ out: | |||
166 | return error; | 166 | return error; |
167 | } | 167 | } |
168 | 168 | ||
169 | asmlinkage long | ||
170 | sysn32_waitid(int which, compat_pid_t pid, | ||
171 | siginfo_t __user *uinfo, int options, | ||
172 | struct compat_rusage __user *uru) | ||
173 | { | ||
174 | struct rusage ru; | ||
175 | long ret; | ||
176 | mm_segment_t old_fs = get_fs(); | ||
177 | int si_signo; | ||
178 | |||
179 | if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo))) | ||
180 | return -EFAULT; | ||
181 | |||
182 | set_fs (KERNEL_DS); | ||
183 | ret = sys_waitid(which, pid, uinfo, options, | ||
184 | uru ? (struct rusage __user *) &ru : NULL); | ||
185 | set_fs (old_fs); | ||
186 | |||
187 | if (__get_user(si_signo, &uinfo->si_signo)) | ||
188 | return -EFAULT; | ||
189 | if (ret < 0 || si_signo == 0) | ||
190 | return ret; | ||
191 | |||
192 | if (uru) | ||
193 | ret = put_compat_rusage(&ru, uru); | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | #define RLIM_INFINITY32 0x7fffffff | 169 | #define RLIM_INFINITY32 0x7fffffff |
198 | #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) | 170 | #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) |
199 | 171 | ||
@@ -339,6 +311,8 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, | |||
339 | return ret; | 311 | return ret; |
340 | } | 312 | } |
341 | 313 | ||
314 | #ifdef CONFIG_SYSVIPC | ||
315 | |||
342 | asmlinkage long | 316 | asmlinkage long |
343 | sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) | 317 | sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) |
344 | { | 318 | { |
@@ -396,6 +370,16 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) | |||
396 | return err; | 370 | return err; |
397 | } | 371 | } |
398 | 372 | ||
373 | #else | ||
374 | |||
375 | asmlinkage long | ||
376 | sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) | ||
377 | { | ||
378 | return -ENOSYS; | ||
379 | } | ||
380 | |||
381 | #endif /* CONFIG_SYSVIPC */ | ||
382 | |||
399 | #ifdef CONFIG_MIPS32_N32 | 383 | #ifdef CONFIG_MIPS32_N32 |
400 | asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg) | 384 | asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg) |
401 | { | 385 | { |
@@ -572,151 +556,6 @@ asmlinkage long sys32_sync_file_range(int fd, int __pad, | |||
572 | flags); | 556 | flags); |
573 | } | 557 | } |
574 | 558 | ||
575 | /* Argument list sizes for sys_socketcall */ | ||
576 | #define AL(x) ((x) * sizeof(unsigned int)) | ||
577 | static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), | ||
578 | AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), | ||
579 | AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; | ||
580 | #undef AL | ||
581 | |||
582 | /* | ||
583 | * System call vectors. | ||
584 | * | ||
585 | * Argument checking cleaned up. Saved 20% in size. | ||
586 | * This function doesn't need to set the kernel lock because | ||
587 | * it is set by the callees. | ||
588 | */ | ||
589 | |||
590 | asmlinkage long sys32_socketcall(int call, unsigned int __user *args32) | ||
591 | { | ||
592 | unsigned int a[6]; | ||
593 | unsigned int a0,a1; | ||
594 | int err; | ||
595 | |||
596 | extern asmlinkage long sys_socket(int family, int type, int protocol); | ||
597 | extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); | ||
598 | extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen); | ||
599 | extern asmlinkage long sys_listen(int fd, int backlog); | ||
600 | extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen); | ||
601 | extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); | ||
602 | extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); | ||
603 | extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec); | ||
604 | extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags); | ||
605 | extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags, | ||
606 | struct sockaddr __user *addr, int addr_len); | ||
607 | extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags); | ||
608 | extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags, | ||
609 | struct sockaddr __user *addr, int __user *addr_len); | ||
610 | extern asmlinkage long sys_shutdown(int fd, int how); | ||
611 | extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen); | ||
612 | extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen); | ||
613 | extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); | ||
614 | extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags); | ||
615 | |||
616 | |||
617 | if(call<1||call>SYS_RECVMSG) | ||
618 | return -EINVAL; | ||
619 | |||
620 | /* copy_from_user should be SMP safe. */ | ||
621 | if (copy_from_user(a, args32, socketcall_nargs[call])) | ||
622 | return -EFAULT; | ||
623 | |||
624 | a0=a[0]; | ||
625 | a1=a[1]; | ||
626 | |||
627 | switch(call) | ||
628 | { | ||
629 | case SYS_SOCKET: | ||
630 | err = sys_socket(a0,a1,a[2]); | ||
631 | break; | ||
632 | case SYS_BIND: | ||
633 | err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]); | ||
634 | break; | ||
635 | case SYS_CONNECT: | ||
636 | err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]); | ||
637 | break; | ||
638 | case SYS_LISTEN: | ||
639 | err = sys_listen(a0,a1); | ||
640 | break; | ||
641 | case SYS_ACCEPT: | ||
642 | err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); | ||
643 | break; | ||
644 | case SYS_GETSOCKNAME: | ||
645 | err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); | ||
646 | break; | ||
647 | case SYS_GETPEERNAME: | ||
648 | err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2])); | ||
649 | break; | ||
650 | case SYS_SOCKETPAIR: | ||
651 | err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3])); | ||
652 | break; | ||
653 | case SYS_SEND: | ||
654 | err = sys_send(a0, (void __user *)A(a1), a[2], a[3]); | ||
655 | break; | ||
656 | case SYS_SENDTO: | ||
657 | err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3], | ||
658 | (struct sockaddr __user *)A(a[4]), a[5]); | ||
659 | break; | ||
660 | case SYS_RECV: | ||
661 | err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]); | ||
662 | break; | ||
663 | case SYS_RECVFROM: | ||
664 | err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3], | ||
665 | (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5])); | ||
666 | break; | ||
667 | case SYS_SHUTDOWN: | ||
668 | err = sys_shutdown(a0,a1); | ||
669 | break; | ||
670 | case SYS_SETSOCKOPT: | ||
671 | err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]); | ||
672 | break; | ||
673 | case SYS_GETSOCKOPT: | ||
674 | err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4])); | ||
675 | break; | ||
676 | case SYS_SENDMSG: | ||
677 | err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]); | ||
678 | break; | ||
679 | case SYS_RECVMSG: | ||
680 | err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]); | ||
681 | break; | ||
682 | default: | ||
683 | err = -EINVAL; | ||
684 | break; | ||
685 | } | ||
686 | return err; | ||
687 | } | ||
688 | |||
689 | struct sigevent32 { | ||
690 | u32 sigev_value; | ||
691 | u32 sigev_signo; | ||
692 | u32 sigev_notify; | ||
693 | u32 payload[(64 / 4) - 3]; | ||
694 | }; | ||
695 | |||
696 | extern asmlinkage long | ||
697 | sys_timer_create(clockid_t which_clock, | ||
698 | struct sigevent __user *timer_event_spec, | ||
699 | timer_t __user * created_timer_id); | ||
700 | |||
701 | long | ||
702 | sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id) | ||
703 | { | ||
704 | struct sigevent __user *p = NULL; | ||
705 | if (se32) { | ||
706 | struct sigevent se; | ||
707 | p = compat_alloc_user_space(sizeof(struct sigevent)); | ||
708 | memset(&se, 0, sizeof(struct sigevent)); | ||
709 | if (get_user(se.sigev_value.sival_int, &se32->sigev_value) || | ||
710 | __get_user(se.sigev_signo, &se32->sigev_signo) || | ||
711 | __get_user(se.sigev_notify, &se32->sigev_notify) || | ||
712 | __copy_from_user(&se._sigev_un._pad, &se32->payload, | ||
713 | sizeof(se32->payload)) || | ||
714 | copy_to_user(p, &se, sizeof(se))) | ||
715 | return -EFAULT; | ||
716 | } | ||
717 | return sys_timer_create(clock, p, timer_id); | ||
718 | } | ||
719 | |||
720 | save_static_function(sys32_clone); | 559 | save_static_function(sys32_clone); |
721 | __attribute_used__ noinline static int | 560 | __attribute_used__ noinline static int |
722 | _sys32_clone(nabi_no_regargs struct pt_regs regs) | 561 | _sys32_clone(nabi_no_regargs struct pt_regs regs) |
@@ -737,49 +576,3 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs) | |||
737 | return do_fork(clone_flags, newsp, ®s, 0, | 576 | return do_fork(clone_flags, newsp, ®s, 0, |
738 | parent_tidptr, child_tidptr); | 577 | parent_tidptr, child_tidptr); |
739 | } | 578 | } |
740 | |||
741 | /* | ||
742 | * Implement the event wait interface for the eventpoll file. It is the kernel | ||
743 | * part of the user space epoll_pwait(2). | ||
744 | */ | ||
745 | asmlinkage long compat_sys_epoll_pwait(int epfd, | ||
746 | struct epoll_event __user *events, int maxevents, int timeout, | ||
747 | const compat_sigset_t __user *sigmask, size_t sigsetsize) | ||
748 | { | ||
749 | int error; | ||
750 | sigset_t ksigmask, sigsaved; | ||
751 | |||
752 | /* | ||
753 | * If the caller wants a certain signal mask to be set during the wait, | ||
754 | * we apply it here. | ||
755 | */ | ||
756 | if (sigmask) { | ||
757 | if (sigsetsize != sizeof(sigset_t)) | ||
758 | return -EINVAL; | ||
759 | if (!access_ok(VERIFY_READ, sigmask, sizeof(ksigmask))) | ||
760 | return -EFAULT; | ||
761 | if (__copy_conv_sigset_from_user(&ksigmask, sigmask)) | ||
762 | return -EFAULT; | ||
763 | sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP)); | ||
764 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | ||
765 | } | ||
766 | |||
767 | error = sys_epoll_wait(epfd, events, maxevents, timeout); | ||
768 | |||
769 | /* | ||
770 | * If we changed the signal mask, we need to restore the original one. | ||
771 | * In case we've got a signal while waiting, we do not restore the | ||
772 | * signal mask yet, and we allow do_signal() to deliver the signal on | ||
773 | * the way back to userspace, before the signal mask is restored. | ||
774 | */ | ||
775 | if (sigmask) { | ||
776 | if (error == -EINTR) { | ||
777 | memcpy(¤t->saved_sigmask, &sigsaved, | ||
778 | sizeof(sigsaved)); | ||
779 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
780 | } else | ||
781 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); | ||
782 | } | ||
783 | |||
784 | return error; | ||
785 | } | ||
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c index e0ad754c7edd..8f42fa85ac9e 100644 --- a/arch/mips/kernel/machine_kexec.c +++ b/arch/mips/kernel/machine_kexec.c | |||
@@ -13,8 +13,8 @@ | |||
13 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
14 | #include <asm/page.h> | 14 | #include <asm/page.h> |
15 | 15 | ||
16 | const extern unsigned char relocate_new_kernel[]; | 16 | extern const unsigned char relocate_new_kernel[]; |
17 | const extern unsigned int relocate_new_kernel_size; | 17 | extern const unsigned int relocate_new_kernel_size; |
18 | 18 | ||
19 | extern unsigned long kexec_start_address; | 19 | extern unsigned long kexec_start_address; |
20 | extern unsigned long kexec_indirection_page; | 20 | extern unsigned long kexec_indirection_page; |
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 2ef857c3ee53..225755d0c1f6 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c | |||
@@ -37,6 +37,7 @@ EXPORT_SYMBOL(kernel_thread); | |||
37 | * Userspace access stuff. | 37 | * Userspace access stuff. |
38 | */ | 38 | */ |
39 | EXPORT_SYMBOL(__copy_user); | 39 | EXPORT_SYMBOL(__copy_user); |
40 | EXPORT_SYMBOL(__copy_user_inatomic); | ||
40 | EXPORT_SYMBOL(__bzero); | 41 | EXPORT_SYMBOL(__bzero); |
41 | EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); | 42 | EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm); |
42 | EXPORT_SYMBOL(__strncpy_from_user_asm); | 43 | EXPORT_SYMBOL(__strncpy_from_user_asm); |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 04e5b38d327d..6bdfb5a9fa1a 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/completion.h> | 26 | #include <linux/completion.h> |
27 | #include <linux/kallsyms.h> | 27 | #include <linux/kallsyms.h> |
28 | 28 | ||
29 | #include <asm/abi.h> | ||
30 | #include <asm/bootinfo.h> | 29 | #include <asm/bootinfo.h> |
31 | #include <asm/cpu.h> | 30 | #include <asm/cpu.h> |
32 | #include <asm/dsp.h> | 31 | #include <asm/dsp.h> |
@@ -52,11 +51,11 @@ ATTRIB_NORET void cpu_idle(void) | |||
52 | /* endless idle loop with no priority at all */ | 51 | /* endless idle loop with no priority at all */ |
53 | while (1) { | 52 | while (1) { |
54 | while (!need_resched()) { | 53 | while (!need_resched()) { |
55 | #ifdef CONFIG_MIPS_MT_SMTC | 54 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
56 | extern void smtc_idle_loop_hook(void); | 55 | extern void smtc_idle_loop_hook(void); |
57 | 56 | ||
58 | smtc_idle_loop_hook(); | 57 | smtc_idle_loop_hook(); |
59 | #endif /* CONFIG_MIPS_MT_SMTC */ | 58 | #endif |
60 | if (cpu_wait) | 59 | if (cpu_wait) |
61 | (*cpu_wait)(); | 60 | (*cpu_wait)(); |
62 | } | 61 | } |
@@ -66,38 +65,6 @@ ATTRIB_NORET void cpu_idle(void) | |||
66 | } | 65 | } |
67 | } | 66 | } |
68 | 67 | ||
69 | /* | ||
70 | * Native o32 and N64 ABI without DSP ASE | ||
71 | */ | ||
72 | struct mips_abi mips_abi = { | ||
73 | .do_signal = do_signal, | ||
74 | #ifdef CONFIG_TRAD_SIGNALS | ||
75 | .setup_frame = setup_frame, | ||
76 | #endif | ||
77 | .setup_rt_frame = setup_rt_frame | ||
78 | }; | ||
79 | |||
80 | #ifdef CONFIG_MIPS32_O32 | ||
81 | /* | ||
82 | * o32 compatibility on 64-bit kernels, without DSP ASE | ||
83 | */ | ||
84 | struct mips_abi mips_abi_32 = { | ||
85 | .do_signal = do_signal32, | ||
86 | .setup_frame = setup_frame_32, | ||
87 | .setup_rt_frame = setup_rt_frame_32 | ||
88 | }; | ||
89 | #endif /* CONFIG_MIPS32_O32 */ | ||
90 | |||
91 | #ifdef CONFIG_MIPS32_N32 | ||
92 | /* | ||
93 | * N32 on 64-bit kernels, without DSP ASE | ||
94 | */ | ||
95 | struct mips_abi mips_abi_n32 = { | ||
96 | .do_signal = do_signal, | ||
97 | .setup_rt_frame = setup_rt_frame_n32 | ||
98 | }; | ||
99 | #endif /* CONFIG_MIPS32_N32 */ | ||
100 | |||
101 | asmlinkage void ret_from_fork(void); | 68 | asmlinkage void ret_from_fork(void); |
102 | 69 | ||
103 | void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) | 70 | void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) |
@@ -246,7 +213,7 @@ int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr) | |||
246 | /* | 213 | /* |
247 | * Create a kernel thread | 214 | * Create a kernel thread |
248 | */ | 215 | */ |
249 | ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) | 216 | static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) |
250 | { | 217 | { |
251 | do_exit(fn(arg)); | 218 | do_exit(fn(arg)); |
252 | } | 219 | } |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 258d74fd0b63..201ae194d1b8 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -236,6 +236,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
236 | case MMLO: | 236 | case MMLO: |
237 | tmp = regs->lo; | 237 | tmp = regs->lo; |
238 | break; | 238 | break; |
239 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | ||
240 | case ACX: | ||
241 | tmp = regs->acx; | ||
242 | break; | ||
243 | #endif | ||
239 | case FPC_CSR: | 244 | case FPC_CSR: |
240 | tmp = child->thread.fpu.fcr31; | 245 | tmp = child->thread.fpu.fcr31; |
241 | break; | 246 | break; |
@@ -362,6 +367,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
362 | case MMLO: | 367 | case MMLO: |
363 | regs->lo = data; | 368 | regs->lo = data; |
364 | break; | 369 | break; |
370 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | ||
371 | case ACX: | ||
372 | regs->acx = data; | ||
373 | break; | ||
374 | #endif | ||
365 | case FPC_CSR: | 375 | case FPC_CSR: |
366 | child->thread.fpu.fcr31 = data; | 376 | child->thread.fpu.fcr31 = data; |
367 | break; | 377 | break; |
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 59c1577ecbb3..dbd42adc52ed 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S | |||
@@ -114,14 +114,6 @@ LEAF(_save_fp_context32) | |||
114 | */ | 114 | */ |
115 | LEAF(_restore_fp_context) | 115 | LEAF(_restore_fp_context) |
116 | EX lw t0, SC_FPC_CSR(a0) | 116 | EX lw t0, SC_FPC_CSR(a0) |
117 | |||
118 | /* Fail if the CSR has exceptions pending */ | ||
119 | srl t1, t0, 5 | ||
120 | and t1, t0 | ||
121 | andi t1, 0x1f << 7 | ||
122 | bnez t1, fault | ||
123 | nop | ||
124 | |||
125 | #ifdef CONFIG_64BIT | 117 | #ifdef CONFIG_64BIT |
126 | EX ldc1 $f1, SC_FPREGS+8(a0) | 118 | EX ldc1 $f1, SC_FPREGS+8(a0) |
127 | EX ldc1 $f3, SC_FPREGS+24(a0) | 119 | EX ldc1 $f3, SC_FPREGS+24(a0) |
@@ -165,14 +157,6 @@ LEAF(_restore_fp_context) | |||
165 | LEAF(_restore_fp_context32) | 157 | LEAF(_restore_fp_context32) |
166 | /* Restore an o32 sigcontext. */ | 158 | /* Restore an o32 sigcontext. */ |
167 | EX lw t0, SC32_FPC_CSR(a0) | 159 | EX lw t0, SC32_FPC_CSR(a0) |
168 | |||
169 | /* Fail if the CSR has exceptions pending */ | ||
170 | srl t1, t0, 5 | ||
171 | and t1, t0 | ||
172 | andi t1, 0x1f << 7 | ||
173 | bnez t1, fault | ||
174 | nop | ||
175 | |||
176 | EX ldc1 $f0, SC32_FPREGS+0(a0) | 160 | EX ldc1 $f0, SC32_FPREGS+0(a0) |
177 | EX ldc1 $f2, SC32_FPREGS+16(a0) | 161 | EX ldc1 $f2, SC32_FPREGS+16(a0) |
178 | EX ldc1 $f4, SC32_FPREGS+32(a0) | 162 | EX ldc1 $f4, SC32_FPREGS+32(a0) |
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index d92c48e0d7a6..bfc8ca168f83 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
@@ -53,7 +53,8 @@ static char module_name[] = "rtlx"; | |||
53 | static struct chan_waitqueues { | 53 | static struct chan_waitqueues { |
54 | wait_queue_head_t rt_queue; | 54 | wait_queue_head_t rt_queue; |
55 | wait_queue_head_t lx_queue; | 55 | wait_queue_head_t lx_queue; |
56 | int in_open; | 56 | atomic_t in_open; |
57 | struct mutex mutex; | ||
57 | } channel_wqs[RTLX_CHANNELS]; | 58 | } channel_wqs[RTLX_CHANNELS]; |
58 | 59 | ||
59 | static struct irqaction irq; | 60 | static struct irqaction irq; |
@@ -146,110 +147,91 @@ static void stopping(int vpe) | |||
146 | 147 | ||
147 | int rtlx_open(int index, int can_sleep) | 148 | int rtlx_open(int index, int can_sleep) |
148 | { | 149 | { |
149 | int ret; | 150 | struct rtlx_info **p; |
150 | struct rtlx_channel *chan; | 151 | struct rtlx_channel *chan; |
151 | volatile struct rtlx_info **p; | 152 | enum rtlx_state state; |
153 | int ret = 0; | ||
152 | 154 | ||
153 | if (index >= RTLX_CHANNELS) { | 155 | if (index >= RTLX_CHANNELS) { |
154 | printk(KERN_DEBUG "rtlx_open index out of range\n"); | 156 | printk(KERN_DEBUG "rtlx_open index out of range\n"); |
155 | return -ENOSYS; | 157 | return -ENOSYS; |
156 | } | 158 | } |
157 | 159 | ||
158 | if (channel_wqs[index].in_open) { | 160 | if (atomic_inc_return(&channel_wqs[index].in_open) > 1) { |
159 | printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); | 161 | printk(KERN_DEBUG "rtlx_open channel %d already opened\n", |
160 | return -EBUSY; | 162 | index); |
163 | ret = -EBUSY; | ||
164 | goto out_fail; | ||
161 | } | 165 | } |
162 | 166 | ||
163 | channel_wqs[index].in_open++; | ||
164 | |||
165 | if (rtlx == NULL) { | 167 | if (rtlx == NULL) { |
166 | if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { | 168 | if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { |
167 | if (can_sleep) { | 169 | if (can_sleep) { |
168 | DECLARE_WAITQUEUE(wait, current); | 170 | __wait_event_interruptible(channel_wqs[index].lx_queue, |
169 | 171 | (p = vpe_get_shared(RTLX_TARG_VPE)), | |
170 | /* go to sleep */ | 172 | ret); |
171 | add_wait_queue(&channel_wqs[index].lx_queue, &wait); | 173 | if (ret) |
172 | 174 | goto out_fail; | |
173 | set_current_state(TASK_INTERRUPTIBLE); | ||
174 | while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { | ||
175 | schedule(); | ||
176 | set_current_state(TASK_INTERRUPTIBLE); | ||
177 | } | ||
178 | |||
179 | set_current_state(TASK_RUNNING); | ||
180 | remove_wait_queue(&channel_wqs[index].lx_queue, &wait); | ||
181 | |||
182 | /* back running */ | ||
183 | } else { | 175 | } else { |
184 | printk( KERN_DEBUG "No SP program loaded, and device " | 176 | printk(KERN_DEBUG "No SP program loaded, and device " |
185 | "opened with O_NONBLOCK\n"); | 177 | "opened with O_NONBLOCK\n"); |
186 | channel_wqs[index].in_open = 0; | 178 | ret = -ENOSYS; |
187 | return -ENOSYS; | 179 | goto out_fail; |
188 | } | 180 | } |
189 | } | 181 | } |
190 | 182 | ||
183 | smp_rmb(); | ||
191 | if (*p == NULL) { | 184 | if (*p == NULL) { |
192 | if (can_sleep) { | 185 | if (can_sleep) { |
193 | DECLARE_WAITQUEUE(wait, current); | 186 | DEFINE_WAIT(wait); |
194 | 187 | ||
195 | /* go to sleep */ | 188 | for (;;) { |
196 | add_wait_queue(&channel_wqs[index].lx_queue, &wait); | 189 | prepare_to_wait(&channel_wqs[index].lx_queue, &wait, TASK_INTERRUPTIBLE); |
197 | 190 | smp_rmb(); | |
198 | set_current_state(TASK_INTERRUPTIBLE); | 191 | if (*p != NULL) |
199 | while (*p == NULL) { | 192 | break; |
200 | schedule(); | 193 | if (!signal_pending(current)) { |
201 | 194 | schedule(); | |
202 | /* reset task state to interruptable otherwise | 195 | continue; |
203 | we'll whizz round here like a very fast loopy | 196 | } |
204 | thing. schedule() appears to return with state | 197 | ret = -ERESTARTSYS; |
205 | set to TASK_RUNNING. | 198 | goto out_fail; |
206 | |||
207 | If the loaded SP program, for whatever reason, | ||
208 | doesn't set up the shared structure *p will never | ||
209 | become true. So whoever connected to either /dev/rt? | ||
210 | or if it was kspd, will then take up rather a lot of | ||
211 | processor cycles. | ||
212 | */ | ||
213 | |||
214 | set_current_state(TASK_INTERRUPTIBLE); | ||
215 | } | 199 | } |
216 | 200 | finish_wait(&channel_wqs[index].lx_queue, &wait); | |
217 | set_current_state(TASK_RUNNING); | 201 | } else { |
218 | remove_wait_queue(&channel_wqs[index].lx_queue, &wait); | ||
219 | |||
220 | /* back running */ | ||
221 | } | ||
222 | else { | ||
223 | printk(" *vpe_get_shared is NULL. " | 202 | printk(" *vpe_get_shared is NULL. " |
224 | "Has an SP program been loaded?\n"); | 203 | "Has an SP program been loaded?\n"); |
225 | channel_wqs[index].in_open = 0; | 204 | ret = -ENOSYS; |
226 | return -ENOSYS; | 205 | goto out_fail; |
227 | } | 206 | } |
228 | } | 207 | } |
229 | 208 | ||
230 | if ((unsigned int)*p < KSEG0) { | 209 | if ((unsigned int)*p < KSEG0) { |
231 | printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " | 210 | printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " |
232 | "maybe an error code %d\n", (int)*p); | 211 | "maybe an error code %d\n", (int)*p); |
233 | channel_wqs[index].in_open = 0; | 212 | ret = -ENOSYS; |
234 | return -ENOSYS; | 213 | goto out_fail; |
235 | } | 214 | } |
236 | 215 | ||
237 | if ((ret = rtlx_init(*p)) < 0) { | 216 | if ((ret = rtlx_init(*p)) < 0) |
238 | channel_wqs[index].in_open = 0; | 217 | goto out_ret; |
239 | return ret; | ||
240 | } | ||
241 | } | 218 | } |
242 | 219 | ||
243 | chan = &rtlx->channel[index]; | 220 | chan = &rtlx->channel[index]; |
244 | 221 | ||
245 | if (chan->lx_state == RTLX_STATE_OPENED) { | 222 | state = xchg(&chan->lx_state, RTLX_STATE_OPENED); |
246 | channel_wqs[index].in_open = 0; | 223 | if (state == RTLX_STATE_OPENED) { |
247 | return -EBUSY; | 224 | ret = -EBUSY; |
248 | } | 225 | goto out_fail; |
226 | } | ||
249 | 227 | ||
250 | chan->lx_state = RTLX_STATE_OPENED; | 228 | out_fail: |
251 | channel_wqs[index].in_open = 0; | 229 | smp_mb(); |
252 | return 0; | 230 | atomic_dec(&channel_wqs[index].in_open); |
231 | smp_mb(); | ||
232 | |||
233 | out_ret: | ||
234 | return ret; | ||
253 | } | 235 | } |
254 | 236 | ||
255 | int rtlx_release(int index) | 237 | int rtlx_release(int index) |
@@ -270,30 +252,17 @@ unsigned int rtlx_read_poll(int index, int can_sleep) | |||
270 | /* data available to read? */ | 252 | /* data available to read? */ |
271 | if (chan->lx_read == chan->lx_write) { | 253 | if (chan->lx_read == chan->lx_write) { |
272 | if (can_sleep) { | 254 | if (can_sleep) { |
273 | DECLARE_WAITQUEUE(wait, current); | 255 | int ret = 0; |
274 | |||
275 | /* go to sleep */ | ||
276 | add_wait_queue(&channel_wqs[index].lx_queue, &wait); | ||
277 | |||
278 | set_current_state(TASK_INTERRUPTIBLE); | ||
279 | while (chan->lx_read == chan->lx_write) { | ||
280 | schedule(); | ||
281 | 256 | ||
282 | set_current_state(TASK_INTERRUPTIBLE); | 257 | __wait_event_interruptible(channel_wqs[index].lx_queue, |
258 | chan->lx_read != chan->lx_write || sp_stopping, | ||
259 | ret); | ||
260 | if (ret) | ||
261 | return ret; | ||
283 | 262 | ||
284 | if (sp_stopping) { | 263 | if (sp_stopping) |
285 | set_current_state(TASK_RUNNING); | 264 | return 0; |
286 | remove_wait_queue(&channel_wqs[index].lx_queue, &wait); | 265 | } else |
287 | return 0; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | set_current_state(TASK_RUNNING); | ||
292 | remove_wait_queue(&channel_wqs[index].lx_queue, &wait); | ||
293 | |||
294 | /* back running */ | ||
295 | } | ||
296 | else | ||
297 | return 0; | 266 | return 0; |
298 | } | 267 | } |
299 | 268 | ||
@@ -320,56 +289,53 @@ unsigned int rtlx_write_poll(int index) | |||
320 | return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); | 289 | return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); |
321 | } | 290 | } |
322 | 291 | ||
323 | static inline void copy_to(void *dst, void *src, size_t count, int user) | 292 | ssize_t rtlx_read(int index, void __user *buff, size_t count) |
324 | { | 293 | { |
325 | if (user) | 294 | size_t lx_write, fl = 0L; |
326 | copy_to_user(dst, src, count); | ||
327 | else | ||
328 | memcpy(dst, src, count); | ||
329 | } | ||
330 | |||
331 | static inline void copy_from(void *dst, void *src, size_t count, int user) | ||
332 | { | ||
333 | if (user) | ||
334 | copy_from_user(dst, src, count); | ||
335 | else | ||
336 | memcpy(dst, src, count); | ||
337 | } | ||
338 | |||
339 | ssize_t rtlx_read(int index, void *buff, size_t count, int user) | ||
340 | { | ||
341 | size_t fl = 0L; | ||
342 | struct rtlx_channel *lx; | 295 | struct rtlx_channel *lx; |
296 | unsigned long failed; | ||
343 | 297 | ||
344 | if (rtlx == NULL) | 298 | if (rtlx == NULL) |
345 | return -ENOSYS; | 299 | return -ENOSYS; |
346 | 300 | ||
347 | lx = &rtlx->channel[index]; | 301 | lx = &rtlx->channel[index]; |
348 | 302 | ||
303 | mutex_lock(&channel_wqs[index].mutex); | ||
304 | smp_rmb(); | ||
305 | lx_write = lx->lx_write; | ||
306 | |||
349 | /* find out how much in total */ | 307 | /* find out how much in total */ |
350 | count = min(count, | 308 | count = min(count, |
351 | (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) | 309 | (size_t)(lx_write + lx->buffer_size - lx->lx_read) |
352 | % lx->buffer_size); | 310 | % lx->buffer_size); |
353 | 311 | ||
354 | /* then how much from the read pointer onwards */ | 312 | /* then how much from the read pointer onwards */ |
355 | fl = min( count, (size_t)lx->buffer_size - lx->lx_read); | 313 | fl = min(count, (size_t)lx->buffer_size - lx->lx_read); |
356 | 314 | ||
357 | copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user); | 315 | failed = copy_to_user(buff, lx->lx_buffer + lx->lx_read, fl); |
316 | if (failed) | ||
317 | goto out; | ||
358 | 318 | ||
359 | /* and if there is anything left at the beginning of the buffer */ | 319 | /* and if there is anything left at the beginning of the buffer */ |
360 | if ( count - fl ) | 320 | if (count - fl) |
361 | copy_to (buff + fl, lx->lx_buffer, count - fl, user); | 321 | failed = copy_to_user(buff + fl, lx->lx_buffer, count - fl); |
322 | |||
323 | out: | ||
324 | count -= failed; | ||
362 | 325 | ||
363 | /* update the index */ | 326 | smp_wmb(); |
364 | lx->lx_read += count; | 327 | lx->lx_read = (lx->lx_read + count) % lx->buffer_size; |
365 | lx->lx_read %= lx->buffer_size; | 328 | smp_wmb(); |
329 | mutex_unlock(&channel_wqs[index].mutex); | ||
366 | 330 | ||
367 | return count; | 331 | return count; |
368 | } | 332 | } |
369 | 333 | ||
370 | ssize_t rtlx_write(int index, void *buffer, size_t count, int user) | 334 | ssize_t rtlx_write(int index, const void __user *buffer, size_t count) |
371 | { | 335 | { |
372 | struct rtlx_channel *rt; | 336 | struct rtlx_channel *rt; |
337 | unsigned long failed; | ||
338 | size_t rt_read; | ||
373 | size_t fl; | 339 | size_t fl; |
374 | 340 | ||
375 | if (rtlx == NULL) | 341 | if (rtlx == NULL) |
@@ -377,24 +343,35 @@ ssize_t rtlx_write(int index, void *buffer, size_t count, int user) | |||
377 | 343 | ||
378 | rt = &rtlx->channel[index]; | 344 | rt = &rtlx->channel[index]; |
379 | 345 | ||
346 | mutex_lock(&channel_wqs[index].mutex); | ||
347 | smp_rmb(); | ||
348 | rt_read = rt->rt_read; | ||
349 | |||
380 | /* total number of bytes to copy */ | 350 | /* total number of bytes to copy */ |
381 | count = min(count, | 351 | count = min(count, |
382 | (size_t)write_spacefree(rt->rt_read, rt->rt_write, | 352 | (size_t)write_spacefree(rt_read, rt->rt_write, rt->buffer_size)); |
383 | rt->buffer_size)); | ||
384 | 353 | ||
385 | /* first bit from write pointer to the end of the buffer, or count */ | 354 | /* first bit from write pointer to the end of the buffer, or count */ |
386 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); | 355 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); |
387 | 356 | ||
388 | copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user); | 357 | failed = copy_from_user(rt->rt_buffer + rt->rt_write, buffer, fl); |
358 | if (failed) | ||
359 | goto out; | ||
389 | 360 | ||
390 | /* if there's any left copy to the beginning of the buffer */ | 361 | /* if there's any left copy to the beginning of the buffer */ |
391 | if( count - fl ) | 362 | if (count - fl) { |
392 | copy_from (rt->rt_buffer, buffer + fl, count - fl, user); | 363 | failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl); |
364 | } | ||
393 | 365 | ||
394 | rt->rt_write += count; | 366 | out: |
395 | rt->rt_write %= rt->buffer_size; | 367 | count -= failed; |
396 | 368 | ||
397 | return(count); | 369 | smp_wmb(); |
370 | rt->rt_write = (rt->rt_write + count) % rt->buffer_size; | ||
371 | smp_wmb(); | ||
372 | mutex_unlock(&channel_wqs[index].mutex); | ||
373 | |||
374 | return count; | ||
398 | } | 375 | } |
399 | 376 | ||
400 | 377 | ||
@@ -446,7 +423,7 @@ static ssize_t file_read(struct file *file, char __user * buffer, size_t count, | |||
446 | return 0; // -EAGAIN makes cat whinge | 423 | return 0; // -EAGAIN makes cat whinge |
447 | } | 424 | } |
448 | 425 | ||
449 | return rtlx_read(minor, buffer, count, 1); | 426 | return rtlx_read(minor, buffer, count); |
450 | } | 427 | } |
451 | 428 | ||
452 | static ssize_t file_write(struct file *file, const char __user * buffer, | 429 | static ssize_t file_write(struct file *file, const char __user * buffer, |
@@ -454,28 +431,25 @@ static ssize_t file_write(struct file *file, const char __user * buffer, | |||
454 | { | 431 | { |
455 | int minor; | 432 | int minor; |
456 | struct rtlx_channel *rt; | 433 | struct rtlx_channel *rt; |
457 | DECLARE_WAITQUEUE(wait, current); | ||
458 | 434 | ||
459 | minor = iminor(file->f_path.dentry->d_inode); | 435 | minor = iminor(file->f_path.dentry->d_inode); |
460 | rt = &rtlx->channel[minor]; | 436 | rt = &rtlx->channel[minor]; |
461 | 437 | ||
462 | /* any space left... */ | 438 | /* any space left... */ |
463 | if (!rtlx_write_poll(minor)) { | 439 | if (!rtlx_write_poll(minor)) { |
440 | int ret = 0; | ||
464 | 441 | ||
465 | if (file->f_flags & O_NONBLOCK) | 442 | if (file->f_flags & O_NONBLOCK) |
466 | return -EAGAIN; | 443 | return -EAGAIN; |
467 | 444 | ||
468 | add_wait_queue(&channel_wqs[minor].rt_queue, &wait); | 445 | __wait_event_interruptible(channel_wqs[minor].rt_queue, |
469 | set_current_state(TASK_INTERRUPTIBLE); | 446 | rtlx_write_poll(minor), |
470 | 447 | ret); | |
471 | while (!rtlx_write_poll(minor)) | 448 | if (ret) |
472 | schedule(); | 449 | return ret; |
473 | |||
474 | set_current_state(TASK_RUNNING); | ||
475 | remove_wait_queue(&channel_wqs[minor].rt_queue, &wait); | ||
476 | } | 450 | } |
477 | 451 | ||
478 | return rtlx_write(minor, (void *)buffer, count, 1); | 452 | return rtlx_write(minor, buffer, count); |
479 | } | 453 | } |
480 | 454 | ||
481 | static const struct file_operations rtlx_fops = { | 455 | static const struct file_operations rtlx_fops = { |
@@ -513,7 +487,8 @@ static int rtlx_module_init(void) | |||
513 | for (i = 0; i < RTLX_CHANNELS; i++) { | 487 | for (i = 0; i < RTLX_CHANNELS; i++) { |
514 | init_waitqueue_head(&channel_wqs[i].rt_queue); | 488 | init_waitqueue_head(&channel_wqs[i].rt_queue); |
515 | init_waitqueue_head(&channel_wqs[i].lx_queue); | 489 | init_waitqueue_head(&channel_wqs[i].lx_queue); |
516 | channel_wqs[i].in_open = 0; | 490 | atomic_set(&channel_wqs[i].in_open, 0); |
491 | mutex_init(&channel_wqs[i].mutex); | ||
517 | 492 | ||
518 | dev = device_create(mt_class, NULL, MKDEV(major, i), | 493 | dev = device_create(mt_class, NULL, MKDEV(major, i), |
519 | "%s%d", module_name, i); | 494 | "%s%d", module_name, i); |
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 7c0b3936ba44..0c9a9ff8cd25 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S | |||
@@ -656,6 +656,8 @@ einval: li v0, -EINVAL | |||
656 | sys sys_kexec_load 4 | 656 | sys sys_kexec_load 4 |
657 | sys sys_getcpu 3 | 657 | sys sys_getcpu 3 |
658 | sys sys_epoll_pwait 6 | 658 | sys sys_epoll_pwait 6 |
659 | sys sys_ioprio_set 3 | ||
660 | sys sys_ioprio_get 2 | ||
659 | .endm | 661 | .endm |
660 | 662 | ||
661 | /* We pre-compute the number of _instruction_ bytes needed to | 663 | /* We pre-compute the number of _instruction_ bytes needed to |
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 10e9a18630aa..23f3b118f718 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S | |||
@@ -470,4 +470,7 @@ sys_call_table: | |||
470 | PTR sys_get_robust_list | 470 | PTR sys_get_robust_list |
471 | PTR sys_kexec_load /* 5270 */ | 471 | PTR sys_kexec_load /* 5270 */ |
472 | PTR sys_getcpu | 472 | PTR sys_getcpu |
473 | PTR compat_sys_epoll_pwait | 473 | PTR sys_epoll_pwait |
474 | PTR sys_ioprio_set | ||
475 | PTR sys_ioprio_get | ||
476 | .size sys_call_table,.-sys_call_table | ||
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 2ceda4644a4d..6eac28337423 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
@@ -340,7 +340,7 @@ EXPORT(sysn32_call_table) | |||
340 | PTR compat_sys_statfs64 | 340 | PTR compat_sys_statfs64 |
341 | PTR compat_sys_fstatfs64 | 341 | PTR compat_sys_fstatfs64 |
342 | PTR sys_sendfile64 | 342 | PTR sys_sendfile64 |
343 | PTR sys32_timer_create /* 6220 */ | 343 | PTR compat_sys_timer_create /* 6220 */ |
344 | PTR compat_sys_timer_settime | 344 | PTR compat_sys_timer_settime |
345 | PTR compat_sys_timer_gettime | 345 | PTR compat_sys_timer_gettime |
346 | PTR sys_timer_getoverrun | 346 | PTR sys_timer_getoverrun |
@@ -361,7 +361,7 @@ EXPORT(sysn32_call_table) | |||
361 | PTR compat_sys_mq_notify | 361 | PTR compat_sys_mq_notify |
362 | PTR compat_sys_mq_getsetattr | 362 | PTR compat_sys_mq_getsetattr |
363 | PTR sys_ni_syscall /* 6240, sys_vserver */ | 363 | PTR sys_ni_syscall /* 6240, sys_vserver */ |
364 | PTR sysn32_waitid | 364 | PTR compat_sys_waitid |
365 | PTR sys_ni_syscall /* available, was setaltroot */ | 365 | PTR sys_ni_syscall /* available, was setaltroot */ |
366 | PTR sys_add_key | 366 | PTR sys_add_key |
367 | PTR sys_request_key | 367 | PTR sys_request_key |
@@ -395,5 +395,8 @@ EXPORT(sysn32_call_table) | |||
395 | PTR compat_sys_set_robust_list | 395 | PTR compat_sys_set_robust_list |
396 | PTR compat_sys_get_robust_list | 396 | PTR compat_sys_get_robust_list |
397 | PTR compat_sys_kexec_load | 397 | PTR compat_sys_kexec_load |
398 | PTR sys_getcpu | 398 | PTR sys_getcpu /* 6275 */ |
399 | PTR compat_sys_epoll_pwait | 399 | PTR compat_sys_epoll_pwait |
400 | PTR sys_ioprio_set | ||
401 | PTR sys_ioprio_get | ||
402 | .size sysn32_call_table,.-sysn32_call_table | ||
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index c5f590ca99b0..7e74b412a782 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
@@ -307,7 +307,7 @@ sys_call_table: | |||
307 | PTR compat_sys_statfs | 307 | PTR compat_sys_statfs |
308 | PTR compat_sys_fstatfs /* 4100 */ | 308 | PTR compat_sys_fstatfs /* 4100 */ |
309 | PTR sys_ni_syscall /* sys_ioperm */ | 309 | PTR sys_ni_syscall /* sys_ioperm */ |
310 | PTR sys32_socketcall | 310 | PTR compat_sys_socketcall |
311 | PTR sys_syslog | 311 | PTR sys_syslog |
312 | PTR compat_sys_setitimer | 312 | PTR compat_sys_setitimer |
313 | PTR compat_sys_getitimer /* 4105 */ | 313 | PTR compat_sys_getitimer /* 4105 */ |
@@ -462,7 +462,7 @@ sys_call_table: | |||
462 | PTR sys_fadvise64_64 | 462 | PTR sys_fadvise64_64 |
463 | PTR compat_sys_statfs64 /* 4255 */ | 463 | PTR compat_sys_statfs64 /* 4255 */ |
464 | PTR compat_sys_fstatfs64 | 464 | PTR compat_sys_fstatfs64 |
465 | PTR sys32_timer_create | 465 | PTR compat_sys_timer_create |
466 | PTR compat_sys_timer_settime | 466 | PTR compat_sys_timer_settime |
467 | PTR compat_sys_timer_gettime | 467 | PTR compat_sys_timer_gettime |
468 | PTR sys_timer_getoverrun /* 4260 */ | 468 | PTR sys_timer_getoverrun /* 4260 */ |
@@ -518,5 +518,7 @@ sys_call_table: | |||
518 | PTR compat_sys_get_robust_list /* 4310 */ | 518 | PTR compat_sys_get_robust_list /* 4310 */ |
519 | PTR compat_sys_kexec_load | 519 | PTR compat_sys_kexec_load |
520 | PTR sys_getcpu | 520 | PTR sys_getcpu |
521 | PTR sys_epoll_pwait | 521 | PTR compat_sys_epoll_pwait |
522 | PTR sys_ioprio_set | ||
523 | PTR sys_ioprio_get /* 4315 */ | ||
522 | .size sys_call_table,.-sys_call_table | 524 | .size sys_call_table,.-sys_call_table |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 394540fad769..4975da0bfb63 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -525,6 +525,14 @@ void __init setup_arch(char **cmdline_p) | |||
525 | { | 525 | { |
526 | cpu_probe(); | 526 | cpu_probe(); |
527 | prom_init(); | 527 | prom_init(); |
528 | |||
529 | #ifdef CONFIG_EARLY_PRINTK | ||
530 | { | ||
531 | extern void setup_early_printk(void); | ||
532 | |||
533 | setup_early_printk(); | ||
534 | } | ||
535 | #endif | ||
528 | cpu_report(); | 536 | cpu_report(); |
529 | 537 | ||
530 | #if defined(CONFIG_VT) | 538 | #if defined(CONFIG_VT) |
@@ -543,7 +551,7 @@ void __init setup_arch(char **cmdline_p) | |||
543 | #endif | 551 | #endif |
544 | } | 552 | } |
545 | 553 | ||
546 | int __init fpu_disable(char *s) | 554 | static int __init fpu_disable(char *s) |
547 | { | 555 | { |
548 | int i; | 556 | int i; |
549 | 557 | ||
@@ -555,7 +563,7 @@ int __init fpu_disable(char *s) | |||
555 | 563 | ||
556 | __setup("nofpu", fpu_disable); | 564 | __setup("nofpu", fpu_disable); |
557 | 565 | ||
558 | int __init dsp_disable(char *s) | 566 | static int __init dsp_disable(char *s) |
559 | { | 567 | { |
560 | cpu_data[0].ases &= ~MIPS_ASE_DSP; | 568 | cpu_data[0].ases &= ~MIPS_ASE_DSP; |
561 | 569 | ||
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index fdbdbdc65b54..c0faabd52010 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h | |||
@@ -31,4 +31,16 @@ extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
31 | */ | 31 | */ |
32 | extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); | 32 | extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); |
33 | 33 | ||
34 | /* Check and clear pending FPU exceptions in saved CSR */ | ||
35 | extern int fpcsr_pending(unsigned int __user *fpcsr); | ||
36 | |||
37 | /* Make sure we will not lose FPU ownership */ | ||
38 | #ifdef CONFIG_PREEMPT | ||
39 | #define lock_fpu_owner() preempt_disable() | ||
40 | #define unlock_fpu_owner() preempt_enable() | ||
41 | #else | ||
42 | #define lock_fpu_owner() pagefault_disable() | ||
43 | #define unlock_fpu_owner() pagefault_enable() | ||
44 | #endif | ||
45 | |||
34 | #endif /* __SIGNAL_COMMON_H */ | 46 | #endif /* __SIGNAL_COMMON_H */ |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index b2e9ab1bb101..07d67309451a 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/ptrace.h> | 20 | #include <linux/ptrace.h> |
21 | #include <linux/unistd.h> | 21 | #include <linux/unistd.h> |
22 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
23 | #include <linux/uaccess.h> | ||
23 | 24 | ||
24 | #include <asm/abi.h> | 25 | #include <asm/abi.h> |
25 | #include <asm/asm.h> | 26 | #include <asm/asm.h> |
@@ -27,7 +28,6 @@ | |||
27 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
28 | #include <asm/fpu.h> | 29 | #include <asm/fpu.h> |
29 | #include <asm/sim.h> | 30 | #include <asm/sim.h> |
30 | #include <asm/uaccess.h> | ||
31 | #include <asm/ucontext.h> | 31 | #include <asm/ucontext.h> |
32 | #include <asm/cpu-features.h> | 32 | #include <asm/cpu-features.h> |
33 | #include <asm/war.h> | 33 | #include <asm/war.h> |
@@ -78,10 +78,51 @@ struct rt_sigframe { | |||
78 | /* | 78 | /* |
79 | * Helper routines | 79 | * Helper routines |
80 | */ | 80 | */ |
81 | static int protected_save_fp_context(struct sigcontext __user *sc) | ||
82 | { | ||
83 | int err; | ||
84 | while (1) { | ||
85 | lock_fpu_owner(); | ||
86 | own_fpu_inatomic(1); | ||
87 | err = save_fp_context(sc); /* this might fail */ | ||
88 | unlock_fpu_owner(); | ||
89 | if (likely(!err)) | ||
90 | break; | ||
91 | /* touch the sigcontext and try again */ | ||
92 | err = __put_user(0, &sc->sc_fpregs[0]) | | ||
93 | __put_user(0, &sc->sc_fpregs[31]) | | ||
94 | __put_user(0, &sc->sc_fpc_csr); | ||
95 | if (err) | ||
96 | break; /* really bad sigcontext */ | ||
97 | } | ||
98 | return err; | ||
99 | } | ||
100 | |||
101 | static int protected_restore_fp_context(struct sigcontext __user *sc) | ||
102 | { | ||
103 | int err, tmp; | ||
104 | while (1) { | ||
105 | lock_fpu_owner(); | ||
106 | own_fpu_inatomic(0); | ||
107 | err = restore_fp_context(sc); /* this might fail */ | ||
108 | unlock_fpu_owner(); | ||
109 | if (likely(!err)) | ||
110 | break; | ||
111 | /* touch the sigcontext and try again */ | ||
112 | err = __get_user(tmp, &sc->sc_fpregs[0]) | | ||
113 | __get_user(tmp, &sc->sc_fpregs[31]) | | ||
114 | __get_user(tmp, &sc->sc_fpc_csr); | ||
115 | if (err) | ||
116 | break; /* really bad sigcontext */ | ||
117 | } | ||
118 | return err; | ||
119 | } | ||
120 | |||
81 | int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | 121 | int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
82 | { | 122 | { |
83 | int err = 0; | 123 | int err = 0; |
84 | int i; | 124 | int i; |
125 | unsigned int used_math; | ||
85 | 126 | ||
86 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | 127 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); |
87 | 128 | ||
@@ -89,6 +130,9 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
89 | for (i = 1; i < 32; i++) | 130 | for (i = 1; i < 32; i++) |
90 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); | 131 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); |
91 | 132 | ||
133 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | ||
134 | err |= __put_user(regs->acx, &sc->sc_acx); | ||
135 | #endif | ||
92 | err |= __put_user(regs->hi, &sc->sc_mdhi); | 136 | err |= __put_user(regs->hi, &sc->sc_mdhi); |
93 | err |= __put_user(regs->lo, &sc->sc_mdlo); | 137 | err |= __put_user(regs->lo, &sc->sc_mdlo); |
94 | if (cpu_has_dsp) { | 138 | if (cpu_has_dsp) { |
@@ -101,24 +145,48 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
101 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | 145 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); |
102 | } | 146 | } |
103 | 147 | ||
104 | err |= __put_user(!!used_math(), &sc->sc_used_math); | 148 | used_math = !!used_math(); |
149 | err |= __put_user(used_math, &sc->sc_used_math); | ||
105 | 150 | ||
106 | if (used_math()) { | 151 | if (used_math) { |
107 | /* | 152 | /* |
108 | * Save FPU state to signal context. Signal handler | 153 | * Save FPU state to signal context. Signal handler |
109 | * will "inherit" current FPU state. | 154 | * will "inherit" current FPU state. |
110 | */ | 155 | */ |
111 | preempt_disable(); | 156 | err |= protected_save_fp_context(sc); |
157 | } | ||
158 | return err; | ||
159 | } | ||
112 | 160 | ||
113 | if (!is_fpu_owner()) { | 161 | int fpcsr_pending(unsigned int __user *fpcsr) |
114 | own_fpu(); | 162 | { |
115 | restore_fp(current); | 163 | int err, sig = 0; |
116 | } | 164 | unsigned int csr, enabled; |
117 | err |= save_fp_context(sc); | ||
118 | 165 | ||
119 | preempt_enable(); | 166 | err = __get_user(csr, fpcsr); |
167 | enabled = FPU_CSR_UNI_X | ((csr & FPU_CSR_ALL_E) << 5); | ||
168 | /* | ||
169 | * If the signal handler set some FPU exceptions, clear it and | ||
170 | * send SIGFPE. | ||
171 | */ | ||
172 | if (csr & enabled) { | ||
173 | csr &= ~enabled; | ||
174 | err |= __put_user(csr, fpcsr); | ||
175 | sig = SIGFPE; | ||
120 | } | 176 | } |
121 | return err; | 177 | return err ?: sig; |
178 | } | ||
179 | |||
180 | static int | ||
181 | check_and_restore_fp_context(struct sigcontext __user *sc) | ||
182 | { | ||
183 | int err, sig; | ||
184 | |||
185 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | ||
186 | if (err > 0) | ||
187 | err = 0; | ||
188 | err |= protected_restore_fp_context(sc); | ||
189 | return err ?: sig; | ||
122 | } | 190 | } |
123 | 191 | ||
124 | int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | 192 | int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
@@ -132,6 +200,10 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
132 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 200 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
133 | 201 | ||
134 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | 202 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); |
203 | |||
204 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | ||
205 | err |= __get_user(regs->acx, &sc->sc_acx); | ||
206 | #endif | ||
135 | err |= __get_user(regs->hi, &sc->sc_mdhi); | 207 | err |= __get_user(regs->hi, &sc->sc_mdhi); |
136 | err |= __get_user(regs->lo, &sc->sc_mdlo); | 208 | err |= __get_user(regs->lo, &sc->sc_mdlo); |
137 | if (cpu_has_dsp) { | 209 | if (cpu_has_dsp) { |
@@ -150,19 +222,15 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
150 | err |= __get_user(used_math, &sc->sc_used_math); | 222 | err |= __get_user(used_math, &sc->sc_used_math); |
151 | conditional_used_math(used_math); | 223 | conditional_used_math(used_math); |
152 | 224 | ||
153 | preempt_disable(); | 225 | if (used_math) { |
154 | |||
155 | if (used_math()) { | ||
156 | /* restore fpu context if we have used it before */ | 226 | /* restore fpu context if we have used it before */ |
157 | own_fpu(); | 227 | if (!err) |
158 | err |= restore_fp_context(sc); | 228 | err = check_and_restore_fp_context(sc); |
159 | } else { | 229 | } else { |
160 | /* signal handler may have used FPU. Give it up. */ | 230 | /* signal handler may have used FPU. Give it up. */ |
161 | lose_fpu(); | 231 | lose_fpu(0); |
162 | } | 232 | } |
163 | 233 | ||
164 | preempt_enable(); | ||
165 | |||
166 | return err; | 234 | return err; |
167 | } | 235 | } |
168 | 236 | ||
@@ -325,6 +393,7 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
325 | { | 393 | { |
326 | struct sigframe __user *frame; | 394 | struct sigframe __user *frame; |
327 | sigset_t blocked; | 395 | sigset_t blocked; |
396 | int sig; | ||
328 | 397 | ||
329 | frame = (struct sigframe __user *) regs.regs[29]; | 398 | frame = (struct sigframe __user *) regs.regs[29]; |
330 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 399 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -338,8 +407,11 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
338 | recalc_sigpending(); | 407 | recalc_sigpending(); |
339 | spin_unlock_irq(¤t->sighand->siglock); | 408 | spin_unlock_irq(¤t->sighand->siglock); |
340 | 409 | ||
341 | if (restore_sigcontext(®s, &frame->sf_sc)) | 410 | sig = restore_sigcontext(®s, &frame->sf_sc); |
411 | if (sig < 0) | ||
342 | goto badframe; | 412 | goto badframe; |
413 | else if (sig) | ||
414 | force_sig(sig, current); | ||
343 | 415 | ||
344 | /* | 416 | /* |
345 | * Don't let your children do this ... | 417 | * Don't let your children do this ... |
@@ -361,6 +433,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
361 | struct rt_sigframe __user *frame; | 433 | struct rt_sigframe __user *frame; |
362 | sigset_t set; | 434 | sigset_t set; |
363 | stack_t st; | 435 | stack_t st; |
436 | int sig; | ||
364 | 437 | ||
365 | frame = (struct rt_sigframe __user *) regs.regs[29]; | 438 | frame = (struct rt_sigframe __user *) regs.regs[29]; |
366 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 439 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -374,8 +447,11 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
374 | recalc_sigpending(); | 447 | recalc_sigpending(); |
375 | spin_unlock_irq(¤t->sighand->siglock); | 448 | spin_unlock_irq(¤t->sighand->siglock); |
376 | 449 | ||
377 | if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) | 450 | sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); |
451 | if (sig < 0) | ||
378 | goto badframe; | 452 | goto badframe; |
453 | else if (sig) | ||
454 | force_sig(sig, current); | ||
379 | 455 | ||
380 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) | 456 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) |
381 | goto badframe; | 457 | goto badframe; |
@@ -398,7 +474,7 @@ badframe: | |||
398 | } | 474 | } |
399 | 475 | ||
400 | #ifdef CONFIG_TRAD_SIGNALS | 476 | #ifdef CONFIG_TRAD_SIGNALS |
401 | int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | 477 | static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, |
402 | int signr, sigset_t *set) | 478 | int signr, sigset_t *set) |
403 | { | 479 | { |
404 | struct sigframe __user *frame; | 480 | struct sigframe __user *frame; |
@@ -443,7 +519,7 @@ give_sigsegv: | |||
443 | } | 519 | } |
444 | #endif | 520 | #endif |
445 | 521 | ||
446 | int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | 522 | static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, |
447 | int signr, sigset_t *set, siginfo_t *info) | 523 | int signr, sigset_t *set, siginfo_t *info) |
448 | { | 524 | { |
449 | struct rt_sigframe __user *frame; | 525 | struct rt_sigframe __user *frame; |
@@ -501,6 +577,14 @@ give_sigsegv: | |||
501 | return -EFAULT; | 577 | return -EFAULT; |
502 | } | 578 | } |
503 | 579 | ||
580 | struct mips_abi mips_abi = { | ||
581 | #ifdef CONFIG_TRAD_SIGNALS | ||
582 | .setup_frame = setup_frame, | ||
583 | #endif | ||
584 | .setup_rt_frame = setup_rt_frame, | ||
585 | .restart = __NR_restart_syscall | ||
586 | }; | ||
587 | |||
504 | static int handle_signal(unsigned long sig, siginfo_t *info, | 588 | static int handle_signal(unsigned long sig, siginfo_t *info, |
505 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) | 589 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) |
506 | { | 590 | { |
@@ -539,7 +623,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
539 | return ret; | 623 | return ret; |
540 | } | 624 | } |
541 | 625 | ||
542 | void do_signal(struct pt_regs *regs) | 626 | static void do_signal(struct pt_regs *regs) |
543 | { | 627 | { |
544 | struct k_sigaction ka; | 628 | struct k_sigaction ka; |
545 | sigset_t *oldset; | 629 | sigset_t *oldset; |
@@ -589,7 +673,7 @@ void do_signal(struct pt_regs *regs) | |||
589 | regs->cp0_epc -= 8; | 673 | regs->cp0_epc -= 8; |
590 | } | 674 | } |
591 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { | 675 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { |
592 | regs->regs[2] = __NR_restart_syscall; | 676 | regs->regs[2] = current->thread.abi->restart; |
593 | regs->regs[7] = regs->regs[26]; | 677 | regs->regs[7] = regs->regs[26]; |
594 | regs->cp0_epc -= 4; | 678 | regs->cp0_epc -= 4; |
595 | } | 679 | } |
@@ -615,5 +699,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | |||
615 | { | 699 | { |
616 | /* deal with pending signal delivery */ | 700 | /* deal with pending signal delivery */ |
617 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 701 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) |
618 | current->thread.abi->do_signal(regs); | 702 | do_signal(regs); |
619 | } | 703 | } |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index c28cb21514c8..b9a014411f83 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/compat.h> | 22 | #include <linux/compat.h> |
23 | #include <linux/suspend.h> | 23 | #include <linux/suspend.h> |
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/uaccess.h> | ||
25 | 26 | ||
26 | #include <asm/abi.h> | 27 | #include <asm/abi.h> |
27 | #include <asm/asm.h> | 28 | #include <asm/asm.h> |
@@ -29,7 +30,6 @@ | |||
29 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
30 | #include <asm/cacheflush.h> | 31 | #include <asm/cacheflush.h> |
31 | #include <asm/sim.h> | 32 | #include <asm/sim.h> |
32 | #include <asm/uaccess.h> | ||
33 | #include <asm/ucontext.h> | 33 | #include <asm/ucontext.h> |
34 | #include <asm/system.h> | 34 | #include <asm/system.h> |
35 | #include <asm/fpu.h> | 35 | #include <asm/fpu.h> |
@@ -104,17 +104,10 @@ typedef struct compat_siginfo { | |||
104 | */ | 104 | */ |
105 | #define __NR_O32_sigreturn 4119 | 105 | #define __NR_O32_sigreturn 4119 |
106 | #define __NR_O32_rt_sigreturn 4193 | 106 | #define __NR_O32_rt_sigreturn 4193 |
107 | #define __NR_O32_restart_syscall 4253 | 107 | #define __NR_O32_restart_syscall 4253 |
108 | 108 | ||
109 | /* 32-bit compatibility types */ | 109 | /* 32-bit compatibility types */ |
110 | 110 | ||
111 | #define _NSIG_BPW32 32 | ||
112 | #define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32) | ||
113 | |||
114 | typedef struct { | ||
115 | unsigned int sig[_NSIG_WORDS32]; | ||
116 | } sigset_t32; | ||
117 | |||
118 | typedef unsigned int __sighandler32_t; | 111 | typedef unsigned int __sighandler32_t; |
119 | typedef void (*vfptr_t)(void); | 112 | typedef void (*vfptr_t)(void); |
120 | 113 | ||
@@ -136,7 +129,7 @@ struct ucontext32 { | |||
136 | s32 uc_link; | 129 | s32 uc_link; |
137 | stack32_t uc_stack; | 130 | stack32_t uc_stack; |
138 | struct sigcontext32 uc_mcontext; | 131 | struct sigcontext32 uc_mcontext; |
139 | sigset_t32 uc_sigmask; /* mask last for extensibility */ | 132 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ |
140 | }; | 133 | }; |
141 | 134 | ||
142 | /* | 135 | /* |
@@ -150,7 +143,7 @@ struct sigframe32 { | |||
150 | u32 sf_ass[4]; /* argument save space for o32 */ | 143 | u32 sf_ass[4]; /* argument save space for o32 */ |
151 | u32 sf_code[2]; /* signal trampoline */ | 144 | u32 sf_code[2]; /* signal trampoline */ |
152 | struct sigcontext32 sf_sc; | 145 | struct sigcontext32 sf_sc; |
153 | sigset_t sf_mask; | 146 | compat_sigset_t sf_mask; |
154 | }; | 147 | }; |
155 | 148 | ||
156 | struct rt_sigframe32 { | 149 | struct rt_sigframe32 { |
@@ -166,7 +159,7 @@ struct sigframe32 { | |||
166 | u32 sf_ass[4]; /* argument save space for o32 */ | 159 | u32 sf_ass[4]; /* argument save space for o32 */ |
167 | u32 sf_pad[2]; | 160 | u32 sf_pad[2]; |
168 | struct sigcontext32 sf_sc; /* hw context */ | 161 | struct sigcontext32 sf_sc; /* hw context */ |
169 | sigset_t sf_mask; | 162 | compat_sigset_t sf_mask; |
170 | u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ | 163 | u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ |
171 | }; | 164 | }; |
172 | 165 | ||
@@ -183,11 +176,52 @@ struct rt_sigframe32 { | |||
183 | /* | 176 | /* |
184 | * sigcontext handlers | 177 | * sigcontext handlers |
185 | */ | 178 | */ |
179 | static int protected_save_fp_context32(struct sigcontext32 __user *sc) | ||
180 | { | ||
181 | int err; | ||
182 | while (1) { | ||
183 | lock_fpu_owner(); | ||
184 | own_fpu_inatomic(1); | ||
185 | err = save_fp_context32(sc); /* this might fail */ | ||
186 | unlock_fpu_owner(); | ||
187 | if (likely(!err)) | ||
188 | break; | ||
189 | /* touch the sigcontext and try again */ | ||
190 | err = __put_user(0, &sc->sc_fpregs[0]) | | ||
191 | __put_user(0, &sc->sc_fpregs[31]) | | ||
192 | __put_user(0, &sc->sc_fpc_csr); | ||
193 | if (err) | ||
194 | break; /* really bad sigcontext */ | ||
195 | } | ||
196 | return err; | ||
197 | } | ||
198 | |||
199 | static int protected_restore_fp_context32(struct sigcontext32 __user *sc) | ||
200 | { | ||
201 | int err, tmp; | ||
202 | while (1) { | ||
203 | lock_fpu_owner(); | ||
204 | own_fpu_inatomic(0); | ||
205 | err = restore_fp_context32(sc); /* this might fail */ | ||
206 | unlock_fpu_owner(); | ||
207 | if (likely(!err)) | ||
208 | break; | ||
209 | /* touch the sigcontext and try again */ | ||
210 | err = __get_user(tmp, &sc->sc_fpregs[0]) | | ||
211 | __get_user(tmp, &sc->sc_fpregs[31]) | | ||
212 | __get_user(tmp, &sc->sc_fpc_csr); | ||
213 | if (err) | ||
214 | break; /* really bad sigcontext */ | ||
215 | } | ||
216 | return err; | ||
217 | } | ||
218 | |||
186 | static int setup_sigcontext32(struct pt_regs *regs, | 219 | static int setup_sigcontext32(struct pt_regs *regs, |
187 | struct sigcontext32 __user *sc) | 220 | struct sigcontext32 __user *sc) |
188 | { | 221 | { |
189 | int err = 0; | 222 | int err = 0; |
190 | int i; | 223 | int i; |
224 | u32 used_math; | ||
191 | 225 | ||
192 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | 226 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); |
193 | 227 | ||
@@ -207,26 +241,31 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
207 | err |= __put_user(mflo3(), &sc->sc_lo3); | 241 | err |= __put_user(mflo3(), &sc->sc_lo3); |
208 | } | 242 | } |
209 | 243 | ||
210 | err |= __put_user(!!used_math(), &sc->sc_used_math); | 244 | used_math = !!used_math(); |
245 | err |= __put_user(used_math, &sc->sc_used_math); | ||
211 | 246 | ||
212 | if (used_math()) { | 247 | if (used_math) { |
213 | /* | 248 | /* |
214 | * Save FPU state to signal context. Signal handler | 249 | * Save FPU state to signal context. Signal handler |
215 | * will "inherit" current FPU state. | 250 | * will "inherit" current FPU state. |
216 | */ | 251 | */ |
217 | preempt_disable(); | 252 | err |= protected_save_fp_context32(sc); |
218 | |||
219 | if (!is_fpu_owner()) { | ||
220 | own_fpu(); | ||
221 | restore_fp(current); | ||
222 | } | ||
223 | err |= save_fp_context32(sc); | ||
224 | |||
225 | preempt_enable(); | ||
226 | } | 253 | } |
227 | return err; | 254 | return err; |
228 | } | 255 | } |
229 | 256 | ||
257 | static int | ||
258 | check_and_restore_fp_context32(struct sigcontext32 __user *sc) | ||
259 | { | ||
260 | int err, sig; | ||
261 | |||
262 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | ||
263 | if (err > 0) | ||
264 | err = 0; | ||
265 | err |= protected_restore_fp_context32(sc); | ||
266 | return err ?: sig; | ||
267 | } | ||
268 | |||
230 | static int restore_sigcontext32(struct pt_regs *regs, | 269 | static int restore_sigcontext32(struct pt_regs *regs, |
231 | struct sigcontext32 __user *sc) | 270 | struct sigcontext32 __user *sc) |
232 | { | 271 | { |
@@ -257,19 +296,15 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
257 | err |= __get_user(used_math, &sc->sc_used_math); | 296 | err |= __get_user(used_math, &sc->sc_used_math); |
258 | conditional_used_math(used_math); | 297 | conditional_used_math(used_math); |
259 | 298 | ||
260 | preempt_disable(); | 299 | if (used_math) { |
261 | |||
262 | if (used_math()) { | ||
263 | /* restore fpu context if we have used it before */ | 300 | /* restore fpu context if we have used it before */ |
264 | own_fpu(); | 301 | if (!err) |
265 | err |= restore_fp_context32(sc); | 302 | err = check_and_restore_fp_context32(sc); |
266 | } else { | 303 | } else { |
267 | /* signal handler may have used FPU. Give it up. */ | 304 | /* signal handler may have used FPU. Give it up. */ |
268 | lose_fpu(); | 305 | lose_fpu(0); |
269 | } | 306 | } |
270 | 307 | ||
271 | preempt_enable(); | ||
272 | |||
273 | return err; | 308 | return err; |
274 | } | 309 | } |
275 | 310 | ||
@@ -515,6 +550,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
515 | { | 550 | { |
516 | struct sigframe32 __user *frame; | 551 | struct sigframe32 __user *frame; |
517 | sigset_t blocked; | 552 | sigset_t blocked; |
553 | int sig; | ||
518 | 554 | ||
519 | frame = (struct sigframe32 __user *) regs.regs[29]; | 555 | frame = (struct sigframe32 __user *) regs.regs[29]; |
520 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 556 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -528,8 +564,11 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
528 | recalc_sigpending(); | 564 | recalc_sigpending(); |
529 | spin_unlock_irq(¤t->sighand->siglock); | 565 | spin_unlock_irq(¤t->sighand->siglock); |
530 | 566 | ||
531 | if (restore_sigcontext32(®s, &frame->sf_sc)) | 567 | sig = restore_sigcontext32(®s, &frame->sf_sc); |
568 | if (sig < 0) | ||
532 | goto badframe; | 569 | goto badframe; |
570 | else if (sig) | ||
571 | force_sig(sig, current); | ||
533 | 572 | ||
534 | /* | 573 | /* |
535 | * Don't let your children do this ... | 574 | * Don't let your children do this ... |
@@ -552,6 +591,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
552 | sigset_t set; | 591 | sigset_t set; |
553 | stack_t st; | 592 | stack_t st; |
554 | s32 sp; | 593 | s32 sp; |
594 | int sig; | ||
555 | 595 | ||
556 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; | 596 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; |
557 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 597 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -565,8 +605,11 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
565 | recalc_sigpending(); | 605 | recalc_sigpending(); |
566 | spin_unlock_irq(¤t->sighand->siglock); | 606 | spin_unlock_irq(¤t->sighand->siglock); |
567 | 607 | ||
568 | if (restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext)) | 608 | sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); |
609 | if (sig < 0) | ||
569 | goto badframe; | 610 | goto badframe; |
611 | else if (sig) | ||
612 | force_sig(sig, current); | ||
570 | 613 | ||
571 | /* The ucontext contains a stack32_t, so we must convert! */ | 614 | /* The ucontext contains a stack32_t, so we must convert! */ |
572 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 615 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
@@ -598,7 +641,7 @@ badframe: | |||
598 | force_sig(SIGSEGV, current); | 641 | force_sig(SIGSEGV, current); |
599 | } | 642 | } |
600 | 643 | ||
601 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 644 | static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
602 | int signr, sigset_t *set) | 645 | int signr, sigset_t *set) |
603 | { | 646 | { |
604 | struct sigframe32 __user *frame; | 647 | struct sigframe32 __user *frame; |
@@ -644,7 +687,7 @@ give_sigsegv: | |||
644 | return -EFAULT; | 687 | return -EFAULT; |
645 | } | 688 | } |
646 | 689 | ||
647 | int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 690 | static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
648 | int signr, sigset_t *set, siginfo_t *info) | 691 | int signr, sigset_t *set, siginfo_t *info) |
649 | { | 692 | { |
650 | struct rt_sigframe32 __user *frame; | 693 | struct rt_sigframe32 __user *frame; |
@@ -704,110 +747,14 @@ give_sigsegv: | |||
704 | return -EFAULT; | 747 | return -EFAULT; |
705 | } | 748 | } |
706 | 749 | ||
707 | static inline int handle_signal(unsigned long sig, siginfo_t *info, | 750 | /* |
708 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) | 751 | * o32 compatibility on 64-bit kernels, without DSP ASE |
709 | { | 752 | */ |
710 | int ret; | 753 | struct mips_abi mips_abi_32 = { |
711 | 754 | .setup_frame = setup_frame_32, | |
712 | switch (regs->regs[0]) { | 755 | .setup_rt_frame = setup_rt_frame_32, |
713 | case ERESTART_RESTARTBLOCK: | 756 | .restart = __NR_O32_restart_syscall |
714 | case ERESTARTNOHAND: | 757 | }; |
715 | regs->regs[2] = EINTR; | ||
716 | break; | ||
717 | case ERESTARTSYS: | ||
718 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
719 | regs->regs[2] = EINTR; | ||
720 | break; | ||
721 | } | ||
722 | /* fallthrough */ | ||
723 | case ERESTARTNOINTR: /* Userland will reload $v0. */ | ||
724 | regs->regs[7] = regs->regs[26]; | ||
725 | regs->cp0_epc -= 8; | ||
726 | } | ||
727 | |||
728 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
729 | |||
730 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
731 | ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); | ||
732 | else | ||
733 | ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); | ||
734 | |||
735 | spin_lock_irq(¤t->sighand->siglock); | ||
736 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
737 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
738 | sigaddset(¤t->blocked,sig); | ||
739 | recalc_sigpending(); | ||
740 | spin_unlock_irq(¤t->sighand->siglock); | ||
741 | |||
742 | return ret; | ||
743 | } | ||
744 | |||
745 | void do_signal32(struct pt_regs *regs) | ||
746 | { | ||
747 | struct k_sigaction ka; | ||
748 | sigset_t *oldset; | ||
749 | siginfo_t info; | ||
750 | int signr; | ||
751 | |||
752 | /* | ||
753 | * We want the common case to go fast, which is why we may in certain | ||
754 | * cases get here from kernel mode. Just return without doing anything | ||
755 | * if so. | ||
756 | */ | ||
757 | if (!user_mode(regs)) | ||
758 | return; | ||
759 | |||
760 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
761 | oldset = ¤t->saved_sigmask; | ||
762 | else | ||
763 | oldset = ¤t->blocked; | ||
764 | |||
765 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
766 | if (signr > 0) { | ||
767 | /* Whee! Actually deliver the signal. */ | ||
768 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | ||
769 | /* | ||
770 | * A signal was successfully delivered; the saved | ||
771 | * sigmask will have been stored in the signal frame, | ||
772 | * and will be restored by sigreturn, so we can simply | ||
773 | * clear the TIF_RESTORE_SIGMASK flag. | ||
774 | */ | ||
775 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
776 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
777 | } | ||
778 | |||
779 | return; | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * Who's code doesn't conform to the restartable syscall convention | ||
784 | * dies here!!! The li instruction, a single machine instruction, | ||
785 | * must directly be followed by the syscall instruction. | ||
786 | */ | ||
787 | if (regs->regs[0]) { | ||
788 | if (regs->regs[2] == ERESTARTNOHAND || | ||
789 | regs->regs[2] == ERESTARTSYS || | ||
790 | regs->regs[2] == ERESTARTNOINTR) { | ||
791 | regs->regs[7] = regs->regs[26]; | ||
792 | regs->cp0_epc -= 8; | ||
793 | } | ||
794 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { | ||
795 | regs->regs[2] = __NR_O32_restart_syscall; | ||
796 | regs->regs[7] = regs->regs[26]; | ||
797 | regs->cp0_epc -= 4; | ||
798 | } | ||
799 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
800 | } | ||
801 | |||
802 | /* | ||
803 | * If there's no signal to deliver, we just put the saved sigmask | ||
804 | * back | ||
805 | */ | ||
806 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
807 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
808 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
809 | } | ||
810 | } | ||
811 | 758 | ||
812 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, | 759 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, |
813 | struct sigaction32 __user *oact, | 760 | struct sigaction32 __user *oact, |
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 7ca2a078841f..a9202fa95987 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/compat.h> | 29 | #include <linux/compat.h> |
30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
31 | 31 | ||
32 | #include <asm/abi.h> | ||
32 | #include <asm/asm.h> | 33 | #include <asm/asm.h> |
33 | #include <asm/cacheflush.h> | 34 | #include <asm/cacheflush.h> |
34 | #include <asm/compat-signal.h> | 35 | #include <asm/compat-signal.h> |
@@ -126,6 +127,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
126 | sigset_t set; | 127 | sigset_t set; |
127 | stack_t st; | 128 | stack_t st; |
128 | s32 sp; | 129 | s32 sp; |
130 | int sig; | ||
129 | 131 | ||
130 | frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; | 132 | frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; |
131 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 133 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
@@ -139,8 +141,11 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
139 | recalc_sigpending(); | 141 | recalc_sigpending(); |
140 | spin_unlock_irq(¤t->sighand->siglock); | 142 | spin_unlock_irq(¤t->sighand->siglock); |
141 | 143 | ||
142 | if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) | 144 | sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); |
145 | if (sig < 0) | ||
143 | goto badframe; | 146 | goto badframe; |
147 | else if (sig) | ||
148 | force_sig(sig, current); | ||
144 | 149 | ||
145 | /* The ucontext contains a stack32_t, so we must convert! */ | 150 | /* The ucontext contains a stack32_t, so we must convert! */ |
146 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 151 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
@@ -169,7 +174,7 @@ badframe: | |||
169 | force_sig(SIGSEGV, current); | 174 | force_sig(SIGSEGV, current); |
170 | } | 175 | } |
171 | 176 | ||
172 | int setup_rt_frame_n32(struct k_sigaction * ka, | 177 | static int setup_rt_frame_n32(struct k_sigaction * ka, |
173 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) | 178 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) |
174 | { | 179 | { |
175 | struct rt_sigframe_n32 __user *frame; | 180 | struct rt_sigframe_n32 __user *frame; |
@@ -228,3 +233,8 @@ give_sigsegv: | |||
228 | force_sigsegv(signr, current); | 233 | force_sigsegv(signr, current); |
229 | return -EFAULT; | 234 | return -EFAULT; |
230 | } | 235 | } |
236 | |||
237 | struct mips_abi mips_abi_n32 = { | ||
238 | .setup_rt_frame = setup_rt_frame_n32, | ||
239 | .restart = __NR_N32_restart_syscall | ||
240 | }; | ||
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 0555fc554f65..c46e479c992b 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -51,31 +51,14 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ | |||
51 | EXPORT_SYMBOL(phys_cpu_present_map); | 51 | EXPORT_SYMBOL(phys_cpu_present_map); |
52 | EXPORT_SYMBOL(cpu_online_map); | 52 | EXPORT_SYMBOL(cpu_online_map); |
53 | 53 | ||
54 | /* This happens early in bootup, can't really do it better */ | ||
54 | static void smp_tune_scheduling (void) | 55 | static void smp_tune_scheduling (void) |
55 | { | 56 | { |
56 | struct cache_desc *cd = ¤t_cpu_data.scache; | 57 | struct cache_desc *cd = ¤t_cpu_data.scache; |
57 | unsigned long cachesize; /* kB */ | 58 | unsigned long cachesize = cd->linesz * cd->sets * cd->ways; |
58 | unsigned long cpu_khz; | ||
59 | 59 | ||
60 | /* | 60 | if (cachesize > max_cache_size) |
61 | * Crude estimate until we actually meassure ... | 61 | max_cache_size = cachesize; |
62 | */ | ||
63 | cpu_khz = loops_per_jiffy * 2 * HZ / 1000; | ||
64 | |||
65 | /* | ||
66 | * Rough estimation for SMP scheduling, this is the number of | ||
67 | * cycles it takes for a fully memory-limited process to flush | ||
68 | * the SMP-local cache. | ||
69 | * | ||
70 | * (For a P5 this pretty much means we will choose another idle | ||
71 | * CPU almost always at wakeup time (this is due to the small | ||
72 | * L1 cache), on PIIs it's around 50-100 usecs, depending on | ||
73 | * the cache size) | ||
74 | */ | ||
75 | if (!cpu_khz) | ||
76 | return; | ||
77 | |||
78 | cachesize = cd->linesz * cd->sets * cd->ways; | ||
79 | } | 62 | } |
80 | 63 | ||
81 | extern void __init calibrate_delay(void); | 64 | extern void __init calibrate_delay(void); |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 9251ea824937..5dcfab6b288e 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
5 | #include <linux/cpumask.h> | 5 | #include <linux/cpumask.h> |
6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
7 | #include <linux/kernel_stat.h> | ||
7 | #include <linux/module.h> | 8 | #include <linux/module.h> |
8 | 9 | ||
9 | #include <asm/cpu.h> | 10 | #include <asm/cpu.h> |
@@ -14,6 +15,7 @@ | |||
14 | #include <asm/hazards.h> | 15 | #include <asm/hazards.h> |
15 | #include <asm/mmu_context.h> | 16 | #include <asm/mmu_context.h> |
16 | #include <asm/smp.h> | 17 | #include <asm/smp.h> |
18 | #include <asm/mips-boards/maltaint.h> | ||
17 | #include <asm/mipsregs.h> | 19 | #include <asm/mipsregs.h> |
18 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
19 | #include <asm/time.h> | 21 | #include <asm/time.h> |
@@ -75,7 +77,7 @@ static struct smtc_ipi_q freeIPIq; | |||
75 | 77 | ||
76 | void ipi_decode(struct smtc_ipi *); | 78 | void ipi_decode(struct smtc_ipi *); |
77 | static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); | 79 | static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); |
78 | static void setup_cross_vpe_interrupts(void); | 80 | static void setup_cross_vpe_interrupts(unsigned int nvpe); |
79 | void init_smtc_stats(void); | 81 | void init_smtc_stats(void); |
80 | 82 | ||
81 | /* Global SMTC Status */ | 83 | /* Global SMTC Status */ |
@@ -141,10 +143,7 @@ __setup("ipibufs=", ipibufs); | |||
141 | __setup("nostlb", stlb_disable); | 143 | __setup("nostlb", stlb_disable); |
142 | __setup("asidmask=", asidmask_set); | 144 | __setup("asidmask=", asidmask_set); |
143 | 145 | ||
144 | /* Enable additional debug checks before going into CPU idle loop */ | 146 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
145 | #define SMTC_IDLE_HOOK_DEBUG | ||
146 | |||
147 | #ifdef SMTC_IDLE_HOOK_DEBUG | ||
148 | 147 | ||
149 | static int hang_trig = 0; | 148 | static int hang_trig = 0; |
150 | 149 | ||
@@ -171,12 +170,15 @@ __setup("tintq=", tintq); | |||
171 | 170 | ||
172 | int imstuckcount[2][8]; | 171 | int imstuckcount[2][8]; |
173 | /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ | 172 | /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ |
174 | int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}}; | 173 | int vpemask[2][8] = { |
174 | {0, 0, 1, 0, 0, 0, 0, 1}, | ||
175 | {0, 0, 0, 0, 0, 0, 0, 1} | ||
176 | }; | ||
175 | int tcnoprog[NR_CPUS]; | 177 | int tcnoprog[NR_CPUS]; |
176 | static atomic_t idle_hook_initialized = {0}; | 178 | static atomic_t idle_hook_initialized = {0}; |
177 | static int clock_hang_reported[NR_CPUS]; | 179 | static int clock_hang_reported[NR_CPUS]; |
178 | 180 | ||
179 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 181 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ |
180 | 182 | ||
181 | /* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */ | 183 | /* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */ |
182 | 184 | ||
@@ -394,10 +396,10 @@ void mipsmt_prepare_cpus(void) | |||
394 | printk("ASID mask value override to 0x%x\n", asidmask); | 396 | printk("ASID mask value override to 0x%x\n", asidmask); |
395 | 397 | ||
396 | /* Temporary */ | 398 | /* Temporary */ |
397 | #ifdef SMTC_IDLE_HOOK_DEBUG | 399 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
398 | if (hang_trig) | 400 | if (hang_trig) |
399 | printk("Logic Analyser Trigger on suspected TC hang\n"); | 401 | printk("Logic Analyser Trigger on suspected TC hang\n"); |
400 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 402 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ |
401 | 403 | ||
402 | /* Put MVPE's into 'configuration state' */ | 404 | /* Put MVPE's into 'configuration state' */ |
403 | write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC ); | 405 | write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC ); |
@@ -504,8 +506,7 @@ void mipsmt_prepare_cpus(void) | |||
504 | 506 | ||
505 | /* If we have multiple VPEs running, set up the cross-VPE interrupt */ | 507 | /* If we have multiple VPEs running, set up the cross-VPE interrupt */ |
506 | 508 | ||
507 | if (nvpe > 1) | 509 | setup_cross_vpe_interrupts(nvpe); |
508 | setup_cross_vpe_interrupts(); | ||
509 | 510 | ||
510 | /* Set up queue of free IPI "messages". */ | 511 | /* Set up queue of free IPI "messages". */ |
511 | nipi = NR_CPUS * IPIBUF_PER_CPU; | 512 | nipi = NR_CPUS * IPIBUF_PER_CPU; |
@@ -610,7 +611,12 @@ void smtc_cpus_done(void) | |||
610 | int setup_irq_smtc(unsigned int irq, struct irqaction * new, | 611 | int setup_irq_smtc(unsigned int irq, struct irqaction * new, |
611 | unsigned long hwmask) | 612 | unsigned long hwmask) |
612 | { | 613 | { |
614 | unsigned int vpe = current_cpu_data.vpe_id; | ||
615 | |||
613 | irq_hwmask[irq] = hwmask; | 616 | irq_hwmask[irq] = hwmask; |
617 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG | ||
618 | vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1; | ||
619 | #endif | ||
614 | 620 | ||
615 | return setup_irq(irq, new); | 621 | return setup_irq(irq, new); |
616 | } | 622 | } |
@@ -815,12 +821,15 @@ void ipi_decode(struct smtc_ipi *pipi) | |||
815 | smtc_ipi_nq(&freeIPIq, pipi); | 821 | smtc_ipi_nq(&freeIPIq, pipi); |
816 | switch (type_copy) { | 822 | switch (type_copy) { |
817 | case SMTC_CLOCK_TICK: | 823 | case SMTC_CLOCK_TICK: |
824 | irq_enter(); | ||
825 | kstat_this_cpu.irqs[MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR]++; | ||
818 | /* Invoke Clock "Interrupt" */ | 826 | /* Invoke Clock "Interrupt" */ |
819 | ipi_timer_latch[dest_copy] = 0; | 827 | ipi_timer_latch[dest_copy] = 0; |
820 | #ifdef SMTC_IDLE_HOOK_DEBUG | 828 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
821 | clock_hang_reported[dest_copy] = 0; | 829 | clock_hang_reported[dest_copy] = 0; |
822 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 830 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ |
823 | local_timer_interrupt(0, NULL); | 831 | local_timer_interrupt(0, NULL); |
832 | irq_exit(); | ||
824 | break; | 833 | break; |
825 | case LINUX_SMP_IPI: | 834 | case LINUX_SMP_IPI: |
826 | switch ((int)arg_copy) { | 835 | switch ((int)arg_copy) { |
@@ -968,8 +977,11 @@ static void ipi_irq_dispatch(void) | |||
968 | 977 | ||
969 | static struct irqaction irq_ipi; | 978 | static struct irqaction irq_ipi; |
970 | 979 | ||
971 | static void setup_cross_vpe_interrupts(void) | 980 | static void setup_cross_vpe_interrupts(unsigned int nvpe) |
972 | { | 981 | { |
982 | if (nvpe < 1) | ||
983 | return; | ||
984 | |||
973 | if (!cpu_has_vint) | 985 | if (!cpu_has_vint) |
974 | panic("SMTC Kernel requires Vectored Interupt support"); | 986 | panic("SMTC Kernel requires Vectored Interupt support"); |
975 | 987 | ||
@@ -987,10 +999,17 @@ static void setup_cross_vpe_interrupts(void) | |||
987 | 999 | ||
988 | /* | 1000 | /* |
989 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 1001 | * SMTC-specific hacks invoked from elsewhere in the kernel. |
1002 | * | ||
1003 | * smtc_ipi_replay is called from raw_local_irq_restore which is only ever | ||
1004 | * called with interrupts disabled. We do rely on interrupts being disabled | ||
1005 | * here because using spin_lock_irqsave()/spin_unlock_irqrestore() would | ||
1006 | * result in a recursive call to raw_local_irq_restore(). | ||
990 | */ | 1007 | */ |
991 | 1008 | ||
992 | void smtc_ipi_replay(void) | 1009 | static void __smtc_ipi_replay(void) |
993 | { | 1010 | { |
1011 | unsigned int cpu = smp_processor_id(); | ||
1012 | |||
994 | /* | 1013 | /* |
995 | * To the extent that we've ever turned interrupts off, | 1014 | * To the extent that we've ever turned interrupts off, |
996 | * we may have accumulated deferred IPIs. This is subtle. | 1015 | * we may have accumulated deferred IPIs. This is subtle. |
@@ -1005,22 +1024,35 @@ void smtc_ipi_replay(void) | |||
1005 | * is clear, and we'll handle it as a real pseudo-interrupt | 1024 | * is clear, and we'll handle it as a real pseudo-interrupt |
1006 | * and not a pseudo-pseudo interrupt. | 1025 | * and not a pseudo-pseudo interrupt. |
1007 | */ | 1026 | */ |
1008 | if (IPIQ[smp_processor_id()].depth > 0) { | 1027 | if (IPIQ[cpu].depth > 0) { |
1009 | struct smtc_ipi *pipi; | 1028 | while (1) { |
1010 | extern void self_ipi(struct smtc_ipi *); | 1029 | struct smtc_ipi_q *q = &IPIQ[cpu]; |
1030 | struct smtc_ipi *pipi; | ||
1031 | extern void self_ipi(struct smtc_ipi *); | ||
1032 | |||
1033 | spin_lock(&q->lock); | ||
1034 | pipi = __smtc_ipi_dq(q); | ||
1035 | spin_unlock(&q->lock); | ||
1036 | if (!pipi) | ||
1037 | break; | ||
1011 | 1038 | ||
1012 | while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { | ||
1013 | self_ipi(pipi); | 1039 | self_ipi(pipi); |
1014 | smtc_cpu_stats[smp_processor_id()].selfipis++; | 1040 | smtc_cpu_stats[cpu].selfipis++; |
1015 | } | 1041 | } |
1016 | } | 1042 | } |
1017 | } | 1043 | } |
1018 | 1044 | ||
1045 | void smtc_ipi_replay(void) | ||
1046 | { | ||
1047 | raw_local_irq_disable(); | ||
1048 | __smtc_ipi_replay(); | ||
1049 | } | ||
1050 | |||
1019 | EXPORT_SYMBOL(smtc_ipi_replay); | 1051 | EXPORT_SYMBOL(smtc_ipi_replay); |
1020 | 1052 | ||
1021 | void smtc_idle_loop_hook(void) | 1053 | void smtc_idle_loop_hook(void) |
1022 | { | 1054 | { |
1023 | #ifdef SMTC_IDLE_HOOK_DEBUG | 1055 | #ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG |
1024 | int im; | 1056 | int im; |
1025 | int flags; | 1057 | int flags; |
1026 | int mtflags; | 1058 | int mtflags; |
@@ -1113,14 +1145,20 @@ void smtc_idle_loop_hook(void) | |||
1113 | local_irq_restore(flags); | 1145 | local_irq_restore(flags); |
1114 | if (pdb_msg != &id_ho_db_msg[0]) | 1146 | if (pdb_msg != &id_ho_db_msg[0]) |
1115 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); | 1147 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); |
1116 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 1148 | #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ |
1117 | 1149 | ||
1118 | /* | 1150 | /* |
1119 | * Replay any accumulated deferred IPIs. If "Instant Replay" | 1151 | * Replay any accumulated deferred IPIs. If "Instant Replay" |
1120 | * is in use, there should never be any. | 1152 | * is in use, there should never be any. |
1121 | */ | 1153 | */ |
1122 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY | 1154 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY |
1123 | smtc_ipi_replay(); | 1155 | { |
1156 | unsigned long flags; | ||
1157 | |||
1158 | local_irq_save(flags); | ||
1159 | __smtc_ipi_replay(); | ||
1160 | local_irq_restore(flags); | ||
1161 | } | ||
1124 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ | 1162 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ |
1125 | } | 1163 | } |
1126 | 1164 | ||
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 2a932cada244..493cb29b8a42 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -229,6 +229,9 @@ void show_regs(struct pt_regs *regs) | |||
229 | printk("\n"); | 229 | printk("\n"); |
230 | } | 230 | } |
231 | 231 | ||
232 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | ||
233 | printk("Acx : %0*lx\n", field, regs->acx); | ||
234 | #endif | ||
232 | printk("Hi : %0*lx\n", field, regs->hi); | 235 | printk("Hi : %0*lx\n", field, regs->hi); |
233 | printk("Lo : %0*lx\n", field, regs->lo); | 236 | printk("Lo : %0*lx\n", field, regs->lo); |
234 | 237 | ||
@@ -340,13 +343,9 @@ NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs) | |||
340 | extern const struct exception_table_entry __start___dbe_table[]; | 343 | extern const struct exception_table_entry __start___dbe_table[]; |
341 | extern const struct exception_table_entry __stop___dbe_table[]; | 344 | extern const struct exception_table_entry __stop___dbe_table[]; |
342 | 345 | ||
343 | void __declare_dbe_table(void) | 346 | __asm__( |
344 | { | 347 | " .section __dbe_table, \"a\"\n" |
345 | __asm__ __volatile__( | 348 | " .previous \n"); |
346 | ".section\t__dbe_table,\"a\"\n\t" | ||
347 | ".previous" | ||
348 | ); | ||
349 | } | ||
350 | 349 | ||
351 | /* Given an address, look for it in the exception tables. */ | 350 | /* Given an address, look for it in the exception tables. */ |
352 | static const struct exception_table_entry *search_dbe_tables(unsigned long addr) | 351 | static const struct exception_table_entry *search_dbe_tables(unsigned long addr) |
@@ -611,16 +610,6 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
611 | if (fcr31 & FPU_CSR_UNI_X) { | 610 | if (fcr31 & FPU_CSR_UNI_X) { |
612 | int sig; | 611 | int sig; |
613 | 612 | ||
614 | preempt_disable(); | ||
615 | |||
616 | #ifdef CONFIG_PREEMPT | ||
617 | if (!is_fpu_owner()) { | ||
618 | /* We might lose fpu before disabling preempt... */ | ||
619 | own_fpu(); | ||
620 | BUG_ON(!used_math()); | ||
621 | restore_fp(current); | ||
622 | } | ||
623 | #endif | ||
624 | /* | 613 | /* |
625 | * Unimplemented operation exception. If we've got the full | 614 | * Unimplemented operation exception. If we've got the full |
626 | * software emulator on-board, let's use it... | 615 | * software emulator on-board, let's use it... |
@@ -631,18 +620,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
631 | * register operands before invoking the emulator, which seems | 620 | * register operands before invoking the emulator, which seems |
632 | * a bit extreme for what should be an infrequent event. | 621 | * a bit extreme for what should be an infrequent event. |
633 | */ | 622 | */ |
634 | save_fp(current); | ||
635 | /* Ensure 'resume' not overwrite saved fp context again. */ | 623 | /* Ensure 'resume' not overwrite saved fp context again. */ |
636 | lose_fpu(); | 624 | lose_fpu(1); |
637 | |||
638 | preempt_enable(); | ||
639 | 625 | ||
640 | /* Run the emulator */ | 626 | /* Run the emulator */ |
641 | sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); | 627 | sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); |
642 | 628 | ||
643 | preempt_disable(); | ||
644 | |||
645 | own_fpu(); /* Using the FPU again. */ | ||
646 | /* | 629 | /* |
647 | * We can't allow the emulated instruction to leave any of | 630 | * We can't allow the emulated instruction to leave any of |
648 | * the cause bit set in $fcr31. | 631 | * the cause bit set in $fcr31. |
@@ -650,9 +633,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
650 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; | 633 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; |
651 | 634 | ||
652 | /* Restore the hardware register state */ | 635 | /* Restore the hardware register state */ |
653 | restore_fp(current); | 636 | own_fpu(1); /* Using the FPU again. */ |
654 | |||
655 | preempt_enable(); | ||
656 | 637 | ||
657 | /* If something went wrong, signal */ | 638 | /* If something went wrong, signal */ |
658 | if (sig) | 639 | if (sig) |
@@ -669,7 +650,7 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
669 | unsigned int opcode, bcode; | 650 | unsigned int opcode, bcode; |
670 | siginfo_t info; | 651 | siginfo_t info; |
671 | 652 | ||
672 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) | 653 | if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
673 | goto out_sigsegv; | 654 | goto out_sigsegv; |
674 | 655 | ||
675 | /* | 656 | /* |
@@ -708,6 +689,7 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
708 | die_if_kernel("Break instruction in kernel code", regs); | 689 | die_if_kernel("Break instruction in kernel code", regs); |
709 | force_sig(SIGTRAP, current); | 690 | force_sig(SIGTRAP, current); |
710 | } | 691 | } |
692 | return; | ||
711 | 693 | ||
712 | out_sigsegv: | 694 | out_sigsegv: |
713 | force_sig(SIGSEGV, current); | 695 | force_sig(SIGSEGV, current); |
@@ -718,7 +700,7 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
718 | unsigned int opcode, tcode = 0; | 700 | unsigned int opcode, tcode = 0; |
719 | siginfo_t info; | 701 | siginfo_t info; |
720 | 702 | ||
721 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) | 703 | if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
722 | goto out_sigsegv; | 704 | goto out_sigsegv; |
723 | 705 | ||
724 | /* Immediate versions don't provide a code. */ | 706 | /* Immediate versions don't provide a code. */ |
@@ -751,6 +733,7 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
751 | die_if_kernel("Trap instruction in kernel code", regs); | 733 | die_if_kernel("Trap instruction in kernel code", regs); |
752 | force_sig(SIGTRAP, current); | 734 | force_sig(SIGTRAP, current); |
753 | } | 735 | } |
736 | return; | ||
754 | 737 | ||
755 | out_sigsegv: | 738 | out_sigsegv: |
756 | force_sig(SIGSEGV, current); | 739 | force_sig(SIGSEGV, current); |
@@ -790,21 +773,15 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
790 | break; | 773 | break; |
791 | 774 | ||
792 | case 1: | 775 | case 1: |
793 | preempt_disable(); | 776 | if (used_math()) /* Using the FPU again. */ |
794 | 777 | own_fpu(1); | |
795 | own_fpu(); | 778 | else { /* First time FPU user. */ |
796 | if (used_math()) { /* Using the FPU again. */ | ||
797 | restore_fp(current); | ||
798 | } else { /* First time FPU user. */ | ||
799 | init_fpu(); | 779 | init_fpu(); |
800 | set_used_math(); | 780 | set_used_math(); |
801 | } | 781 | } |
802 | 782 | ||
803 | if (cpu_has_fpu) { | 783 | if (!raw_cpu_has_fpu) { |
804 | preempt_enable(); | ||
805 | } else { | ||
806 | int sig; | 784 | int sig; |
807 | preempt_enable(); | ||
808 | sig = fpu_emulator_cop1Handler(regs, | 785 | sig = fpu_emulator_cop1Handler(regs, |
809 | ¤t->thread.fpu, 0); | 786 | ¤t->thread.fpu, 0); |
810 | if (sig) | 787 | if (sig) |
@@ -845,7 +822,6 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
845 | 822 | ||
846 | case 2: | 823 | case 2: |
847 | case 3: | 824 | case 3: |
848 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
849 | break; | 825 | break; |
850 | } | 826 | } |
851 | 827 | ||
@@ -1258,26 +1234,26 @@ static inline void mips_srs_init(void) | |||
1258 | /* | 1234 | /* |
1259 | * This is used by native signal handling | 1235 | * This is used by native signal handling |
1260 | */ | 1236 | */ |
1261 | asmlinkage int (*save_fp_context)(struct sigcontext *sc); | 1237 | asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); |
1262 | asmlinkage int (*restore_fp_context)(struct sigcontext *sc); | 1238 | asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); |
1263 | 1239 | ||
1264 | extern asmlinkage int _save_fp_context(struct sigcontext *sc); | 1240 | extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); |
1265 | extern asmlinkage int _restore_fp_context(struct sigcontext *sc); | 1241 | extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); |
1266 | 1242 | ||
1267 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); | 1243 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); |
1268 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); | 1244 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); |
1269 | 1245 | ||
1270 | #ifdef CONFIG_SMP | 1246 | #ifdef CONFIG_SMP |
1271 | static int smp_save_fp_context(struct sigcontext *sc) | 1247 | static int smp_save_fp_context(struct sigcontext __user *sc) |
1272 | { | 1248 | { |
1273 | return cpu_has_fpu | 1249 | return raw_cpu_has_fpu |
1274 | ? _save_fp_context(sc) | 1250 | ? _save_fp_context(sc) |
1275 | : fpu_emulator_save_context(sc); | 1251 | : fpu_emulator_save_context(sc); |
1276 | } | 1252 | } |
1277 | 1253 | ||
1278 | static int smp_restore_fp_context(struct sigcontext *sc) | 1254 | static int smp_restore_fp_context(struct sigcontext __user *sc) |
1279 | { | 1255 | { |
1280 | return cpu_has_fpu | 1256 | return raw_cpu_has_fpu |
1281 | ? _restore_fp_context(sc) | 1257 | ? _restore_fp_context(sc) |
1282 | : fpu_emulator_restore_context(sc); | 1258 | : fpu_emulator_restore_context(sc); |
1283 | } | 1259 | } |
@@ -1305,14 +1281,14 @@ static inline void signal_init(void) | |||
1305 | /* | 1281 | /* |
1306 | * This is used by 32-bit signal stuff on the 64-bit kernel | 1282 | * This is used by 32-bit signal stuff on the 64-bit kernel |
1307 | */ | 1283 | */ |
1308 | asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); | 1284 | asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); |
1309 | asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); | 1285 | asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); |
1310 | 1286 | ||
1311 | extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc); | 1287 | extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); |
1312 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc); | 1288 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); |
1313 | 1289 | ||
1314 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc); | 1290 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); |
1315 | extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc); | 1291 | extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc); |
1316 | 1292 | ||
1317 | static inline void signal32_init(void) | 1293 | static inline void signal32_init(void) |
1318 | { | 1294 | { |
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 7e7d54823486..24b7b053cfe9 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -515,7 +515,7 @@ asmlinkage void do_ade(struct pt_regs *regs) | |||
515 | goto sigbus; | 515 | goto sigbus; |
516 | 516 | ||
517 | pc = (unsigned int __user *) exception_epc(regs); | 517 | pc = (unsigned int __user *) exception_epc(regs); |
518 | if ((current->thread.mflags & MF_FIXADE) == 0) | 518 | if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0) |
519 | goto sigbus; | 519 | goto sigbus; |
520 | 520 | ||
521 | /* | 521 | /* |
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 9aca871a307f..c9ee9d2d5856 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
@@ -1079,6 +1079,7 @@ static int getcwd(char *buff, int size) | |||
1079 | static int vpe_open(struct inode *inode, struct file *filp) | 1079 | static int vpe_open(struct inode *inode, struct file *filp) |
1080 | { | 1080 | { |
1081 | int minor, ret; | 1081 | int minor, ret; |
1082 | enum vpe_state state; | ||
1082 | struct vpe *v; | 1083 | struct vpe *v; |
1083 | struct vpe_notifications *not; | 1084 | struct vpe_notifications *not; |
1084 | 1085 | ||
@@ -1093,7 +1094,8 @@ static int vpe_open(struct inode *inode, struct file *filp) | |||
1093 | return -ENODEV; | 1094 | return -ENODEV; |
1094 | } | 1095 | } |
1095 | 1096 | ||
1096 | if (v->state != VPE_STATE_UNUSED) { | 1097 | state = xchg(&v->state, VPE_STATE_INUSE); |
1098 | if (state != VPE_STATE_UNUSED) { | ||
1097 | dvpe(); | 1099 | dvpe(); |
1098 | 1100 | ||
1099 | printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); | 1101 | printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); |
@@ -1108,9 +1110,6 @@ static int vpe_open(struct inode *inode, struct file *filp) | |||
1108 | cleanup_tc(get_tc(minor)); | 1110 | cleanup_tc(get_tc(minor)); |
1109 | } | 1111 | } |
1110 | 1112 | ||
1111 | // allocate it so when we get write ops we know it's expected. | ||
1112 | v->state = VPE_STATE_INUSE; | ||
1113 | |||
1114 | /* this of-course trashes what was there before... */ | 1113 | /* this of-course trashes what was there before... */ |
1115 | v->pbuffer = vmalloc(P_SIZE); | 1114 | v->pbuffer = vmalloc(P_SIZE); |
1116 | v->plen = P_SIZE; | 1115 | v->plen = P_SIZE; |