From: James S. <jsi...@us...> - 2001-11-13 23:35:02
|
Update of /cvsroot/linux-mips/linux/arch/mips/kernel In directory usw-pr-cvs1:/tmp/cvs-serv6444 Modified Files: traps.c Log Message: Some cleanup. Index: traps.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/kernel/traps.c,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- traps.c 2001/11/06 00:30:42 1.23 +++ traps.c 2001/11/13 23:34:59 1.24 @@ -77,12 +77,9 @@ */ #define MODULE_RANGE (8*1024*1024) -#ifndef CONFIG_CPU_HAS_LLSC /* * This stuff is needed for the userland ll-sc emulation for R2300 */ -void simulate_ll(struct pt_regs *regs, unsigned int opcode); -void simulate_sc(struct pt_regs *regs, unsigned int opcode); #define OPCODE 0xfc000000 #define BASE 0x03e00000 @@ -90,8 +87,97 @@ #define OFFSET 0x0000ffff #define LL 0xc0000000 #define SC 0xe0000000 + +/* + * The ll_bit is cleared by r*_switch.S + */ + +unsigned long ll_bit; +#ifdef CONFIG_PROC_FS +extern unsigned long ll_ops; +extern unsigned long sc_ops; #endif +static struct task_struct *ll_task = NULL; + +static inline void simulate_ll(struct pt_regs *regp, unsigned int opcode) +{ + unsigned long value, *vaddr; + long offset; + int signal = 0; + + /* + * analyse the ll instruction that just caused a ri exception + * and put the referenced address to addr. + */ + + /* sign extend offset */ + offset = opcode & OFFSET; + offset <<= 16; + offset >>= 16; + + vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); + +#ifdef CONFIG_PROC_FS + ll_ops++; +#endif + + if ((unsigned long)vaddr & 3) + signal = SIGBUS; + else if (get_user(value, vaddr)) + signal = SIGSEGV; + else { + if (ll_task == NULL || ll_task == current) { + ll_bit = 1; + } else { + ll_bit = 0; + } + ll_task = current; + regp->regs[(opcode & RT) >> 16] = value; + } + if (compute_return_epc(regp)) + return; + if (signal) + send_sig(signal, current, 1); +} + +static inline void simulate_sc(struct pt_regs *regp, unsigned int opcode) +{ + unsigned long *vaddr, reg; + long offset; + int signal = 0; + + /* + * analyse the sc instruction that just caused a ri exception + * and put the referenced address to addr. + */ + + /* sign extend offset */ + offset = opcode & OFFSET; + offset <<= 16; + offset >>= 16; + + vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); + reg = (opcode & RT) >> 16; + +#ifdef CONFIG_PROC_FS + sc_ops++; +#endif + + if ((unsigned long)vaddr & 3) + signal = SIGBUS; + else if (ll_bit == 0 || ll_task != current) + regp->regs[reg] = 0; + else if (put_user(regp->regs[reg], vaddr)) + signal = SIGSEGV; + else + regp->regs[reg] = 1; + if (compute_return_epc(regp)) + return; + if (signal) + send_sig(signal, current, 1); +} + /* * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... @@ -516,12 +602,6 @@ force_sig(SIGSEGV, current); } -#ifndef CONFIG_CPU_HAS_LLSC - -#ifdef CONFIG_SMP -#error "ll/sc emulation is not SMP safe" -#endif - /* * userland emulation for R2300 CPUs * needed for the multithreading part of glibc @@ -531,11 +611,19 @@ */ asmlinkage void do_ri(struct pt_regs *regs) { - unsigned int opcode; if (!user_mode(regs)) BUG(); +#ifndef CONFIG_CPU_HAS_LLSC + +#ifdef CONFIG_SMP +#error "ll/sc emulation is not SMP safe" +#endif + + { + unsigned int opcode; + if (!get_insn_opcode(regs, &opcode)) { if ((opcode & OPCODE) == LL) { simulate_ll(regs, opcode); @@ -546,113 +634,13 @@ return; } } - - if (compute_return_epc(regs)) - return; - force_sig(SIGILL, current); -} - -/* - * The ll_bit is cleared by r*_switch.S - */ - -unsigned long ll_bit; -#ifdef CONFIG_PROC_FS -extern unsigned long ll_ops; -extern unsigned long sc_ops; -#endif - -static struct task_struct *ll_task = NULL; - -void simulate_ll(struct pt_regs *regp, unsigned int opcode) -{ - unsigned long value, *vaddr; - long offset; - int signal = 0; - - /* - * analyse the ll instruction that just caused a ri exception - * and put the referenced address to addr. - */ - - /* sign extend offset */ - offset = opcode & OFFSET; - offset <<= 16; - offset >>= 16; - - vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); - -#ifdef CONFIG_PROC_FS - ll_ops++; -#endif - - if ((unsigned long)vaddr & 3) - signal = SIGBUS; - else if (get_user(value, vaddr)) - signal = SIGSEGV; - else { - if (ll_task == NULL || ll_task == current) { - ll_bit = 1; - } else { - ll_bit = 0; - } - ll_task = current; - regp->regs[(opcode & RT) >> 16] = value; } - if (compute_return_epc(regp)) - return; - if (signal) - send_sig(signal, current, 1); -} - -void simulate_sc(struct pt_regs *regp, unsigned int opcode) -{ - unsigned long *vaddr, reg; - long offset; - int signal = 0; - - /* - * analyse the sc instruction that just caused a ri exception - * and put the referenced address to addr. - */ - - /* sign extend offset */ - offset = opcode & OFFSET; - offset <<= 16; - offset >>= 16; - - vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); - reg = (opcode & RT) >> 16; - -#ifdef CONFIG_PROC_FS - sc_ops++; -#endif - - if ((unsigned long)vaddr & 3) - signal = SIGBUS; - else if (ll_bit == 0 || ll_task != current) - regp->regs[reg] = 0; - else if (put_user(regp->regs[reg], vaddr)) - signal = SIGSEGV; - else - regp->regs[reg] = 1; - if (compute_return_epc(regp)) - return; - if (signal) - send_sig(signal, current, 1); -} - -#else /* MIPS 2 or higher */ +#endif /* CONFIG_CPU_HAS_LLSC */ -asmlinkage void do_ri(struct pt_regs *regs) -{ if (compute_return_epc(regs)) return; - force_sig(SIGILL, current); } - -#endif asmlinkage void do_cpu(struct pt_regs *regs) { |