diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-02-09 16:49:55 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-02-09 16:49:55 +0000 |
commit | ce4defa062c5e6d940f73a1013f8770f23b0f4bf (patch) | |
tree | 685dfe397fa69b4ef03be4a197644a4b6daa86f7 | |
parent | b88a38324b9cc469d6fffaecacbeb106a248a4cf (diff) |
Arm Linux EABI syscall support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1756 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | linux-user/main.c | 6 | ||||
-rw-r--r-- | linux-user/syscall.c | 149 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 44 | ||||
-rw-r--r-- | target-arm/cpu.h | 5 |
4 files changed, 171 insertions, 33 deletions
diff --git a/linux-user/main.c b/linux-user/main.c index 56accfbb52..afcf4f4b1b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -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, diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 164eb394a1..ab7846d7ac 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -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: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 68f7e7f017..c722e3a427 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -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 */ diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7cc7da60e9..052634cd50 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -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; |