diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 30 | ||||
-rw-r--r-- | arch/mips/kernel/cpufreq/loongson2_cpufreq.c | 4 | ||||
-rw-r--r-- | arch/mips/kernel/ftrace.c | 184 | ||||
-rw-r--r-- | arch/mips/kernel/i8253.c | 14 | ||||
-rw-r--r-- | arch/mips/kernel/kgdb.c | 27 | ||||
-rw-r--r-- | arch/mips/kernel/mcount.S | 55 | ||||
-rw-r--r-- | arch/mips/kernel/mips-mt-fpaff.c | 87 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n32.S | 3 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 21 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 33 | ||||
-rw-r--r-- | arch/mips/kernel/vdso.c | 4 |
11 files changed, 298 insertions, 164 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index be5bb16be4e..3562b854f2c 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -125,6 +125,30 @@ static int __init wait_disable(char *s) __setup("nowait", wait_disable); +static int __cpuinitdata mips_fpu_disabled; + +static int __init fpu_disable(char *s) +{ + cpu_data[0].options &= ~MIPS_CPU_FPU; + mips_fpu_disabled = 1; + + return 1; +} + +__setup("nofpu", fpu_disable); + +int __cpuinitdata mips_dsp_disabled; + +static int __init dsp_disable(char *s) +{ + cpu_data[0].ases &= ~MIPS_ASE_DSP; + mips_dsp_disabled = 1; + + return 1; +} + +__setup("nodsp", dsp_disable); + void __init check_wait(void) { struct cpuinfo_mips *c = ¤t_cpu_data; @@ -982,6 +1006,12 @@ __cpuinit void cpu_probe(void) */ BUG_ON(current_cpu_type() != c->cputype); + if (mips_fpu_disabled) + c->options &= ~MIPS_CPU_FPU; + + if (mips_dsp_disabled) + c->ases &= ~MIPS_ASE_DSP; + if (c->options & MIPS_CPU_FPU) { c->fpu_id = cpu_get_fpu_id(); diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c index 2f6a0b147ab..ae5db206347 100644 --- a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c +++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c @@ -65,7 +65,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, return -ENODEV; cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); if (cpufreq_frequency_table_target (policy, &loongson2_clockmod_table[0], target_freq, relation, @@ -91,7 +91,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy, /* notifiers */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - set_cpus_allowed(current, cpus_allowed); + set_cpus_allowed_ptr(current, &cpus_allowed); /* setting the cpu frequency */ clk_set_rate(cpuclk, freq); diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index e9e64e0ff7a..5a84a1f1123 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -2,7 +2,7 @@ * Code for replacing ftrace calls with jumps. * * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> - * Copyright (C) 2009 DSLab, Lanzhou University, China + * Copyright (C) 2009, 2010 DSLab, Lanzhou University, China * Author: Wu Zhangjin <wuzhangjin@gmail.com> * * Thanks goes to Steven Rostedt for writing the original x86 version. @@ -12,18 +12,62 @@ #include <linux/init.h> #include <linux/ftrace.h> -#include <asm/cacheflush.h> #include <asm/asm.h> #include <asm/asm-offsets.h> +#include <asm/cacheflush.h> +#include <asm/uasm.h> + +/* + * If the Instruction Pointer is in module space (0xc0000000), return true; + * otherwise, it is in kernel space (0x80000000), return false. + * + * FIXME: This will not work when the kernel space and module space are the + * same. If they are the same, we need to modify scripts/recordmcount.pl, + * ftrace_make_nop/call() and the other related parts to ensure the + * enabling/disabling of the calling site to _mcount is right for both kernel + * and module. + */ + +static inline int in_module(unsigned long ip) +{ + return ip & 0x40000000; +} #ifdef CONFIG_DYNAMIC_FTRACE #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ -#define jump_insn_encode(op_code, addr) \ - ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK))) -static unsigned int ftrace_nop = 0x00000000; +#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ +#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ +#define INSN_NOP 0x00000000 /* nop */ +#define INSN_JAL(addr) \ + ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) + +static unsigned int insn_jal_ftrace_caller __read_mostly; +static unsigned int insn_lui_v1_hi16_mcount __read_mostly; +static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly; + +static inline void ftrace_dyn_arch_init_insns(void) +{ + u32 *buf; + unsigned int v1; + + /* lui v1, hi16_mcount */ + v1 = 3; + buf = (u32 *)&insn_lui_v1_hi16_mcount; + UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR); + + /* jal (ftrace_caller + 8), jump over the first two instruction */ + buf = (u32 *)&insn_jal_ftrace_caller; + uasm_i_jal(&buf, (FTRACE_ADDR + 8)); + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + /* j ftrace_graph_caller */ + buf = (u32 *)&insn_j_ftrace_graph_caller; + uasm_i_j(&buf, (unsigned long)ftrace_graph_caller); +#endif +} static int ftrace_modify_code(unsigned long ip, unsigned int new_code) { @@ -40,67 +84,56 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) return 0; } -static int lui_v1; -static int jal_mcount; - int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { unsigned int new; - int faulted; unsigned long ip = rec->ip; - /* We have compiled module with -mlong-calls, but compiled the kernel - * without it, we need to cope with them respectively. */ - if (ip & 0x40000000) { - /* record it for ftrace_make_call */ - if (lui_v1 == 0) { - /* lui_v1 = *(unsigned int *)ip; */ - safe_load_code(lui_v1, ip, faulted); - - if (unlikely(faulted)) - return -EFAULT; - } - - /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) + /* + * We have compiled module with -mlong-calls, but compiled the kernel + * without it, we need to cope with them respectively. + */ + if (in_module(ip)) { +#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) + /* + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) + * addiu v1, v1, low_16bit_of_mcount + * move at, ra + * move $12, ra_address + * jalr v1 + * sub sp, sp, 8 + * 1: offset = 5 instructions + */ + new = INSN_B_1F_5; +#else + /* + * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) * addiu v1, v1, low_16bit_of_mcount * move at, ra * jalr v1 - * nop - * 1f: (ip + 12) + * nop | move $12, ra_address | sub sp, sp, 8 + * 1: offset = 4 instructions */ - new = 0x10000004; + new = INSN_B_1F_4; +#endif } else { - /* record/calculate it for ftrace_make_call */ - if (jal_mcount == 0) { - /* We can record it directly like this: - * jal_mcount = *(unsigned int *)ip; - * Herein, jump over the first two nop instructions */ - jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8)); - } - - /* move at, ra - * jalr v1 --> nop + /* + * move at, ra + * jal _mcount --> nop */ - new = ftrace_nop; + new = INSN_NOP; } return ftrace_modify_code(ip, new); } -static int modified; /* initialized as 0 by default */ - int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { unsigned int new; unsigned long ip = rec->ip; - /* We just need to remove the "b ftrace_stub" at the fist time! */ - if (modified == 0) { - modified = 1; - ftrace_modify_code(addr, ftrace_nop); - } /* ip, module: 0xc0000000, kernel: 0x80000000 */ - new = (ip & 0x40000000) ? lui_v1 : jal_mcount; + new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; return ftrace_modify_code(ip, new); } @@ -111,44 +144,48 @@ int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned int new; - new = jump_insn_encode(JAL, (unsigned long)func); + new = INSN_JAL((unsigned long)func); return ftrace_modify_code(FTRACE_CALL_IP, new); } int __init ftrace_dyn_arch_init(void *data) { + /* Encode the instructions when booting */ + ftrace_dyn_arch_init_insns(); + + /* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */ + ftrace_modify_code(MCOUNT_ADDR, INSN_NOP); + /* The return code is retured via data */ *(unsigned long *)data = 0; return 0; } -#endif /* CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_DYNAMIC_FTRACE extern void ftrace_graph_call(void); -#define JMP 0x08000000 /* jump to target directly */ -#define CALL_FTRACE_GRAPH_CALLER \ - jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller)) #define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call)) int ftrace_enable_ftrace_graph_caller(void) { return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, - CALL_FTRACE_GRAPH_CALLER); + insn_j_ftrace_graph_caller); } int ftrace_disable_ftrace_graph_caller(void) { - return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop); + return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP); } -#endif /* !CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_DYNAMIC_FTRACE */ #ifndef KBUILD_MCOUNT_RA_ADDRESS + #define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ @@ -162,17 +199,17 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, unsigned int code; int faulted; - /* in module or kernel? */ - if (self_addr & 0x40000000) { - /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */ - ip = self_addr - 20; - } else { - /* kernel: move to the instruction "move ra, at" */ - ip = self_addr - 12; - } + /* + * For module, move the ip from calling site of mcount to the + * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for + * kernel, move to the instruction "move ra, at"(offset is 12) + */ + ip = self_addr - (in_module(self_addr) ? 20 : 12); - /* search the text until finding the non-store instruction or "s{d,w} - * ra, offset(sp)" instruction */ + /* + * search the text until finding the non-store instruction or "s{d,w} + * ra, offset(sp)" instruction + */ do { ip -= 4; @@ -181,10 +218,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, if (unlikely(faulted)) return 0; - - /* If we hit the non-store instruction before finding where the + /* + * If we hit the non-store instruction before finding where the * ra is stored, then this is a leaf function and it does not - * store the ra on the stack. */ + * store the ra on the stack + */ if ((code & S_R_SP) != S_R_SP) return parent_addr; @@ -202,7 +240,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, return 0; } -#endif +#endif /* !KBUILD_MCOUNT_RA_ADDRESS */ /* * Hook the return address and push it in the stack of return addrs @@ -220,7 +258,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, if (unlikely(atomic_read(¤t->tracing_graph_pause))) return; - /* "parent" is the stack address saved the return address of the caller + /* + * "parent" is the stack address saved the return address of the caller * of _mcount. * * if the gcc < 4.5, a leaf function does not save the return address @@ -242,10 +281,11 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, goto out; #ifndef KBUILD_MCOUNT_RA_ADDRESS parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, - (unsigned long)parent, - fp); - /* If fails when getting the stack address of the non-leaf function's - * ra, stop function graph tracer and return */ + (unsigned long)parent, fp); + /* + * If fails when getting the stack address of the non-leaf function's + * ra, stop function graph tracer and return + */ if (parent == 0) goto out; #endif @@ -272,4 +312,4 @@ out: ftrace_graph_stop(); WARN_ON(1); } -#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c index ed5c441615e..94794062a17 100644 --- a/arch/mips/kernel/i8253.c +++ b/arch/mips/kernel/i8253.c @@ -15,7 +15,7 @@ #include <asm/io.h> #include <asm/time.h> -DEFINE_SPINLOCK(i8253_lock); +DEFINE_RAW_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); /* @@ -26,7 +26,7 @@ EXPORT_SYMBOL(i8253_lock); static void init_pit_timer(enum clock_event_mode mode, struct clock_event_device *evt) { - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); switch(mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -55,7 +55,7 @@ static void init_pit_timer(enum clock_event_mode mode, /* Nothing to do here */ break; } - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); } /* @@ -65,10 +65,10 @@ static void init_pit_timer(enum clock_event_mode mode, */ static int pit_next_event(unsigned long delta, struct clock_event_device *evt) { - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); outb_p(delta & 0xff , PIT_CH0); /* LSB */ outb(delta >> 8 , PIT_CH0); /* MSB */ - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); return 0; } @@ -137,7 +137,7 @@ static cycle_t pit_read(struct clocksource *cs) static int old_count; static u32 old_jifs; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); /* * Although our caller may have the read side of xtime_lock, * this is now a seqlock, and we are cheating in this routine @@ -183,7 +183,7 @@ static cycle_t pit_read(struct clocksource *cs) old_count = count; old_jifs = jifs; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); count = (LATCH - 1) - count; diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 50c9bb88066..9b78ff6e9b8 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -180,6 +180,11 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) *(ptr++) = regs->cp0_epc; } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) +{ + regs->cp0_epc = pc; +} + /* * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, * then try to fall into the debugger @@ -198,7 +203,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, if (atomic_read(&kgdb_active) != -1) kgdb_nmicallback(smp_processor_id(), regs); - if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs)) + if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs)) return NOTIFY_DONE; if (atomic_read(&kgdb_setting_breakpoint)) @@ -212,6 +217,26 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, return NOTIFY_STOP; } +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP +int kgdb_ll_trap(int cmd, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig, + + }; + + if (!kgdb_io_module_registered) + return NOTIFY_DONE; + + return kgdb_mips_notify(NULL, cmd, &args); +} +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ + static struct notifier_block kgdb_notifier = { .notifier_call = kgdb_mips_notify, }; diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 6851fc97a51..6bfcb7a00ec 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -6,6 +6,7 @@ * more details. * * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China + * Copyright (C) 2010 DSLab, Lanzhou University, China * Author: Wu Zhangjin <wuzhangjin@gmail.com> */ @@ -45,8 +46,6 @@ PTR_L a5, PT_R9(sp) PTR_L a6, PT_R10(sp) PTR_L a7, PT_R11(sp) -#endif -#ifdef CONFIG_64BIT PTR_ADDIU sp, PT_SIZE #else PTR_ADDIU sp, (PT_SIZE + 8) @@ -58,6 +57,12 @@ move ra, AT .endm +/* + * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass + * the location of the parent's return address. + */ +#define MCOUNT_RA_ADDRESS_REG $12 + #ifdef CONFIG_DYNAMIC_FTRACE NESTED(ftrace_caller, PT_SIZE, ra) @@ -71,14 +76,14 @@ _mcount: MCOUNT_SAVE_REGS #ifdef KBUILD_MCOUNT_RA_ADDRESS - PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */ + PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) #endif - move a0, ra /* arg1: next ip, selfaddr */ + move a0, ra /* arg1: self return address */ .globl ftrace_call ftrace_call: nop /* a placeholder for the call to a real tracing function */ - move a1, AT /* arg2: the caller's next ip, parent */ + move a1, AT /* arg2: parent's return address */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER .globl ftrace_graph_call @@ -119,9 +124,9 @@ NESTED(_mcount, PT_SIZE, ra) static_trace: MCOUNT_SAVE_REGS - move a0, ra /* arg1: next ip, selfaddr */ + move a0, ra /* arg1: self return address */ jalr t2 /* (1) call *ftrace_trace_function */ - move a1, AT /* arg2: the caller's next ip, parent */ + move a1, AT /* arg2: parent's return address */ MCOUNT_RESTORE_REGS .globl ftrace_stub @@ -134,28 +139,34 @@ ftrace_stub: #ifdef CONFIG_FUNCTION_GRAPH_TRACER NESTED(ftrace_graph_caller, PT_SIZE, ra) -#ifdef CONFIG_DYNAMIC_FTRACE - PTR_L a1, PT_R31(sp) /* load the original ra from the stack */ -#ifdef KBUILD_MCOUNT_RA_ADDRESS - PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */ -#endif -#else +#ifndef CONFIG_DYNAMIC_FTRACE MCOUNT_SAVE_REGS - move a1, ra /* arg2: next ip, selfaddr */ #endif + /* arg1: Get the location of the parent's return address */ #ifdef KBUILD_MCOUNT_RA_ADDRESS - bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */ +#ifdef CONFIG_DYNAMIC_FTRACE + PTR_L a0, PT_R12(sp) +#else + move a0, MCOUNT_RA_ADDRESS_REG +#endif + bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */ nop - PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */ -1: move a0, t0 /* arg1: the location of the return address */ +#endif + PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */ +1: + + /* arg2: Get self return address */ +#ifdef CONFIG_DYNAMIC_FTRACE + PTR_L a1, PT_R31(sp) #else - PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */ + move a1, ra #endif - jal prepare_ftrace_return + + /* arg3: Get frame pointer of current stack */ #ifdef CONFIG_FRAME_POINTER - move a2, fp /* arg3: frame pointer */ -#else + move a2, fp +#else /* ! CONFIG_FRAME_POINTER */ #ifdef CONFIG_64BIT PTR_LA a2, PT_SIZE(sp) #else @@ -163,6 +174,8 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) #endif #endif + jal prepare_ftrace_return + nop MCOUNT_RESTORE_REGS RETURN_BACK END(ftrace_graph_caller) diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index cbc6182b006..2340f11dc29 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -3,6 +3,7 @@ * Copyright (C) 2005 Mips Technologies, Inc */ #include <linux/cpu.h> +#include <linux/cpuset.h> #include <linux/cpumask.h> #include <linux/delay.h> #include <linux/kernel.h> @@ -39,6 +40,21 @@ static inline struct task_struct *find_process_by_pid(pid_t pid) return pid ? find_task_by_vpid(pid) : current; } +/* + * check the target process has a UID that matches the current process's + */ +static bool check_same_owner(struct task_struct *p) +{ + const struct cred *cred = current_cred(), *pcred; + bool match; + + rcu_read_lock(); + pcred = __task_cred(p); + match = (cred->euid == pcred->euid || + cred->euid == pcred->uid); + rcu_read_unlock(); + return match; +} /* * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process @@ -46,12 +62,10 @@ static inline struct task_struct *find_process_by_pid(pid_t pid) asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long __user *user_mask_ptr) { - cpumask_t new_mask; - cpumask_t effective_mask; - int retval; - struct task_struct *p; + cpumask_var_t cpus_allowed, new_mask, effective_mask; struct thread_info *ti; - uid_t euid; + struct task_struct *p; + int retval; if (len < sizeof(new_mask)) return -EINVAL; @@ -60,53 +74,74 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, return -EFAULT; get_online_cpus(); - read_lock(&tasklist_lock); + rcu_read_lock(); p = find_process_by_pid(pid); if (!p) { - read_unlock(&tasklist_lock); + rcu_read_unlock(); put_online_cpus(); return -ESRCH; } - /* - * It is not safe to call set_cpus_allowed with the - * tasklist_lock held. We will bump the task_struct's - * usage count and drop tasklist_lock before invoking - * set_cpus_allowed. - */ + /* Prevent p going away */ get_task_struct(p); + rcu_read_unlock(); - euid = current_euid(); + if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) { + retval = -ENOMEM; + goto out_put_task; + } + if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { + retval = -ENOMEM; + goto out_free_cpus_allowed; + } + if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) { + retval = -ENOMEM; + goto out_free_new_mask; + } retval = -EPERM; - if (euid != p->cred->euid && euid != p->cred->uid && - !capable(CAP_SYS_NICE)) { - read_unlock(&tasklist_lock); + if (!check_same_owner(p) && !capable(CAP_SYS_NICE)) goto out_unlock; - } retval = security_task_setscheduler(p, 0, NULL); if (retval) goto out_unlock; /* Record new user-specified CPU set for future reference */ - p->thread.user_cpus_allowed = new_mask; - - /* Unlock the task list */ - read_unlock(&tasklist_lock); + cpumask_copy(&p->thread.user_cpus_allowed, new_mask); + again: /* Compute new global allowed CPU set if necessary */ ti = task_thread_info(p); if (test_ti_thread_flag(ti, TIF_FPUBOUND) && - cpus_intersects(new_mask, mt_fpu_cpumask)) { - cpus_and(effective_mask, new_mask, mt_fpu_cpumask); - retval = set_cpus_allowed(p, effective_mask); + cpus_intersects(*new_mask, mt_fpu_cpumask)) { + cpus_and(*effective_mask, *new_mask, mt_fpu_cpumask); + retval = set_cpus_allowed_ptr(p, effective_mask); } else { + cpumask_copy(effective_mask, new_mask); clear_ti_thread_flag(ti, TIF_FPUBOUND); - retval = set_cpus_allowed(p, new_mask); + retval = set_cpus_allowed_ptr(p, new_mask); } + if (!retval) { + cpuset_cpus_allowed(p, cpus_allowed); + if (!cpumask_subset(effective_mask, cpus_allowed)) { + /* + * We must have raced with a concurrent cpuset + * update. Just reset the cpus_allowed to the + * cpuset's cpus_allowed + */ + cpumask_copy(new_mask, cpus_allowed); + goto again; + } + } out_unlock: + free_cpumask_var(effective_mask); +out_free_new_mask: + free_cpumask_var(new_mask); +out_free_cpus_allowed: + free_cpumask_var(cpus_allowed); +out_put_task: put_task_struct(p); put_online_cpus(); return retval; diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 44337ba0371..a4faceea9d8 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -385,7 +385,7 @@ EXPORT(sysn32_call_table) PTR sys_fchmodat PTR sys_faccessat PTR compat_sys_pselect6 - PTR sys_ppoll /* 6265 */ + PTR compat_sys_ppoll /* 6265 */ PTR sys_unshare PTR sys_splice PTR sys_sync_file_range @@ -419,4 +419,5 @@ EXPORT(sysn32_call_table) PTR sys_perf_event_open PTR sys_accept4 PTR compat_sys_recvmmsg + PTR sys_getdents .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index f9513f9e61d..85aef3fc671 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -569,27 +569,6 @@ void __init setup_arch(char **cmdline_p) plat_smp_setup(); } -static int __init fpu_disable(char *s) -{ - int i; - - for (i = 0; i < NR_CPUS; i++) - cpu_data[i].options &= ~MIPS_CPU_FPU; - - return 1; -} - -__setup("nofpu", fpu_disable); - -static int __init dsp_disable(char *s) -{ - cpu_data[0].ases &= ~MIPS_ASE_DSP; - - return 1; -} - -__setup("nodsp", dsp_disable); - unsigned long kernelsp[NR_CPUS]; unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 1a4dd657ccb..852780868fb 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -26,6 +26,7 @@ #include <linux/kgdb.h> #include <linux/kdebug.h> #include <linux/notifier.h> +#include <linux/kdb.h> #include <asm/bootinfo.h> #include <asm/branch.h> @@ -185,6 +186,11 @@ void show_stack(struct task_struct *task, unsigned long *sp) regs.regs[29] = task->thread.reg29; regs.regs[31] = 0; regs.cp0_epc = task->thread.reg31; +#ifdef CONFIG_KGDB_KDB + } else if (atomic_read(&kgdb_active) != -1 && + kdb_current_regs) { + memcpy(®s, kdb_current_regs, sizeof(regs)); +#endif /* CONFIG_KGDB_KDB */ } else { prepare_frametrace(®s); } @@ -352,19 +358,26 @@ void show_registers(const struct pt_regs *regs) static DEFINE_SPINLOCK(die_lock); -void __noreturn die(const char * str, const struct pt_regs * regs) +void __noreturn die(const char * str, struct pt_regs * regs) { static int die_counter; + int sig = SIGSEGV; #ifdef CONFIG_MIPS_MT_SMTC unsigned long dvpret = dvpe(); #endif /* CONFIG_MIPS_MT_SMTC */ + notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0); + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); #ifdef CONFIG_MIPS_MT_SMTC mips_mt_regdump(dvpret); #endif /* CONFIG_MIPS_MT_SMTC */ + + if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) + sig = 0; + printk("%s[#%d]:\n", str, ++die_counter); show_registers(regs); add_taint(TAINT_DIE); @@ -379,7 +392,7 @@ void __noreturn die(const char * str, const struct pt_regs * regs) panic("Fatal exception"); } - do_exit(SIGSEGV); + do_exit(sig); } extern struct exception_table_entry __start___dbe_table[]; @@ -699,6 +712,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, siginfo_t info; char b[40]; +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP + if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) + return; +#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ + if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP) return; @@ -849,7 +867,7 @@ static void mt_ase_fp_affinity(void) = current->cpus_allowed; cpus_and(tmask, current->cpus_allowed, mt_fpu_cpumask); - set_cpus_allowed(current, tmask); + set_cpus_allowed_ptr(current, &tmask); set_thread_flag(TIF_FPUBOUND); } } @@ -958,7 +976,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) case 2: raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); - break; + return; case 3: break; @@ -1557,12 +1575,7 @@ static char panic_null_cerr[] __cpuinitdata = void __cpuinit set_uncached_handler(unsigned long offset, void *addr, unsigned long size) { -#ifdef CONFIG_32BIT - unsigned long uncached_ebase = KSEG1ADDR(ebase); -#endif -#ifdef CONFIG_64BIT - unsigned long uncached_ebase = TO_UNCAC(ebase); -#endif + unsigned long uncached_ebase = CKSEG1ADDR(ebase); if (!addr) panic(panic_null_cerr); diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index b773c1112b1..e5cdfd603f8 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -61,11 +61,9 @@ static int __init init_vdso(void) vunmap(vdso); - pr_notice("init_vdso successfull\n"); - return 0; } -device_initcall(init_vdso); +subsys_initcall(init_vdso); static unsigned long vdso_addr(unsigned long start) { |