Merge remote-tracking branch 'remotes/riku/linux-user-for-upstream' into staging

* remotes/riku/linux-user-for-upstream:
  linux-user: set minimum kernel version to 2.6.32
  linux-user: correct handling of break exception for MIPS
  linux-user: translate signal number on return from sigtimedwait
  linux-user: Implement sendmmsg syscall
  linux-user: Fix getresuid, getresgid if !USE_UID16
  linux-user: Don't use UID16 on AArch64
  linux-user: AArch64: Implement SA_RESTORER for signal handlers
  linux-user/signal.c: Fix AArch64 big-endian FP register restore

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-03-10 16:22:39 +00:00
commit 3f1506704e
20 changed files with 143 additions and 33 deletions

View File

@ -39,6 +39,7 @@ struct target_pt_regs {
};
#define UNAME_MACHINE "alpha"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#undef TARGET_EDEADLK
#define TARGET_EDEADLK 11

View File

@ -40,5 +40,6 @@ struct target_pt_regs {
#else
#define UNAME_MACHINE "armv5tel"
#endif
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS

View File

@ -1,8 +1,8 @@
#ifndef CRIS_SYSCALL_H
#define CRIS_SYSCALL_H 1
#define UNAME_MACHINE "cris"
#define UNAME_MINIMUM_RELEASE "2.6.32"
/* pt_regs not only specifices the format in the user-struct during
* ptrace but is also the frame format used in the kernel prologue/epilogues

View File

@ -144,5 +144,6 @@ struct target_vm86plus_struct {
};
#define UNAME_MACHINE "i686"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS

View File

@ -15,7 +15,7 @@ struct target_pt_regs {
uint16_t __fill;
};
#define UNAME_MACHINE "m68k"
#define UNAME_MINIMUM_RELEASE "2.6.32"
void do_m68k_simcall(CPUM68KState *, int);

View File

@ -2400,6 +2400,10 @@ static int do_break(CPUMIPSState *env, target_siginfo_t *info,
ret = 0;
break;
default:
info->si_signo = TARGET_SIGTRAP;
info->si_errno = 0;
queue_signal(env, info->si_signo, &*info);
ret = 0;
break;
}

View File

@ -1,8 +1,8 @@
#ifndef MICROBLAZE_SYSCALLS_H
#define MICROBLAZE_SYSCALLS_H 1
#define UNAME_MACHINE "microblaze"
#define UNAME_MINIMUM_RELEASE "2.6.32"
/* We use microblaze_reg_t to keep things similar to the kernel sources. */
typedef uint32_t microblaze_reg_t;

View File

@ -225,5 +225,6 @@ struct target_pt_regs {
#define TARGET_QEMU_ESIGRETURN 255
#define UNAME_MACHINE "mips"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS

View File

@ -222,5 +222,6 @@ struct target_pt_regs {
#define TARGET_QEMU_ESIGRETURN 255
#define UNAME_MACHINE "mips64"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS

View File

@ -22,3 +22,4 @@ struct target_pt_regs {
};
#define UNAME_MACHINE "openrisc"
#define UNAME_MINIMUM_RELEASE "2.6.32"

View File

@ -62,5 +62,6 @@ struct target_revectored_struct {
#else
#define UNAME_MACHINE "ppc"
#endif
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS

View File

@ -21,5 +21,6 @@ struct target_pt_regs {
};
#define UNAME_MACHINE "s390x"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS2

View File

@ -10,3 +10,4 @@ struct target_pt_regs {
};
#define UNAME_MACHINE "sh4"
#define UNAME_MINIMUM_RELEASE "2.6.32"

View File

@ -1233,8 +1233,14 @@ static int target_restore_sigframe(CPUARMState *env,
return 1;
}
for (i = 0; i < 32 * 2; i++) {
__get_user(env->vfp.regs[i], &aux->fpsimd.vregs[i]);
for (i = 0; i < 32; i++) {
#ifdef TARGET_WORDS_BIGENDIAN
__get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
__get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
#else
__get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
__get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
#endif
}
__get_user(fpsr, &aux->fpsimd.fpsr);
vfp_set_fpsr(env, fpsr);
@ -1267,7 +1273,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
CPUARMState *env)
{
struct target_rt_sigframe *frame;
abi_ulong frame_addr;
abi_ulong frame_addr, return_addr;
frame_addr = get_sigframe(ka, env);
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
@ -1284,15 +1290,19 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
__put_user(target_sigaltstack_used.ss_size,
&frame->uc.tuc_stack.ss_size);
target_setup_sigframe(frame, env, set);
/* mov x8,#__NR_rt_sigreturn; svc #0 */
__put_user(0xd2801168, &frame->tramp[0]);
__put_user(0xd4000001, &frame->tramp[1]);
if (ka->sa_flags & TARGET_SA_RESTORER) {
return_addr = ka->sa_restorer;
} else {
/* mov x8,#__NR_rt_sigreturn; svc #0 */
__put_user(0xd2801168, &frame->tramp[0]);
__put_user(0xd4000001, &frame->tramp[1]);
return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp);
}
env->xregs[0] = usig;
env->xregs[31] = frame_addr;
env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp);
env->pc = ka->_sa_handler;
env->xregs[30] = env->xregs[31] +
offsetof(struct target_rt_sigframe, tramp);
env->xregs[30] = return_addr;
if (info) {
if (copy_siginfo_to_user(&frame->info, info)) {
goto give_sigsegv;

View File

@ -7,6 +7,7 @@ struct target_pt_regs {
};
#define UNAME_MACHINE "sun4"
#define UNAME_MINIMUM_RELEASE "2.6.32"
/* SPARC kernels don't define this in their Kconfig, but they have the
* same ABI as if they did, implemented by sparc-specific code which fishes

View File

@ -8,6 +8,7 @@ struct target_pt_regs {
};
#define UNAME_MACHINE "sun4u"
#define UNAME_MINIMUM_RELEASE "2.6.32"
/* SPARC kernels don't define this in their Kconfig, but they have the
* same ABI as if they did, implemented by sparc-specific code which fishes

View File

@ -1904,23 +1904,16 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
return get_errno(connect(sockfd, addr, addrlen));
}
/* do_sendrecvmsg() Must return target values and target errnos. */
static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
int flags, int send)
/* do_sendrecvmsg_locked() Must return target values and target errnos. */
static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
int flags, int send)
{
abi_long ret, len;
struct target_msghdr *msgp;
struct msghdr msg;
int count;
struct iovec *vec;
abi_ulong target_vec;
/* FIXME */
if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
msgp,
target_msg,
send ? 1 : 0))
return -TARGET_EFAULT;
if (msgp->msg_name) {
msg.msg_namelen = tswap32(msgp->msg_namelen);
msg.msg_name = alloca(msg.msg_namelen);
@ -1975,10 +1968,75 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
out:
unlock_iovec(vec, target_vec, count, !send);
out2:
return ret;
}
static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
int flags, int send)
{
abi_long ret;
struct target_msghdr *msgp;
if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
msgp,
target_msg,
send ? 1 : 0)) {
return -TARGET_EFAULT;
}
ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
return ret;
}
#ifdef TARGET_NR_sendmmsg
/* We don't rely on the C library to have sendmmsg/recvmmsg support,
* so it might not have this *mmsg-specific flag either.
*/
#ifndef MSG_WAITFORONE
#define MSG_WAITFORONE 0x10000
#endif
static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
unsigned int vlen, unsigned int flags,
int send)
{
struct target_mmsghdr *mmsgp;
abi_long ret = 0;
int i;
if (vlen > UIO_MAXIOV) {
vlen = UIO_MAXIOV;
}
mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
if (!mmsgp) {
return -TARGET_EFAULT;
}
for (i = 0; i < vlen; i++) {
ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
if (is_error(ret)) {
break;
}
mmsgp[i].msg_len = tswap32(ret);
/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
if (flags & MSG_WAITFORONE) {
flags |= MSG_DONTWAIT;
}
}
unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
/* Return number of datagrams sent if we sent any at all;
* otherwise return the error.
*/
if (i) {
return i;
}
return ret;
}
#endif
/* If we don't have a system accept4() then just call accept.
* The callsites to do_accept4() will ensure that they don't
* pass a non-zero flags argument in this config.
@ -4528,6 +4586,9 @@ static inline int tswapid(int id)
{
return tswap16(id);
}
#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
#else /* !USE_UID16 */
static inline int high2lowuid(int uid)
{
@ -4549,6 +4610,9 @@ static inline int tswapid(int id)
{
return tswap32(id);
}
#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
#endif /* USE_UID16 */
void syscall_init(void)
@ -6121,11 +6185,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
puts = NULL;
}
ret = get_errno(sigtimedwait(&set, &uinfo, puts));
if (!is_error(ret) && arg2) {
if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
goto efault;
host_to_target_siginfo(p, &uinfo);
unlock_user(p, arg2, sizeof(target_siginfo_t));
if (!is_error(ret)) {
if (arg2) {
p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
0);
if (!p) {
goto efault;
}
host_to_target_siginfo(p, &uinfo);
unlock_user(p, arg2, sizeof(target_siginfo_t));
}
ret = host_to_target_signal(ret);
}
}
break;
@ -6710,6 +6780,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
break;
#endif
#ifdef TARGET_NR_sendmmsg
case TARGET_NR_sendmmsg:
ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
break;
case TARGET_NR_recvmmsg:
ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
break;
#endif
#ifdef TARGET_NR_sendto
case TARGET_NR_sendto:
ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
@ -7805,9 +7883,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
uid_t ruid, euid, suid;
ret = get_errno(getresuid(&ruid, &euid, &suid));
if (!is_error(ret)) {
if (put_user_u16(high2lowuid(ruid), arg1)
|| put_user_u16(high2lowuid(euid), arg2)
|| put_user_u16(high2lowuid(suid), arg3))
if (put_user_id(high2lowuid(ruid), arg1)
|| put_user_id(high2lowuid(euid), arg2)
|| put_user_id(high2lowuid(suid), arg3))
goto efault;
}
}
@ -7826,9 +7904,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
gid_t rgid, egid, sgid;
ret = get_errno(getresgid(&rgid, &egid, &sgid));
if (!is_error(ret)) {
if (put_user_u16(high2lowgid(rgid), arg1)
|| put_user_u16(high2lowgid(egid), arg2)
|| put_user_u16(high2lowgid(sgid), arg3))
if (put_user_id(high2lowgid(rgid), arg1)
|| put_user_id(high2lowgid(egid), arg2)
|| put_user_id(high2lowgid(sgid), arg3))
goto efault;
}
}

View File

@ -53,7 +53,8 @@
#define TARGET_IOC_NRBITS 8
#define TARGET_IOC_TYPEBITS 8
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
#if defined(TARGET_I386) || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|| defined(TARGET_SPARC) \
|| defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
/* 16 bit uid wrappers emulation */
#define USE_UID16
@ -239,6 +240,10 @@ __target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cms
return __cmsg;
}
struct target_mmsghdr {
struct target_msghdr msg_hdr; /* Message header */
unsigned int msg_len; /* Number of bytes transmitted */
};
struct target_rusage {
struct target_timeval ru_utime; /* user time used */

View File

@ -51,5 +51,6 @@ struct target_pt_regs {
#define UC32_SYSCALL_NR_set_tls (UC32_SYSCALL_ARCH_BASE + 5)
#define UNAME_MACHINE "UniCore-II"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#endif /* __UC32_SYSCALL_H__ */

View File

@ -91,6 +91,7 @@ struct target_msqid64_ds {
};
#define UNAME_MACHINE "x86_64"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_ARCH_SET_GS 0x1001
#define TARGET_ARCH_SET_FS 0x1002