Merge branch 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu
* 'linux-user-for-upstream' of git://git.linaro.org/people/rikuvoipio/qemu: linux-user: register align p{read, write}64 linux-user: ppc: mark as long long aligned tcg: Remove TCG_TARGET_HAS_GUEST_BASE define configure: Remove unnecessary host_guest_base code linux-user: If loading fails, print error as string, not number linux-user: Fix siginfo handling alpha-linux-user: Fix sigaltstack structure definition linux-user: Implement gethostname linux-user: Perform more checks on iovec lists linux-user: fix multi-threaded /proc/self/maps linux-user: fix statfs
This commit is contained in:
commit
41a05a4576
|
@ -199,7 +199,7 @@ cocoa="no"
|
||||||
softmmu="yes"
|
softmmu="yes"
|
||||||
linux_user="no"
|
linux_user="no"
|
||||||
bsd_user="no"
|
bsd_user="no"
|
||||||
guest_base=""
|
guest_base="yes"
|
||||||
uname_release=""
|
uname_release=""
|
||||||
mixemu="no"
|
mixemu="no"
|
||||||
aix="no"
|
aix="no"
|
||||||
|
@ -871,63 +871,36 @@ for opt do
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
host_guest_base="no"
|
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
sparc)
|
sparc)
|
||||||
LDFLAGS="-m32 $LDFLAGS"
|
LDFLAGS="-m32 $LDFLAGS"
|
||||||
QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS"
|
QEMU_CFLAGS="-m32 -mcpu=ultrasparc $QEMU_CFLAGS"
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
;;
|
||||||
sparc64)
|
sparc64)
|
||||||
LDFLAGS="-m64 $LDFLAGS"
|
LDFLAGS="-m64 $LDFLAGS"
|
||||||
QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS"
|
QEMU_CFLAGS="-m64 -mcpu=ultrasparc $QEMU_CFLAGS"
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
;;
|
||||||
s390)
|
s390)
|
||||||
QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
|
QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
|
||||||
LDFLAGS="-m31 $LDFLAGS"
|
LDFLAGS="-m31 $LDFLAGS"
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
;;
|
||||||
s390x)
|
s390x)
|
||||||
QEMU_CFLAGS="-m64 -march=z990 $QEMU_CFLAGS"
|
QEMU_CFLAGS="-m64 -march=z990 $QEMU_CFLAGS"
|
||||||
LDFLAGS="-m64 $LDFLAGS"
|
LDFLAGS="-m64 $LDFLAGS"
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
;;
|
||||||
i386)
|
i386)
|
||||||
QEMU_CFLAGS="-m32 $QEMU_CFLAGS"
|
QEMU_CFLAGS="-m32 $QEMU_CFLAGS"
|
||||||
LDFLAGS="-m32 $LDFLAGS"
|
LDFLAGS="-m32 $LDFLAGS"
|
||||||
cc_i386='$(CC) -m32'
|
cc_i386='$(CC) -m32'
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
;;
|
||||||
x86_64)
|
x86_64)
|
||||||
QEMU_CFLAGS="-m64 $QEMU_CFLAGS"
|
QEMU_CFLAGS="-m64 $QEMU_CFLAGS"
|
||||||
LDFLAGS="-m64 $LDFLAGS"
|
LDFLAGS="-m64 $LDFLAGS"
|
||||||
cc_i386='$(CC) -m32'
|
cc_i386='$(CC) -m32'
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
|
||||||
arm*)
|
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
|
||||||
ppc*)
|
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
|
||||||
mips*)
|
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
|
||||||
ia64*)
|
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
|
||||||
hppa*)
|
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
|
||||||
unicore32*)
|
|
||||||
host_guest_base="yes"
|
|
||||||
;;
|
;;
|
||||||
|
# No special flags required for other host CPUs
|
||||||
esac
|
esac
|
||||||
|
|
||||||
[ -z "$guest_base" ] && guest_base="$host_guest_base"
|
|
||||||
|
|
||||||
|
|
||||||
default_target_list=""
|
default_target_list=""
|
||||||
|
|
||||||
# these targets are portable
|
# these targets are portable
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
/* this struct defines a stack used during syscall handling */
|
/* this struct defines a stack used during syscall handling */
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
typedef struct target_sigaltstack {
|
||||||
abi_ulong ss_sp;
|
abi_ulong ss_sp;
|
||||||
abi_long ss_flags;
|
int32_t ss_flags;
|
||||||
abi_ulong ss_size;
|
int32_t dummy;
|
||||||
|
abi_ulong ss_size;
|
||||||
} target_stack_t;
|
} target_stack_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -140,8 +140,9 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
|
||||||
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
|
bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
|
||||||
memset(bprm->page, 0, sizeof(bprm->page));
|
memset(bprm->page, 0, sizeof(bprm->page));
|
||||||
retval = open(filename, O_RDONLY);
|
retval = open(filename, O_RDONLY);
|
||||||
if (retval < 0)
|
if (retval < 0) {
|
||||||
return retval;
|
return -errno;
|
||||||
|
}
|
||||||
bprm->fd = retval;
|
bprm->fd = retval;
|
||||||
bprm->filename = (char *)filename;
|
bprm->filename = (char *)filename;
|
||||||
bprm->argc = count(argv);
|
bprm->argc = count(argv);
|
||||||
|
@ -165,8 +166,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
|
||||||
retval = load_flt_binary(bprm,regs,infop);
|
retval = load_flt_binary(bprm,regs,infop);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown binary format\n");
|
return -ENOEXEC;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3574,7 +3574,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
ret = loader_exec(filename, target_argv, target_environ, regs,
|
ret = loader_exec(filename, target_argv, target_environ, regs,
|
||||||
info, &bprm);
|
info, &bprm);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printf("Error %d while loading %s\n", ret, filename);
|
printf("Error while loading %s: %s\n", filename, strerror(-ret));
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,9 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
|
|
||||||
#include "qemu-log.h"
|
#include "qemu-log.h"
|
||||||
|
|
||||||
|
/* syscall.c */
|
||||||
|
int host_to_target_waitstatus(int status);
|
||||||
|
|
||||||
/* strace.c */
|
/* strace.c */
|
||||||
void print_syscall(int num,
|
void print_syscall(int num,
|
||||||
abi_long arg1, abi_long arg2, abi_long arg3,
|
abi_long arg1, abi_long arg2, abi_long arg3,
|
||||||
|
|
|
@ -202,46 +202,67 @@ void target_to_host_old_sigset(sigset_t *sigset,
|
||||||
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
|
static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
|
||||||
const siginfo_t *info)
|
const siginfo_t *info)
|
||||||
{
|
{
|
||||||
int sig;
|
int sig = host_to_target_signal(info->si_signo);
|
||||||
sig = host_to_target_signal(info->si_signo);
|
|
||||||
tinfo->si_signo = sig;
|
tinfo->si_signo = sig;
|
||||||
tinfo->si_errno = 0;
|
tinfo->si_errno = 0;
|
||||||
tinfo->si_code = info->si_code;
|
tinfo->si_code = info->si_code;
|
||||||
if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
|
|
||||||
sig == SIGBUS || sig == SIGTRAP) {
|
if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
|
||||||
/* should never come here, but who knows. The information for
|
|| sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
|
||||||
the target is irrelevant */
|
/* Should never come here, but who knows. The information for
|
||||||
|
the target is irrelevant. */
|
||||||
tinfo->_sifields._sigfault._addr = 0;
|
tinfo->_sifields._sigfault._addr = 0;
|
||||||
} else if (sig == SIGIO) {
|
} else if (sig == TARGET_SIGIO) {
|
||||||
|
tinfo->_sifields._sigpoll._band = info->si_band;
|
||||||
tinfo->_sifields._sigpoll._fd = info->si_fd;
|
tinfo->_sifields._sigpoll._fd = info->si_fd;
|
||||||
|
} else if (sig == TARGET_SIGCHLD) {
|
||||||
|
tinfo->_sifields._sigchld._pid = info->si_pid;
|
||||||
|
tinfo->_sifields._sigchld._uid = info->si_uid;
|
||||||
|
tinfo->_sifields._sigchld._status
|
||||||
|
= host_to_target_waitstatus(info->si_status);
|
||||||
|
tinfo->_sifields._sigchld._utime = info->si_utime;
|
||||||
|
tinfo->_sifields._sigchld._stime = info->si_stime;
|
||||||
} else if (sig >= TARGET_SIGRTMIN) {
|
} else if (sig >= TARGET_SIGRTMIN) {
|
||||||
tinfo->_sifields._rt._pid = info->si_pid;
|
tinfo->_sifields._rt._pid = info->si_pid;
|
||||||
tinfo->_sifields._rt._uid = info->si_uid;
|
tinfo->_sifields._rt._uid = info->si_uid;
|
||||||
/* XXX: potential problem if 64 bit */
|
/* XXX: potential problem if 64 bit */
|
||||||
tinfo->_sifields._rt._sigval.sival_ptr =
|
tinfo->_sifields._rt._sigval.sival_ptr
|
||||||
(abi_ulong)(unsigned long)info->si_value.sival_ptr;
|
= (abi_ulong)(unsigned long)info->si_value.sival_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tswap_siginfo(target_siginfo_t *tinfo,
|
static void tswap_siginfo(target_siginfo_t *tinfo,
|
||||||
const target_siginfo_t *info)
|
const target_siginfo_t *info)
|
||||||
{
|
{
|
||||||
int sig;
|
int sig = info->si_signo;
|
||||||
sig = info->si_signo;
|
|
||||||
tinfo->si_signo = tswap32(sig);
|
tinfo->si_signo = tswap32(sig);
|
||||||
tinfo->si_errno = tswap32(info->si_errno);
|
tinfo->si_errno = tswap32(info->si_errno);
|
||||||
tinfo->si_code = tswap32(info->si_code);
|
tinfo->si_code = tswap32(info->si_code);
|
||||||
if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
|
|
||||||
sig == SIGBUS || sig == SIGTRAP) {
|
if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
|
||||||
tinfo->_sifields._sigfault._addr =
|
|| sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
|
||||||
tswapal(info->_sifields._sigfault._addr);
|
tinfo->_sifields._sigfault._addr
|
||||||
} else if (sig == SIGIO) {
|
= tswapal(info->_sifields._sigfault._addr);
|
||||||
tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
|
} else if (sig == TARGET_SIGIO) {
|
||||||
|
tinfo->_sifields._sigpoll._band
|
||||||
|
= tswap32(info->_sifields._sigpoll._band);
|
||||||
|
tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd);
|
||||||
|
} else if (sig == TARGET_SIGCHLD) {
|
||||||
|
tinfo->_sifields._sigchld._pid
|
||||||
|
= tswap32(info->_sifields._sigchld._pid);
|
||||||
|
tinfo->_sifields._sigchld._uid
|
||||||
|
= tswap32(info->_sifields._sigchld._uid);
|
||||||
|
tinfo->_sifields._sigchld._status
|
||||||
|
= tswap32(info->_sifields._sigchld._status);
|
||||||
|
tinfo->_sifields._sigchld._utime
|
||||||
|
= tswapal(info->_sifields._sigchld._utime);
|
||||||
|
tinfo->_sifields._sigchld._stime
|
||||||
|
= tswapal(info->_sifields._sigchld._stime);
|
||||||
} else if (sig >= TARGET_SIGRTMIN) {
|
} else if (sig >= TARGET_SIGRTMIN) {
|
||||||
tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
|
tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid);
|
||||||
tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
|
tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
|
||||||
tinfo->_sifields._rt._sigval.sival_ptr =
|
tinfo->_sifields._rt._sigval.sival_ptr
|
||||||
tswapal(info->_sifields._rt._sigval.sival_ptr);
|
= tswapal(info->_sifields._rt._sigval.sival_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -587,12 +587,17 @@ extern int setfsgid(int);
|
||||||
extern int setgroups(int, gid_t *);
|
extern int setgroups(int, gid_t *);
|
||||||
|
|
||||||
/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
|
/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
|
||||||
#ifdef TARGET_ARM
|
#ifdef TARGET_ARM
|
||||||
static inline int regpairs_aligned(void *cpu_env) {
|
static inline int regpairs_aligned(void *cpu_env) {
|
||||||
return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
|
return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
|
||||||
}
|
}
|
||||||
#elif defined(TARGET_MIPS)
|
#elif defined(TARGET_MIPS)
|
||||||
static inline int regpairs_aligned(void *cpu_env) { return 1; }
|
static inline int regpairs_aligned(void *cpu_env) { return 1; }
|
||||||
|
#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
|
||||||
|
/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
|
||||||
|
* of registers which translates to the same as ARM/MIPS, because we start with
|
||||||
|
* r3 as arg1 */
|
||||||
|
static inline int regpairs_aligned(void *cpu_env) { return 1; }
|
||||||
#else
|
#else
|
||||||
static inline int regpairs_aligned(void *cpu_env) { return 0; }
|
static inline int regpairs_aligned(void *cpu_env) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
@ -1744,55 +1749,96 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME
|
static struct iovec *lock_iovec(int type, abi_ulong target_addr,
|
||||||
* lock_iovec()/unlock_iovec() have a return code of 0 for success where
|
int count, int copy)
|
||||||
* other lock functions have a return code of 0 for failure.
|
|
||||||
*/
|
|
||||||
static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
|
|
||||||
int count, int copy)
|
|
||||||
{
|
{
|
||||||
struct target_iovec *target_vec;
|
struct target_iovec *target_vec;
|
||||||
abi_ulong base;
|
struct iovec *vec;
|
||||||
|
abi_ulong total_len, max_len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
|
if (count == 0) {
|
||||||
if (!target_vec)
|
errno = 0;
|
||||||
return -TARGET_EFAULT;
|
return NULL;
|
||||||
for(i = 0;i < count; i++) {
|
|
||||||
base = tswapal(target_vec[i].iov_base);
|
|
||||||
vec[i].iov_len = tswapal(target_vec[i].iov_len);
|
|
||||||
if (vec[i].iov_len != 0) {
|
|
||||||
vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
|
|
||||||
/* Don't check lock_user return value. We must call writev even
|
|
||||||
if a element has invalid base address. */
|
|
||||||
} else {
|
|
||||||
/* zero length pointer is ignored */
|
|
||||||
vec[i].iov_base = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unlock_user (target_vec, target_addr, 0);
|
if (count > IOV_MAX) {
|
||||||
return 0;
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec = calloc(count, sizeof(struct iovec));
|
||||||
|
if (vec == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_vec = lock_user(VERIFY_READ, target_addr,
|
||||||
|
count * sizeof(struct target_iovec), 1);
|
||||||
|
if (target_vec == NULL) {
|
||||||
|
errno = EFAULT;
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ??? If host page size > target page size, this will result in a
|
||||||
|
value larger than what we can actually support. */
|
||||||
|
max_len = 0x7fffffff & TARGET_PAGE_MASK;
|
||||||
|
total_len = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
abi_ulong base = tswapal(target_vec[i].iov_base);
|
||||||
|
abi_long len = tswapal(target_vec[i].iov_len);
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto fail;
|
||||||
|
} else if (len == 0) {
|
||||||
|
/* Zero length pointer is ignored. */
|
||||||
|
vec[i].iov_base = 0;
|
||||||
|
} else {
|
||||||
|
vec[i].iov_base = lock_user(type, base, len, copy);
|
||||||
|
if (!vec[i].iov_base) {
|
||||||
|
errno = EFAULT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (len > max_len - total_len) {
|
||||||
|
len = max_len - total_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec[i].iov_len = len;
|
||||||
|
total_len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_user(target_vec, target_addr, 0);
|
||||||
|
return vec;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(vec);
|
||||||
|
fail2:
|
||||||
|
unlock_user(target_vec, target_addr, 0);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
|
static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
|
||||||
int count, int copy)
|
int count, int copy)
|
||||||
{
|
{
|
||||||
struct target_iovec *target_vec;
|
struct target_iovec *target_vec;
|
||||||
abi_ulong base;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
|
target_vec = lock_user(VERIFY_READ, target_addr,
|
||||||
if (!target_vec)
|
count * sizeof(struct target_iovec), 1);
|
||||||
return -TARGET_EFAULT;
|
if (target_vec) {
|
||||||
for(i = 0;i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
if (target_vec[i].iov_base) {
|
abi_ulong base = tswapal(target_vec[i].iov_base);
|
||||||
base = tswapal(target_vec[i].iov_base);
|
abi_long len = tswapal(target_vec[i].iov_base);
|
||||||
|
if (len < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
|
unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
|
||||||
}
|
}
|
||||||
|
unlock_user(target_vec, target_addr, 0);
|
||||||
}
|
}
|
||||||
unlock_user (target_vec, target_addr, 0);
|
|
||||||
|
|
||||||
return 0;
|
free(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do_socket() Must return target values and target errnos. */
|
/* do_socket() Must return target values and target errnos. */
|
||||||
|
@ -1888,8 +1934,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
|
||||||
ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
|
ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
|
||||||
msg.msg_namelen);
|
msg.msg_namelen);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
goto out2;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msg.msg_name = NULL;
|
msg.msg_name = NULL;
|
||||||
|
@ -1900,9 +1945,13 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
|
||||||
msg.msg_flags = tswap32(msgp->msg_flags);
|
msg.msg_flags = tswap32(msgp->msg_flags);
|
||||||
|
|
||||||
count = tswapal(msgp->msg_iovlen);
|
count = tswapal(msgp->msg_iovlen);
|
||||||
vec = alloca(count * sizeof(struct iovec));
|
|
||||||
target_vec = tswapal(msgp->msg_iov);
|
target_vec = tswapal(msgp->msg_iov);
|
||||||
lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
|
vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
|
||||||
|
target_vec, count, send);
|
||||||
|
if (vec == NULL) {
|
||||||
|
ret = -host_to_target_errno(errno);
|
||||||
|
goto out2;
|
||||||
|
}
|
||||||
msg.msg_iovlen = count;
|
msg.msg_iovlen = count;
|
||||||
msg.msg_iov = vec;
|
msg.msg_iov = vec;
|
||||||
|
|
||||||
|
@ -1932,6 +1981,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
unlock_iovec(vec, target_vec, count, !send);
|
unlock_iovec(vec, target_vec, count, !send);
|
||||||
|
out2:
|
||||||
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -4873,7 +4923,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
|
||||||
|
|
||||||
/* Map host to target signal numbers for the wait family of syscalls.
|
/* Map host to target signal numbers for the wait family of syscalls.
|
||||||
Assume all other status bits are the same. */
|
Assume all other status bits are the same. */
|
||||||
static int host_to_target_waitstatus(int status)
|
int host_to_target_waitstatus(int status)
|
||||||
{
|
{
|
||||||
if (WIFSIGNALED(status)) {
|
if (WIFSIGNALED(status)) {
|
||||||
return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
|
return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
|
||||||
|
@ -4962,8 +5012,8 @@ static int open_self_maps(void *cpu_env, int fd)
|
||||||
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
|
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
|
||||||
dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
|
dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
|
||||||
(unsigned long long)ts->info->stack_limit,
|
(unsigned long long)ts->info->stack_limit,
|
||||||
(unsigned long long)(ts->stack_base + (TARGET_PAGE_SIZE - 1))
|
(unsigned long long)(ts->info->start_stack +
|
||||||
& TARGET_PAGE_MASK,
|
(TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK,
|
||||||
(unsigned long long)0);
|
(unsigned long long)0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -6529,6 +6579,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
|
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
|
||||||
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
|
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
|
||||||
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
|
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
|
||||||
|
__put_user(stfs.f_frsize, &target_stfs->f_frsize);
|
||||||
|
memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
|
||||||
unlock_user_struct(target_stfs, arg2, 1);
|
unlock_user_struct(target_stfs, arg2, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -6557,6 +6609,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
|
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
|
||||||
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
|
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
|
||||||
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
|
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
|
||||||
|
__put_user(stfs.f_frsize, &target_stfs->f_frsize);
|
||||||
|
memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
|
||||||
unlock_user_struct(target_stfs, arg3, 1);
|
unlock_user_struct(target_stfs, arg3, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -7186,26 +7240,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
break;
|
break;
|
||||||
case TARGET_NR_readv:
|
case TARGET_NR_readv:
|
||||||
{
|
{
|
||||||
int count = arg3;
|
struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
|
||||||
struct iovec *vec;
|
if (vec != NULL) {
|
||||||
|
ret = get_errno(readv(arg1, vec, arg3));
|
||||||
vec = alloca(count * sizeof(struct iovec));
|
unlock_iovec(vec, arg2, arg3, 1);
|
||||||
if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
|
} else {
|
||||||
goto efault;
|
ret = -host_to_target_errno(errno);
|
||||||
ret = get_errno(readv(arg1, vec, count));
|
}
|
||||||
unlock_iovec(vec, arg2, count, 1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TARGET_NR_writev:
|
case TARGET_NR_writev:
|
||||||
{
|
{
|
||||||
int count = arg3;
|
struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
|
||||||
struct iovec *vec;
|
if (vec != NULL) {
|
||||||
|
ret = get_errno(writev(arg1, vec, arg3));
|
||||||
vec = alloca(count * sizeof(struct iovec));
|
unlock_iovec(vec, arg2, arg3, 0);
|
||||||
if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
|
} else {
|
||||||
goto efault;
|
ret = -host_to_target_errno(errno);
|
||||||
ret = get_errno(writev(arg1, vec, count));
|
}
|
||||||
unlock_iovec(vec, arg2, count, 0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TARGET_NR_getsid:
|
case TARGET_NR_getsid:
|
||||||
|
@ -7417,12 +7469,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_NR_pread64
|
#ifdef TARGET_NR_pread64
|
||||||
case TARGET_NR_pread64:
|
case TARGET_NR_pread64:
|
||||||
|
if (regpairs_aligned(cpu_env)) {
|
||||||
|
arg4 = arg5;
|
||||||
|
arg5 = arg6;
|
||||||
|
}
|
||||||
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
||||||
goto efault;
|
goto efault;
|
||||||
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
||||||
unlock_user(p, arg2, ret);
|
unlock_user(p, arg2, ret);
|
||||||
break;
|
break;
|
||||||
case TARGET_NR_pwrite64:
|
case TARGET_NR_pwrite64:
|
||||||
|
if (regpairs_aligned(cpu_env)) {
|
||||||
|
arg4 = arg5;
|
||||||
|
arg5 = arg6;
|
||||||
|
}
|
||||||
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
||||||
goto efault;
|
goto efault;
|
||||||
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
|
||||||
|
@ -8630,14 +8690,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
#ifdef TARGET_NR_vmsplice
|
#ifdef TARGET_NR_vmsplice
|
||||||
case TARGET_NR_vmsplice:
|
case TARGET_NR_vmsplice:
|
||||||
{
|
{
|
||||||
int count = arg3;
|
struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
|
||||||
struct iovec *vec;
|
if (vec != NULL) {
|
||||||
|
ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
|
||||||
vec = alloca(count * sizeof(struct iovec));
|
unlock_iovec(vec, arg2, arg3, 0);
|
||||||
if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
|
} else {
|
||||||
goto efault;
|
ret = -host_to_target_errno(errno);
|
||||||
ret = get_errno(vmsplice(arg1, vec, count, arg4));
|
}
|
||||||
unlock_iovec(vec, arg2, count, 0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -8823,6 +8882,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_NR_gethostname
|
||||||
|
case TARGET_NR_gethostname:
|
||||||
|
{
|
||||||
|
char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
|
||||||
|
if (name) {
|
||||||
|
ret = get_errno(gethostname(name, arg2));
|
||||||
|
unlock_user(name, arg1, arg2);
|
||||||
|
} else {
|
||||||
|
ret = -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
unimplemented:
|
unimplemented:
|
||||||
|
|
|
@ -75,8 +75,6 @@ typedef enum {
|
||||||
#define TCG_TARGET_HAS_deposit_i32 0
|
#define TCG_TARGET_HAS_deposit_i32 0
|
||||||
#define TCG_TARGET_HAS_movcond_i32 1
|
#define TCG_TARGET_HAS_movcond_i32 1
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TCG_AREG0 = TCG_REG_R6,
|
TCG_AREG0 = TCG_REG_R6,
|
||||||
};
|
};
|
||||||
|
|
|
@ -103,8 +103,6 @@ typedef enum {
|
||||||
#define TCG_TARGET_HAS_ext8u_i32 0 /* and rd, rs, 0xff */
|
#define TCG_TARGET_HAS_ext8u_i32 0 /* and rd, rs, 0xff */
|
||||||
#define TCG_TARGET_HAS_ext16u_i32 0 /* and rd, rs, 0xffff */
|
#define TCG_TARGET_HAS_ext16u_i32 0 /* and rd, rs, 0xffff */
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_R17
|
#define TCG_AREG0 TCG_REG_R17
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -125,8 +125,6 @@ typedef enum {
|
||||||
((ofs) == 0 && (len) == 16))
|
((ofs) == 0 && (len) == 16))
|
||||||
#define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid
|
#define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
# define TCG_AREG0 TCG_REG_R14
|
# define TCG_AREG0 TCG_REG_R14
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -147,9 +147,6 @@ typedef enum {
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_R7
|
#define TCG_AREG0 TCG_REG_R7
|
||||||
|
|
||||||
/* Guest base is supported */
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
static inline void flush_icache_range(tcg_target_ulong start,
|
static inline void flush_icache_range(tcg_target_ulong start,
|
||||||
tcg_target_ulong stop)
|
tcg_target_ulong stop)
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,9 +116,6 @@ typedef enum {
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_S0
|
#define TCG_AREG0 TCG_REG_S0
|
||||||
|
|
||||||
/* guest base is supported */
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
#include <machine/sysarch.h>
|
#include <machine/sysarch.h>
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -96,8 +96,6 @@ typedef enum {
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_R27
|
#define TCG_AREG0 TCG_REG_R27
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
#define tcg_qemu_tb_exec(env, tb_ptr) \
|
#define tcg_qemu_tb_exec(env, tb_ptr) \
|
||||||
((long __attribute__ ((longcall)) \
|
((long __attribute__ ((longcall)) \
|
||||||
(*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
(*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
||||||
|
|
|
@ -108,5 +108,4 @@ typedef enum {
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_R27
|
#define TCG_AREG0 TCG_REG_R27
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
#define TCG_TARGET_EXTEND_ARGS 1
|
#define TCG_TARGET_EXTEND_ARGS 1
|
||||||
|
|
|
@ -88,8 +88,6 @@ typedef enum TCGReg {
|
||||||
#define TCG_TARGET_HAS_movcond_i64 0
|
#define TCG_TARGET_HAS_movcond_i64 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
/* used for function call generation */
|
/* used for function call generation */
|
||||||
#define TCG_REG_CALL_STACK TCG_REG_R15
|
#define TCG_REG_CALL_STACK TCG_REG_R15
|
||||||
#define TCG_TARGET_STACK_ALIGN 8
|
#define TCG_TARGET_STACK_ALIGN 8
|
||||||
|
|
|
@ -125,8 +125,6 @@ typedef enum {
|
||||||
#define TCG_TARGET_HAS_movcond_i64 1
|
#define TCG_TARGET_HAS_movcond_i64 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
#define TCG_AREG0 TCG_REG_I0
|
#define TCG_AREG0 TCG_REG_I0
|
||||||
|
|
||||||
static inline void flush_icache_range(tcg_target_ulong start,
|
static inline void flush_icache_range(tcg_target_ulong start,
|
||||||
|
|
|
@ -62,10 +62,6 @@
|
||||||
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
|
||||||
#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
|
|
||||||
#error GUEST_BASE not supported on this host.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Forward declarations for functions declared in tcg-target.c and used here. */
|
/* Forward declarations for functions declared in tcg-target.c and used here. */
|
||||||
static void tcg_target_init(TCGContext *s);
|
static void tcg_target_init(TCGContext *s);
|
||||||
static void tcg_target_qemu_prologue(TCGContext *s);
|
static void tcg_target_qemu_prologue(TCGContext *s);
|
||||||
|
|
|
@ -102,9 +102,6 @@
|
||||||
#define TCG_TARGET_HAS_movcond_i64 0
|
#define TCG_TARGET_HAS_movcond_i64 0
|
||||||
#endif /* TCG_TARGET_REG_BITS == 64 */
|
#endif /* TCG_TARGET_REG_BITS == 64 */
|
||||||
|
|
||||||
/* Offset to user memory in user mode. */
|
|
||||||
#define TCG_TARGET_HAS_GUEST_BASE
|
|
||||||
|
|
||||||
/* Number of registers available.
|
/* Number of registers available.
|
||||||
For 32 bit hosts, we need more than 8 registers (call arguments). */
|
For 32 bit hosts, we need more than 8 registers (call arguments). */
|
||||||
/* #define TCG_TARGET_NB_REGS 8 */
|
/* #define TCG_TARGET_NB_REGS 8 */
|
||||||
|
|
Loading…
Reference in New Issue