Arm Linux EABI syscall support.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1756 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2006-02-09 16:49:55 +00:00
parent b88a38324b
commit ce4defa062
4 changed files with 170 additions and 32 deletions

View File

@ -360,6 +360,7 @@ void cpu_loop(CPUARMState *env)
case EXCP_SWI: case EXCP_SWI:
case EXCP_BKPT: case EXCP_BKPT:
{ {
env->eabi = 1;
/* system call */ /* system call */
if (trapnr == EXCP_BKPT) { if (trapnr == EXCP_BKPT) {
if (env->thumb) { if (env->thumb) {
@ -386,13 +387,14 @@ void cpu_loop(CPUARMState *env)
} else if (n == ARM_NR_semihosting } else if (n == ARM_NR_semihosting
|| n == ARM_NR_thumb_semihosting) { || n == ARM_NR_thumb_semihosting) {
env->regs[0] = do_arm_semihosting (env); 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)) { || (env->thumb && n == ARM_THUMB_SYSCALL)) {
/* linux syscall */ /* linux syscall */
if (env->thumb) { if (env->thumb || n == 0) {
n = env->regs[7]; n = env->regs[7];
} else { } else {
n -= ARM_SYSCALL_BASE; n -= ARM_SYSCALL_BASE;
env->eabi = 0;
} }
env->regs[0] = do_syscall(env, env->regs[0] = do_syscall(env,
n, n,

View 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 do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6) 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 #endif
#ifdef TARGET_NR_truncate64 #ifdef TARGET_NR_truncate64
case 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; break;
#endif #endif
#ifdef TARGET_NR_ftruncate64 #ifdef TARGET_NR_ftruncate64
case TARGET_NR_ftruncate64: case TARGET_NR_ftruncate64:
ret = get_errno(ftruncate64(arg1, arg2)); ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
break; break;
#endif #endif
#ifdef TARGET_NR_stat64 #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)); ret = get_errno(fstat(arg1, &st));
do_stat64: do_stat64:
if (!is_error(ret)) { if (!is_error(ret)) {
struct target_stat64 *target_st = (void *)arg2; #ifdef TARGET_ARM
memset(target_st, 0, sizeof(struct target_stat64)); if (((CPUARMState *)cpu_env)->eabi) {
put_user(st.st_dev, &target_st->st_dev); struct target_eabi_stat64 *target_st = (void *)arg2;
put_user(st.st_ino, &target_st->st_ino); 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 #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
put_user(st.st_ino, &target_st->__st_ino); put_user(st.st_ino, &target_st->__st_ino);
#endif #endif
put_user(st.st_mode, &target_st->st_mode); put_user(st.st_mode, &target_st->st_mode);
put_user(st.st_nlink, &target_st->st_nlink); put_user(st.st_nlink, &target_st->st_nlink);
put_user(st.st_uid, &target_st->st_uid); put_user(st.st_uid, &target_st->st_uid);
put_user(st.st_gid, &target_st->st_gid); put_user(st.st_gid, &target_st->st_gid);
put_user(st.st_rdev, &target_st->st_rdev); put_user(st.st_rdev, &target_st->st_rdev);
/* XXX: better use of kernel struct */ /* XXX: better use of kernel struct */
put_user(st.st_size, &target_st->st_size); put_user(st.st_size, &target_st->st_size);
put_user(st.st_blksize, &target_st->st_blksize); put_user(st.st_blksize, &target_st->st_blksize);
put_user(st.st_blocks, &target_st->st_blocks); put_user(st.st_blocks, &target_st->st_blocks);
put_user(st.st_atime, &target_st->target_st_atime); put_user(st.st_atime, &target_st->target_st_atime);
put_user(st.st_mtime, &target_st->target_st_mtime); put_user(st.st_mtime, &target_st->target_st_mtime);
put_user(st.st_ctime, &target_st->target_st_ctime); 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);
}
} }
} }
break; break;
@ -3150,26 +3214,51 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
{ {
struct flock64 fl; struct flock64 fl;
struct target_flock64 *target_fl = (void *)arg3; struct target_flock64 *target_fl = (void *)arg3;
#ifdef TARGET_ARM
struct target_eabi_flock64 *target_efl = (void *)arg3;
#endif
switch(arg2) { switch(arg2) {
case F_GETLK64: case F_GETLK64:
ret = get_errno(fcntl(arg1, arg2, &fl)); ret = get_errno(fcntl(arg1, arg2, &fl));
if (ret == 0) { if (ret == 0) {
target_fl->l_type = tswap16(fl.l_type); #ifdef TARGET_ARM
target_fl->l_whence = tswap16(fl.l_whence); if (((CPUARMState *)cpu_env)->eabi) {
target_fl->l_start = tswap64(fl.l_start); target_efl->l_type = tswap16(fl.l_type);
target_fl->l_len = tswap64(fl.l_len); target_efl->l_whence = tswap16(fl.l_whence);
target_fl->l_pid = tswapl(fl.l_pid); 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; break;
case F_SETLK64: case F_SETLK64:
case F_SETLKW64: case F_SETLKW64:
fl.l_type = tswap16(target_fl->l_type); #ifdef TARGET_ARM
fl.l_whence = tswap16(target_fl->l_whence); if (((CPUARMState *)cpu_env)->eabi) {
fl.l_start = tswap64(target_fl->l_start); fl.l_type = tswap16(target_efl->l_type);
fl.l_len = tswap64(target_fl->l_len); fl.l_whence = tswap16(target_efl->l_whence);
fl.l_pid = tswapl(target_fl->l_pid); 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)); ret = get_errno(fcntl(arg1, arg2, &fl));
break; break;
default: default:

View File

@ -924,6 +924,38 @@ struct target_stat64 {
unsigned long long st_ino; unsigned long long st_ino;
} __attribute__((packed)); } __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) #elif defined(TARGET_SPARC)
struct target_stat { struct target_stat {
@ -1298,8 +1330,18 @@ struct target_flock64 {
unsigned long long l_start; unsigned long long l_start;
unsigned long long l_len; unsigned long long l_len;
int l_pid; 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 */ /* soundcard defines */
/* XXX: convert them all to arch indepedent entries */ /* XXX: convert them all to arch indepedent entries */

View File

@ -110,6 +110,11 @@ typedef struct CPUARMState {
float_status fp_status; float_status fp_status;
} vfp; } vfp;
#if defined(CONFIG_USER_ONLY)
/* For usermode syscall translation. */
int eabi;
#endif
CPU_COMMON CPU_COMMON
} CPUARMState; } CPUARMState;