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 | 360 | case EXCP_SWI: |
| 361 | 361 | case EXCP_BKPT: |
| 362 | 362 | { |
| 363 | + env->eabi = 1; | |
| 363 | 364 | /* system call */ |
| 364 | 365 | if (trapnr == EXCP_BKPT) { |
| 365 | 366 | if (env->thumb) { |
| ... | ... | @@ -386,13 +387,14 @@ void cpu_loop(CPUARMState *env) |
| 386 | 387 | } else if (n == ARM_NR_semihosting |
| 387 | 388 | || n == ARM_NR_thumb_semihosting) { |
| 388 | 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 | 391 | || (env->thumb && n == ARM_THUMB_SYSCALL)) { |
| 391 | 392 | /* linux syscall */ |
| 392 | - if (env->thumb) { | |
| 393 | + if (env->thumb || n == 0) { | |
| 393 | 394 | n = env->regs[7]; |
| 394 | 395 | } else { |
| 395 | 396 | n -= ARM_SYSCALL_BASE; |
| 397 | + env->eabi = 0; | |
| 396 | 398 | } |
| 397 | 399 | env->regs[0] = do_syscall(env, |
| 398 | 400 | n, | ... | ... |
linux-user/syscall.c
| ... | ... | @@ -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 | 1693 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
| 1655 | 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 | 2883 | #endif |
| 2845 | 2884 | #ifdef TARGET_NR_truncate64 |
| 2846 | 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 | 2887 | break; |
| 2849 | 2888 | #endif |
| 2850 | 2889 | #ifdef TARGET_NR_ftruncate64 |
| 2851 | 2890 | case TARGET_NR_ftruncate64: |
| 2852 | - ret = get_errno(ftruncate64(arg1, arg2)); | |
| 2891 | + ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4); | |
| 2853 | 2892 | break; |
| 2854 | 2893 | #endif |
| 2855 | 2894 | #ifdef TARGET_NR_stat64 |
| ... | ... | @@ -2868,25 +2907,50 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
| 2868 | 2907 | ret = get_errno(fstat(arg1, &st)); |
| 2869 | 2908 | do_stat64: |
| 2870 | 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 | 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 | 2956 | break; |
| ... | ... | @@ -3150,26 +3214,51 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
| 3150 | 3214 | { |
| 3151 | 3215 | struct flock64 fl; |
| 3152 | 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 | 3221 | switch(arg2) { |
| 3155 | 3222 | case F_GETLK64: |
| 3156 | 3223 | ret = get_errno(fcntl(arg1, arg2, &fl)); |
| 3157 | 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 | 3242 | break; |
| 3165 | 3243 | |
| 3166 | 3244 | case F_SETLK64: |
| 3167 | 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 | 3262 | ret = get_errno(fcntl(arg1, arg2, &fl)); |
| 3174 | 3263 | break; |
| 3175 | 3264 | default: | ... | ... |
linux-user/syscall_defs.h
| ... | ... | @@ -924,6 +924,38 @@ struct target_stat64 { |
| 924 | 924 | unsigned long long st_ino; |
| 925 | 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 | 959 | #elif defined(TARGET_SPARC) |
| 928 | 960 | |
| 929 | 961 | struct target_stat { |
| ... | ... | @@ -1298,8 +1330,18 @@ struct target_flock64 { |
| 1298 | 1330 | unsigned long long l_start; |
| 1299 | 1331 | unsigned long long l_len; |
| 1300 | 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 | 1346 | /* soundcard defines */ |
| 1305 | 1347 | /* XXX: convert them all to arch indepedent entries */ | ... | ... |
target-arm/cpu.h