Commit ce4defa062c5e6d940f73a1013f8770f23b0f4bf
1 parent
b88a3832
Arm Linux EABI syscall support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1756 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
171 additions
and
33 deletions
linux-user/main.c
| @@ -360,6 +360,7 @@ void cpu_loop(CPUARMState *env) | @@ -360,6 +360,7 @@ void cpu_loop(CPUARMState *env) | ||
| 360 | case EXCP_SWI: | 360 | case EXCP_SWI: |
| 361 | case EXCP_BKPT: | 361 | case EXCP_BKPT: |
| 362 | { | 362 | { |
| 363 | + env->eabi = 1; | ||
| 363 | /* system call */ | 364 | /* system call */ |
| 364 | if (trapnr == EXCP_BKPT) { | 365 | if (trapnr == EXCP_BKPT) { |
| 365 | if (env->thumb) { | 366 | if (env->thumb) { |
| @@ -386,13 +387,14 @@ void cpu_loop(CPUARMState *env) | @@ -386,13 +387,14 @@ void cpu_loop(CPUARMState *env) | ||
| 386 | } else if (n == ARM_NR_semihosting | 387 | } else if (n == ARM_NR_semihosting |
| 387 | || n == ARM_NR_thumb_semihosting) { | 388 | || n == ARM_NR_thumb_semihosting) { |
| 388 | env->regs[0] = do_arm_semihosting (env); | 389 | env->regs[0] = do_arm_semihosting (env); |
| 389 | - } else if (n >= ARM_SYSCALL_BASE | 390 | + } else if (n == 0 || n >= ARM_SYSCALL_BASE |
| 390 | || (env->thumb && n == ARM_THUMB_SYSCALL)) { | 391 | || (env->thumb && n == ARM_THUMB_SYSCALL)) { |
| 391 | /* linux syscall */ | 392 | /* linux syscall */ |
| 392 | - if (env->thumb) { | 393 | + if (env->thumb || n == 0) { |
| 393 | n = env->regs[7]; | 394 | n = env->regs[7]; |
| 394 | } else { | 395 | } else { |
| 395 | n -= ARM_SYSCALL_BASE; | 396 | n -= ARM_SYSCALL_BASE; |
| 397 | + env->eabi = 0; | ||
| 396 | } | 398 | } |
| 397 | env->regs[0] = do_syscall(env, | 399 | env->regs[0] = do_syscall(env, |
| 398 | n, | 400 | n, |
linux-user/syscall.c
| @@ -1651,6 +1651,45 @@ void syscall_init(void) | @@ -1651,6 +1651,45 @@ void syscall_init(void) | ||
| 1651 | } | 1651 | } |
| 1652 | } | 1652 | } |
| 1653 | 1653 | ||
| 1654 | +static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) | ||
| 1655 | +{ | ||
| 1656 | +#ifdef TARGET_WORDS_BIG_ENDIAN | ||
| 1657 | + return ((uint64_t)word0 << 32) | word1; | ||
| 1658 | +#else | ||
| 1659 | + return ((uint64_t)word1 << 32) | word0; | ||
| 1660 | +#endif | ||
| 1661 | +} | ||
| 1662 | + | ||
| 1663 | +#ifdef TARGET_NR_truncate64 | ||
| 1664 | +static inline long target_truncate64(void *cpu_env, const char *arg1, | ||
| 1665 | + long arg2, long arg3, long arg4) | ||
| 1666 | +{ | ||
| 1667 | +#ifdef TARGET_ARM | ||
| 1668 | + if (((CPUARMState *)cpu_env)->eabi) | ||
| 1669 | + { | ||
| 1670 | + arg2 = arg3; | ||
| 1671 | + arg3 = arg4; | ||
| 1672 | + } | ||
| 1673 | +#endif | ||
| 1674 | + return get_errno(truncate64(arg1, target_offset64(arg2, arg3))); | ||
| 1675 | +} | ||
| 1676 | +#endif | ||
| 1677 | + | ||
| 1678 | +#ifdef TARGET_NR_ftruncate64 | ||
| 1679 | +static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2, | ||
| 1680 | + long arg3, long arg4) | ||
| 1681 | +{ | ||
| 1682 | +#ifdef TARGET_ARM | ||
| 1683 | + if (((CPUARMState *)cpu_env)->eabi) | ||
| 1684 | + { | ||
| 1685 | + arg2 = arg3; | ||
| 1686 | + arg3 = arg4; | ||
| 1687 | + } | ||
| 1688 | +#endif | ||
| 1689 | + return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3))); | ||
| 1690 | +} | ||
| 1691 | +#endif | ||
| 1692 | + | ||
| 1654 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | 1693 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
| 1655 | long arg4, long arg5, long arg6) | 1694 | long arg4, long arg5, long arg6) |
| 1656 | { | 1695 | { |
| @@ -2844,12 +2883,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2844,12 +2883,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2844 | #endif | 2883 | #endif |
| 2845 | #ifdef TARGET_NR_truncate64 | 2884 | #ifdef TARGET_NR_truncate64 |
| 2846 | case TARGET_NR_truncate64: | 2885 | case TARGET_NR_truncate64: |
| 2847 | - ret = get_errno(truncate64((const char *)arg1, arg2)); | 2886 | + ret = target_truncate64(cpu_env, (const char *)arg1, arg2, arg3, arg4); |
| 2848 | break; | 2887 | break; |
| 2849 | #endif | 2888 | #endif |
| 2850 | #ifdef TARGET_NR_ftruncate64 | 2889 | #ifdef TARGET_NR_ftruncate64 |
| 2851 | case TARGET_NR_ftruncate64: | 2890 | case TARGET_NR_ftruncate64: |
| 2852 | - ret = get_errno(ftruncate64(arg1, arg2)); | 2891 | + ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4); |
| 2853 | break; | 2892 | break; |
| 2854 | #endif | 2893 | #endif |
| 2855 | #ifdef TARGET_NR_stat64 | 2894 | #ifdef TARGET_NR_stat64 |
| @@ -2868,25 +2907,50 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2868,25 +2907,50 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 2868 | ret = get_errno(fstat(arg1, &st)); | 2907 | ret = get_errno(fstat(arg1, &st)); |
| 2869 | do_stat64: | 2908 | do_stat64: |
| 2870 | if (!is_error(ret)) { | 2909 | if (!is_error(ret)) { |
| 2871 | - struct target_stat64 *target_st = (void *)arg2; | ||
| 2872 | - memset(target_st, 0, sizeof(struct target_stat64)); | ||
| 2873 | - put_user(st.st_dev, &target_st->st_dev); | ||
| 2874 | - put_user(st.st_ino, &target_st->st_ino); | 2910 | +#ifdef TARGET_ARM |
| 2911 | + if (((CPUARMState *)cpu_env)->eabi) { | ||
| 2912 | + struct target_eabi_stat64 *target_st = (void *)arg2; | ||
| 2913 | + memset(target_st, 0, sizeof(struct target_eabi_stat64)); | ||
| 2914 | + put_user(st.st_dev, &target_st->st_dev); | ||
| 2915 | + put_user(st.st_ino, &target_st->st_ino); | ||
| 2916 | +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | ||
| 2917 | + put_user(st.st_ino, &target_st->__st_ino); | ||
| 2918 | +#endif | ||
| 2919 | + put_user(st.st_mode, &target_st->st_mode); | ||
| 2920 | + put_user(st.st_nlink, &target_st->st_nlink); | ||
| 2921 | + put_user(st.st_uid, &target_st->st_uid); | ||
| 2922 | + put_user(st.st_gid, &target_st->st_gid); | ||
| 2923 | + put_user(st.st_rdev, &target_st->st_rdev); | ||
| 2924 | + /* XXX: better use of kernel struct */ | ||
| 2925 | + put_user(st.st_size, &target_st->st_size); | ||
| 2926 | + put_user(st.st_blksize, &target_st->st_blksize); | ||
| 2927 | + put_user(st.st_blocks, &target_st->st_blocks); | ||
| 2928 | + put_user(st.st_atime, &target_st->target_st_atime); | ||
| 2929 | + put_user(st.st_mtime, &target_st->target_st_mtime); | ||
| 2930 | + put_user(st.st_ctime, &target_st->target_st_ctime); | ||
| 2931 | + } else | ||
| 2932 | +#endif | ||
| 2933 | + { | ||
| 2934 | + struct target_stat64 *target_st = (void *)arg2; | ||
| 2935 | + memset(target_st, 0, sizeof(struct target_stat64)); | ||
| 2936 | + put_user(st.st_dev, &target_st->st_dev); | ||
| 2937 | + put_user(st.st_ino, &target_st->st_ino); | ||
| 2875 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | 2938 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
| 2876 | - put_user(st.st_ino, &target_st->__st_ino); | ||
| 2877 | -#endif | ||
| 2878 | - put_user(st.st_mode, &target_st->st_mode); | ||
| 2879 | - put_user(st.st_nlink, &target_st->st_nlink); | ||
| 2880 | - put_user(st.st_uid, &target_st->st_uid); | ||
| 2881 | - put_user(st.st_gid, &target_st->st_gid); | ||
| 2882 | - put_user(st.st_rdev, &target_st->st_rdev); | ||
| 2883 | - /* XXX: better use of kernel struct */ | ||
| 2884 | - put_user(st.st_size, &target_st->st_size); | ||
| 2885 | - put_user(st.st_blksize, &target_st->st_blksize); | ||
| 2886 | - put_user(st.st_blocks, &target_st->st_blocks); | ||
| 2887 | - put_user(st.st_atime, &target_st->target_st_atime); | ||
| 2888 | - put_user(st.st_mtime, &target_st->target_st_mtime); | ||
| 2889 | - put_user(st.st_ctime, &target_st->target_st_ctime); | 2939 | + put_user(st.st_ino, &target_st->__st_ino); |
| 2940 | +#endif | ||
| 2941 | + put_user(st.st_mode, &target_st->st_mode); | ||
| 2942 | + put_user(st.st_nlink, &target_st->st_nlink); | ||
| 2943 | + put_user(st.st_uid, &target_st->st_uid); | ||
| 2944 | + put_user(st.st_gid, &target_st->st_gid); | ||
| 2945 | + put_user(st.st_rdev, &target_st->st_rdev); | ||
| 2946 | + /* XXX: better use of kernel struct */ | ||
| 2947 | + put_user(st.st_size, &target_st->st_size); | ||
| 2948 | + put_user(st.st_blksize, &target_st->st_blksize); | ||
| 2949 | + put_user(st.st_blocks, &target_st->st_blocks); | ||
| 2950 | + put_user(st.st_atime, &target_st->target_st_atime); | ||
| 2951 | + put_user(st.st_mtime, &target_st->target_st_mtime); | ||
| 2952 | + put_user(st.st_ctime, &target_st->target_st_ctime); | ||
| 2953 | + } | ||
| 2890 | } | 2954 | } |
| 2891 | } | 2955 | } |
| 2892 | break; | 2956 | break; |
| @@ -3150,26 +3214,51 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3150,26 +3214,51 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
| 3150 | { | 3214 | { |
| 3151 | struct flock64 fl; | 3215 | struct flock64 fl; |
| 3152 | struct target_flock64 *target_fl = (void *)arg3; | 3216 | struct target_flock64 *target_fl = (void *)arg3; |
| 3217 | +#ifdef TARGET_ARM | ||
| 3218 | + struct target_eabi_flock64 *target_efl = (void *)arg3; | ||
| 3219 | +#endif | ||
| 3153 | 3220 | ||
| 3154 | switch(arg2) { | 3221 | switch(arg2) { |
| 3155 | case F_GETLK64: | 3222 | case F_GETLK64: |
| 3156 | ret = get_errno(fcntl(arg1, arg2, &fl)); | 3223 | ret = get_errno(fcntl(arg1, arg2, &fl)); |
| 3157 | if (ret == 0) { | 3224 | if (ret == 0) { |
| 3158 | - target_fl->l_type = tswap16(fl.l_type); | ||
| 3159 | - target_fl->l_whence = tswap16(fl.l_whence); | ||
| 3160 | - target_fl->l_start = tswap64(fl.l_start); | ||
| 3161 | - target_fl->l_len = tswap64(fl.l_len); | ||
| 3162 | - target_fl->l_pid = tswapl(fl.l_pid); | 3225 | +#ifdef TARGET_ARM |
| 3226 | + if (((CPUARMState *)cpu_env)->eabi) { | ||
| 3227 | + target_efl->l_type = tswap16(fl.l_type); | ||
| 3228 | + target_efl->l_whence = tswap16(fl.l_whence); | ||
| 3229 | + target_efl->l_start = tswap64(fl.l_start); | ||
| 3230 | + target_efl->l_len = tswap64(fl.l_len); | ||
| 3231 | + target_efl->l_pid = tswapl(fl.l_pid); | ||
| 3232 | + } else | ||
| 3233 | +#endif | ||
| 3234 | + { | ||
| 3235 | + target_fl->l_type = tswap16(fl.l_type); | ||
| 3236 | + target_fl->l_whence = tswap16(fl.l_whence); | ||
| 3237 | + target_fl->l_start = tswap64(fl.l_start); | ||
| 3238 | + target_fl->l_len = tswap64(fl.l_len); | ||
| 3239 | + target_fl->l_pid = tswapl(fl.l_pid); | ||
| 3240 | + } | ||
| 3163 | } | 3241 | } |
| 3164 | break; | 3242 | break; |
| 3165 | 3243 | ||
| 3166 | case F_SETLK64: | 3244 | case F_SETLK64: |
| 3167 | case F_SETLKW64: | 3245 | case F_SETLKW64: |
| 3168 | - fl.l_type = tswap16(target_fl->l_type); | ||
| 3169 | - fl.l_whence = tswap16(target_fl->l_whence); | ||
| 3170 | - fl.l_start = tswap64(target_fl->l_start); | ||
| 3171 | - fl.l_len = tswap64(target_fl->l_len); | ||
| 3172 | - fl.l_pid = tswapl(target_fl->l_pid); | 3246 | +#ifdef TARGET_ARM |
| 3247 | + if (((CPUARMState *)cpu_env)->eabi) { | ||
| 3248 | + fl.l_type = tswap16(target_efl->l_type); | ||
| 3249 | + fl.l_whence = tswap16(target_efl->l_whence); | ||
| 3250 | + fl.l_start = tswap64(target_efl->l_start); | ||
| 3251 | + fl.l_len = tswap64(target_efl->l_len); | ||
| 3252 | + fl.l_pid = tswapl(target_efl->l_pid); | ||
| 3253 | + } else | ||
| 3254 | +#endif | ||
| 3255 | + { | ||
| 3256 | + fl.l_type = tswap16(target_fl->l_type); | ||
| 3257 | + fl.l_whence = tswap16(target_fl->l_whence); | ||
| 3258 | + fl.l_start = tswap64(target_fl->l_start); | ||
| 3259 | + fl.l_len = tswap64(target_fl->l_len); | ||
| 3260 | + fl.l_pid = tswapl(target_fl->l_pid); | ||
| 3261 | + } | ||
| 3173 | ret = get_errno(fcntl(arg1, arg2, &fl)); | 3262 | ret = get_errno(fcntl(arg1, arg2, &fl)); |
| 3174 | break; | 3263 | break; |
| 3175 | default: | 3264 | default: |
linux-user/syscall_defs.h
| @@ -924,6 +924,38 @@ struct target_stat64 { | @@ -924,6 +924,38 @@ struct target_stat64 { | ||
| 924 | unsigned long long st_ino; | 924 | unsigned long long st_ino; |
| 925 | } __attribute__((packed)); | 925 | } __attribute__((packed)); |
| 926 | 926 | ||
| 927 | +#ifdef TARGET_ARM | ||
| 928 | +struct target_eabi_stat64 { | ||
| 929 | + unsigned long long st_dev; | ||
| 930 | + unsigned int __pad1; | ||
| 931 | + unsigned long __st_ino; | ||
| 932 | + unsigned int st_mode; | ||
| 933 | + unsigned int st_nlink; | ||
| 934 | + | ||
| 935 | + unsigned long st_uid; | ||
| 936 | + unsigned long st_gid; | ||
| 937 | + | ||
| 938 | + unsigned long long st_rdev; | ||
| 939 | + unsigned int __pad2[2]; | ||
| 940 | + | ||
| 941 | + long long st_size; | ||
| 942 | + unsigned long st_blksize; | ||
| 943 | + unsigned int __pad3; | ||
| 944 | + unsigned long long st_blocks; | ||
| 945 | + | ||
| 946 | + unsigned long target_st_atime; | ||
| 947 | + unsigned long target_st_atime_nsec; | ||
| 948 | + | ||
| 949 | + unsigned long target_st_mtime; | ||
| 950 | + unsigned long target_st_mtime_nsec; | ||
| 951 | + | ||
| 952 | + unsigned long target_st_ctime; | ||
| 953 | + unsigned long target_st_ctime_nsec; | ||
| 954 | + | ||
| 955 | + unsigned long long st_ino; | ||
| 956 | +} __attribute__ ((packed)); | ||
| 957 | +#endif | ||
| 958 | + | ||
| 927 | #elif defined(TARGET_SPARC) | 959 | #elif defined(TARGET_SPARC) |
| 928 | 960 | ||
| 929 | struct target_stat { | 961 | struct target_stat { |
| @@ -1298,8 +1330,18 @@ struct target_flock64 { | @@ -1298,8 +1330,18 @@ struct target_flock64 { | ||
| 1298 | unsigned long long l_start; | 1330 | unsigned long long l_start; |
| 1299 | unsigned long long l_len; | 1331 | unsigned long long l_len; |
| 1300 | int l_pid; | 1332 | int l_pid; |
| 1301 | -}; | 1333 | +}__attribute__((packed)); |
| 1302 | 1334 | ||
| 1335 | +#ifdef TARGET_ARM | ||
| 1336 | +struct target_eabi_flock64 { | ||
| 1337 | + short l_type; | ||
| 1338 | + short l_whence; | ||
| 1339 | + int __pad; | ||
| 1340 | + unsigned long long l_start; | ||
| 1341 | + unsigned long long l_len; | ||
| 1342 | + int l_pid; | ||
| 1343 | +}__attribute__((packed)); | ||
| 1344 | +#endif | ||
| 1303 | 1345 | ||
| 1304 | /* soundcard defines */ | 1346 | /* soundcard defines */ |
| 1305 | /* XXX: convert them all to arch indepedent entries */ | 1347 | /* XXX: convert them all to arch indepedent entries */ |
target-arm/cpu.h
| @@ -110,6 +110,11 @@ typedef struct CPUARMState { | @@ -110,6 +110,11 @@ typedef struct CPUARMState { | ||
| 110 | float_status fp_status; | 110 | float_status fp_status; |
| 111 | } vfp; | 111 | } vfp; |
| 112 | 112 | ||
| 113 | +#if defined(CONFIG_USER_ONLY) | ||
| 114 | + /* For usermode syscall translation. */ | ||
| 115 | + int eabi; | ||
| 116 | +#endif | ||
| 117 | + | ||
| 113 | CPU_COMMON | 118 | CPU_COMMON |
| 114 | 119 | ||
| 115 | } CPUARMState; | 120 | } CPUARMState; |