Arm Linux EABI syscall support.
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 9 Feb 2006 16:49:55 +0000 (16:49 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 9 Feb 2006 16:49:55 +0000 (16:49 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1756 c046a42c-6fe2-441c-8c8c-71466251a162

linux-user/main.c
linux-user/syscall.c
linux-user/syscall_defs.h
target-arm/cpu.h

index 56accfb..afcf4f4 100644 (file)
@@ -360,6 +360,7 @@ void cpu_loop(CPUARMState *env)
         case EXCP_SWI:
         case EXCP_BKPT:
             {
+                env->eabi = 1;
                 /* system call */
                 if (trapnr == EXCP_BKPT) {
                     if (env->thumb) {
@@ -386,13 +387,14 @@ void cpu_loop(CPUARMState *env)
                 } else if (n == ARM_NR_semihosting
                            || n == ARM_NR_thumb_semihosting) {
                     env->regs[0] = do_arm_semihosting (env);
-                } else if (n >= ARM_SYSCALL_BASE
+                } else if (n == 0 || n >= ARM_SYSCALL_BASE
                            || (env->thumb && n == ARM_THUMB_SYSCALL)) {
                     /* linux syscall */
-                    if (env->thumb) {
+                    if (env->thumb || n == 0) {
                         n = env->regs[7];
                     } else {
                         n -= ARM_SYSCALL_BASE;
+                        env->eabi = 0;
                     }
                     env->regs[0] = do_syscall(env, 
                                               n, 
index 164eb39..ab7846d 100644 (file)
@@ -1651,6 +1651,45 @@ void syscall_init(void)
     }
 }
 
+static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
+{
+#ifdef TARGET_WORDS_BIG_ENDIAN
+    return ((uint64_t)word0 << 32) | word1;
+#else
+    return ((uint64_t)word1 << 32) | word0;
+#endif
+}
+
+#ifdef TARGET_NR_truncate64
+static inline long target_truncate64(void *cpu_env, const char *arg1,
+                                     long arg2, long arg3, long arg4)
+{
+#ifdef TARGET_ARM
+    if (((CPUARMState *)cpu_env)->eabi)
+      {
+        arg2 = arg3;
+        arg3 = arg4;
+      }
+#endif
+    return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
+}
+#endif
+
+#ifdef TARGET_NR_ftruncate64
+static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2,
+                                      long arg3, long arg4)
+{
+#ifdef TARGET_ARM
+    if (((CPUARMState *)cpu_env)->eabi)
+      {
+        arg2 = arg3;
+        arg3 = arg4;
+      }
+#endif
+    return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
+}
+#endif
+
 long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, 
                 long arg4, long arg5, long arg6)
 {
@@ -2844,12 +2883,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
 #endif
 #ifdef TARGET_NR_truncate64
     case TARGET_NR_truncate64:
-       ret = get_errno(truncate64((const char *)arg1, arg2));
+       ret = target_truncate64(cpu_env, (const char *)arg1, arg2, arg3, arg4);
        break;
 #endif
 #ifdef TARGET_NR_ftruncate64
     case TARGET_NR_ftruncate64:
-       ret = get_errno(ftruncate64(arg1, arg2));
+       ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
        break;
 #endif
 #ifdef TARGET_NR_stat64
@@ -2868,25 +2907,50 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
             ret = get_errno(fstat(arg1, &st));
         do_stat64:
             if (!is_error(ret)) {
-                struct target_stat64 *target_st = (void *)arg2;
-                memset(target_st, 0, sizeof(struct target_stat64));
-                put_user(st.st_dev, &target_st->st_dev);
-                put_user(st.st_ino, &target_st->st_ino);
+#ifdef TARGET_ARM
+                if (((CPUARMState *)cpu_env)->eabi) {
+                    struct target_eabi_stat64 *target_st = (void *)arg2;
+                    memset(target_st, 0, sizeof(struct target_eabi_stat64));
+                    put_user(st.st_dev, &target_st->st_dev);
+                    put_user(st.st_ino, &target_st->st_ino);
+#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
+                    put_user(st.st_ino, &target_st->__st_ino);
+#endif
+                    put_user(st.st_mode, &target_st->st_mode);
+                    put_user(st.st_nlink, &target_st->st_nlink);
+                    put_user(st.st_uid, &target_st->st_uid);
+                    put_user(st.st_gid, &target_st->st_gid);
+                    put_user(st.st_rdev, &target_st->st_rdev);
+                    /* XXX: better use of kernel struct */
+                    put_user(st.st_size, &target_st->st_size);
+                    put_user(st.st_blksize, &target_st->st_blksize);
+                    put_user(st.st_blocks, &target_st->st_blocks);
+                    put_user(st.st_atime, &target_st->target_st_atime);
+                    put_user(st.st_mtime, &target_st->target_st_mtime);
+                    put_user(st.st_ctime, &target_st->target_st_ctime);
+                } else
+#endif
+                {
+                    struct target_stat64 *target_st = (void *)arg2;
+                    memset(target_st, 0, sizeof(struct target_stat64));
+                    put_user(st.st_dev, &target_st->st_dev);
+                    put_user(st.st_ino, &target_st->st_ino);
 #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
-                put_user(st.st_ino, &target_st->__st_ino);
-#endif
-                put_user(st.st_mode, &target_st->st_mode);
-                put_user(st.st_nlink, &target_st->st_nlink);
-                put_user(st.st_uid, &target_st->st_uid);
-                put_user(st.st_gid, &target_st->st_gid);
-                put_user(st.st_rdev, &target_st->st_rdev);
-                /* XXX: better use of kernel struct */
-                put_user(st.st_size, &target_st->st_size);
-                put_user(st.st_blksize, &target_st->st_blksize);
-                put_user(st.st_blocks, &target_st->st_blocks);
-                put_user(st.st_atime, &target_st->target_st_atime);
-                put_user(st.st_mtime, &target_st->target_st_mtime);
-                put_user(st.st_ctime, &target_st->target_st_ctime);
+                    put_user(st.st_ino, &target_st->__st_ino);
+#endif
+                    put_user(st.st_mode, &target_st->st_mode);
+                    put_user(st.st_nlink, &target_st->st_nlink);
+                    put_user(st.st_uid, &target_st->st_uid);
+                    put_user(st.st_gid, &target_st->st_gid);
+                    put_user(st.st_rdev, &target_st->st_rdev);
+                    /* XXX: better use of kernel struct */
+                    put_user(st.st_size, &target_st->st_size);
+                    put_user(st.st_blksize, &target_st->st_blksize);
+                    put_user(st.st_blocks, &target_st->st_blocks);
+                    put_user(st.st_atime, &target_st->target_st_atime);
+                    put_user(st.st_mtime, &target_st->target_st_mtime);
+                    put_user(st.st_ctime, &target_st->target_st_ctime);
+                }
             }
         }
         break;
@@ -3150,26 +3214,51 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     {
        struct flock64 fl;
        struct target_flock64 *target_fl = (void *)arg3;
+#ifdef TARGET_ARM
+       struct target_eabi_flock64 *target_efl = (void *)arg3;
+#endif
 
         switch(arg2) {
         case F_GETLK64:
             ret = get_errno(fcntl(arg1, arg2, &fl));
            if (ret == 0) {
-               target_fl->l_type = tswap16(fl.l_type);
-               target_fl->l_whence = tswap16(fl.l_whence);
-               target_fl->l_start = tswap64(fl.l_start);
-               target_fl->l_len = tswap64(fl.l_len);
-               target_fl->l_pid = tswapl(fl.l_pid);
+#ifdef TARGET_ARM
+                if (((CPUARMState *)cpu_env)->eabi) {
+                    target_efl->l_type = tswap16(fl.l_type);
+                    target_efl->l_whence = tswap16(fl.l_whence);
+                    target_efl->l_start = tswap64(fl.l_start);
+                    target_efl->l_len = tswap64(fl.l_len);
+                    target_efl->l_pid = tswapl(fl.l_pid);
+                } else
+#endif
+                {
+                    target_fl->l_type = tswap16(fl.l_type);
+                    target_fl->l_whence = tswap16(fl.l_whence);
+                    target_fl->l_start = tswap64(fl.l_start);
+                    target_fl->l_len = tswap64(fl.l_len);
+                    target_fl->l_pid = tswapl(fl.l_pid);
+                }
            }
            break;
 
         case F_SETLK64:
         case F_SETLKW64:
-           fl.l_type = tswap16(target_fl->l_type);
-           fl.l_whence = tswap16(target_fl->l_whence);
-           fl.l_start = tswap64(target_fl->l_start);
-           fl.l_len = tswap64(target_fl->l_len);
-           fl.l_pid = tswapl(target_fl->l_pid);
+#ifdef TARGET_ARM
+            if (((CPUARMState *)cpu_env)->eabi) {
+                fl.l_type = tswap16(target_efl->l_type);
+                fl.l_whence = tswap16(target_efl->l_whence);
+                fl.l_start = tswap64(target_efl->l_start);
+                fl.l_len = tswap64(target_efl->l_len);
+                fl.l_pid = tswapl(target_efl->l_pid);
+            } else
+#endif
+            {
+                fl.l_type = tswap16(target_fl->l_type);
+                fl.l_whence = tswap16(target_fl->l_whence);
+                fl.l_start = tswap64(target_fl->l_start);
+                fl.l_len = tswap64(target_fl->l_len);
+                fl.l_pid = tswapl(target_fl->l_pid);
+            }
             ret = get_errno(fcntl(arg1, arg2, &fl));
            break;
         default:
index 68f7e7f..c722e3a 100644 (file)
@@ -924,6 +924,38 @@ struct target_stat64 {
        unsigned long long      st_ino;
 } __attribute__((packed));
 
+#ifdef TARGET_ARM
+struct target_eabi_stat64 {
+        unsigned long long st_dev;
+        unsigned int    __pad1;
+        unsigned long   __st_ino;
+        unsigned int    st_mode;
+        unsigned int    st_nlink;
+
+        unsigned long   st_uid;
+        unsigned long   st_gid;
+
+        unsigned long long st_rdev;
+        unsigned int    __pad2[2];
+
+        long long       st_size;
+        unsigned long   st_blksize;
+        unsigned int    __pad3;
+        unsigned long long st_blocks;
+
+        unsigned long   target_st_atime;
+        unsigned long   target_st_atime_nsec;
+
+        unsigned long   target_st_mtime;
+        unsigned long   target_st_mtime_nsec;
+
+        unsigned long   target_st_ctime;
+        unsigned long   target_st_ctime_nsec;
+
+        unsigned long long st_ino;
+} __attribute__ ((packed));
+#endif
+
 #elif defined(TARGET_SPARC)
 
 struct target_stat {
@@ -1298,8 +1330,18 @@ struct target_flock64 {
        unsigned long long l_start;
        unsigned long long l_len;
        int  l_pid;
-};
+}__attribute__((packed));
 
+#ifdef TARGET_ARM
+struct target_eabi_flock64 {
+       short  l_type;
+       short  l_whence;
+        int __pad;
+       unsigned long long l_start;
+       unsigned long long l_len;
+       int  l_pid;
+}__attribute__((packed));
+#endif
 
 /* soundcard defines */
 /* XXX: convert them all to arch indepedent entries */
index 7cc7da6..052634c 100644 (file)
@@ -110,6 +110,11 @@ typedef struct CPUARMState {
         float_status fp_status;
     } vfp;
 
+#if defined(CONFIG_USER_ONLY)
+    /* For usermode syscall translation.  */
+    int eabi;
+#endif
+
     CPU_COMMON
 
 } CPUARMState;