mirror of https://gitee.com/openkylin/qemu.git
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:
commit
3f1506704e
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -144,5 +144,6 @@ struct target_vm86plus_struct {
|
|||
};
|
||||
|
||||
#define UNAME_MACHINE "i686"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -22,3 +22,4 @@ struct target_pt_regs {
|
|||
};
|
||||
|
||||
#define UNAME_MACHINE "openrisc"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,5 +21,6 @@ struct target_pt_regs {
|
|||
};
|
||||
|
||||
#define UNAME_MACHINE "s390x"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
#define TARGET_CLONE_BACKWARDS2
|
||||
|
|
|
@ -10,3 +10,4 @@ struct target_pt_regs {
|
|||
};
|
||||
|
||||
#define UNAME_MACHINE "sh4"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue