diff mbox

[1/4] Add NPTL support for ColdFire

Message ID 4B8C160A.2000108@codesourcery.com
State New
Headers show

Commit Message

Maxim Kuvyrkov March 1, 2010, 7:31 p.m. UTC
From 1e505c8434d42f9b4fb1cc60934f856ffc06b476 Mon Sep 17 00:00:00 2001
From: Maxim Kuvyrkov <maxim@codesourcery.com>
Date: Mon, 1 Mar 2010 02:35:53 -0800
Subject: [PATCH 1/4] Add NPTL support for ColdFire

Add emulation of new m68k syscalls that provide kernel support for NPTL.

Signed-off-by: Maxim Kuvyrkov <maxim@codesourcery.com>
---
 configure                    |    1 +
 linux-user/m68k/syscall_nr.h |    5 +++++
 linux-user/main.c            |   21 +++++++++++++++++++++
 linux-user/strace.list       |    6 ++++++
 linux-user/syscall.c         |   20 ++++++++++++++++++++
 target-m68k/cpu.h            |   21 ++++++++++++++++++++-
 6 files changed, 73 insertions(+), 1 deletions(-)
diff mbox

Patch

diff --git a/configure b/configure
index 8eb5f5b..0c03640 100755
--- a/configure
+++ b/configure
@@ -2375,6 +2375,7 @@  case "$target_arch2" in
   ;;
   m68k)
     bflt="yes"
+    target_nptl="yes"
     gdb_xml_files="cf-core.xml cf-fp.xml"
     target_phys_bits=32
   ;;
diff --git a/linux-user/m68k/syscall_nr.h b/linux-user/m68k/syscall_nr.h
index 1c0ba07..00d4966 100644
--- a/linux-user/m68k/syscall_nr.h
+++ b/linux-user/m68k/syscall_nr.h
@@ -328,3 +328,8 @@ 
 #define TARGET_NR_dup3			326
 #define TARGET_NR_pipe2		327
 #define TARGET_NR_inotify_init1	328
+
+#define TARGET_NR_get_thread_area	333
+#define TARGET_NR_set_thread_area	334
+#define TARGET_NR_atomic_cmpxchg_32	335
+#define TARGET_NR_atomic_barrier	336
diff --git a/linux-user/main.c b/linux-user/main.c
index eeae22e..70e39fc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2256,6 +2256,27 @@  void cpu_loop (CPUState *env)
 
 #ifdef TARGET_M68K
 
+uint32_t do_cmpxchg_32 (uint32_t addr, uint32_t oldval, uint32_t newval)
+{
+    uint32_t val;
+
+    /* XXX: This only works between threads, not between processes.
+       It's probably possible to implement this with native host
+       operations. However things like ldrex/strex are much harder so
+       there's not much point trying.  */
+    start_exclusive();
+
+    /* FIXME: This should SEGV if the access fails.  */
+    get_user_u32(val, addr);
+    if (val == oldval)
+        /* FIXME: Check for segfaults.  */
+        put_user_u32(newval, addr);
+
+    end_exclusive();
+
+    return val;
+}
+
 void cpu_loop(CPUM68KState *env)
 {
     int trapnr;
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 97b7f76..c8c79cc 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -33,6 +33,12 @@ 
 #ifdef TARGET_NR_arm_fadvise64_64
 { TARGET_NR_arm_fadvise64_64, "arm_fadvise64_64" , NULL, NULL, NULL },
 #endif
+#ifdef TARGET_NR_atomic_barrier
+{ TARGET_NR_atomic_barrier, "atomic_barrier" , NULL, NULL, NULL },
+#endif
+#ifdef TARGET_NR_atomic_cmpxchg_32
+{ TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32" , NULL, NULL, NULL },
+#endif
 #ifdef TARGET_NR_bdflush
 { TARGET_NR_bdflush, "bdflush" , NULL, NULL, NULL },
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 38eb35f..364f671 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5756,6 +5756,8 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
 #elif defined(TARGET_CRIS)
         ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
+#elif defined(TARGET_M68K)
+	ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
 #else
         ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
 #endif
@@ -6943,6 +6945,10 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #elif defined(TARGET_I386) && defined(TARGET_ABI32)
       ret = do_set_thread_area(cpu_env, arg1);
       break;
+#elif defined(TARGET_M68K)
+      cpu_set_tls (cpu_env, arg1);
+      ret = 0;
+      break;
 #else
       goto unimplemented_nowarn;
 #endif
@@ -6951,6 +6957,10 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_get_thread_area:
 #if defined(TARGET_I386) && defined(TARGET_ABI32)
         ret = do_get_thread_area(cpu_env, arg1);
+	break;
+#elif defined(TARGET_M68K)
+	ret = cpu_get_tls (cpu_env);
+	break;
 #else
         goto unimplemented_nowarn;
 #endif
@@ -7197,6 +7207,16 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
         break;
 #endif
+#ifdef TARGET_NR_atomic_cmpxchg_32
+	case TARGET_NR_atomic_cmpxchg_32:
+	ret = do_cmpxchg_32 (arg6, arg2, arg1);
+	break;
+#endif
+#ifdef TARGET_NR_atomic_barrier
+	case TARGET_NR_atomic_barrier:
+	ret = 0;
+	break;
+#endif
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 68a7e41..6bafc40 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -109,6 +109,9 @@  typedef struct CPUM68KState {
 
     uint32_t qregs[MAX_QREGS];
 
+    /* For usermode emulation */
+    target_ulong tls_value;
+
     CPU_COMMON
 
     uint32_t features;
@@ -126,6 +129,8 @@  int cpu_m68k_signal_handler(int host_signum, void *pinfo,
                            void *puc);
 void cpu_m68k_flush_flags(CPUM68KState *, int);
 
+uint32_t do_cmpxchg_32 (uint32_t, uint32_t, uint32_t);
+
 enum {
     CC_OP_DYNAMIC, /* Use env->cc_op  */
     CC_OP_FLAGS, /* CC_DEST = CVZN, CC_SRC = unused */
@@ -236,7 +241,21 @@  static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
         env->aregs[7] = newsp;
     env->dregs[0] = 0;
 }
-#endif
+
+static inline target_ulong cpu_get_tls(CPUState *env)
+{
+    return env->tls_value;
+}
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+    env->tls_value = newtls;
+}
+
+static inline void cpu_clear_exclusive(void)
+{
+}
+#endif /* CONFIG_USER_ONLY */
 
 #include "cpu-all.h"
 #include "exec-all.h"