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:
parent
b88a38324b
commit
ce4defa062
@ -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,
|
||||||
|
@ -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:
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user