Merge remote-tracking branch 'remotes/riku/linux-user-for-upstream' into staging
* remotes/riku/linux-user-for-upstream: (22 commits) linux-user: check return value of malloc() linux-user: writev Partial Writes linux-user: Support target-to-host translation of mlockall argument linux-user: clock_nanosleep errno Handling on PPC linux-user: Minimum Sig Handler Stack Size for PPC64 ELF V2 linux-user: Move get_ppc64_abi linux-user: Detect fault in sched_rr_get_interval linux-user: Handle NULL sched_param argument to sched_* linux-user: Detect Negative Message Sizes in msgsnd System Call linux-user: Conditionally Pass Attribute Pointer to mq_open() linux-user: Make ipc syscall's third argument an abi_long linux-user: Properly Handle semun Structure In Cross-Endian Situations linux-user: Dereference Pointer Argument to ipc/semctl Sys Call linux-user: PPC64 semid_ds Doesnt Include _unused1 and _unused2 linux-user: add setns and unshare linux-user: support ioprio_{get, set} syscalls linux-user: support timerfd_{create, gettime, settime} syscalls linux-user: fix readlink handling with magic exe symlink linux-user: Fix conversion of sigevent argument to timer_create linux-user: Fix syscall instruction usermode emulation on X86_64 ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
43fe62757b
37
configure
vendored
37
configure
vendored
@ -3456,6 +3456,37 @@ if compile_prog "" "" ; then
|
||||
sendfile=yes
|
||||
fi
|
||||
|
||||
# check for timerfd support (glibc 2.8 and newer)
|
||||
timerfd=no
|
||||
cat > $TMPC << EOF
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return(timerfd_create(CLOCK_REALTIME, 0));
|
||||
}
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
timerfd=yes
|
||||
fi
|
||||
|
||||
# check for setns and unshare support
|
||||
setns=no
|
||||
cat > $TMPC << EOF
|
||||
#include <sched.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
ret = setns(0, 0);
|
||||
ret = unshare(0);
|
||||
return ret;
|
||||
}
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
setns=yes
|
||||
fi
|
||||
|
||||
# Check if tools are available to build documentation.
|
||||
if test "$docs" != "no" ; then
|
||||
if has makeinfo && has pod2man; then
|
||||
@ -4524,6 +4555,12 @@ fi
|
||||
if test "$sendfile" = "yes" ; then
|
||||
echo "CONFIG_SENDFILE=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$timerfd" = "yes" ; then
|
||||
echo "CONFIG_TIMERFD=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$setns" = "yes" ; then
|
||||
echo "CONFIG_SETNS=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$inotify" = "yes" ; then
|
||||
echo "CONFIG_INOTIFY=y" >> $config_host_mak
|
||||
fi
|
||||
|
@ -198,6 +198,8 @@ extern unsigned long reserved_va;
|
||||
#define RESERVED_VA 0ul
|
||||
#endif
|
||||
|
||||
#define GUEST_ADDR_MAX (RESERVED_VA ? RESERVED_VA : \
|
||||
(1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
|
||||
#endif
|
||||
|
||||
/* page related stuff */
|
||||
|
@ -8,3 +8,6 @@ struct target_pt_regs {
|
||||
#define UNAME_MACHINE "aarch64"
|
||||
#define UNAME_MINIMUM_RELEASE "3.8.0"
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -252,3 +252,6 @@ struct target_pt_regs {
|
||||
#define TARGET_UAC_NOPRINT 1
|
||||
#define TARGET_UAC_NOFIX 2
|
||||
#define TARGET_UAC_SIGBUS 4
|
||||
#define TARGET_MINSIGSTKSZ 4096
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 0x2000
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 0x4000
|
||||
|
@ -44,3 +44,7 @@ struct target_pt_regs {
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -39,5 +39,8 @@ struct target_pt_regs {
|
||||
};
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS2
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
||||
#endif
|
||||
|
@ -824,8 +824,6 @@ static uint32_t get_elf_hwcap2(void)
|
||||
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
|
||||
} while (0)
|
||||
|
||||
static inline uint32_t get_ppc64_abi(struct image_info *infop);
|
||||
|
||||
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
|
||||
{
|
||||
_regs->gpr[1] = infop->start_stack;
|
||||
@ -1205,13 +1203,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
#ifdef TARGET_PPC
|
||||
static inline uint32_t get_ppc64_abi(struct image_info *infop)
|
||||
{
|
||||
return infop->elf_flags & EF_PPC64_ABI;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct exec
|
||||
{
|
||||
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
|
||||
|
@ -147,3 +147,6 @@ struct target_vm86plus_struct {
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -18,4 +18,8 @@ struct target_pt_regs {
|
||||
#define UNAME_MACHINE "m68k"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
||||
void do_m68k_simcall(CPUM68KState *, int);
|
||||
|
@ -309,7 +309,6 @@ void cpu_loop(CPUX86State *env)
|
||||
env->regs[8],
|
||||
env->regs[9],
|
||||
0, 0);
|
||||
env->eip = env->exception_next_eip;
|
||||
break;
|
||||
#endif
|
||||
case EXCP0B_NOSEG:
|
||||
|
@ -49,5 +49,8 @@ struct target_pt_regs {
|
||||
};
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
||||
#endif
|
||||
|
@ -228,3 +228,6 @@ struct target_pt_regs {
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -225,3 +225,6 @@ struct target_pt_regs {
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -23,3 +23,7 @@ struct target_pt_regs {
|
||||
|
||||
#define UNAME_MACHINE "openrisc"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -69,3 +69,7 @@ struct target_revectored_struct {
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 0x2000
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 0x4000
|
||||
|
@ -38,4 +38,14 @@ static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef EF_PPC64_ABI
|
||||
#define EF_PPC64_ABI 0x3
|
||||
#endif
|
||||
|
||||
static inline uint32_t get_ppc64_abi(struct image_info *infop)
|
||||
{
|
||||
return infop->elf_flags & EF_PPC64_ABI;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -24,3 +24,6 @@ struct target_pt_regs {
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS2
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -11,3 +11,7 @@ struct target_pt_regs {
|
||||
|
||||
#define UNAME_MACHINE "sh4"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -617,6 +617,15 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
|
||||
{
|
||||
struct target_sigaltstack *uss;
|
||||
struct target_sigaltstack ss;
|
||||
size_t minstacksize = TARGET_MINSIGSTKSZ;
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
/* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
|
||||
struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
|
||||
if (get_ppc64_abi(image) > 1) {
|
||||
minstacksize = 4096;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = -TARGET_EFAULT;
|
||||
if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) {
|
||||
@ -642,8 +651,9 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
|
||||
ss.ss_sp = 0;
|
||||
} else {
|
||||
ret = -TARGET_ENOMEM;
|
||||
if (ss.ss_size < MINSIGSTKSZ)
|
||||
if (ss.ss_size < minstacksize) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
target_sigaltstack_used.ss_sp = ss.ss_sp;
|
||||
|
@ -15,3 +15,6 @@ struct target_pt_regs {
|
||||
* and copy_thread().
|
||||
*/
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 4096
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 0x2000
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 0x4000
|
||||
|
@ -16,3 +16,6 @@ struct target_pt_regs {
|
||||
* and copy_thread().
|
||||
*/
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
#define TARGET_MINSIGSTKSZ 4096
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 0x2000
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 0x4000
|
||||
|
@ -1185,6 +1185,9 @@
|
||||
#ifdef TARGET_NR_set_mempolicy
|
||||
{ TARGET_NR_set_mempolicy, "set_mempolicy" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_setns
|
||||
{ TARGET_NR_setns, "setns" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_setpgid
|
||||
{ TARGET_NR_setpgid, "setpgid" , NULL, NULL, NULL },
|
||||
#endif
|
||||
@ -1404,6 +1407,15 @@
|
||||
#ifdef TARGET_NR_timer_settime
|
||||
{ TARGET_NR_timer_settime, "timer_settime" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_timerfd_create
|
||||
{ TARGET_NR_timerfd_create, "timerfd_create" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_timerfd_gettime
|
||||
{ TARGET_NR_timerfd_gettime, "timerfd_gettime" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_timerfd_settime
|
||||
{ TARGET_NR_timerfd_settime, "timerfd_settime" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_times
|
||||
{ TARGET_NR_times, "times" , NULL, NULL, NULL },
|
||||
#endif
|
||||
|
@ -58,6 +58,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
||||
#include <sys/shm.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <utime.h>
|
||||
#include <sys/sysinfo.h>
|
||||
//#include <sys/user.h>
|
||||
@ -251,6 +252,12 @@ _syscall2(int, capget, struct __user_cap_header_struct *, header,
|
||||
struct __user_cap_data_struct *, data);
|
||||
_syscall2(int, capset, struct __user_cap_header_struct *, header,
|
||||
struct __user_cap_data_struct *, data);
|
||||
#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
|
||||
_syscall2(int, ioprio_get, int, which, int, who)
|
||||
#endif
|
||||
#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
|
||||
_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
|
||||
#endif
|
||||
|
||||
static bitmask_transtbl fcntl_flags_tbl[] = {
|
||||
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
|
||||
@ -294,7 +301,6 @@ static int sys_getcwd1(char *buf, size_t size)
|
||||
return strlen(buf)+1;
|
||||
}
|
||||
|
||||
#ifdef TARGET_NR_openat
|
||||
static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
/*
|
||||
@ -306,7 +312,6 @@ static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
|
||||
}
|
||||
return (openat(dirfd, pathname, flags));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_utimensat
|
||||
#ifdef CONFIG_UTIMENSAT
|
||||
@ -1798,6 +1803,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
|
||||
abi_ulong total_len, max_len;
|
||||
int i;
|
||||
int err = 0;
|
||||
bool bad_address = false;
|
||||
|
||||
if (count == 0) {
|
||||
errno = 0;
|
||||
@ -1838,9 +1844,20 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
|
||||
vec[i].iov_base = 0;
|
||||
} else {
|
||||
vec[i].iov_base = lock_user(type, base, len, copy);
|
||||
/* If the first buffer pointer is bad, this is a fault. But
|
||||
* subsequent bad buffers will result in a partial write; this
|
||||
* is realized by filling the vector with null pointers and
|
||||
* zero lengths. */
|
||||
if (!vec[i].iov_base) {
|
||||
err = EFAULT;
|
||||
goto fail;
|
||||
if (i == 0) {
|
||||
err = EFAULT;
|
||||
goto fail;
|
||||
} else {
|
||||
bad_address = true;
|
||||
}
|
||||
}
|
||||
if (bad_address) {
|
||||
len = 0;
|
||||
}
|
||||
if (len > max_len - total_len) {
|
||||
len = max_len - total_len;
|
||||
@ -2419,9 +2436,13 @@ struct target_semid_ds
|
||||
{
|
||||
struct target_ipc_perm sem_perm;
|
||||
abi_ulong sem_otime;
|
||||
#if !defined(TARGET_PPC64)
|
||||
abi_ulong __unused1;
|
||||
#endif
|
||||
abi_ulong sem_ctime;
|
||||
#if !defined(TARGET_PPC64)
|
||||
abi_ulong __unused2;
|
||||
#endif
|
||||
abi_ulong sem_nsems;
|
||||
abi_ulong __unused3;
|
||||
abi_ulong __unused4;
|
||||
@ -2643,9 +2664,18 @@ static inline abi_long do_semctl(int semid, int semnum, int cmd,
|
||||
switch( cmd ) {
|
||||
case GETVAL:
|
||||
case SETVAL:
|
||||
arg.val = tswap32(target_su.val);
|
||||
/* In 64 bit cross-endian situations, we will erroneously pick up
|
||||
* the wrong half of the union for the "val" element. To rectify
|
||||
* this, the entire 8-byte structure is byteswapped, followed by
|
||||
* a swap of the 4 byte val field. In other cases, the data is
|
||||
* already in proper host byte order. */
|
||||
if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
|
||||
target_su.buf = tswapal(target_su.buf);
|
||||
arg.val = tswap32(target_su.val);
|
||||
} else {
|
||||
arg.val = target_su.val;
|
||||
}
|
||||
ret = get_errno(semctl(semid, semnum, cmd, arg));
|
||||
target_su.val = tswap32(arg.val);
|
||||
break;
|
||||
case GETALL:
|
||||
case SETALL:
|
||||
@ -2861,15 +2891,23 @@ struct target_msgbuf {
|
||||
};
|
||||
|
||||
static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
||||
unsigned int msgsz, int msgflg)
|
||||
ssize_t msgsz, int msgflg)
|
||||
{
|
||||
struct target_msgbuf *target_mb;
|
||||
struct msgbuf *host_mb;
|
||||
abi_long ret = 0;
|
||||
|
||||
if (msgsz < 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
|
||||
return -TARGET_EFAULT;
|
||||
host_mb = malloc(msgsz+sizeof(long));
|
||||
if (!host_mb) {
|
||||
unlock_user_struct(target_mb, msgp, 0);
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
|
||||
memcpy(host_mb->mtext, target_mb->mtext, msgsz);
|
||||
ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
|
||||
@ -3112,8 +3150,8 @@ static inline abi_long do_shmdt(abi_ulong shmaddr)
|
||||
#ifdef TARGET_NR_ipc
|
||||
/* ??? This only works with linear mappings. */
|
||||
/* do_ipc() must return target values and target errnos. */
|
||||
static abi_long do_ipc(unsigned int call, int first,
|
||||
int second, int third,
|
||||
static abi_long do_ipc(unsigned int call, abi_long first,
|
||||
abi_long second, abi_long third,
|
||||
abi_long ptr, abi_long fifth)
|
||||
{
|
||||
int version;
|
||||
@ -3131,9 +3169,15 @@ static abi_long do_ipc(unsigned int call, int first,
|
||||
ret = get_errno(semget(first, second, third));
|
||||
break;
|
||||
|
||||
case IPCOP_semctl:
|
||||
ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
|
||||
case IPCOP_semctl: {
|
||||
/* The semun argument to semctl is passed by value, so dereference the
|
||||
* ptr argument. */
|
||||
abi_ulong atptr;
|
||||
get_user_ual(atptr, ptr);
|
||||
ret = do_semctl(first, second, third,
|
||||
(union target_semun) atptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case IPCOP_msgget:
|
||||
ret = get_errno(msgget(first, second));
|
||||
@ -4914,6 +4958,47 @@ static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
|
||||
abi_ulong target_addr)
|
||||
{
|
||||
struct target_sigevent *target_sevp;
|
||||
|
||||
if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
/* This union is awkward on 64 bit systems because it has a 32 bit
|
||||
* integer and a pointer in it; we follow the conversion approach
|
||||
* used for handling sigval types in signal.c so the guest should get
|
||||
* the correct value back even if we did a 64 bit byteswap and it's
|
||||
* using the 32 bit integer.
|
||||
*/
|
||||
host_sevp->sigev_value.sival_ptr =
|
||||
(void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
|
||||
host_sevp->sigev_signo =
|
||||
target_to_host_signal(tswap32(target_sevp->sigev_signo));
|
||||
host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
|
||||
host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
|
||||
|
||||
unlock_user_struct(target_sevp, target_addr, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(TARGET_NR_mlockall)
|
||||
static inline int target_to_host_mlockall_arg(int arg)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
|
||||
result |= MCL_CURRENT;
|
||||
}
|
||||
if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
|
||||
result |= MCL_FUTURE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
|
||||
static inline abi_long host_to_target_stat64(void *cpu_env,
|
||||
abi_ulong target_addr,
|
||||
@ -5092,10 +5177,8 @@ static int open_self_cmdline(void *cpu_env, int fd)
|
||||
|
||||
static int open_self_maps(void *cpu_env, int fd)
|
||||
{
|
||||
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
|
||||
CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
|
||||
TaskState *ts = cpu->opaque;
|
||||
#endif
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
@ -5118,13 +5201,18 @@ static int open_self_maps(void *cpu_env, int fd)
|
||||
if ((fields < 10) || (fields > 11)) {
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(path, "[stack]", 7)) {
|
||||
continue;
|
||||
}
|
||||
if (h2g_valid(min) && h2g_valid(max)) {
|
||||
if (h2g_valid(min)) {
|
||||
int flags = page_get_flags(h2g(min));
|
||||
max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX);
|
||||
if (page_check_range(h2g(min), max - min, flags) == -1) {
|
||||
continue;
|
||||
}
|
||||
if (h2g(min) == ts->info->stack_limit) {
|
||||
pstrcpy(path, sizeof(path), " [stack]");
|
||||
}
|
||||
dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx
|
||||
" %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
|
||||
h2g(min), h2g(max), flag_r, flag_w,
|
||||
h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
|
||||
flag_x, flag_p, offset, dev_maj, dev_min, inode,
|
||||
path[0] ? " " : "", path);
|
||||
}
|
||||
@ -5133,14 +5221,6 @@ static int open_self_maps(void *cpu_env, int fd)
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
|
||||
dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
|
||||
(unsigned long long)ts->info->stack_limit,
|
||||
(unsigned long long)(ts->info->start_stack +
|
||||
(TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK,
|
||||
(unsigned long long)0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5279,7 +5359,7 @@ static int open_net_route(void *cpu_env, int fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||
static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
struct fake_open {
|
||||
const char *filename;
|
||||
@ -5300,7 +5380,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||
|
||||
if (is_proc_myself(pathname, "exe")) {
|
||||
int execfd = qemu_getauxval(AT_EXECFD);
|
||||
return execfd ? execfd : get_errno(open(exec_path, flags, mode));
|
||||
return execfd ? execfd : get_errno(sys_openat(dirfd, exec_path, flags, mode));
|
||||
}
|
||||
|
||||
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
||||
@ -5334,7 +5414,7 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||
return fd;
|
||||
}
|
||||
|
||||
return get_errno(open(path(pathname), flags, mode));
|
||||
return get_errno(sys_openat(dirfd, path(pathname), flags, mode));
|
||||
}
|
||||
|
||||
/* do_syscall() should always have a single exit point at the end so
|
||||
@ -5409,22 +5489,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
case TARGET_NR_open:
|
||||
if (!(p = lock_user_string(arg1)))
|
||||
goto efault;
|
||||
ret = get_errno(do_open(cpu_env, p,
|
||||
target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
||||
arg3));
|
||||
ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
|
||||
target_to_host_bitmask(arg2, fcntl_flags_tbl),
|
||||
arg3));
|
||||
unlock_user(p, arg1, 0);
|
||||
break;
|
||||
#if defined(TARGET_NR_openat) && defined(__NR_openat)
|
||||
case TARGET_NR_openat:
|
||||
if (!(p = lock_user_string(arg2)))
|
||||
goto efault;
|
||||
ret = get_errno(sys_openat(arg1,
|
||||
path(p),
|
||||
target_to_host_bitmask(arg3, fcntl_flags_tbl),
|
||||
arg4));
|
||||
ret = get_errno(do_openat(cpu_env, arg1, p,
|
||||
target_to_host_bitmask(arg3, fcntl_flags_tbl),
|
||||
arg4));
|
||||
unlock_user(p, arg2, 0);
|
||||
break;
|
||||
#endif
|
||||
case TARGET_NR_close:
|
||||
ret = get_errno(close(arg1));
|
||||
break;
|
||||
@ -6620,11 +6697,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
||||
if (!p || !p2) {
|
||||
ret = -TARGET_EFAULT;
|
||||
} else if (!arg3) {
|
||||
/* Short circuit this for the magic exe check. */
|
||||
ret = -TARGET_EINVAL;
|
||||
} else if (is_proc_myself((const char *)p, "exe")) {
|
||||
char real[PATH_MAX], *temp;
|
||||
temp = realpath(exec_path, real);
|
||||
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
|
||||
snprintf((char *)p2, arg3, "%s", real);
|
||||
/* Return value is # of bytes that we wrote to the buffer. */
|
||||
if (temp == NULL) {
|
||||
ret = get_errno(-1);
|
||||
} else {
|
||||
/* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error. */
|
||||
ret = MIN(strlen(real), arg3);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(p2, real, ret);
|
||||
}
|
||||
} else {
|
||||
ret = get_errno(readlink(path(p), p2, arg3));
|
||||
}
|
||||
@ -6763,7 +6851,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#endif
|
||||
#ifdef TARGET_NR_mlockall
|
||||
case TARGET_NR_mlockall:
|
||||
ret = get_errno(mlockall(arg1));
|
||||
ret = get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_munlockall
|
||||
@ -7679,6 +7767,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
struct sched_param *target_schp;
|
||||
struct sched_param schp;
|
||||
|
||||
if (arg2 == 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
|
||||
goto efault;
|
||||
schp.sched_priority = tswap32(target_schp->sched_priority);
|
||||
@ -7690,6 +7781,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
{
|
||||
struct sched_param *target_schp;
|
||||
struct sched_param schp;
|
||||
|
||||
if (arg2 == 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
ret = get_errno(sched_getparam(arg1, &schp));
|
||||
if (!is_error(ret)) {
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
|
||||
@ -7703,6 +7798,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
{
|
||||
struct sched_param *target_schp;
|
||||
struct sched_param schp;
|
||||
if (arg3 == 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
|
||||
goto efault;
|
||||
schp.sched_priority = tswap32(target_schp->sched_priority);
|
||||
@ -7727,7 +7825,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
struct timespec ts;
|
||||
ret = get_errno(sched_rr_get_interval(arg1, &ts));
|
||||
if (!is_error(ret)) {
|
||||
host_to_target_timespec(arg2, &ts);
|
||||
ret = host_to_target_timespec(arg2, &ts);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -8966,6 +9064,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
|
||||
if (arg4)
|
||||
host_to_target_timespec(arg4, &ts);
|
||||
|
||||
#if defined(TARGET_PPC)
|
||||
/* clock_nanosleep is odd in that it returns positive errno values.
|
||||
* On PPC, CR0 bit 3 should be set in such a situation. */
|
||||
if (ret) {
|
||||
((CPUPPCState *)cpu_env)->crf[0] |= 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -9062,12 +9168,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
|
||||
case TARGET_NR_mq_open:
|
||||
{
|
||||
struct mq_attr posix_mq_attr;
|
||||
struct mq_attr posix_mq_attr, *attrp;
|
||||
|
||||
p = lock_user_string(arg1 - 1);
|
||||
if (arg4 != 0)
|
||||
if (arg4 != 0) {
|
||||
copy_from_user_mq_attr (&posix_mq_attr, arg4);
|
||||
ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
|
||||
attrp = &posix_mq_attr;
|
||||
} else {
|
||||
attrp = 0;
|
||||
}
|
||||
ret = get_errno(mq_open(p, arg2, arg3, attrp));
|
||||
unlock_user (p, arg1, 0);
|
||||
}
|
||||
break;
|
||||
@ -9413,7 +9523,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
/* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
|
||||
|
||||
struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
|
||||
struct target_sigevent *ptarget_sevp;
|
||||
struct target_timer_t *ptarget_timer;
|
||||
|
||||
int clkid = arg1;
|
||||
@ -9425,14 +9534,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
timer_t *phtimer = g_posix_timers + timer_index;
|
||||
|
||||
if (arg2) {
|
||||
if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
|
||||
goto efault;
|
||||
}
|
||||
|
||||
host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
|
||||
host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
|
||||
|
||||
phost_sevp = &host_sevp;
|
||||
ret = target_to_host_sigevent(phost_sevp, arg2);
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
|
||||
@ -9524,6 +9630,73 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_create:
|
||||
ret = get_errno(timerfd_create(arg1,
|
||||
target_to_host_bitmask(arg2, fcntl_flags_tbl)));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_gettime:
|
||||
{
|
||||
struct itimerspec its_curr;
|
||||
|
||||
ret = get_errno(timerfd_gettime(arg1, &its_curr));
|
||||
|
||||
if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
|
||||
goto efault;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_settime:
|
||||
{
|
||||
struct itimerspec its_new, its_old, *p_new;
|
||||
|
||||
if (arg3) {
|
||||
if (target_to_host_itimerspec(&its_new, arg3)) {
|
||||
goto efault;
|
||||
}
|
||||
p_new = &its_new;
|
||||
} else {
|
||||
p_new = NULL;
|
||||
}
|
||||
|
||||
ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
|
||||
|
||||
if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
|
||||
goto efault;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
|
||||
case TARGET_NR_ioprio_get:
|
||||
ret = get_errno(ioprio_get(arg1, arg2));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
|
||||
case TARGET_NR_ioprio_set:
|
||||
ret = get_errno(ioprio_set(arg1, arg2, arg3));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
|
||||
case TARGET_NR_setns:
|
||||
ret = get_errno(setns(arg1, arg2));
|
||||
break;
|
||||
#endif
|
||||
#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
|
||||
case TARGET_NR_unshare:
|
||||
ret = get_errno(unshare(arg1));
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
unimplemented:
|
||||
gemu_log("qemu: Unsupported syscall: %d\n", num);
|
||||
|
@ -53,4 +53,8 @@ struct target_pt_regs {
|
||||
#define UNAME_MACHINE "UniCore-II"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
||||
#endif /* __UC32_SYSCALL_H__ */
|
||||
|
@ -97,3 +97,6 @@ struct target_msqid64_ds {
|
||||
#define TARGET_ARCH_SET_FS 0x1002
|
||||
#define TARGET_ARCH_GET_FS 0x1003
|
||||
#define TARGET_ARCH_GET_GS 0x1004
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
@ -1127,8 +1127,8 @@ static void do_interrupt_user(CPUX86State *env, int intno, int is_int,
|
||||
|
||||
/* Since we emulate only user space, we cannot do more than
|
||||
exiting the emulation with the suitable exception and error
|
||||
code */
|
||||
if (is_int) {
|
||||
code. So update EIP for INT 0x80 and EXCP_SYSCALL. */
|
||||
if (is_int || intno == EXCP_SYSCALL) {
|
||||
env->eip = next_eip;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user