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