X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fm32r%2Fkernel%2Fsys_m32r.c;h=b4e7bcb43540444d6db2f4a56855711cc56ffe02;hb=refs%2Fheads%2Fvserver;hp=356e895fa0a893f94602e46f077379bf4fca1520;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index 356e895fa..b4e7bcb43 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -7,7 +7,6 @@ * Taken from i386 version. */ -#include #include #include #include @@ -26,45 +25,56 @@ #include #include #include +#include +#include /* * sys_tas() - test-and-set - * linuxthreads testing version */ -#ifndef CONFIG_SMP -asmlinkage int sys_tas(int *addr) +asmlinkage int sys_tas(int __user *addr) { int oldval; - unsigned long flags; if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) return -EFAULT; - local_irq_save(flags); - oldval = *addr; - *addr = 1; - local_irq_restore(flags); - return oldval; -} -#else /* CONFIG_SMP */ -#include - -static DEFINE_SPINLOCK(tas_lock); - -asmlinkage int sys_tas(int *addr) -{ - int oldval; - if (!access_ok(VERIFY_WRITE, addr, sizeof (int))) - return -EFAULT; - - _raw_spin_lock(&tas_lock); - oldval = *addr; - *addr = 1; - _raw_spin_unlock(&tas_lock); + /* atomic operation: + * oldval = *addr; *addr = 1; + */ + __asm__ __volatile__ ( + DCACHE_CLEAR("%0", "r4", "%1") + " .fillinsn\n" + "1:\n" + " lock %0, @%1 -> unlock %2, @%1\n" + "2:\n" + /* NOTE: + * The m32r processor can accept interrupts only + * at the 32-bit instruction boundary. + * So, in the above code, the "unlock" instruction + * can be executed continuously after the "lock" + * instruction execution without any interruptions. + */ + ".section .fixup,\"ax\"\n" + " .balign 4\n" + "3: ldi %0, #%3\n" + " seth r14, #high(2b)\n" + " or3 r14, r14, #low(2b)\n" + " jmp r14\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 1b,3b\n" + ".previous\n" + : "=&r" (oldval) + : "r" (addr), "r" (1), "i"(-EFAULT) + : "r14", "memory" +#ifdef CONFIG_CHIP_M32700_TS1 + , "r4" +#endif /* CONFIG_CHIP_M32700_TS1 */ + ); return oldval; } -#endif /* CONFIG_SMP */ /* * sys_pipe() is the normal C calling standard for creating @@ -80,7 +90,7 @@ sys_pipe(unsigned long r0, unsigned long r1, unsigned long r2, error = do_pipe(fd); if (!error) { - if (copy_to_user((void *)r0, (void *)fd, 2*sizeof(int))) + if (copy_to_user((void __user *)r0, fd, 2*sizeof(int))) error = -EFAULT; } return error; @@ -171,9 +181,9 @@ asmlinkage int sys_ipc(uint call, int first, int second, case SHMAT: { ulong raddr; - if ((ret = verify_area(VERIFY_WRITE, (ulong __user *) third, - sizeof(ulong)))) - return ret; + if (!access_ok(VERIFY_WRITE, (ulong __user *) third, + sizeof(ulong))) + return -EFAULT; ret = do_shmat (first, (char __user *) ptr, second, &raddr); if (ret) return ret; @@ -191,13 +201,13 @@ asmlinkage int sys_ipc(uint call, int first, int second, } } -asmlinkage int sys_uname(struct old_utsname * name) +asmlinkage int sys_uname(struct old_utsname __user * name) { int err; if (!name) return -EFAULT; down_read(&uts_sem); - err=copy_to_user(name, &system_utsname, sizeof (*name)); + err = copy_to_user(name, utsname(), sizeof (*name)); up_read(&uts_sem); return err?-EFAULT:0; } @@ -215,3 +225,21 @@ asmlinkage int sys_cachectl(char *addr, int nbytes, int op) return -ENOSYS; } +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + register long __scno __asm__ ("r7") = __NR_execve; + register long __arg3 __asm__ ("r2") = (long)(envp); + register long __arg2 __asm__ ("r1") = (long)(argv); + register long __res __asm__ ("r0") = (long)(filename); + __asm__ __volatile__ ( + "trap #" SYSCALL_VECTOR "|| nop" + : "=r" (__res) + : "r" (__scno), "0" (__res), "r" (__arg2), + "r" (__arg3) + : "memory"); + return __res; +}