patch-2.4.6 linux/arch/mips/kernel/sysmips.c
Next file: linux/arch/mips/kernel/time.c
Previous file: linux/arch/mips/kernel/sysirix.c
Back to the patch index
Back to the overall index
- Lines: 90
- Date:
Mon Jul 2 13:56:40 2001
- Orig file:
v2.4.5/linux/arch/mips/kernel/sysmips.c
- Orig date:
Sun Jul 9 22:18:15 2000
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
@@ -7,6 +7,7 @@
*
* Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/mm.h>
@@ -21,6 +22,8 @@
#include <asm/sysmips.h>
#include <asm/uaccess.h>
+extern asmlinkage void syscall_trace(void);
+
/*
* How long a hostname can we get from user space?
* -EFAULT if invalid area or too long
@@ -49,7 +52,7 @@
{
int *p;
char *name;
- int flags, tmp, len, retval, errno;
+ int tmp, len, retval, errno;
switch(cmd) {
case SETNAME: {
@@ -72,8 +75,7 @@
}
case MIPS_ATOMIC_SET: {
- /* This is broken in case of page faults and SMP ...
- Risc/OS faults after maximum 20 tries with EAGAIN. */
+#ifdef CONFIG_CPU_HAS_LLSC
unsigned int tmp;
p = (int *) arg1;
@@ -81,16 +83,46 @@
if (errno)
return errno;
errno = 0;
- save_and_cli(flags);
- errno |= __get_user(tmp, p);
- errno |= __put_user(arg2, p);
- restore_flags(flags);
+
+ __asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t"
+ ".set\tmips2\n\t"
+ ".set\tnoat\n\t"
+ "1:\tll\t%0, %4\n\t"
+ "move\t$1, %3\n\t"
+ "2:\tsc\t$1, %1\n\t"
+ "beqz\t$1, 1b\n\t"
+ ".set\tpop\n\t"
+ ".section\t.fixup,\"ax\"\n"
+ "3:\tli\t%2, 1\t\t\t# error\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ ".word\t1b, 3b\n\t"
+ ".word\t2b, 3b\n\t"
+ ".previous\n\t"
+ : "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno)
+ : "r" (arg2), "o" (* (u32 *) p), "2" (errno)
+ : "$1");
if (errno)
- return tmp;
+ return -EFAULT;
- return tmp; /* This is broken ... */
- }
+ /* We're skipping error handling etc. */
+ if (current->ptrace & PT_TRACESYS)
+ syscall_trace();
+
+ ((struct pt_regs *)&cmd)->regs[2] = tmp;
+ ((struct pt_regs *)&cmd)->regs[7] = 0;
+
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\to32_ret_from_sys_call"
+ : /* No outputs */
+ : "r" (&cmd));
+ /* Unreached */
+#else
+ printk("sys_sysmips(MIPS_ATOMIC_SET, ...) not ready for !CONFIG_CPU_HAS_LLSC\n");
+#endif
+ }
case MIPS_FIXADE:
tmp = current->thread.mflags & ~3;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)