diff options
Diffstat (limited to 'arch/mips/kernel')
26 files changed, 460 insertions, 380 deletions
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index d8e2674a1543..4a9f1ecefaf2 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c | |||
| @@ -103,8 +103,9 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) | |||
| 103 | * one divide. | 103 | * one divide. |
| 104 | */ | 104 | */ |
| 105 | u64 nsec = (u64)jiffies * TICK_NSEC; | 105 | u64 nsec = (u64)jiffies * TICK_NSEC; |
| 106 | value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); | 106 | long rem; |
| 107 | value->tv_usec /= NSEC_PER_USEC; | 107 | value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &rem); |
| 108 | value->tv_usec = rem / NSEC_PER_USEC; | ||
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | #define ELF_CORE_EFLAGS EF_MIPS_ABI2 | 111 | #define ELF_CORE_EFLAGS EF_MIPS_ABI2 |
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index cec5f327e360..e31813779895 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c | |||
| @@ -105,8 +105,9 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) | |||
| 105 | * one divide. | 105 | * one divide. |
| 106 | */ | 106 | */ |
| 107 | u64 nsec = (u64)jiffies * TICK_NSEC; | 107 | u64 nsec = (u64)jiffies * TICK_NSEC; |
| 108 | value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); | 108 | long rem; |
| 109 | value->tv_usec /= NSEC_PER_USEC; | 109 | value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &rem); |
| 110 | value->tv_usec = rem / NSEC_PER_USEC; | ||
| 110 | } | 111 | } |
| 111 | 112 | ||
| 112 | #undef ELF_CORE_COPY_REGS | 113 | #undef ELF_CORE_COPY_REGS |
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index fac48ad27b34..292f8b243a5e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | * Processor capabilities determination functions. | 2 | * Processor capabilities determination functions. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) xxxx the Anonymous | 4 | * Copyright (C) xxxx the Anonymous |
| 5 | * Copyright (C) 1994 - 2006 Ralf Baechle | ||
| 5 | * Copyright (C) 2003, 2004 Maciej W. Rozycki | 6 | * Copyright (C) 2003, 2004 Maciej W. Rozycki |
| 6 | * Copyright (C) 1994 - 2003 Ralf Baechle | ||
| 7 | * Copyright (C) 2001, 2004 MIPS Inc. | 7 | * Copyright (C) 2001, 2004 MIPS Inc. |
| 8 | * | 8 | * |
| 9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
| @@ -641,10 +641,9 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c) | |||
| 641 | switch (c->processor_id & 0xff00) { | 641 | switch (c->processor_id & 0xff00) { |
| 642 | case PRID_IMP_SB1: | 642 | case PRID_IMP_SB1: |
| 643 | c->cputype = CPU_SB1; | 643 | c->cputype = CPU_SB1; |
| 644 | #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS | ||
| 645 | /* FPU in pass1 is known to have issues. */ | 644 | /* FPU in pass1 is known to have issues. */ |
| 646 | c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR); | 645 | if ((c->processor_id & 0xff) < 0x20) |
| 647 | #endif | 646 | c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR); |
| 648 | break; | 647 | break; |
| 649 | case PRID_IMP_SB1A: | 648 | case PRID_IMP_SB1A: |
| 650 | c->cputype = CPU_SB1A; | 649 | c->cputype = CPU_SB1A; |
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c index 96d18c43dca0..d4f88e0af24c 100644 --- a/arch/mips/kernel/gdb-stub.c +++ b/arch/mips/kernel/gdb-stub.c | |||
| @@ -178,7 +178,7 @@ int kgdb_enabled; | |||
| 178 | */ | 178 | */ |
| 179 | static DEFINE_SPINLOCK(kgdb_lock); | 179 | static DEFINE_SPINLOCK(kgdb_lock); |
| 180 | static raw_spinlock_t kgdb_cpulock[NR_CPUS] = { | 180 | static raw_spinlock_t kgdb_cpulock[NR_CPUS] = { |
| 181 | [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED; | 181 | [0 ... NR_CPUS-1] = __RAW_SPIN_LOCK_UNLOCKED, |
| 182 | }; | 182 | }; |
| 183 | 183 | ||
| 184 | /* | 184 | /* |
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index aa18a8b7b380..13f22d1d0e8b 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S | |||
| @@ -233,11 +233,11 @@ NESTED(except_vec_nmi, 0, sp) | |||
| 233 | NESTED(nmi_handler, PT_SIZE, sp) | 233 | NESTED(nmi_handler, PT_SIZE, sp) |
| 234 | .set push | 234 | .set push |
| 235 | .set noat | 235 | .set noat |
| 236 | .set mips3 | ||
| 237 | SAVE_ALL | 236 | SAVE_ALL |
| 238 | move a0, sp | 237 | move a0, sp |
| 239 | jal nmi_exception_handler | 238 | jal nmi_exception_handler |
| 240 | RESTORE_ALL | 239 | RESTORE_ALL |
| 240 | .set mips3 | ||
| 241 | eret | 241 | eret |
| 242 | .set pop | 242 | .set pop |
| 243 | END(nmi_handler) | 243 | END(nmi_handler) |
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c index 0ac067f45cf5..0613f1f36b1b 100644 --- a/arch/mips/kernel/irq-mv6434x.c +++ b/arch/mips/kernel/irq-mv6434x.c | |||
| @@ -11,12 +11,14 @@ | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <asm/ptrace.h> | ||
| 15 | #include <linux/sched.h> | ||
| 16 | #include <linux/kernel_stat.h> | 14 | #include <linux/kernel_stat.h> |
| 15 | #include <linux/mv643xx.h> | ||
| 16 | #include <linux/sched.h> | ||
| 17 | |||
| 18 | #include <asm/ptrace.h> | ||
| 17 | #include <asm/io.h> | 19 | #include <asm/io.h> |
| 18 | #include <asm/irq.h> | 20 | #include <asm/irq.h> |
| 19 | #include <linux/mv643xx.h> | 21 | #include <asm/marvell.h> |
| 20 | 22 | ||
| 21 | static unsigned int irq_base; | 23 | static unsigned int irq_base; |
| 22 | 24 | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 60353f5acc48..e00e5f6e7fdd 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
| @@ -161,60 +161,6 @@ out: | |||
| 161 | return error; | 161 | return error; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | struct dirent32 { | ||
| 165 | unsigned int d_ino; | ||
| 166 | unsigned int d_off; | ||
| 167 | unsigned short d_reclen; | ||
| 168 | char d_name[NAME_MAX + 1]; | ||
| 169 | }; | ||
| 170 | |||
| 171 | static void | ||
| 172 | xlate_dirent(void *dirent64, void *dirent32, long n) | ||
| 173 | { | ||
| 174 | long off; | ||
| 175 | struct dirent *dirp; | ||
| 176 | struct dirent32 *dirp32; | ||
| 177 | |||
| 178 | off = 0; | ||
| 179 | while (off < n) { | ||
| 180 | dirp = (struct dirent *)(dirent64 + off); | ||
| 181 | dirp32 = (struct dirent32 *)(dirent32 + off); | ||
| 182 | off += dirp->d_reclen; | ||
| 183 | dirp32->d_ino = dirp->d_ino; | ||
| 184 | dirp32->d_off = (unsigned int)dirp->d_off; | ||
| 185 | dirp32->d_reclen = dirp->d_reclen; | ||
| 186 | strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2)); | ||
| 187 | } | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | asmlinkage long | ||
| 192 | sys32_getdents(unsigned int fd, void * dirent32, unsigned int count) | ||
| 193 | { | ||
| 194 | long n; | ||
| 195 | void *dirent64; | ||
| 196 | |||
| 197 | dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1)); | ||
| 198 | if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0) | ||
| 199 | return(n); | ||
| 200 | xlate_dirent(dirent64, dirent32, n); | ||
| 201 | return(n); | ||
| 202 | } | ||
| 203 | |||
| 204 | asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count); | ||
| 205 | |||
| 206 | asmlinkage int | ||
| 207 | sys32_readdir(unsigned int fd, void * dirent32, unsigned int count) | ||
| 208 | { | ||
| 209 | int n; | ||
| 210 | struct dirent dirent64; | ||
| 211 | |||
| 212 | if ((n = old_readdir(fd, &dirent64, count)) < 0) | ||
| 213 | return(n); | ||
| 214 | xlate_dirent(&dirent64, dirent32, dirent64.d_reclen); | ||
| 215 | return(n); | ||
| 216 | } | ||
| 217 | |||
| 218 | asmlinkage int | 164 | asmlinkage int |
| 219 | sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) | 165 | sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) |
| 220 | { | 166 | { |
| @@ -230,6 +176,9 @@ sysn32_waitid(int which, compat_pid_t pid, | |||
| 230 | long ret; | 176 | long ret; |
| 231 | mm_segment_t old_fs = get_fs(); | 177 | mm_segment_t old_fs = get_fs(); |
| 232 | 178 | ||
| 179 | if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo))) | ||
| 180 | return -EFAULT; | ||
| 181 | |||
| 233 | set_fs (KERNEL_DS); | 182 | set_fs (KERNEL_DS); |
| 234 | ret = sys_waitid(which, pid, uinfo, options, | 183 | ret = sys_waitid(which, pid, uinfo, options, |
| 235 | uru ? (struct rusage __user *) &ru : NULL); | 184 | uru ? (struct rusage __user *) &ru : NULL); |
| @@ -1450,25 +1399,6 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *ti | |||
| 1450 | return sys_timer_create(clock, p, timer_id); | 1399 | return sys_timer_create(clock, p, timer_id); |
| 1451 | } | 1400 | } |
| 1452 | 1401 | ||
| 1453 | asmlinkage long | ||
| 1454 | sysn32_rt_sigtimedwait(const sigset_t __user *uthese, | ||
| 1455 | siginfo_t __user *uinfo, | ||
| 1456 | const struct compat_timespec __user *uts32, | ||
| 1457 | size_t sigsetsize) | ||
| 1458 | { | ||
| 1459 | struct timespec __user *uts = NULL; | ||
| 1460 | |||
| 1461 | if (uts32) { | ||
| 1462 | struct timespec ts; | ||
| 1463 | uts = compat_alloc_user_space(sizeof(struct timespec)); | ||
| 1464 | if (get_user(ts.tv_sec, &uts32->tv_sec) || | ||
| 1465 | get_user(ts.tv_nsec, &uts32->tv_nsec) || | ||
| 1466 | copy_to_user (uts, &ts, sizeof (ts))) | ||
| 1467 | return -EFAULT; | ||
| 1468 | } | ||
| 1469 | return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | save_static_function(sys32_clone); | 1402 | save_static_function(sys32_clone); |
| 1473 | __attribute_used__ noinline static int | 1403 | __attribute_used__ noinline static int |
| 1474 | _sys32_clone(nabi_no_regargs struct pt_regs regs) | 1404 | _sys32_clone(nabi_no_regargs struct pt_regs regs) |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index fa98f10d0132..092679c2dca9 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * for more details. | 4 | * for more details. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. | 6 | * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. |
| 7 | * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org) | ||
| 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
| 8 | * Copyright (C) 2004 Thiemo Seufer | 9 | * Copyright (C) 2004 Thiemo Seufer |
| 9 | */ | 10 | */ |
| @@ -24,6 +25,7 @@ | |||
| 24 | #include <linux/a.out.h> | 25 | #include <linux/a.out.h> |
| 25 | #include <linux/init.h> | 26 | #include <linux/init.h> |
| 26 | #include <linux/completion.h> | 27 | #include <linux/completion.h> |
| 28 | #include <linux/kallsyms.h> | ||
| 27 | 29 | ||
| 28 | #include <asm/abi.h> | 30 | #include <asm/abi.h> |
| 29 | #include <asm/bootinfo.h> | 31 | #include <asm/bootinfo.h> |
| @@ -58,8 +60,8 @@ ATTRIB_NORET void cpu_idle(void) | |||
| 58 | } | 60 | } |
| 59 | } | 61 | } |
| 60 | 62 | ||
| 61 | extern int do_signal(sigset_t *oldset, struct pt_regs *regs); | 63 | extern void do_signal(struct pt_regs *regs); |
| 62 | extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); | 64 | extern void do_signal32(struct pt_regs *regs); |
| 63 | 65 | ||
| 64 | /* | 66 | /* |
| 65 | * Native o32 and N64 ABI without DSP ASE | 67 | * Native o32 and N64 ABI without DSP ASE |
| @@ -271,46 +273,19 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |||
| 271 | 273 | ||
| 272 | static struct mips_frame_info { | 274 | static struct mips_frame_info { |
| 273 | void *func; | 275 | void *func; |
| 274 | int omit_fp; /* compiled without fno-omit-frame-pointer */ | 276 | unsigned long func_size; |
| 275 | int frame_offset; | 277 | int frame_size; |
| 276 | int pc_offset; | 278 | int pc_offset; |
| 277 | } schedule_frame, mfinfo[] = { | 279 | } *schedule_frame, mfinfo[64]; |
| 278 | { schedule, 0 }, /* must be first */ | 280 | static int mfinfo_num; |
| 279 | /* arch/mips/kernel/semaphore.c */ | ||
| 280 | { __down, 1 }, | ||
| 281 | { __down_interruptible, 1 }, | ||
| 282 | /* kernel/sched.c */ | ||
| 283 | #ifdef CONFIG_PREEMPT | ||
| 284 | { preempt_schedule, 0 }, | ||
| 285 | #endif | ||
| 286 | { wait_for_completion, 0 }, | ||
| 287 | { interruptible_sleep_on, 0 }, | ||
| 288 | { interruptible_sleep_on_timeout, 0 }, | ||
| 289 | { sleep_on, 0 }, | ||
| 290 | { sleep_on_timeout, 0 }, | ||
| 291 | { yield, 0 }, | ||
| 292 | { io_schedule, 0 }, | ||
| 293 | { io_schedule_timeout, 0 }, | ||
| 294 | #if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) | ||
| 295 | { __preempt_spin_lock, 0 }, | ||
| 296 | { __preempt_write_lock, 0 }, | ||
| 297 | #endif | ||
| 298 | /* kernel/timer.c */ | ||
| 299 | { schedule_timeout, 1 }, | ||
| 300 | /* { nanosleep_restart, 1 }, */ | ||
| 301 | /* lib/rwsem-spinlock.c */ | ||
| 302 | { __down_read, 1 }, | ||
| 303 | { __down_write, 1 }, | ||
| 304 | }; | ||
| 305 | 281 | ||
| 306 | static int mips_frame_info_initialized; | ||
| 307 | static int __init get_frame_info(struct mips_frame_info *info) | 282 | static int __init get_frame_info(struct mips_frame_info *info) |
| 308 | { | 283 | { |
| 309 | int i; | 284 | int i; |
| 310 | void *func = info->func; | 285 | void *func = info->func; |
| 311 | union mips_instruction *ip = (union mips_instruction *)func; | 286 | union mips_instruction *ip = (union mips_instruction *)func; |
| 312 | info->pc_offset = -1; | 287 | info->pc_offset = -1; |
| 313 | info->frame_offset = info->omit_fp ? 0 : -1; | 288 | info->frame_size = 0; |
| 314 | for (i = 0; i < 128; i++, ip++) { | 289 | for (i = 0; i < 128; i++, ip++) { |
| 315 | /* if jal, jalr, jr, stop. */ | 290 | /* if jal, jalr, jr, stop. */ |
| 316 | if (ip->j_format.opcode == jal_op || | 291 | if (ip->j_format.opcode == jal_op || |
| @@ -319,6 +294,23 @@ static int __init get_frame_info(struct mips_frame_info *info) | |||
| 319 | ip->r_format.func == jr_op))) | 294 | ip->r_format.func == jr_op))) |
| 320 | break; | 295 | break; |
| 321 | 296 | ||
| 297 | if (info->func_size && i >= info->func_size / 4) | ||
| 298 | break; | ||
| 299 | if ( | ||
| 300 | #ifdef CONFIG_32BIT | ||
| 301 | ip->i_format.opcode == addiu_op && | ||
| 302 | #endif | ||
| 303 | #ifdef CONFIG_64BIT | ||
| 304 | ip->i_format.opcode == daddiu_op && | ||
| 305 | #endif | ||
| 306 | ip->i_format.rs == 29 && | ||
| 307 | ip->i_format.rt == 29) { | ||
| 308 | /* addiu/daddiu sp,sp,-imm */ | ||
| 309 | if (info->frame_size) | ||
| 310 | continue; | ||
| 311 | info->frame_size = - ip->i_format.simmediate; | ||
| 312 | } | ||
| 313 | |||
| 322 | if ( | 314 | if ( |
| 323 | #ifdef CONFIG_32BIT | 315 | #ifdef CONFIG_32BIT |
| 324 | ip->i_format.opcode == sw_op && | 316 | ip->i_format.opcode == sw_op && |
| @@ -326,31 +318,20 @@ static int __init get_frame_info(struct mips_frame_info *info) | |||
| 326 | #ifdef CONFIG_64BIT | 318 | #ifdef CONFIG_64BIT |
| 327 | ip->i_format.opcode == sd_op && | 319 | ip->i_format.opcode == sd_op && |
| 328 | #endif | 320 | #endif |
| 329 | ip->i_format.rs == 29) | 321 | ip->i_format.rs == 29 && |
| 330 | { | 322 | ip->i_format.rt == 31) { |
| 331 | /* sw / sd $ra, offset($sp) */ | 323 | /* sw / sd $ra, offset($sp) */ |
| 332 | if (ip->i_format.rt == 31) { | 324 | if (info->pc_offset != -1) |
| 333 | if (info->pc_offset != -1) | 325 | continue; |
| 334 | continue; | 326 | info->pc_offset = |
| 335 | info->pc_offset = | 327 | ip->i_format.simmediate / sizeof(long); |
| 336 | ip->i_format.simmediate / sizeof(long); | ||
| 337 | } | ||
| 338 | /* sw / sd $s8, offset($sp) */ | ||
| 339 | if (ip->i_format.rt == 30) { | ||
| 340 | //#if 0 /* gcc 3.4 does aggressive optimization... */ | ||
| 341 | if (info->frame_offset != -1) | ||
| 342 | continue; | ||
| 343 | //#endif | ||
| 344 | info->frame_offset = | ||
| 345 | ip->i_format.simmediate / sizeof(long); | ||
| 346 | } | ||
| 347 | } | 328 | } |
| 348 | } | 329 | } |
| 349 | if (info->pc_offset == -1 || info->frame_offset == -1) { | 330 | if (info->pc_offset == -1 || info->frame_size == 0) { |
| 350 | printk("Can't analyze prologue code at %p\n", func); | 331 | if (func == schedule) |
| 332 | printk("Can't analyze prologue code at %p\n", func); | ||
| 351 | info->pc_offset = -1; | 333 | info->pc_offset = -1; |
| 352 | info->frame_offset = -1; | 334 | info->frame_size = 0; |
| 353 | return -1; | ||
| 354 | } | 335 | } |
| 355 | 336 | ||
| 356 | return 0; | 337 | return 0; |
| @@ -358,25 +339,36 @@ static int __init get_frame_info(struct mips_frame_info *info) | |||
| 358 | 339 | ||
| 359 | static int __init frame_info_init(void) | 340 | static int __init frame_info_init(void) |
| 360 | { | 341 | { |
| 361 | int i, found; | 342 | int i; |
| 362 | for (i = 0; i < ARRAY_SIZE(mfinfo); i++) | 343 | #ifdef CONFIG_KALLSYMS |
| 363 | if (get_frame_info(&mfinfo[i])) | 344 | char *modname; |
| 364 | return -1; | 345 | char namebuf[KSYM_NAME_LEN + 1]; |
| 365 | schedule_frame = mfinfo[0]; | 346 | unsigned long start, size, ofs; |
| 366 | /* bubble sort */ | 347 | extern char __sched_text_start[], __sched_text_end[]; |
| 367 | do { | 348 | extern char __lock_text_start[], __lock_text_end[]; |
| 368 | struct mips_frame_info tmp; | 349 | |
| 369 | found = 0; | 350 | start = (unsigned long)__sched_text_start; |
| 370 | for (i = 1; i < ARRAY_SIZE(mfinfo); i++) { | 351 | for (i = 0; i < ARRAY_SIZE(mfinfo); i++) { |
| 371 | if (mfinfo[i-1].func > mfinfo[i].func) { | 352 | if (start == (unsigned long)schedule) |
| 372 | tmp = mfinfo[i]; | 353 | schedule_frame = &mfinfo[i]; |
| 373 | mfinfo[i] = mfinfo[i-1]; | 354 | if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf)) |
| 374 | mfinfo[i-1] = tmp; | 355 | break; |
| 375 | found = 1; | 356 | mfinfo[i].func = (void *)(start + ofs); |
| 376 | } | 357 | mfinfo[i].func_size = size; |
| 377 | } | 358 | start += size - ofs; |
| 378 | } while (found); | 359 | if (start >= (unsigned long)__lock_text_end) |
| 379 | mips_frame_info_initialized = 1; | 360 | break; |
| 361 | if (start == (unsigned long)__sched_text_end) | ||
| 362 | start = (unsigned long)__lock_text_start; | ||
| 363 | } | ||
| 364 | #else | ||
| 365 | mfinfo[0].func = schedule; | ||
| 366 | schedule_frame = &mfinfo[0]; | ||
| 367 | #endif | ||
| 368 | for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++) | ||
| 369 | get_frame_info(&mfinfo[i]); | ||
| 370 | |||
| 371 | mfinfo_num = i; | ||
| 380 | return 0; | 372 | return 0; |
| 381 | } | 373 | } |
| 382 | 374 | ||
| @@ -393,47 +385,52 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
| 393 | if (t->reg31 == (unsigned long) ret_from_fork) | 385 | if (t->reg31 == (unsigned long) ret_from_fork) |
| 394 | return t->reg31; | 386 | return t->reg31; |
| 395 | 387 | ||
| 396 | if (schedule_frame.pc_offset < 0) | 388 | if (!schedule_frame || schedule_frame->pc_offset < 0) |
| 397 | return 0; | 389 | return 0; |
| 398 | return ((unsigned long *)t->reg29)[schedule_frame.pc_offset]; | 390 | return ((unsigned long *)t->reg29)[schedule_frame->pc_offset]; |
| 399 | } | 391 | } |
| 400 | 392 | ||
| 401 | /* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */ | 393 | /* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */ |
| 402 | unsigned long get_wchan(struct task_struct *p) | 394 | unsigned long get_wchan(struct task_struct *p) |
| 403 | { | 395 | { |
| 404 | unsigned long stack_page; | 396 | unsigned long stack_page; |
| 405 | unsigned long frame, pc; | 397 | unsigned long pc; |
| 398 | #ifdef CONFIG_KALLSYMS | ||
| 399 | unsigned long frame; | ||
| 400 | #endif | ||
| 406 | 401 | ||
| 407 | if (!p || p == current || p->state == TASK_RUNNING) | 402 | if (!p || p == current || p->state == TASK_RUNNING) |
| 408 | return 0; | 403 | return 0; |
| 409 | 404 | ||
| 410 | stack_page = (unsigned long)task_stack_page(p); | 405 | stack_page = (unsigned long)task_stack_page(p); |
| 411 | if (!stack_page || !mips_frame_info_initialized) | 406 | if (!stack_page || !mfinfo_num) |
| 412 | return 0; | 407 | return 0; |
| 413 | 408 | ||
| 414 | pc = thread_saved_pc(p); | 409 | pc = thread_saved_pc(p); |
| 410 | #ifdef CONFIG_KALLSYMS | ||
| 415 | if (!in_sched_functions(pc)) | 411 | if (!in_sched_functions(pc)) |
| 416 | return pc; | 412 | return pc; |
| 417 | 413 | ||
| 418 | frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset]; | 414 | frame = p->thread.reg29 + schedule_frame->frame_size; |
| 419 | do { | 415 | do { |
| 420 | int i; | 416 | int i; |
| 421 | 417 | ||
| 422 | if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32) | 418 | if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32) |
| 423 | return 0; | 419 | return 0; |
| 424 | 420 | ||
| 425 | for (i = ARRAY_SIZE(mfinfo) - 1; i >= 0; i--) { | 421 | for (i = mfinfo_num - 1; i >= 0; i--) { |
| 426 | if (pc >= (unsigned long) mfinfo[i].func) | 422 | if (pc >= (unsigned long) mfinfo[i].func) |
| 427 | break; | 423 | break; |
| 428 | } | 424 | } |
| 429 | if (i < 0) | 425 | if (i < 0) |
| 430 | break; | 426 | break; |
| 431 | 427 | ||
| 432 | if (mfinfo[i].omit_fp) | ||
| 433 | break; | ||
| 434 | pc = ((unsigned long *)frame)[mfinfo[i].pc_offset]; | 428 | pc = ((unsigned long *)frame)[mfinfo[i].pc_offset]; |
| 435 | frame = ((unsigned long *)frame)[mfinfo[i].frame_offset]; | 429 | if (!mfinfo[i].frame_size) |
| 430 | break; | ||
| 431 | frame += mfinfo[i].frame_size; | ||
| 436 | } while (in_sched_functions(pc)); | 432 | } while (in_sched_functions(pc)); |
| 433 | #endif | ||
| 437 | 434 | ||
| 438 | return pc; | 435 | return pc; |
| 439 | } | 436 | } |
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 0c82b25d8c6d..0d5cf97af727 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c | |||
| @@ -88,7 +88,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
| 88 | ret = -EIO; | 88 | ret = -EIO; |
| 89 | if (copied != sizeof(tmp)) | 89 | if (copied != sizeof(tmp)) |
| 90 | break; | 90 | break; |
| 91 | ret = put_user(tmp, (unsigned int *) (unsigned long) data); | 91 | ret = put_user(tmp, (unsigned int __user *) (unsigned long) data); |
| 92 | break; | 92 | break; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| @@ -174,8 +174,10 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
| 174 | case FPC_EIR: { /* implementation / version register */ | 174 | case FPC_EIR: { /* implementation / version register */ |
| 175 | unsigned int flags; | 175 | unsigned int flags; |
| 176 | 176 | ||
| 177 | if (!cpu_has_fpu) | 177 | if (!cpu_has_fpu) { |
| 178 | tmp = 0; | ||
| 178 | break; | 179 | break; |
| 180 | } | ||
| 179 | 181 | ||
| 180 | preempt_disable(); | 182 | preempt_disable(); |
| 181 | if (cpu_has_mipsmt) { | 183 | if (cpu_has_mipsmt) { |
| @@ -194,15 +196,18 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
| 194 | preempt_enable(); | 196 | preempt_enable(); |
| 195 | break; | 197 | break; |
| 196 | } | 198 | } |
| 197 | case DSP_BASE ... DSP_BASE + 5: | 199 | case DSP_BASE ... DSP_BASE + 5: { |
| 200 | dspreg_t *dregs; | ||
| 201 | |||
| 198 | if (!cpu_has_dsp) { | 202 | if (!cpu_has_dsp) { |
| 199 | tmp = 0; | 203 | tmp = 0; |
| 200 | ret = -EIO; | 204 | ret = -EIO; |
| 201 | goto out_tsk; | 205 | goto out_tsk; |
| 202 | } | 206 | } |
| 203 | dspreg_t *dregs = __get_dsp_regs(child); | 207 | dregs = __get_dsp_regs(child); |
| 204 | tmp = (unsigned long) (dregs[addr - DSP_BASE]); | 208 | tmp = (unsigned long) (dregs[addr - DSP_BASE]); |
| 205 | break; | 209 | break; |
| 210 | } | ||
| 206 | case DSP_CONTROL: | 211 | case DSP_CONTROL: |
| 207 | if (!cpu_has_dsp) { | 212 | if (!cpu_has_dsp) { |
| 208 | tmp = 0; | 213 | tmp = 0; |
| @@ -216,7 +221,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
| 216 | ret = -EIO; | 221 | ret = -EIO; |
| 217 | goto out_tsk; | 222 | goto out_tsk; |
| 218 | } | 223 | } |
| 219 | ret = put_user(tmp, (unsigned *) (unsigned long) data); | 224 | ret = put_user(tmp, (unsigned __user *) (unsigned long) data); |
| 220 | break; | 225 | break; |
| 221 | } | 226 | } |
| 222 | 227 | ||
| @@ -304,15 +309,18 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) | |||
| 304 | else | 309 | else |
| 305 | child->thread.fpu.soft.fcr31 = data; | 310 | child->thread.fpu.soft.fcr31 = data; |
| 306 | break; | 311 | break; |
| 307 | case DSP_BASE ... DSP_BASE + 5: | 312 | case DSP_BASE ... DSP_BASE + 5: { |
| 313 | dspreg_t *dregs; | ||
| 314 | |||
| 308 | if (!cpu_has_dsp) { | 315 | if (!cpu_has_dsp) { |
| 309 | ret = -EIO; | 316 | ret = -EIO; |
| 310 | break; | 317 | break; |
| 311 | } | 318 | } |
| 312 | 319 | ||
| 313 | dspreg_t *dregs = __get_dsp_regs(child); | 320 | dregs = __get_dsp_regs(child); |
| 314 | dregs[addr - DSP_BASE] = data; | 321 | dregs[addr - DSP_BASE] = data; |
| 315 | break; | 322 | break; |
| 323 | } | ||
| 316 | case DSP_CONTROL: | 324 | case DSP_CONTROL: |
| 317 | if (!cpu_has_dsp) { | 325 | if (!cpu_has_dsp) { |
| 318 | ret = -EIO; | 326 | ret = -EIO; |
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index 5e37df3111ad..621037db2290 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c | |||
| @@ -3,17 +3,16 @@ | |||
| 3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
| 4 | * for more details. | 4 | * for more details. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2001 by Ralf Baechle | 6 | * Copyright (C) 2001, 06 by Ralf Baechle (ralf@linux-mips.org) |
| 7 | * Copyright (C) 2001 MIPS Technologies, Inc. | 7 | * Copyright (C) 2001 MIPS Technologies, Inc. |
| 8 | */ | 8 | */ |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/pm.h> | ||
| 11 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 12 | #include <linux/reboot.h> | 13 | #include <linux/reboot.h> |
| 13 | #include <asm/reboot.h> | ||
| 14 | 14 | ||
| 15 | void (*pm_power_off)(void); | 15 | #include <asm/reboot.h> |
| 16 | EXPORT_SYMBOL(pm_power_off); | ||
| 17 | 16 | ||
| 18 | /* | 17 | /* |
| 19 | * Urgs ... Too many MIPS machines to handle this in a generic way. | 18 | * Urgs ... Too many MIPS machines to handle this in a generic way. |
| @@ -22,23 +21,22 @@ EXPORT_SYMBOL(pm_power_off); | |||
| 22 | */ | 21 | */ |
| 23 | void (*_machine_restart)(char *command); | 22 | void (*_machine_restart)(char *command); |
| 24 | void (*_machine_halt)(void); | 23 | void (*_machine_halt)(void); |
| 25 | void (*_machine_power_off)(void); | 24 | void (*pm_power_off)(void); |
| 26 | 25 | ||
| 27 | void machine_restart(char *command) | 26 | void machine_restart(char *command) |
| 28 | { | 27 | { |
| 29 | _machine_restart(command); | 28 | if (_machine_restart) |
| 29 | _machine_restart(command); | ||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void machine_halt(void) | 32 | void machine_halt(void) |
| 33 | { | 33 | { |
| 34 | _machine_halt(); | 34 | if (_machine_halt) |
| 35 | _machine_halt(); | ||
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | void machine_power_off(void) | 38 | void machine_power_off(void) |
| 38 | { | 39 | { |
| 39 | if (pm_power_off) | 40 | if (pm_power_off) |
| 40 | pm_power_off(); | 41 | pm_power_off(); |
| 41 | |||
| 42 | _machine_power_off(); | ||
| 43 | } | 42 | } |
| 44 | |||
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 1d855112bac2..986a9cf23067 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. | 2 | * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. |
| 3 | * Copyright (C) 2005, 06 Ralf Baechle (ralf@linux-mips.org) | ||
| 3 | * | 4 | * |
| 4 | * This program is free software; you can distribute it and/or modify it | 5 | * This program is free software; you can distribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License (Version 2) as | 6 | * under the terms of the GNU General Public License (Version 2) as |
| @@ -20,9 +21,12 @@ | |||
| 20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 21 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
| 22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/irq.h> | ||
| 23 | #include <linux/poll.h> | 26 | #include <linux/poll.h> |
| 24 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
| 25 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
| 29 | |||
| 26 | #include <asm/mipsmtregs.h> | 30 | #include <asm/mipsmtregs.h> |
| 27 | #include <asm/bitops.h> | 31 | #include <asm/bitops.h> |
| 28 | #include <asm/cpu.h> | 32 | #include <asm/cpu.h> |
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index a42e0e8caa7b..2f2dc54b2e26 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S | |||
| @@ -617,6 +617,23 @@ einval: li v0, -EINVAL | |||
| 617 | sys sys_inotify_init 0 | 617 | sys sys_inotify_init 0 |
| 618 | sys sys_inotify_add_watch 3 /* 4285 */ | 618 | sys sys_inotify_add_watch 3 /* 4285 */ |
| 619 | sys sys_inotify_rm_watch 2 | 619 | sys sys_inotify_rm_watch 2 |
| 620 | sys sys_migrate_pages 4 | ||
| 621 | sys sys_openat 4 | ||
| 622 | sys sys_mkdirat 3 | ||
| 623 | sys sys_mknodat 4 /* 4290 */ | ||
| 624 | sys sys_fchownat 5 | ||
| 625 | sys sys_futimesat 3 | ||
| 626 | sys sys_fstatat64 4 | ||
| 627 | sys sys_unlinkat 3 | ||
| 628 | sys sys_renameat 4 /* 4295 */ | ||
| 629 | sys sys_linkat 5 | ||
| 630 | sys sys_symlinkat 3 | ||
| 631 | sys sys_readlinkat 4 | ||
| 632 | sys sys_fchmodat 3 | ||
| 633 | sys sys_faccessat 3 /* 4300 */ | ||
| 634 | sys sys_pselect6 6 | ||
| 635 | sys sys_ppoll 5 | ||
| 636 | sys sys_unshare 1 | ||
| 620 | .endm | 637 | .endm |
| 621 | 638 | ||
| 622 | /* We pre-compute the number of _instruction_ bytes needed to | 639 | /* 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 47bfbd416709..98bf25df56f3 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S | |||
| @@ -443,3 +443,20 @@ sys_call_table: | |||
| 443 | PTR sys_inotify_init | 443 | PTR sys_inotify_init |
| 444 | PTR sys_inotify_add_watch | 444 | PTR sys_inotify_add_watch |
| 445 | PTR sys_inotify_rm_watch /* 5245 */ | 445 | PTR sys_inotify_rm_watch /* 5245 */ |
| 446 | PTR sys_migrate_pages | ||
| 447 | PTR sys_openat | ||
| 448 | PTR sys_mkdirat | ||
| 449 | PTR sys_mknodat | ||
| 450 | PTR sys_fchownat /* 5250 */ | ||
| 451 | PTR sys_futimesat | ||
| 452 | PTR sys_newfstatat | ||
| 453 | PTR sys_unlinkat | ||
| 454 | PTR sys_renameat | ||
| 455 | PTR sys_linkat /* 5255 */ | ||
| 456 | PTR sys_symlinkat | ||
| 457 | PTR sys_readlinkat | ||
| 458 | PTR sys_fchmodat | ||
| 459 | PTR sys_faccessat | ||
| 460 | PTR sys_pselect6 /* 5260 */ | ||
| 461 | PTR sys_ppoll | ||
| 462 | PTR sys_unshare | ||
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index b465ced1758f..02c8267e45e7 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
| @@ -195,7 +195,7 @@ EXPORT(sysn32_call_table) | |||
| 195 | PTR sys_fdatasync | 195 | PTR sys_fdatasync |
| 196 | PTR sys_truncate | 196 | PTR sys_truncate |
| 197 | PTR sys_ftruncate /* 6075 */ | 197 | PTR sys_ftruncate /* 6075 */ |
| 198 | PTR sys32_getdents | 198 | PTR compat_sys_getdents |
| 199 | PTR sys_getcwd | 199 | PTR sys_getcwd |
| 200 | PTR sys_chdir | 200 | PTR sys_chdir |
| 201 | PTR sys_fchdir | 201 | PTR sys_fchdir |
| @@ -245,9 +245,9 @@ EXPORT(sysn32_call_table) | |||
| 245 | PTR sys_capget | 245 | PTR sys_capget |
| 246 | PTR sys_capset | 246 | PTR sys_capset |
| 247 | PTR sys32_rt_sigpending /* 6125 */ | 247 | PTR sys32_rt_sigpending /* 6125 */ |
| 248 | PTR sysn32_rt_sigtimedwait | 248 | PTR compat_sys_rt_sigtimedwait |
| 249 | PTR sys_rt_sigqueueinfo | 249 | PTR sys_rt_sigqueueinfo |
| 250 | PTR sys32_rt_sigsuspend | 250 | PTR sysn32_rt_sigsuspend |
| 251 | PTR sys32_sigaltstack | 251 | PTR sys32_sigaltstack |
| 252 | PTR compat_sys_utime /* 6130 */ | 252 | PTR compat_sys_utime /* 6130 */ |
| 253 | PTR sys_mknod | 253 | PTR sys_mknod |
| @@ -369,3 +369,20 @@ EXPORT(sysn32_call_table) | |||
| 369 | PTR sys_inotify_init | 369 | PTR sys_inotify_init |
| 370 | PTR sys_inotify_add_watch | 370 | PTR sys_inotify_add_watch |
| 371 | PTR sys_inotify_rm_watch | 371 | PTR sys_inotify_rm_watch |
| 372 | PTR sys_migrate_pages /* 6250 */ | ||
| 373 | PTR sys_openat | ||
| 374 | PTR sys_mkdirat | ||
| 375 | PTR sys_mknodat | ||
| 376 | PTR sys_fchownat | ||
| 377 | PTR sys_futimesat /* 6255 */ | ||
| 378 | PTR sys_newfstatat | ||
| 379 | PTR sys_unlinkat | ||
| 380 | PTR sys_renameat | ||
| 381 | PTR sys_linkat | ||
| 382 | PTR sys_symlinkat /* 6260 */ | ||
| 383 | PTR sys_readlinkat | ||
| 384 | PTR sys_fchmodat | ||
| 385 | PTR sys_faccessat | ||
| 386 | PTR sys_pselect6 | ||
| 387 | PTR sys_ppoll /* 6265 */ | ||
| 388 | PTR sys_unshare | ||
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 3d338ca7eeeb..797e0d874889 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
| @@ -293,7 +293,7 @@ sys_call_table: | |||
| 293 | PTR sys_uselib | 293 | PTR sys_uselib |
| 294 | PTR sys_swapon | 294 | PTR sys_swapon |
| 295 | PTR sys_reboot | 295 | PTR sys_reboot |
| 296 | PTR sys32_readdir | 296 | PTR compat_sys_old_readdir |
| 297 | PTR old_mmap /* 4090 */ | 297 | PTR old_mmap /* 4090 */ |
| 298 | PTR sys_munmap | 298 | PTR sys_munmap |
| 299 | PTR sys_truncate | 299 | PTR sys_truncate |
| @@ -345,7 +345,7 @@ sys_call_table: | |||
| 345 | PTR sys_setfsuid | 345 | PTR sys_setfsuid |
| 346 | PTR sys_setfsgid | 346 | PTR sys_setfsgid |
| 347 | PTR sys32_llseek /* 4140 */ | 347 | PTR sys32_llseek /* 4140 */ |
| 348 | PTR sys32_getdents | 348 | PTR compat_sys_getdents |
| 349 | PTR compat_sys_select | 349 | PTR compat_sys_select |
| 350 | PTR sys_flock | 350 | PTR sys_flock |
| 351 | PTR sys_msync | 351 | PTR sys_msync |
| @@ -491,4 +491,21 @@ sys_call_table: | |||
| 491 | PTR sys_inotify_init | 491 | PTR sys_inotify_init |
| 492 | PTR sys_inotify_add_watch /* 4285 */ | 492 | PTR sys_inotify_add_watch /* 4285 */ |
| 493 | PTR sys_inotify_rm_watch | 493 | PTR sys_inotify_rm_watch |
| 494 | PTR sys_migrate_pages | ||
| 495 | PTR compat_sys_openat | ||
| 496 | PTR sys_mkdirat | ||
| 497 | PTR sys_mknodat /* 4290 */ | ||
| 498 | PTR sys_fchownat | ||
| 499 | PTR compat_sys_futimesat | ||
| 500 | PTR compat_sys_newfstatat | ||
| 501 | PTR sys_unlinkat | ||
| 502 | PTR sys_renameat /* 4295 */ | ||
| 503 | PTR sys_linkat | ||
| 504 | PTR sys_symlinkat | ||
| 505 | PTR sys_readlinkat | ||
| 506 | PTR sys_fchmodat | ||
| 507 | PTR sys_faccessat /* 4300 */ | ||
| 508 | PTR sys_pselect6 | ||
| 509 | PTR sys_ppoll | ||
| 510 | PTR sys_unshare | ||
| 494 | .size sys_call_table,.-sys_call_table | 511 | .size sys_call_table,.-sys_call_table |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index d86affa21278..d9293c558e41 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
| @@ -540,6 +540,9 @@ void __init setup_arch(char **cmdline_p) | |||
| 540 | sparse_init(); | 540 | sparse_init(); |
| 541 | paging_init(); | 541 | paging_init(); |
| 542 | resource_init(); | 542 | resource_init(); |
| 543 | #ifdef CONFIG_SMP | ||
| 544 | plat_smp_setup(); | ||
| 545 | #endif | ||
| 543 | } | 546 | } |
| 544 | 547 | ||
| 545 | int __init fpu_disable(char *s) | 548 | int __init fpu_disable(char *s) |
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index 0f66ae5838b9..36bfc2588aa3 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include <linux/config.h> | 11 | #include <linux/config.h> |
| 12 | 12 | ||
| 13 | static inline int | 13 | static inline int |
| 14 | setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) | 14 | setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
| 15 | { | 15 | { |
| 16 | int err = 0; | 16 | int err = 0; |
| 17 | 17 | ||
| @@ -82,7 +82,7 @@ out: | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static inline int | 84 | static inline int |
| 85 | restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) | 85 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
| 86 | { | 86 | { |
| 87 | unsigned int used_math; | 87 | unsigned int used_math; |
| 88 | unsigned long treg; | 88 | unsigned long treg; |
| @@ -157,7 +157,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) | |||
| 157 | /* | 157 | /* |
| 158 | * Determine which stack to use.. | 158 | * Determine which stack to use.. |
| 159 | */ | 159 | */ |
| 160 | static inline void * | 160 | static inline void __user * |
| 161 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | 161 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) |
| 162 | { | 162 | { |
| 163 | unsigned long sp; | 163 | unsigned long sp; |
| @@ -176,7 +176,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
| 176 | if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) | 176 | if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) |
| 177 | sp = current->sas_ss_sp + current->sas_ss_size; | 177 | sp = current->sas_ss_sp + current->sas_ss_size; |
| 178 | 178 | ||
| 179 | return (void *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK)); | 179 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | static inline int install_sigtramp(unsigned int __user *tramp, | 182 | static inline int install_sigtramp(unsigned int __user *tramp, |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 7d1800fe7038..c974cc9b30eb 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
| @@ -39,8 +39,6 @@ | |||
| 39 | 39 | ||
| 40 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 40 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 41 | 41 | ||
| 42 | int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
| 43 | |||
| 44 | /* | 42 | /* |
| 45 | * Atomically swap in the new signal mask, and wait for a signal. | 43 | * Atomically swap in the new signal mask, and wait for a signal. |
| 46 | */ | 44 | */ |
| @@ -50,7 +48,7 @@ save_static_function(sys_sigsuspend); | |||
| 50 | __attribute_used__ noinline static int | 48 | __attribute_used__ noinline static int |
| 51 | _sys_sigsuspend(nabi_no_regargs struct pt_regs regs) | 49 | _sys_sigsuspend(nabi_no_regargs struct pt_regs regs) |
| 52 | { | 50 | { |
| 53 | sigset_t saveset, newset; | 51 | sigset_t newset; |
| 54 | sigset_t __user *uset; | 52 | sigset_t __user *uset; |
| 55 | 53 | ||
| 56 | uset = (sigset_t __user *) regs.regs[4]; | 54 | uset = (sigset_t __user *) regs.regs[4]; |
| @@ -59,19 +57,15 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
| 59 | sigdelsetmask(&newset, ~_BLOCKABLE); | 57 | sigdelsetmask(&newset, ~_BLOCKABLE); |
| 60 | 58 | ||
| 61 | spin_lock_irq(¤t->sighand->siglock); | 59 | spin_lock_irq(¤t->sighand->siglock); |
| 62 | saveset = current->blocked; | 60 | current->saved_sigmask = current->blocked; |
| 63 | current->blocked = newset; | 61 | current->blocked = newset; |
| 64 | recalc_sigpending(); | 62 | recalc_sigpending(); |
| 65 | spin_unlock_irq(¤t->sighand->siglock); | 63 | spin_unlock_irq(¤t->sighand->siglock); |
| 66 | 64 | ||
| 67 | regs.regs[2] = EINTR; | 65 | current->state = TASK_INTERRUPTIBLE; |
| 68 | regs.regs[7] = 1; | 66 | schedule(); |
| 69 | while (1) { | 67 | set_thread_flag(TIF_RESTORE_SIGMASK); |
| 70 | current->state = TASK_INTERRUPTIBLE; | 68 | return -ERESTARTNOHAND; |
| 71 | schedule(); | ||
| 72 | if (do_signal(&saveset, ®s)) | ||
| 73 | return -EINTR; | ||
| 74 | } | ||
| 75 | } | 69 | } |
| 76 | #endif | 70 | #endif |
| 77 | 71 | ||
| @@ -79,7 +73,7 @@ save_static_function(sys_rt_sigsuspend); | |||
| 79 | __attribute_used__ noinline static int | 73 | __attribute_used__ noinline static int |
| 80 | _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | 74 | _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) |
| 81 | { | 75 | { |
| 82 | sigset_t saveset, newset; | 76 | sigset_t newset; |
| 83 | sigset_t __user *unewset; | 77 | sigset_t __user *unewset; |
| 84 | size_t sigsetsize; | 78 | size_t sigsetsize; |
| 85 | 79 | ||
| @@ -94,19 +88,15 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
| 94 | sigdelsetmask(&newset, ~_BLOCKABLE); | 88 | sigdelsetmask(&newset, ~_BLOCKABLE); |
| 95 | 89 | ||
| 96 | spin_lock_irq(¤t->sighand->siglock); | 90 | spin_lock_irq(¤t->sighand->siglock); |
| 97 | saveset = current->blocked; | 91 | current->saved_sigmask = current->blocked; |
| 98 | current->blocked = newset; | 92 | current->blocked = newset; |
| 99 | recalc_sigpending(); | 93 | recalc_sigpending(); |
| 100 | spin_unlock_irq(¤t->sighand->siglock); | 94 | spin_unlock_irq(¤t->sighand->siglock); |
| 101 | 95 | ||
| 102 | regs.regs[2] = EINTR; | 96 | current->state = TASK_INTERRUPTIBLE; |
| 103 | regs.regs[7] = 1; | 97 | schedule(); |
| 104 | while (1) { | 98 | set_thread_flag(TIF_RESTORE_SIGMASK); |
| 105 | current->state = TASK_INTERRUPTIBLE; | 99 | return -ERESTARTNOHAND; |
| 106 | schedule(); | ||
| 107 | if (do_signal(&saveset, ®s)) | ||
| 108 | return -EINTR; | ||
| 109 | } | ||
| 110 | } | 100 | } |
| 111 | 101 | ||
| 112 | #ifdef CONFIG_TRAD_SIGNALS | 102 | #ifdef CONFIG_TRAD_SIGNALS |
| @@ -199,10 +189,10 @@ save_static_function(sys_sigreturn); | |||
| 199 | __attribute_used__ noinline static void | 189 | __attribute_used__ noinline static void |
| 200 | _sys_sigreturn(nabi_no_regargs struct pt_regs regs) | 190 | _sys_sigreturn(nabi_no_regargs struct pt_regs regs) |
| 201 | { | 191 | { |
| 202 | struct sigframe *frame; | 192 | struct sigframe __user *frame; |
| 203 | sigset_t blocked; | 193 | sigset_t blocked; |
| 204 | 194 | ||
| 205 | frame = (struct sigframe *) regs.regs[29]; | 195 | frame = (struct sigframe __user *) regs.regs[29]; |
| 206 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 196 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 207 | goto badframe; | 197 | goto badframe; |
| 208 | if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) | 198 | if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) |
| @@ -236,11 +226,11 @@ save_static_function(sys_rt_sigreturn); | |||
| 236 | __attribute_used__ noinline static void | 226 | __attribute_used__ noinline static void |
| 237 | _sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | 227 | _sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
| 238 | { | 228 | { |
| 239 | struct rt_sigframe *frame; | 229 | struct rt_sigframe __user *frame; |
| 240 | sigset_t set; | 230 | sigset_t set; |
| 241 | stack_t st; | 231 | stack_t st; |
| 242 | 232 | ||
| 243 | frame = (struct rt_sigframe *) regs.regs[29]; | 233 | frame = (struct rt_sigframe __user *) regs.regs[29]; |
| 244 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 234 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 245 | goto badframe; | 235 | goto badframe; |
| 246 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) | 236 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) |
| @@ -259,7 +249,7 @@ _sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 259 | goto badframe; | 249 | goto badframe; |
| 260 | /* It is more difficult to avoid calling this function than to | 250 | /* It is more difficult to avoid calling this function than to |
| 261 | call it and ignore errors. */ | 251 | call it and ignore errors. */ |
| 262 | do_sigaltstack(&st, NULL, regs.regs[29]); | 252 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); |
| 263 | 253 | ||
| 264 | /* | 254 | /* |
| 265 | * Don't let your children do this ... | 255 | * Don't let your children do this ... |
| @@ -279,7 +269,7 @@ badframe: | |||
| 279 | int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | 269 | int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, |
| 280 | int signr, sigset_t *set) | 270 | int signr, sigset_t *set) |
| 281 | { | 271 | { |
| 282 | struct sigframe *frame; | 272 | struct sigframe __user *frame; |
| 283 | int err = 0; | 273 | int err = 0; |
| 284 | 274 | ||
| 285 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 275 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| @@ -315,18 +305,18 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 315 | current->comm, current->pid, | 305 | current->comm, current->pid, |
| 316 | frame, regs->cp0_epc, frame->regs[31]); | 306 | frame, regs->cp0_epc, frame->regs[31]); |
| 317 | #endif | 307 | #endif |
| 318 | return 1; | 308 | return 0; |
| 319 | 309 | ||
| 320 | give_sigsegv: | 310 | give_sigsegv: |
| 321 | force_sigsegv(signr, current); | 311 | force_sigsegv(signr, current); |
| 322 | return 0; | 312 | return -EFAULT; |
| 323 | } | 313 | } |
| 324 | #endif | 314 | #endif |
| 325 | 315 | ||
| 326 | int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | 316 | int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, |
| 327 | int signr, sigset_t *set, siginfo_t *info) | 317 | int signr, sigset_t *set, siginfo_t *info) |
| 328 | { | 318 | { |
| 329 | struct rt_sigframe *frame; | 319 | struct rt_sigframe __user *frame; |
| 330 | int err = 0; | 320 | int err = 0; |
| 331 | 321 | ||
| 332 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 322 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| @@ -340,7 +330,7 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 340 | 330 | ||
| 341 | /* Create the ucontext. */ | 331 | /* Create the ucontext. */ |
| 342 | err |= __put_user(0, &frame->rs_uc.uc_flags); | 332 | err |= __put_user(0, &frame->rs_uc.uc_flags); |
| 343 | err |= __put_user(0, &frame->rs_uc.uc_link); | 333 | err |= __put_user(NULL, &frame->rs_uc.uc_link); |
| 344 | err |= __put_user((void *)current->sas_ss_sp, | 334 | err |= __put_user((void *)current->sas_ss_sp, |
| 345 | &frame->rs_uc.uc_stack.ss_sp); | 335 | &frame->rs_uc.uc_stack.ss_sp); |
| 346 | err |= __put_user(sas_ss_flags(regs->regs[29]), | 336 | err |= __put_user(sas_ss_flags(regs->regs[29]), |
| @@ -375,11 +365,11 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 375 | current->comm, current->pid, | 365 | current->comm, current->pid, |
| 376 | frame, regs->cp0_epc, regs->regs[31]); | 366 | frame, regs->cp0_epc, regs->regs[31]); |
| 377 | #endif | 367 | #endif |
| 378 | return 1; | 368 | return 0; |
| 379 | 369 | ||
| 380 | give_sigsegv: | 370 | give_sigsegv: |
| 381 | force_sigsegv(signr, current); | 371 | force_sigsegv(signr, current); |
| 382 | return 0; | 372 | return -EFAULT; |
| 383 | } | 373 | } |
| 384 | 374 | ||
| 385 | static inline int handle_signal(unsigned long sig, siginfo_t *info, | 375 | static inline int handle_signal(unsigned long sig, siginfo_t *info, |
| @@ -393,7 +383,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 393 | regs->regs[2] = EINTR; | 383 | regs->regs[2] = EINTR; |
| 394 | break; | 384 | break; |
| 395 | case ERESTARTSYS: | 385 | case ERESTARTSYS: |
| 396 | if(!(ka->sa.sa_flags & SA_RESTART)) { | 386 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
| 397 | regs->regs[2] = EINTR; | 387 | regs->regs[2] = EINTR; |
| 398 | break; | 388 | break; |
| 399 | } | 389 | } |
| @@ -420,9 +410,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 420 | return ret; | 410 | return ret; |
| 421 | } | 411 | } |
| 422 | 412 | ||
| 423 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | 413 | void do_signal(struct pt_regs *regs) |
| 424 | { | 414 | { |
| 425 | struct k_sigaction ka; | 415 | struct k_sigaction ka; |
| 416 | sigset_t *oldset; | ||
| 426 | siginfo_t info; | 417 | siginfo_t info; |
| 427 | int signr; | 418 | int signr; |
| 428 | 419 | ||
| @@ -432,17 +423,31 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
| 432 | * if so. | 423 | * if so. |
| 433 | */ | 424 | */ |
| 434 | if (!user_mode(regs)) | 425 | if (!user_mode(regs)) |
| 435 | return 1; | 426 | return; |
| 436 | 427 | ||
| 437 | if (try_to_freeze()) | 428 | if (try_to_freeze()) |
| 438 | goto no_signal; | 429 | goto no_signal; |
| 439 | 430 | ||
| 440 | if (!oldset) | 431 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 432 | oldset = ¤t->saved_sigmask; | ||
| 433 | else | ||
| 441 | oldset = ¤t->blocked; | 434 | oldset = ¤t->blocked; |
| 442 | 435 | ||
| 436 | |||
| 443 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 437 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| 444 | if (signr > 0) | 438 | if (signr > 0) { |
| 445 | return handle_signal(signr, &info, &ka, oldset, regs); | 439 | /* Whee! Actually deliver the signal. */ |
| 440 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | ||
| 441 | /* | ||
| 442 | * A signal was successfully delivered; the saved | ||
| 443 | * sigmask will have been stored in the signal frame, | ||
| 444 | * and will be restored by sigreturn, so we can simply | ||
| 445 | * clear the TIF_RESTORE_SIGMASK flag. | ||
| 446 | */ | ||
| 447 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 448 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 449 | } | ||
| 450 | } | ||
| 446 | 451 | ||
| 447 | no_signal: | 452 | no_signal: |
| 448 | /* | 453 | /* |
| @@ -463,18 +468,25 @@ no_signal: | |||
| 463 | regs->cp0_epc -= 4; | 468 | regs->cp0_epc -= 4; |
| 464 | } | 469 | } |
| 465 | } | 470 | } |
| 466 | return 0; | 471 | |
| 472 | /* | ||
| 473 | * If there's no signal to deliver, we just put the saved sigmask | ||
| 474 | * back | ||
| 475 | */ | ||
| 476 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 477 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 478 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 479 | } | ||
| 467 | } | 480 | } |
| 468 | 481 | ||
| 469 | /* | 482 | /* |
| 470 | * notification of userspace execution resumption | 483 | * notification of userspace execution resumption |
| 471 | * - triggered by current->work.notify_resume | 484 | * - triggered by the TIF_WORK_MASK flags |
| 472 | */ | 485 | */ |
| 473 | asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, | 486 | asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, |
| 474 | __u32 thread_info_flags) | 487 | __u32 thread_info_flags) |
| 475 | { | 488 | { |
| 476 | /* deal with pending signal delivery */ | 489 | /* deal with pending signal delivery */ |
| 477 | if (thread_info_flags & _TIF_SIGPENDING) { | 490 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) |
| 478 | current->thread.abi->do_signal(oldset, regs); | 491 | current->thread.abi->do_signal(regs); |
| 479 | } | ||
| 480 | } | 492 | } |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 98b185bbc947..237cd8a2cd32 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * for more details. | 4 | * for more details. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1991, 1992 Linus Torvalds | 6 | * Copyright (C) 1991, 1992 Linus Torvalds |
| 7 | * Copyright (C) 1994 - 2000 Ralf Baechle | 7 | * Copyright (C) 1994 - 2000, 2006 Ralf Baechle |
| 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
| 9 | */ | 9 | */ |
| 10 | #include <linux/cache.h> | 10 | #include <linux/cache.h> |
| @@ -106,8 +106,6 @@ typedef struct compat_siginfo { | |||
| 106 | 106 | ||
| 107 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 107 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 108 | 108 | ||
| 109 | extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); | ||
| 110 | |||
| 111 | /* 32-bit compatibility types */ | 109 | /* 32-bit compatibility types */ |
| 112 | 110 | ||
| 113 | #define _NSIG_BPW32 32 | 111 | #define _NSIG_BPW32 32 |
| @@ -144,7 +142,7 @@ struct ucontext32 { | |||
| 144 | extern void __put_sigset_unknown_nsig(void); | 142 | extern void __put_sigset_unknown_nsig(void); |
| 145 | extern void __get_sigset_unknown_nsig(void); | 143 | extern void __get_sigset_unknown_nsig(void); |
| 146 | 144 | ||
| 147 | static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf) | 145 | static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf) |
| 148 | { | 146 | { |
| 149 | int err = 0; | 147 | int err = 0; |
| 150 | 148 | ||
| @@ -198,7 +196,7 @@ __attribute_used__ noinline static int | |||
| 198 | _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) | 196 | _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) |
| 199 | { | 197 | { |
| 200 | compat_sigset_t *uset; | 198 | compat_sigset_t *uset; |
| 201 | sigset_t newset, saveset; | 199 | sigset_t newset; |
| 202 | 200 | ||
| 203 | uset = (compat_sigset_t *) regs.regs[4]; | 201 | uset = (compat_sigset_t *) regs.regs[4]; |
| 204 | if (get_sigset(&newset, uset)) | 202 | if (get_sigset(&newset, uset)) |
| @@ -206,19 +204,15 @@ _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
| 206 | sigdelsetmask(&newset, ~_BLOCKABLE); | 204 | sigdelsetmask(&newset, ~_BLOCKABLE); |
| 207 | 205 | ||
| 208 | spin_lock_irq(¤t->sighand->siglock); | 206 | spin_lock_irq(¤t->sighand->siglock); |
| 209 | saveset = current->blocked; | 207 | current->saved_sigmask = current->blocked; |
| 210 | current->blocked = newset; | 208 | current->blocked = newset; |
| 211 | recalc_sigpending(); | 209 | recalc_sigpending(); |
| 212 | spin_unlock_irq(¤t->sighand->siglock); | 210 | spin_unlock_irq(¤t->sighand->siglock); |
| 213 | 211 | ||
| 214 | regs.regs[2] = EINTR; | 212 | current->state = TASK_INTERRUPTIBLE; |
| 215 | regs.regs[7] = 1; | 213 | schedule(); |
| 216 | while (1) { | 214 | set_thread_flag(TIF_RESTORE_SIGMASK); |
| 217 | current->state = TASK_INTERRUPTIBLE; | 215 | return -ERESTARTNOHAND; |
| 218 | schedule(); | ||
| 219 | if (do_signal32(&saveset, ®s)) | ||
| 220 | return -EINTR; | ||
| 221 | } | ||
| 222 | } | 216 | } |
| 223 | 217 | ||
| 224 | save_static_function(sys32_rt_sigsuspend); | 218 | save_static_function(sys32_rt_sigsuspend); |
| @@ -226,8 +220,8 @@ __attribute_used__ noinline static int | |||
| 226 | _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | 220 | _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) |
| 227 | { | 221 | { |
| 228 | compat_sigset_t *uset; | 222 | compat_sigset_t *uset; |
| 229 | sigset_t newset, saveset; | 223 | sigset_t newset; |
| 230 | size_t sigsetsize; | 224 | size_t sigsetsize; |
| 231 | 225 | ||
| 232 | /* XXX Don't preclude handling different sized sigset_t's. */ | 226 | /* XXX Don't preclude handling different sized sigset_t's. */ |
| 233 | sigsetsize = regs.regs[5]; | 227 | sigsetsize = regs.regs[5]; |
| @@ -240,19 +234,15 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
| 240 | sigdelsetmask(&newset, ~_BLOCKABLE); | 234 | sigdelsetmask(&newset, ~_BLOCKABLE); |
| 241 | 235 | ||
| 242 | spin_lock_irq(¤t->sighand->siglock); | 236 | spin_lock_irq(¤t->sighand->siglock); |
| 243 | saveset = current->blocked; | 237 | current->saved_sigmask = current->blocked; |
| 244 | current->blocked = newset; | 238 | current->blocked = newset; |
| 245 | recalc_sigpending(); | 239 | recalc_sigpending(); |
| 246 | spin_unlock_irq(¤t->sighand->siglock); | 240 | spin_unlock_irq(¤t->sighand->siglock); |
| 247 | 241 | ||
| 248 | regs.regs[2] = EINTR; | 242 | current->state = TASK_INTERRUPTIBLE; |
| 249 | regs.regs[7] = 1; | 243 | schedule(); |
| 250 | while (1) { | 244 | set_thread_flag(TIF_RESTORE_SIGMASK); |
| 251 | current->state = TASK_INTERRUPTIBLE; | 245 | return -ERESTARTNOHAND; |
| 252 | schedule(); | ||
| 253 | if (do_signal32(&saveset, ®s)) | ||
| 254 | return -EINTR; | ||
| 255 | } | ||
| 256 | } | 246 | } |
| 257 | 247 | ||
| 258 | asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, | 248 | asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, |
| @@ -269,7 +259,7 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, | |||
| 269 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) | 259 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) |
| 270 | return -EFAULT; | 260 | return -EFAULT; |
| 271 | err |= __get_user(handler, &act->sa_handler); | 261 | err |= __get_user(handler, &act->sa_handler); |
| 272 | new_ka.sa.sa_handler = (void*)(s64)handler; | 262 | new_ka.sa.sa_handler = (void __user *)(s64)handler; |
| 273 | err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); | 263 | err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); |
| 274 | err |= __get_user(mask, &act->sa_mask.sig[0]); | 264 | err |= __get_user(mask, &act->sa_mask.sig[0]); |
| 275 | if (err) | 265 | if (err) |
| @@ -299,8 +289,8 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, | |||
| 299 | 289 | ||
| 300 | asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) | 290 | asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) |
| 301 | { | 291 | { |
| 302 | const stack32_t *uss = (const stack32_t *) regs.regs[4]; | 292 | const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4]; |
| 303 | stack32_t *uoss = (stack32_t *) regs.regs[5]; | 293 | stack32_t __user *uoss = (stack32_t __user *) regs.regs[5]; |
| 304 | unsigned long usp = regs.regs[29]; | 294 | unsigned long usp = regs.regs[29]; |
| 305 | stack_t kss, koss; | 295 | stack_t kss, koss; |
| 306 | int ret, err = 0; | 296 | int ret, err = 0; |
| @@ -319,7 +309,8 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) | |||
| 319 | } | 309 | } |
| 320 | 310 | ||
| 321 | set_fs (KERNEL_DS); | 311 | set_fs (KERNEL_DS); |
| 322 | ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp); | 312 | ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL, |
| 313 | uoss ? (stack_t __user *)&koss : NULL, usp); | ||
| 323 | set_fs (old_fs); | 314 | set_fs (old_fs); |
| 324 | 315 | ||
| 325 | if (!ret && uoss) { | 316 | if (!ret && uoss) { |
| @@ -335,7 +326,7 @@ asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs) | |||
| 335 | return ret; | 326 | return ret; |
| 336 | } | 327 | } |
| 337 | 328 | ||
| 338 | static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc) | 329 | static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc) |
| 339 | { | 330 | { |
| 340 | u32 used_math; | 331 | u32 used_math; |
| 341 | int err = 0; | 332 | int err = 0; |
| @@ -420,7 +411,7 @@ struct rt_sigframe32 { | |||
| 420 | #endif | 411 | #endif |
| 421 | }; | 412 | }; |
| 422 | 413 | ||
| 423 | int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from) | 414 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
| 424 | { | 415 | { |
| 425 | int err; | 416 | int err; |
| 426 | 417 | ||
| @@ -455,7 +446,7 @@ int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from) | |||
| 455 | err |= __put_user(from->si_uid, &to->si_uid); | 446 | err |= __put_user(from->si_uid, &to->si_uid); |
| 456 | break; | 447 | break; |
| 457 | case __SI_FAULT >> 16: | 448 | case __SI_FAULT >> 16: |
| 458 | err |= __put_user((long)from->si_addr, &to->si_addr); | 449 | err |= __put_user((unsigned long)from->si_addr, &to->si_addr); |
| 459 | break; | 450 | break; |
| 460 | case __SI_POLL >> 16: | 451 | case __SI_POLL >> 16: |
| 461 | err |= __put_user(from->si_band, &to->si_band); | 452 | err |= __put_user(from->si_band, &to->si_band); |
| @@ -476,10 +467,10 @@ save_static_function(sys32_sigreturn); | |||
| 476 | __attribute_used__ noinline static void | 467 | __attribute_used__ noinline static void |
| 477 | _sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | 468 | _sys32_sigreturn(nabi_no_regargs struct pt_regs regs) |
| 478 | { | 469 | { |
| 479 | struct sigframe *frame; | 470 | struct sigframe __user *frame; |
| 480 | sigset_t blocked; | 471 | sigset_t blocked; |
| 481 | 472 | ||
| 482 | frame = (struct sigframe *) regs.regs[29]; | 473 | frame = (struct sigframe __user *) regs.regs[29]; |
| 483 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 474 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 484 | goto badframe; | 475 | goto badframe; |
| 485 | if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) | 476 | if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) |
| @@ -512,13 +503,13 @@ save_static_function(sys32_rt_sigreturn); | |||
| 512 | __attribute_used__ noinline static void | 503 | __attribute_used__ noinline static void |
| 513 | _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | 504 | _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
| 514 | { | 505 | { |
| 515 | struct rt_sigframe32 *frame; | 506 | struct rt_sigframe32 __user *frame; |
| 516 | mm_segment_t old_fs; | 507 | mm_segment_t old_fs; |
| 517 | sigset_t set; | 508 | sigset_t set; |
| 518 | stack_t st; | 509 | stack_t st; |
| 519 | s32 sp; | 510 | s32 sp; |
| 520 | 511 | ||
| 521 | frame = (struct rt_sigframe32 *) regs.regs[29]; | 512 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; |
| 522 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 513 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 523 | goto badframe; | 514 | goto badframe; |
| 524 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) | 515 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) |
| @@ -536,7 +527,7 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 536 | /* The ucontext contains a stack32_t, so we must convert! */ | 527 | /* The ucontext contains a stack32_t, so we must convert! */ |
| 537 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 528 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
| 538 | goto badframe; | 529 | goto badframe; |
| 539 | st.ss_size = (long) sp; | 530 | st.ss_sp = (void *)(long) sp; |
| 540 | if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) | 531 | if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) |
| 541 | goto badframe; | 532 | goto badframe; |
| 542 | if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) | 533 | if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) |
| @@ -546,7 +537,7 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 546 | call it and ignore errors. */ | 537 | call it and ignore errors. */ |
| 547 | old_fs = get_fs(); | 538 | old_fs = get_fs(); |
| 548 | set_fs (KERNEL_DS); | 539 | set_fs (KERNEL_DS); |
| 549 | do_sigaltstack(&st, NULL, regs.regs[29]); | 540 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); |
| 550 | set_fs (old_fs); | 541 | set_fs (old_fs); |
| 551 | 542 | ||
| 552 | /* | 543 | /* |
| @@ -564,7 +555,7 @@ badframe: | |||
| 564 | } | 555 | } |
| 565 | 556 | ||
| 566 | static inline int setup_sigcontext32(struct pt_regs *regs, | 557 | static inline int setup_sigcontext32(struct pt_regs *regs, |
| 567 | struct sigcontext32 *sc) | 558 | struct sigcontext32 __user *sc) |
| 568 | { | 559 | { |
| 569 | int err = 0; | 560 | int err = 0; |
| 570 | 561 | ||
| @@ -623,8 +614,9 @@ out: | |||
| 623 | /* | 614 | /* |
| 624 | * Determine which stack to use.. | 615 | * Determine which stack to use.. |
| 625 | */ | 616 | */ |
| 626 | static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 617 | static inline void __user *get_sigframe(struct k_sigaction *ka, |
| 627 | size_t frame_size) | 618 | struct pt_regs *regs, |
| 619 | size_t frame_size) | ||
| 628 | { | 620 | { |
| 629 | unsigned long sp; | 621 | unsigned long sp; |
| 630 | 622 | ||
| @@ -642,13 +634,13 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 642 | if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) | 634 | if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) |
| 643 | sp = current->sas_ss_sp + current->sas_ss_size; | 635 | sp = current->sas_ss_sp + current->sas_ss_size; |
| 644 | 636 | ||
| 645 | return (void *)((sp - frame_size) & ALMASK); | 637 | return (void __user *)((sp - frame_size) & ALMASK); |
| 646 | } | 638 | } |
| 647 | 639 | ||
| 648 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 640 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
| 649 | int signr, sigset_t *set) | 641 | int signr, sigset_t *set) |
| 650 | { | 642 | { |
| 651 | struct sigframe *frame; | 643 | struct sigframe __user *frame; |
| 652 | int err = 0; | 644 | int err = 0; |
| 653 | 645 | ||
| 654 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 646 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| @@ -692,17 +684,17 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 692 | current->comm, current->pid, | 684 | current->comm, current->pid, |
| 693 | frame, regs->cp0_epc, frame->sf_code); | 685 | frame, regs->cp0_epc, frame->sf_code); |
| 694 | #endif | 686 | #endif |
| 695 | return 1; | 687 | return 0; |
| 696 | 688 | ||
| 697 | give_sigsegv: | 689 | give_sigsegv: |
| 698 | force_sigsegv(signr, current); | 690 | force_sigsegv(signr, current); |
| 699 | return 0; | 691 | return -EFAULT; |
| 700 | } | 692 | } |
| 701 | 693 | ||
| 702 | int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 694 | int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, |
| 703 | int signr, sigset_t *set, siginfo_t *info) | 695 | int signr, sigset_t *set, siginfo_t *info) |
| 704 | { | 696 | { |
| 705 | struct rt_sigframe32 *frame; | 697 | struct rt_sigframe32 __user *frame; |
| 706 | int err = 0; | 698 | int err = 0; |
| 707 | s32 sp; | 699 | s32 sp; |
| 708 | 700 | ||
| @@ -763,11 +755,11 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | |||
| 763 | current->comm, current->pid, | 755 | current->comm, current->pid, |
| 764 | frame, regs->cp0_epc, frame->rs_code); | 756 | frame, regs->cp0_epc, frame->rs_code); |
| 765 | #endif | 757 | #endif |
| 766 | return 1; | 758 | return 0; |
| 767 | 759 | ||
| 768 | give_sigsegv: | 760 | give_sigsegv: |
| 769 | force_sigsegv(signr, current); | 761 | force_sigsegv(signr, current); |
| 770 | return 0; | 762 | return -EFAULT; |
| 771 | } | 763 | } |
| 772 | 764 | ||
| 773 | static inline int handle_signal(unsigned long sig, siginfo_t *info, | 765 | static inline int handle_signal(unsigned long sig, siginfo_t *info, |
| @@ -781,7 +773,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 781 | regs->regs[2] = EINTR; | 773 | regs->regs[2] = EINTR; |
| 782 | break; | 774 | break; |
| 783 | case ERESTARTSYS: | 775 | case ERESTARTSYS: |
| 784 | if(!(ka->sa.sa_flags & SA_RESTART)) { | 776 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
| 785 | regs->regs[2] = EINTR; | 777 | regs->regs[2] = EINTR; |
| 786 | break; | 778 | break; |
| 787 | } | 779 | } |
| @@ -808,9 +800,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 808 | return ret; | 800 | return ret; |
| 809 | } | 801 | } |
| 810 | 802 | ||
| 811 | int do_signal32(sigset_t *oldset, struct pt_regs *regs) | 803 | void do_signal32(struct pt_regs *regs) |
| 812 | { | 804 | { |
| 813 | struct k_sigaction ka; | 805 | struct k_sigaction ka; |
| 806 | sigset_t *oldset; | ||
| 814 | siginfo_t info; | 807 | siginfo_t info; |
| 815 | int signr; | 808 | int signr; |
| 816 | 809 | ||
| @@ -820,17 +813,30 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) | |||
| 820 | * if so. | 813 | * if so. |
| 821 | */ | 814 | */ |
| 822 | if (!user_mode(regs)) | 815 | if (!user_mode(regs)) |
| 823 | return 1; | 816 | return; |
| 824 | 817 | ||
| 825 | if (try_to_freeze()) | 818 | if (try_to_freeze()) |
| 826 | goto no_signal; | 819 | goto no_signal; |
| 827 | 820 | ||
| 828 | if (!oldset) | 821 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 822 | oldset = ¤t->saved_sigmask; | ||
| 823 | else | ||
| 829 | oldset = ¤t->blocked; | 824 | oldset = ¤t->blocked; |
| 830 | 825 | ||
| 831 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 826 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| 832 | if (signr > 0) | 827 | if (signr > 0) { |
| 833 | return handle_signal(signr, &info, &ka, oldset, regs); | 828 | /* Whee! Actually deliver the signal. */ |
| 829 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { | ||
| 830 | /* | ||
| 831 | * A signal was successfully delivered; the saved | ||
| 832 | * sigmask will have been stored in the signal frame, | ||
| 833 | * and will be restored by sigreturn, so we can simply | ||
| 834 | * clear the TIF_RESTORE_SIGMASK flag. | ||
| 835 | */ | ||
| 836 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 837 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 838 | } | ||
| 839 | } | ||
| 834 | 840 | ||
| 835 | no_signal: | 841 | no_signal: |
| 836 | /* | 842 | /* |
| @@ -851,11 +857,19 @@ no_signal: | |||
| 851 | regs->cp0_epc -= 4; | 857 | regs->cp0_epc -= 4; |
| 852 | } | 858 | } |
| 853 | } | 859 | } |
| 854 | return 0; | 860 | |
| 861 | /* | ||
| 862 | * If there's no signal to deliver, we just put the saved sigmask | ||
| 863 | * back | ||
| 864 | */ | ||
| 865 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 866 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 867 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 868 | } | ||
| 855 | } | 869 | } |
| 856 | 870 | ||
| 857 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, | 871 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, |
| 858 | struct sigaction32 *oact, | 872 | struct sigaction32 __user *oact, |
| 859 | unsigned int sigsetsize) | 873 | unsigned int sigsetsize) |
| 860 | { | 874 | { |
| 861 | struct k_sigaction new_sa, old_sa; | 875 | struct k_sigaction new_sa, old_sa; |
| @@ -872,7 +886,7 @@ asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, | |||
| 872 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) | 886 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) |
| 873 | return -EFAULT; | 887 | return -EFAULT; |
| 874 | err |= __get_user(handler, &act->sa_handler); | 888 | err |= __get_user(handler, &act->sa_handler); |
| 875 | new_sa.sa.sa_handler = (void*)(s64)handler; | 889 | new_sa.sa.sa_handler = (void __user *)(s64)handler; |
| 876 | err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); | 890 | err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); |
| 877 | err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); | 891 | err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); |
| 878 | if (err) | 892 | if (err) |
| @@ -899,7 +913,7 @@ out: | |||
| 899 | } | 913 | } |
| 900 | 914 | ||
| 901 | asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, | 915 | asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, |
| 902 | compat_sigset_t *oset, unsigned int sigsetsize) | 916 | compat_sigset_t __user *oset, unsigned int sigsetsize) |
| 903 | { | 917 | { |
| 904 | sigset_t old_set, new_set; | 918 | sigset_t old_set, new_set; |
| 905 | int ret; | 919 | int ret; |
| @@ -909,8 +923,9 @@ asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, | |||
| 909 | return -EFAULT; | 923 | return -EFAULT; |
| 910 | 924 | ||
| 911 | set_fs (KERNEL_DS); | 925 | set_fs (KERNEL_DS); |
| 912 | ret = sys_rt_sigprocmask(how, set ? &new_set : NULL, | 926 | ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL, |
| 913 | oset ? &old_set : NULL, sigsetsize); | 927 | oset ? (sigset_t __user *)&old_set : NULL, |
| 928 | sigsetsize); | ||
| 914 | set_fs (old_fs); | 929 | set_fs (old_fs); |
| 915 | 930 | ||
| 916 | if (!ret && oset && put_sigset(&old_set, oset)) | 931 | if (!ret && oset && put_sigset(&old_set, oset)) |
| @@ -919,7 +934,7 @@ asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, | |||
| 919 | return ret; | 934 | return ret; |
| 920 | } | 935 | } |
| 921 | 936 | ||
| 922 | asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, | 937 | asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset, |
| 923 | unsigned int sigsetsize) | 938 | unsigned int sigsetsize) |
| 924 | { | 939 | { |
| 925 | int ret; | 940 | int ret; |
| @@ -927,7 +942,7 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, | |||
| 927 | mm_segment_t old_fs = get_fs(); | 942 | mm_segment_t old_fs = get_fs(); |
| 928 | 943 | ||
| 929 | set_fs (KERNEL_DS); | 944 | set_fs (KERNEL_DS); |
| 930 | ret = sys_rt_sigpending(&set, sigsetsize); | 945 | ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize); |
| 931 | set_fs (old_fs); | 946 | set_fs (old_fs); |
| 932 | 947 | ||
| 933 | if (!ret && put_sigset(&set, uset)) | 948 | if (!ret && put_sigset(&set, uset)) |
| @@ -936,7 +951,7 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, | |||
| 936 | return ret; | 951 | return ret; |
| 937 | } | 952 | } |
| 938 | 953 | ||
| 939 | asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo) | 954 | asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) |
| 940 | { | 955 | { |
| 941 | siginfo_t info; | 956 | siginfo_t info; |
| 942 | int ret; | 957 | int ret; |
| @@ -946,7 +961,7 @@ asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo) | |||
| 946 | copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) | 961 | copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) |
| 947 | return -EFAULT; | 962 | return -EFAULT; |
| 948 | set_fs (KERNEL_DS); | 963 | set_fs (KERNEL_DS); |
| 949 | ret = sys_rt_sigqueueinfo(pid, sig, &info); | 964 | ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); |
| 950 | set_fs (old_fs); | 965 | set_fs (old_fs); |
| 951 | return ret; | 966 | return ret; |
| 952 | } | 967 | } |
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index ec61b2670ba6..3e168c08a3a8 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
| @@ -48,6 +48,8 @@ | |||
| 48 | #define __NR_N32_rt_sigreturn 6211 | 48 | #define __NR_N32_rt_sigreturn 6211 |
| 49 | #define __NR_N32_restart_syscall 6214 | 49 | #define __NR_N32_restart_syscall 6214 |
| 50 | 50 | ||
| 51 | #define DEBUG_SIG 0 | ||
| 52 | |||
| 51 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 53 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 52 | 54 | ||
| 53 | /* IRIX compatible stack_t */ | 55 | /* IRIX compatible stack_t */ |
| @@ -79,16 +81,49 @@ struct rt_sigframe_n32 { | |||
| 79 | #endif | 81 | #endif |
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| 84 | extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat); | ||
| 85 | |||
| 86 | save_static_function(sysn32_rt_sigsuspend); | ||
| 87 | __attribute_used__ noinline static int | ||
| 88 | _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | ||
| 89 | { | ||
| 90 | compat_sigset_t __user *unewset, uset; | ||
| 91 | size_t sigsetsize; | ||
| 92 | sigset_t newset; | ||
| 93 | |||
| 94 | /* XXX Don't preclude handling different sized sigset_t's. */ | ||
| 95 | sigsetsize = regs.regs[5]; | ||
| 96 | if (sigsetsize != sizeof(sigset_t)) | ||
| 97 | return -EINVAL; | ||
| 98 | |||
| 99 | unewset = (compat_sigset_t __user *) regs.regs[4]; | ||
| 100 | if (copy_from_user(&uset, unewset, sizeof(uset))) | ||
| 101 | return -EFAULT; | ||
| 102 | sigset_from_compat (&newset, &uset); | ||
| 103 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
| 104 | |||
| 105 | spin_lock_irq(¤t->sighand->siglock); | ||
| 106 | current->saved_sigmask = current->blocked; | ||
| 107 | current->blocked = newset; | ||
| 108 | recalc_sigpending(); | ||
| 109 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 110 | |||
| 111 | current->state = TASK_INTERRUPTIBLE; | ||
| 112 | schedule(); | ||
| 113 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 114 | return -ERESTARTNOHAND; | ||
| 115 | } | ||
| 116 | |||
| 82 | save_static_function(sysn32_rt_sigreturn); | 117 | save_static_function(sysn32_rt_sigreturn); |
| 83 | __attribute_used__ noinline static void | 118 | __attribute_used__ noinline static void |
| 84 | _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | 119 | _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
| 85 | { | 120 | { |
| 86 | struct rt_sigframe_n32 *frame; | 121 | struct rt_sigframe_n32 __user *frame; |
| 87 | sigset_t set; | 122 | sigset_t set; |
| 88 | stack_t st; | 123 | stack_t st; |
| 89 | s32 sp; | 124 | s32 sp; |
| 90 | 125 | ||
| 91 | frame = (struct rt_sigframe_n32 *) regs.regs[29]; | 126 | frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; |
| 92 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 127 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 93 | goto badframe; | 128 | goto badframe; |
| 94 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) | 129 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) |
| @@ -106,7 +141,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 106 | /* The ucontext contains a stack32_t, so we must convert! */ | 141 | /* The ucontext contains a stack32_t, so we must convert! */ |
| 107 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 142 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
| 108 | goto badframe; | 143 | goto badframe; |
| 109 | st.ss_size = (long) sp; | 144 | st.ss_sp = (void *)(long) sp; |
| 110 | if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) | 145 | if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) |
| 111 | goto badframe; | 146 | goto badframe; |
| 112 | if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) | 147 | if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) |
| @@ -114,7 +149,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 114 | 149 | ||
| 115 | /* It is more difficult to avoid calling this function than to | 150 | /* It is more difficult to avoid calling this function than to |
| 116 | call it and ignore errors. */ | 151 | call it and ignore errors. */ |
| 117 | do_sigaltstack(&st, NULL, regs.regs[29]); | 152 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); |
| 118 | 153 | ||
| 119 | /* | 154 | /* |
| 120 | * Don't let your children do this ... | 155 | * Don't let your children do this ... |
| @@ -133,7 +168,7 @@ badframe: | |||
| 133 | int setup_rt_frame_n32(struct k_sigaction * ka, | 168 | int setup_rt_frame_n32(struct k_sigaction * ka, |
| 134 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) | 169 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) |
| 135 | { | 170 | { |
| 136 | struct rt_sigframe_n32 *frame; | 171 | struct rt_sigframe_n32 __user *frame; |
| 137 | int err = 0; | 172 | int err = 0; |
| 138 | s32 sp; | 173 | s32 sp; |
| 139 | 174 | ||
| @@ -184,9 +219,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka, | |||
| 184 | current->comm, current->pid, | 219 | current->comm, current->pid, |
| 185 | frame, regs->cp0_epc, regs->regs[31]); | 220 | frame, regs->cp0_epc, regs->regs[31]); |
| 186 | #endif | 221 | #endif |
| 187 | return 1; | 222 | return 0; |
| 188 | 223 | ||
| 189 | give_sigsegv: | 224 | give_sigsegv: |
| 190 | force_sigsegv(signr, current); | 225 | force_sigsegv(signr, current); |
| 191 | return 0; | 226 | return -EFAULT; |
| 192 | } | 227 | } |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 25472fcaf715..06ed90752424 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/timex.h> | 29 | #include <linux/timex.h> |
| 30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
| 31 | #include <linux/cpumask.h> | 31 | #include <linux/cpumask.h> |
| 32 | #include <linux/cpu.h> | ||
| 32 | 33 | ||
| 33 | #include <asm/atomic.h> | 34 | #include <asm/atomic.h> |
| 34 | #include <asm/cpu.h> | 35 | #include <asm/cpu.h> |
| @@ -235,7 +236,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
| 235 | init_new_context(current, &init_mm); | 236 | init_new_context(current, &init_mm); |
| 236 | current_thread_info()->cpu = 0; | 237 | current_thread_info()->cpu = 0; |
| 237 | smp_tune_scheduling(); | 238 | smp_tune_scheduling(); |
| 238 | prom_prepare_cpus(max_cpus); | 239 | plat_prepare_cpus(max_cpus); |
| 239 | } | 240 | } |
| 240 | 241 | ||
| 241 | /* preload SMP state for boot cpu */ | 242 | /* preload SMP state for boot cpu */ |
| @@ -424,6 +425,25 @@ void flush_tlb_one(unsigned long vaddr) | |||
| 424 | local_flush_tlb_one(vaddr); | 425 | local_flush_tlb_one(vaddr); |
| 425 | } | 426 | } |
| 426 | 427 | ||
| 428 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | ||
| 429 | |||
| 430 | static int __init topology_init(void) | ||
| 431 | { | ||
| 432 | int cpu; | ||
| 433 | int ret; | ||
| 434 | |||
| 435 | for_each_cpu(cpu) { | ||
| 436 | ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL); | ||
| 437 | if (ret) | ||
| 438 | printk(KERN_WARNING "topology_init: register_cpu %d " | ||
| 439 | "failed (%d)\n", cpu, ret); | ||
| 440 | } | ||
| 441 | |||
| 442 | return 0; | ||
| 443 | } | ||
| 444 | |||
| 445 | subsys_initcall(topology_init); | ||
| 446 | |||
| 427 | EXPORT_SYMBOL(flush_tlb_page); | 447 | EXPORT_SYMBOL(flush_tlb_page); |
| 428 | EXPORT_SYMBOL(flush_tlb_one); | 448 | EXPORT_SYMBOL(flush_tlb_one); |
| 429 | EXPORT_SYMBOL(cpu_data); | 449 | EXPORT_SYMBOL(cpu_data); |
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c index 794a1c3de2a4..993b8bf56aaf 100644 --- a/arch/mips/kernel/smp_mt.c +++ b/arch/mips/kernel/smp_mt.c | |||
| @@ -68,6 +68,8 @@ void __init sanitize_tlb_entries(void) | |||
| 68 | 68 | ||
| 69 | set_c0_mvpcontrol(MVPCONTROL_VPC); | 69 | set_c0_mvpcontrol(MVPCONTROL_VPC); |
| 70 | 70 | ||
| 71 | back_to_back_c0_hazard(); | ||
| 72 | |||
| 71 | /* Disable TLB sharing */ | 73 | /* Disable TLB sharing */ |
| 72 | clear_c0_mvpcontrol(MVPCONTROL_STLB); | 74 | clear_c0_mvpcontrol(MVPCONTROL_STLB); |
| 73 | 75 | ||
| @@ -102,35 +104,6 @@ void __init sanitize_tlb_entries(void) | |||
| 102 | clear_c0_mvpcontrol(MVPCONTROL_VPC); | 104 | clear_c0_mvpcontrol(MVPCONTROL_VPC); |
| 103 | } | 105 | } |
| 104 | 106 | ||
| 105 | #if 0 | ||
| 106 | /* | ||
| 107 | * Use c0_MVPConf0 to find out how many CPUs are available, setting up | ||
| 108 | * phys_cpu_present_map and the logical/physical mappings. | ||
| 109 | */ | ||
| 110 | void __init prom_build_cpu_map(void) | ||
| 111 | { | ||
| 112 | int i, num, ncpus; | ||
| 113 | |||
| 114 | cpus_clear(phys_cpu_present_map); | ||
| 115 | |||
| 116 | /* assume we boot on cpu 0.... */ | ||
| 117 | cpu_set(0, phys_cpu_present_map); | ||
| 118 | __cpu_number_map[0] = 0; | ||
| 119 | __cpu_logical_map[0] = 0; | ||
| 120 | |||
| 121 | if (cpu_has_mipsmt) { | ||
| 122 | ncpus = ((read_c0_mvpconf0() & (MVPCONF0_PVPE)) >> MVPCONF0_PVPE_SHIFT) + 1; | ||
| 123 | for (i=1, num=0; i< NR_CPUS && i<ncpus; i++) { | ||
| 124 | cpu_set(i, phys_cpu_present_map); | ||
| 125 | __cpu_number_map[i] = ++num; | ||
| 126 | __cpu_logical_map[num] = i; | ||
| 127 | } | ||
| 128 | |||
| 129 | printk(KERN_INFO "%i available secondary CPU(s)\n", num); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | #endif | ||
| 133 | |||
| 134 | static void ipi_resched_dispatch (struct pt_regs *regs) | 107 | static void ipi_resched_dispatch (struct pt_regs *regs) |
| 135 | { | 108 | { |
| 136 | do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs); | 109 | do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs); |
| @@ -170,7 +143,7 @@ static struct irqaction irq_call = { | |||
| 170 | * Make sure all CPU's are in a sensible state before we boot any of the | 143 | * Make sure all CPU's are in a sensible state before we boot any of the |
| 171 | * secondarys | 144 | * secondarys |
| 172 | */ | 145 | */ |
| 173 | void prom_prepare_cpus(unsigned int max_cpus) | 146 | void plat_smp_setup(void) |
| 174 | { | 147 | { |
| 175 | unsigned long val; | 148 | unsigned long val; |
| 176 | int i, num; | 149 | int i, num; |
| @@ -206,11 +179,9 @@ void prom_prepare_cpus(unsigned int max_cpus) | |||
| 206 | write_vpe_c0_vpeconf0(tmp); | 179 | write_vpe_c0_vpeconf0(tmp); |
| 207 | 180 | ||
| 208 | /* Record this as available CPU */ | 181 | /* Record this as available CPU */ |
| 209 | if (i < max_cpus) { | 182 | cpu_set(i, phys_cpu_present_map); |
| 210 | cpu_set(i, phys_cpu_present_map); | 183 | __cpu_number_map[i] = ++num; |
| 211 | __cpu_number_map[i] = ++num; | 184 | __cpu_logical_map[num] = i; |
| 212 | __cpu_logical_map[num] = i; | ||
| 213 | } | ||
| 214 | } | 185 | } |
| 215 | 186 | ||
| 216 | /* disable multi-threading with TC's */ | 187 | /* disable multi-threading with TC's */ |
| @@ -222,6 +193,9 @@ void prom_prepare_cpus(unsigned int max_cpus) | |||
| 222 | 193 | ||
| 223 | /* set config to be the same as vpe0, particularly kseg0 coherency alg */ | 194 | /* set config to be the same as vpe0, particularly kseg0 coherency alg */ |
| 224 | write_vpe_c0_config( read_c0_config()); | 195 | write_vpe_c0_config( read_c0_config()); |
| 196 | |||
| 197 | /* Propagate Config7 */ | ||
| 198 | write_vpe_c0_config7(read_c0_config7()); | ||
| 225 | } | 199 | } |
| 226 | 200 | ||
| 227 | } | 201 | } |
| @@ -265,7 +239,10 @@ void prom_prepare_cpus(unsigned int max_cpus) | |||
| 265 | set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); | 239 | set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); |
| 266 | set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); | 240 | set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); |
| 267 | } | 241 | } |
| 242 | } | ||
| 268 | 243 | ||
| 244 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
| 245 | { | ||
| 269 | cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ; | 246 | cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ; |
| 270 | cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ; | 247 | cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ; |
| 271 | 248 | ||
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 332358430ff5..1da2eeb3ef9e 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
| @@ -212,12 +212,12 @@ asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) | |||
| 212 | int error; | 212 | int error; |
| 213 | char * filename; | 213 | char * filename; |
| 214 | 214 | ||
| 215 | filename = getname((char *) (long)regs.regs[4]); | 215 | filename = getname((char __user *) (long)regs.regs[4]); |
| 216 | error = PTR_ERR(filename); | 216 | error = PTR_ERR(filename); |
| 217 | if (IS_ERR(filename)) | 217 | if (IS_ERR(filename)) |
| 218 | goto out; | 218 | goto out; |
| 219 | error = do_execve(filename, (char **) (long)regs.regs[5], | 219 | error = do_execve(filename, (char __user *__user *) (long)regs.regs[5], |
| 220 | (char **) (long)regs.regs[6], ®s); | 220 | (char __user *__user *) (long)regs.regs[6], ®s); |
| 221 | putname(filename); | 221 | putname(filename); |
| 222 | 222 | ||
| 223 | out: | 223 | out: |
| @@ -227,7 +227,7 @@ out: | |||
| 227 | /* | 227 | /* |
| 228 | * Compacrapability ... | 228 | * Compacrapability ... |
| 229 | */ | 229 | */ |
| 230 | asmlinkage int sys_uname(struct old_utsname * name) | 230 | asmlinkage int sys_uname(struct old_utsname __user * name) |
| 231 | { | 231 | { |
| 232 | if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) | 232 | if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) |
| 233 | return 0; | 233 | return 0; |
| @@ -237,7 +237,7 @@ asmlinkage int sys_uname(struct old_utsname * name) | |||
| 237 | /* | 237 | /* |
| 238 | * Compacrapability ... | 238 | * Compacrapability ... |
| 239 | */ | 239 | */ |
| 240 | asmlinkage int sys_olduname(struct oldold_utsname * name) | 240 | asmlinkage int sys_olduname(struct oldold_utsname __user * name) |
| 241 | { | 241 | { |
| 242 | int error; | 242 | int error; |
| 243 | 243 | ||
| @@ -274,7 +274,7 @@ void sys_set_thread_area(unsigned long addr) | |||
| 274 | asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) | 274 | asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) |
| 275 | { | 275 | { |
| 276 | int tmp, len; | 276 | int tmp, len; |
| 277 | char *name; | 277 | char __user *name; |
| 278 | 278 | ||
| 279 | switch(cmd) { | 279 | switch(cmd) { |
| 280 | case SETNAME: { | 280 | case SETNAME: { |
| @@ -283,7 +283,7 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) | |||
| 283 | if (!capable(CAP_SYS_ADMIN)) | 283 | if (!capable(CAP_SYS_ADMIN)) |
| 284 | return -EPERM; | 284 | return -EPERM; |
| 285 | 285 | ||
| 286 | name = (char *) arg1; | 286 | name = (char __user *) arg1; |
| 287 | 287 | ||
| 288 | len = strncpy_from_user(nodename, name, __NEW_UTS_LEN); | 288 | len = strncpy_from_user(nodename, name, __NEW_UTS_LEN); |
| 289 | if (len < 0) | 289 | if (len < 0) |
| @@ -324,7 +324,7 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) | |||
| 324 | * This is really horribly ugly. | 324 | * This is really horribly ugly. |
| 325 | */ | 325 | */ |
| 326 | asmlinkage int sys_ipc (uint call, int first, int second, | 326 | asmlinkage int sys_ipc (uint call, int first, int second, |
| 327 | unsigned long third, void *ptr, long fifth) | 327 | unsigned long third, void __user *ptr, long fifth) |
| 328 | { | 328 | { |
| 329 | int version, ret; | 329 | int version, ret; |
| 330 | 330 | ||
| @@ -333,24 +333,25 @@ asmlinkage int sys_ipc (uint call, int first, int second, | |||
| 333 | 333 | ||
| 334 | switch (call) { | 334 | switch (call) { |
| 335 | case SEMOP: | 335 | case SEMOP: |
| 336 | return sys_semtimedop (first, (struct sembuf *)ptr, second, | 336 | return sys_semtimedop (first, (struct sembuf __user *)ptr, |
| 337 | NULL); | 337 | second, NULL); |
| 338 | case SEMTIMEDOP: | 338 | case SEMTIMEDOP: |
| 339 | return sys_semtimedop (first, (struct sembuf *)ptr, second, | 339 | return sys_semtimedop (first, (struct sembuf __user *)ptr, |
| 340 | (const struct timespec __user *)fifth); | 340 | second, |
| 341 | (const struct timespec __user *)fifth); | ||
| 341 | case SEMGET: | 342 | case SEMGET: |
| 342 | return sys_semget (first, second, third); | 343 | return sys_semget (first, second, third); |
| 343 | case SEMCTL: { | 344 | case SEMCTL: { |
| 344 | union semun fourth; | 345 | union semun fourth; |
| 345 | if (!ptr) | 346 | if (!ptr) |
| 346 | return -EINVAL; | 347 | return -EINVAL; |
| 347 | if (get_user(fourth.__pad, (void **) ptr)) | 348 | if (get_user(fourth.__pad, (void *__user *) ptr)) |
| 348 | return -EFAULT; | 349 | return -EFAULT; |
| 349 | return sys_semctl (first, second, third, fourth); | 350 | return sys_semctl (first, second, third, fourth); |
| 350 | } | 351 | } |
| 351 | 352 | ||
| 352 | case MSGSND: | 353 | case MSGSND: |
| 353 | return sys_msgsnd (first, (struct msgbuf *) ptr, | 354 | return sys_msgsnd (first, (struct msgbuf __user *) ptr, |
| 354 | second, third); | 355 | second, third); |
| 355 | case MSGRCV: | 356 | case MSGRCV: |
| 356 | switch (version) { | 357 | switch (version) { |
| @@ -360,7 +361,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, | |||
| 360 | return -EINVAL; | 361 | return -EINVAL; |
| 361 | 362 | ||
| 362 | if (copy_from_user(&tmp, | 363 | if (copy_from_user(&tmp, |
| 363 | (struct ipc_kludge *) ptr, | 364 | (struct ipc_kludge __user *) ptr, |
| 364 | sizeof (tmp))) | 365 | sizeof (tmp))) |
| 365 | return -EFAULT; | 366 | return -EFAULT; |
| 366 | return sys_msgrcv (first, tmp.msgp, second, | 367 | return sys_msgrcv (first, tmp.msgp, second, |
| @@ -368,35 +369,38 @@ asmlinkage int sys_ipc (uint call, int first, int second, | |||
| 368 | } | 369 | } |
| 369 | default: | 370 | default: |
| 370 | return sys_msgrcv (first, | 371 | return sys_msgrcv (first, |
| 371 | (struct msgbuf *) ptr, | 372 | (struct msgbuf __user *) ptr, |
| 372 | second, fifth, third); | 373 | second, fifth, third); |
| 373 | } | 374 | } |
| 374 | case MSGGET: | 375 | case MSGGET: |
| 375 | return sys_msgget ((key_t) first, second); | 376 | return sys_msgget ((key_t) first, second); |
| 376 | case MSGCTL: | 377 | case MSGCTL: |
| 377 | return sys_msgctl (first, second, (struct msqid_ds *) ptr); | 378 | return sys_msgctl (first, second, |
| 379 | (struct msqid_ds __user *) ptr); | ||
| 378 | 380 | ||
| 379 | case SHMAT: | 381 | case SHMAT: |
| 380 | switch (version) { | 382 | switch (version) { |
| 381 | default: { | 383 | default: { |
| 382 | ulong raddr; | 384 | ulong raddr; |
| 383 | ret = do_shmat (first, (char *) ptr, second, &raddr); | 385 | ret = do_shmat (first, (char __user *) ptr, second, |
| 386 | &raddr); | ||
| 384 | if (ret) | 387 | if (ret) |
| 385 | return ret; | 388 | return ret; |
| 386 | return put_user (raddr, (ulong *) third); | 389 | return put_user (raddr, (ulong __user *) third); |
| 387 | } | 390 | } |
| 388 | case 1: /* iBCS2 emulator entry point */ | 391 | case 1: /* iBCS2 emulator entry point */ |
| 389 | if (!segment_eq(get_fs(), get_ds())) | 392 | if (!segment_eq(get_fs(), get_ds())) |
| 390 | return -EINVAL; | 393 | return -EINVAL; |
| 391 | return do_shmat (first, (char *) ptr, second, (ulong *) third); | 394 | return do_shmat (first, (char __user *) ptr, second, |
| 395 | (ulong *) third); | ||
| 392 | } | 396 | } |
| 393 | case SHMDT: | 397 | case SHMDT: |
| 394 | return sys_shmdt ((char *)ptr); | 398 | return sys_shmdt ((char __user *)ptr); |
| 395 | case SHMGET: | 399 | case SHMGET: |
| 396 | return sys_shmget (first, second, third); | 400 | return sys_shmget (first, second, third); |
| 397 | case SHMCTL: | 401 | case SHMCTL: |
| 398 | return sys_shmctl (first, second, | 402 | return sys_shmctl (first, second, |
| 399 | (struct shmid_ds *) ptr); | 403 | (struct shmid_ds __user *) ptr); |
| 400 | default: | 404 | default: |
| 401 | return -ENOSYS; | 405 | return -ENOSYS; |
| 402 | } | 406 | } |
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 7050b4ffffcd..42c94c771afb 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
| @@ -163,7 +163,7 @@ void do_gettimeofday(struct timeval *tv) | |||
| 163 | unsigned long seq; | 163 | unsigned long seq; |
| 164 | unsigned long lost; | 164 | unsigned long lost; |
| 165 | unsigned long usec, sec; | 165 | unsigned long usec, sec; |
| 166 | unsigned long max_ntp_tick = tick_usec - tickadj; | 166 | unsigned long max_ntp_tick; |
| 167 | 167 | ||
| 168 | do { | 168 | do { |
| 169 | seq = read_seqbegin(&xtime_lock); | 169 | seq = read_seqbegin(&xtime_lock); |
| @@ -178,12 +178,13 @@ void do_gettimeofday(struct timeval *tv) | |||
| 178 | * Better to lose some accuracy than have time go backwards.. | 178 | * Better to lose some accuracy than have time go backwards.. |
| 179 | */ | 179 | */ |
| 180 | if (unlikely(time_adjust < 0)) { | 180 | if (unlikely(time_adjust < 0)) { |
| 181 | max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; | ||
| 181 | usec = min(usec, max_ntp_tick); | 182 | usec = min(usec, max_ntp_tick); |
| 182 | 183 | ||
| 183 | if (lost) | 184 | if (lost) |
| 184 | usec += lost * max_ntp_tick; | 185 | usec += lost * max_ntp_tick; |
| 185 | } else if (unlikely(lost)) | 186 | } else if (unlikely(lost)) |
| 186 | usec += lost * tick_usec; | 187 | usec += lost * (USEC_PER_SEC / HZ); |
| 187 | 188 | ||
| 188 | sec = xtime.tv_sec; | 189 | sec = xtime.tv_sec; |
| 189 | usec += (xtime.tv_nsec / 1000); | 190 | usec += (xtime.tv_nsec / 1000); |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 59a187956de0..005debbfbe84 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
| 4 | * for more details. | 4 | * for more details. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle | 6 | * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle |
| 7 | * Copyright (C) 1995, 1996 Paul M. Antoine | 7 | * Copyright (C) 1995, 1996 Paul M. Antoine |
| 8 | * Copyright (C) 1998 Ulf Carlsson | 8 | * Copyright (C) 1998 Ulf Carlsson |
| 9 | * Copyright (C) 1999 Silicon Graphics, Inc. | 9 | * Copyright (C) 1999 Silicon Graphics, Inc. |
| @@ -548,6 +548,8 @@ asmlinkage void do_ov(struct pt_regs *regs) | |||
| 548 | { | 548 | { |
| 549 | siginfo_t info; | 549 | siginfo_t info; |
| 550 | 550 | ||
| 551 | die_if_kernel("Integer overflow", regs); | ||
| 552 | |||
| 551 | info.si_code = FPE_INTOVF; | 553 | info.si_code = FPE_INTOVF; |
| 552 | info.si_signo = SIGFPE; | 554 | info.si_signo = SIGFPE; |
| 553 | info.si_errno = 0; | 555 | info.si_errno = 0; |
| @@ -1168,7 +1170,7 @@ void __init per_cpu_trap_init(void) | |||
| 1168 | #endif | 1170 | #endif |
| 1169 | if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) | 1171 | if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) |
| 1170 | status_set |= ST0_XX; | 1172 | status_set |= ST0_XX; |
| 1171 | change_c0_status(ST0_CU|ST0_MX|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, | 1173 | change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, |
| 1172 | status_set); | 1174 | status_set); |
| 1173 | 1175 | ||
| 1174 | if (cpu_has_dsp) | 1176 | if (cpu_has_dsp) |
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 25cc856d8e7e..2ad0cedf29fe 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include <linux/config.h> | 1 | #include <linux/config.h> |
| 2 | #include <asm/asm-offsets.h> | ||
| 2 | #include <asm-generic/vmlinux.lds.h> | 3 | #include <asm-generic/vmlinux.lds.h> |
| 3 | 4 | ||
| 4 | #undef mips /* CPP really sucks for this job */ | 5 | #undef mips /* CPP really sucks for this job */ |
| @@ -64,10 +65,10 @@ SECTIONS | |||
| 64 | we can shorten the on-disk segment size. */ | 65 | we can shorten the on-disk segment size. */ |
| 65 | .sdata : { *(.sdata) } | 66 | .sdata : { *(.sdata) } |
| 66 | 67 | ||
| 67 | . = ALIGN(4096); | 68 | . = ALIGN(_PAGE_SIZE); |
| 68 | __nosave_begin = .; | 69 | __nosave_begin = .; |
| 69 | .data_nosave : { *(.data.nosave) } | 70 | .data_nosave : { *(.data.nosave) } |
| 70 | . = ALIGN(4096); | 71 | . = ALIGN(_PAGE_SIZE); |
| 71 | __nosave_end = .; | 72 | __nosave_end = .; |
| 72 | 73 | ||
| 73 | . = ALIGN(32); | 74 | . = ALIGN(32); |
| @@ -76,7 +77,7 @@ SECTIONS | |||
| 76 | _edata = .; /* End of data section */ | 77 | _edata = .; /* End of data section */ |
| 77 | 78 | ||
| 78 | /* will be freed after init */ | 79 | /* will be freed after init */ |
| 79 | . = ALIGN(4096); /* Init code and data */ | 80 | . = ALIGN(_PAGE_SIZE); /* Init code and data */ |
| 80 | __init_begin = .; | 81 | __init_begin = .; |
| 81 | .init.text : { | 82 | .init.text : { |
| 82 | _sinittext = .; | 83 | _sinittext = .; |
| @@ -105,7 +106,10 @@ SECTIONS | |||
| 105 | .con_initcall.init : { *(.con_initcall.init) } | 106 | .con_initcall.init : { *(.con_initcall.init) } |
| 106 | __con_initcall_end = .; | 107 | __con_initcall_end = .; |
| 107 | SECURITY_INIT | 108 | SECURITY_INIT |
| 108 | . = ALIGN(4096); | 109 | /* .exit.text is discarded at runtime, not link time, to deal with |
| 110 | references from .rodata */ | ||
| 111 | .exit.text : { *(.exit.text) } | ||
| 112 | . = ALIGN(_PAGE_SIZE); | ||
| 109 | __initramfs_start = .; | 113 | __initramfs_start = .; |
| 110 | .init.ramfs : { *(.init.ramfs) } | 114 | .init.ramfs : { *(.init.ramfs) } |
| 111 | __initramfs_end = .; | 115 | __initramfs_end = .; |
| @@ -113,7 +117,7 @@ SECTIONS | |||
| 113 | __per_cpu_start = .; | 117 | __per_cpu_start = .; |
| 114 | .data.percpu : { *(.data.percpu) } | 118 | .data.percpu : { *(.data.percpu) } |
| 115 | __per_cpu_end = .; | 119 | __per_cpu_end = .; |
| 116 | . = ALIGN(4096); | 120 | . = ALIGN(_PAGE_SIZE); |
| 117 | __init_end = .; | 121 | __init_end = .; |
| 118 | /* freed after init ends here */ | 122 | /* freed after init ends here */ |
| 119 | 123 | ||
| @@ -132,7 +136,6 @@ SECTIONS | |||
| 132 | 136 | ||
| 133 | /* Sections to be discarded */ | 137 | /* Sections to be discarded */ |
| 134 | /DISCARD/ : { | 138 | /DISCARD/ : { |
| 135 | *(.exit.text) | ||
| 136 | *(.exit.data) | 139 | *(.exit.data) |
| 137 | *(.exitcall.exit) | 140 | *(.exitcall.exit) |
| 138 | 141 | ||
