mirror of https://github.com/xemu-project/xemu.git
linux-user pull request v2 for may 2016
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAV0g0rrRIkN7ePJvAAQh+hA//TZOrmRskN7/PzlGp90pkNVL4Xm6LDNsj fvgzB4ceuA+eRv426ttSpYgZestZjxmb/29c5UJWvH0Otnhrxj0aNKimxAO4FCIV u2u73Mn4cTGZPfoMJesCYihC19LIFIpYFPjXTKz2UJ4Dg/ZLBd6KORDTC7kfXoSx 9wTgaHZkbrUBCwWQ+0SKrbibPJWY4RHUkYCK4dxCCPFRVpGhYFt1vihjZpzDzzNH njjxr/GB8W1OByBI90TWUpx6e0YRqhKluuvr1ObezrK2/nCZhLwOkvgIB1yuew3e AwFz5wUFtx80FV3ThAKDoJadz6tVKPG67OG2w5DmgUrK6gpOTP9n1LcypTK+wti4 /LNb9AhyEqsDD/apFQWNEEdYwCG6qjlaE01zp6ZQPgNUWpN1BSEDmikoHwpUqLaq fXfgJZyOItp6LP3Tajkto2h9iAdXI6eoJHQtMK562J89WZz1Bb4IJxONAkWZq5oV aQCOj0wD/vObUhMU72jLy2cd3kHM/RT5NliMhb+nbR9JY/WXbTeOn41hOhEnkJJJ bjRPCN2O3ULfi3yn3St2ByCngPUG954uqmR2OaOGwEHGx6E/UEkWsduUlRwwY1zK 96pZvsHO8DSIDc5gNmUlvQlBc62v8b+KUcwsbloBCl2YGt9mbZNM9zi0Gg4R97MJ jHkpVjF4L4I= =/Nln -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20160527' into staging linux-user pull request v2 for may 2016 # gpg: Signature made Fri 27 May 2016 12:51:10 BST using RSA key ID DE3C9BC0 # gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>" # gpg: aka "Riku Voipio <riku.voipio@linaro.org>" * remotes/riku/tags/pull-linux-user-20160527: (38 commits) linux-user,target-ppc: fix use of MSR_LE linux-user/signal.c: Use s390 target space address instead of host space linux-user/signal.c: Use target address instead of host address for microblaze restorer linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame linux-user: arm: Remove ARM_cpsr and similar #defines linux-user: Use direct syscalls for setuid(), etc linux-user: x86_64: Don't use 16-bit UIDs linux-user: Use g_try_malloc() in do_msgrcv() linux-user: Handle msgrcv error case correctly linux-user: Handle negative values in timespec conversion linux-user: Use safe_syscall for futex syscall linux-user: Use safe_syscall for pselect, select syscalls linux-user: Use safe_syscall for execve syscall linux-user: Use safe_syscall for wait system calls linux-user: Use safe_syscall for open and openat system calls linux-user: Use safe_syscall for read and write system calls linux-user: Provide safe_syscall for fixing races between signals and syscalls linux-user: Add debug code to exercise restarting system calls linux-user: Support for restarting system calls for Microblaze targets linux-user: Set r14 on exit from microblaze syscall ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d6550e9ed2
|
@ -108,7 +108,12 @@ obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/dpd/decimal128.o
|
|||
|
||||
ifdef CONFIG_LINUX_USER
|
||||
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
|
||||
# Note that we only add linux-user/host/$ARCH if it exists, and
|
||||
# that it must come before linux-user/host/generic in the search path.
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \
|
||||
$(patsubst %,-I%,$(wildcard $(SRC_PATH)/linux-user/host/$(ARCH))) \
|
||||
-I$(SRC_PATH)/linux-user/host/generic \
|
||||
-I$(SRC_PATH)/linux-user
|
||||
|
||||
obj-y += linux-user/
|
||||
obj-y += gdbstub.o thunk.o user-exec.o
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
obj-y = main.o syscall.o strace.o mmap.o signal.o \
|
||||
elfload.o linuxload.o uaccess.o uname.o
|
||||
elfload.o linuxload.o uaccess.o uname.o \
|
||||
safe-syscall.o
|
||||
|
||||
obj-$(TARGET_HAS_BFLT) += flatload.o
|
||||
obj-$(TARGET_I386) += vm86.o
|
||||
|
|
|
@ -27,6 +27,7 @@ static inline abi_ulong get_sp_from_cpustate(CPUAlphaState *state)
|
|||
return state->ir[IR_SP];
|
||||
}
|
||||
|
||||
|
||||
/* From <asm/gentrap.h>. */
|
||||
#define TARGET_GEN_INTOVF -1 /* integer overflow */
|
||||
#define TARGET_GEN_INTDIV -2 /* integer division by zero */
|
||||
|
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
|
|||
return state->regs[13];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -4,29 +4,11 @@
|
|||
/* this struct defines the way the registers are stored on the
|
||||
stack during a system call. */
|
||||
|
||||
/* uregs[0..15] are r0 to r15; uregs[16] is CPSR; uregs[17] is ORIG_r0 */
|
||||
struct target_pt_regs {
|
||||
abi_long uregs[18];
|
||||
};
|
||||
|
||||
#define ARM_cpsr uregs[16]
|
||||
#define ARM_pc uregs[15]
|
||||
#define ARM_lr uregs[14]
|
||||
#define ARM_sp uregs[13]
|
||||
#define ARM_ip uregs[12]
|
||||
#define ARM_fp uregs[11]
|
||||
#define ARM_r10 uregs[10]
|
||||
#define ARM_r9 uregs[9]
|
||||
#define ARM_r8 uregs[8]
|
||||
#define ARM_r7 uregs[7]
|
||||
#define ARM_r6 uregs[6]
|
||||
#define ARM_r5 uregs[5]
|
||||
#define ARM_r4 uregs[4]
|
||||
#define ARM_r3 uregs[3]
|
||||
#define ARM_r2 uregs[2]
|
||||
#define ARM_r1 uregs[1]
|
||||
#define ARM_r0 uregs[0]
|
||||
#define ARM_ORIG_r0 uregs[17]
|
||||
|
||||
#define ARM_SYSCALL_BASE 0x900000
|
||||
#define ARM_THUMB_SYSCALL 0
|
||||
|
||||
|
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUCRISState *state)
|
|||
return state->regs[14];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -274,19 +274,20 @@ static inline void init_thread(struct target_pt_regs *regs,
|
|||
abi_long stack = infop->start_stack;
|
||||
memset(regs, 0, sizeof(*regs));
|
||||
|
||||
regs->ARM_cpsr = 0x10;
|
||||
if (infop->entry & 1)
|
||||
regs->ARM_cpsr |= CPSR_T;
|
||||
regs->ARM_pc = infop->entry & 0xfffffffe;
|
||||
regs->ARM_sp = infop->start_stack;
|
||||
regs->uregs[16] = ARM_CPU_MODE_USR;
|
||||
if (infop->entry & 1) {
|
||||
regs->uregs[16] |= CPSR_T;
|
||||
}
|
||||
regs->uregs[15] = infop->entry & 0xfffffffe;
|
||||
regs->uregs[13] = infop->start_stack;
|
||||
/* FIXME - what to for failure of get_user()? */
|
||||
get_user_ual(regs->ARM_r2, stack + 8); /* envp */
|
||||
get_user_ual(regs->ARM_r1, stack + 4); /* envp */
|
||||
get_user_ual(regs->uregs[2], stack + 8); /* envp */
|
||||
get_user_ual(regs->uregs[1], stack + 4); /* envp */
|
||||
/* XXX: it seems that r0 is zeroed after ! */
|
||||
regs->ARM_r0 = 0;
|
||||
regs->uregs[0] = 0;
|
||||
/* For uClinux PIC binaries. */
|
||||
/* XXX: Linux does this only on ARM with no MMU (do we care ?) */
|
||||
regs->ARM_r10 = infop->start_data;
|
||||
regs->uregs[10] = infop->start_data;
|
||||
}
|
||||
|
||||
#define ELF_NREG 18
|
||||
|
|
|
@ -139,3 +139,20 @@
|
|||
/* for robust mutexes */
|
||||
#define TARGET_EOWNERDEAD 130 /* Owner died */
|
||||
#define TARGET_ENOTRECOVERABLE 131 /* State not recoverable */
|
||||
|
||||
/* QEMU internal, not visible to the guest. This is returned when a
|
||||
* system call should be restarted, to tell the main loop that it
|
||||
* should wind the guest PC backwards so it will re-execute the syscall
|
||||
* after handling any pending signals. They match with the ones the guest
|
||||
* kernel uses for the same purpose.
|
||||
*/
|
||||
#define TARGET_ERESTARTSYS 512 /* Restart system call (if SA_RESTART) */
|
||||
|
||||
/* QEMU internal, not visible to the guest. This is returned by the
|
||||
* do_sigreturn() code after a successful sigreturn syscall, to indicate
|
||||
* that it has correctly set the guest registers and so the main loop
|
||||
* should not touch them. We use the value the guest would use for
|
||||
* ERESTART_NOINTR (which is kernel internal) to guarantee that we won't
|
||||
* clash with a valid guest errno now or in the future.
|
||||
*/
|
||||
#define TARGET_QEMU_ESIGRETURN 513 /* Return from signal */
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* hostdep.h : fallback generic version of header for things
|
||||
* which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_HOSTDEP_H
|
||||
#define QEMU_HOSTDEP_H
|
||||
|
||||
/* This is the fallback header which is only used if the host
|
||||
* architecture doesn't provide one in linux-user/host/$ARCH.
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_HOSTDEP_H
|
||||
#define QEMU_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/* These are defined by the safe-syscall.inc.S file */
|
||||
extern char safe_syscall_start[];
|
||||
extern char safe_syscall_end[];
|
||||
|
||||
/* Adjust the signal context to rewind out of safe-syscall if we're in it */
|
||||
static inline void rewind_if_in_safe_syscall(void *puc)
|
||||
{
|
||||
struct ucontext *uc = puc;
|
||||
greg_t *pcreg = &uc->uc_mcontext.gregs[REG_RIP];
|
||||
|
||||
if (*pcreg > (uintptr_t)safe_syscall_start
|
||||
&& *pcreg < (uintptr_t)safe_syscall_end) {
|
||||
*pcreg = (uintptr_t)safe_syscall_start;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by linux-user/safe-syscall.S
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, @function
|
||||
|
||||
/* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
* We return a long which is the syscall's return value, which
|
||||
* may be negative-errno on failure. Conversion to the
|
||||
* -1-and-errno-set convention is done by the calling wrapper.
|
||||
*/
|
||||
safe_syscall_base:
|
||||
/* This saves a frame pointer and aligns the stack for the syscall.
|
||||
* (It's unclear if the syscall ABI has the same stack alignment
|
||||
* requirements as the userspace function call ABI, but better safe than
|
||||
* sorry. Appendix A2 of http://www.x86-64.org/documentation/abi.pdf
|
||||
* does not list any ABI differences regarding stack alignment.)
|
||||
*/
|
||||
push %rbp
|
||||
|
||||
/* The syscall calling convention isn't the same as the
|
||||
* C one:
|
||||
* we enter with rdi == *signal_pending
|
||||
* rsi == syscall number
|
||||
* rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
|
||||
* and return the result in rax
|
||||
* and the syscall instruction needs
|
||||
* rax == syscall number
|
||||
* rdi, rsi, rdx, r10, r8, r9 == syscall arguments
|
||||
* and returns the result in rax
|
||||
* Shuffle everything around appropriately.
|
||||
* Note that syscall will trash rcx and r11.
|
||||
*/
|
||||
mov %rsi, %rax /* syscall number */
|
||||
mov %rdi, %rbp /* signal_pending pointer */
|
||||
/* and the syscall arguments */
|
||||
mov %rdx, %rdi
|
||||
mov %rcx, %rsi
|
||||
mov %r8, %rdx
|
||||
mov %r9, %r10
|
||||
mov 16(%rsp), %r8
|
||||
mov 24(%rsp), %r9
|
||||
|
||||
/* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* if signal_pending is non-zero, don't do the call */
|
||||
testl $1, (%rbp)
|
||||
jnz return_ERESTARTSYS
|
||||
syscall
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
return_ERESTARTSYS:
|
||||
/* code path when we didn't execute the syscall */
|
||||
mov $-TARGET_ERESTARTSYS, %rax
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUM68KState *state)
|
|||
return state->aregs[7];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -285,6 +285,7 @@ void cpu_loop(CPUX86State *env)
|
|||
CPUState *cs = CPU(x86_env_get_cpu(env));
|
||||
int trapnr;
|
||||
abi_ulong pc;
|
||||
abi_ulong ret;
|
||||
target_siginfo_t info;
|
||||
|
||||
for(;;) {
|
||||
|
@ -294,28 +295,38 @@ void cpu_loop(CPUX86State *env)
|
|||
switch(trapnr) {
|
||||
case 0x80:
|
||||
/* linux syscall from int $0x80 */
|
||||
env->regs[R_EAX] = do_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EBX],
|
||||
env->regs[R_ECX],
|
||||
env->regs[R_EDX],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_EBP],
|
||||
0, 0);
|
||||
ret = do_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EBX],
|
||||
env->regs[R_ECX],
|
||||
env->regs[R_EDX],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_EBP],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->eip -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[R_EAX] = ret;
|
||||
}
|
||||
break;
|
||||
#ifndef TARGET_ABI32
|
||||
case EXCP_SYSCALL:
|
||||
/* linux syscall from syscall instruction */
|
||||
env->regs[R_EAX] = do_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDX],
|
||||
env->regs[10],
|
||||
env->regs[8],
|
||||
env->regs[9],
|
||||
0, 0);
|
||||
ret = do_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_ESI],
|
||||
env->regs[R_EDX],
|
||||
env->regs[10],
|
||||
env->regs[8],
|
||||
env->regs[9],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->eip -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[R_EAX] = ret;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case EXCP0B_NOSEG:
|
||||
|
@ -716,6 +727,7 @@ void cpu_loop(CPUARMState *env)
|
|||
unsigned int n, insn;
|
||||
target_siginfo_t info;
|
||||
uint32_t addr;
|
||||
abi_ulong ret;
|
||||
|
||||
for(;;) {
|
||||
cpu_exec_start(cs);
|
||||
|
@ -854,15 +866,20 @@ void cpu_loop(CPUARMState *env)
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
env->regs[0] = do_syscall(env,
|
||||
n,
|
||||
env->regs[0],
|
||||
env->regs[1],
|
||||
env->regs[2],
|
||||
env->regs[3],
|
||||
env->regs[4],
|
||||
env->regs[5],
|
||||
0, 0);
|
||||
ret = do_syscall(env,
|
||||
n,
|
||||
env->regs[0],
|
||||
env->regs[1],
|
||||
env->regs[2],
|
||||
env->regs[3],
|
||||
env->regs[4],
|
||||
env->regs[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->regs[15] -= env->thumb ? 2 : 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[0] = ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
goto error;
|
||||
|
@ -1045,6 +1062,7 @@ void cpu_loop(CPUARMState *env)
|
|||
{
|
||||
CPUState *cs = CPU(arm_env_get_cpu(env));
|
||||
int trapnr, sig;
|
||||
abi_long ret;
|
||||
target_siginfo_t info;
|
||||
|
||||
for (;;) {
|
||||
|
@ -1054,15 +1072,20 @@ void cpu_loop(CPUARMState *env)
|
|||
|
||||
switch (trapnr) {
|
||||
case EXCP_SWI:
|
||||
env->xregs[0] = do_syscall(env,
|
||||
env->xregs[8],
|
||||
env->xregs[0],
|
||||
env->xregs[1],
|
||||
env->xregs[2],
|
||||
env->xregs[3],
|
||||
env->xregs[4],
|
||||
env->xregs[5],
|
||||
0, 0);
|
||||
ret = do_syscall(env,
|
||||
env->xregs[8],
|
||||
env->xregs[0],
|
||||
env->xregs[1],
|
||||
env->xregs[2],
|
||||
env->xregs[3],
|
||||
env->xregs[4],
|
||||
env->xregs[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->xregs[0] = ret;
|
||||
}
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
|
@ -1148,7 +1171,7 @@ void cpu_loop(CPUUniCore32State *env)
|
|||
cpu_set_tls(env, env->regs[0]);
|
||||
env->regs[0] = 0;
|
||||
} else {
|
||||
env->regs[0] = do_syscall(env,
|
||||
abi_long ret = do_syscall(env,
|
||||
n,
|
||||
env->regs[0],
|
||||
env->regs[1],
|
||||
|
@ -1157,6 +1180,11 @@ void cpu_loop(CPUUniCore32State *env)
|
|||
env->regs[4],
|
||||
env->regs[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->regs[31] -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[0] = ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
goto error;
|
||||
|
@ -1353,6 +1381,9 @@ void cpu_loop (CPUSPARCState *env)
|
|||
env->regwptr[2], env->regwptr[3],
|
||||
env->regwptr[4], env->regwptr[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) {
|
||||
break;
|
||||
}
|
||||
if ((abi_ulong)ret >= (abi_ulong)(-515)) {
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
env->xcc |= PSR_CARRY;
|
||||
|
@ -1964,6 +1995,10 @@ void cpu_loop(CPUPPCState *env)
|
|||
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
|
||||
env->gpr[5], env->gpr[6], env->gpr[7],
|
||||
env->gpr[8], 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->nip -= 4;
|
||||
break;
|
||||
}
|
||||
if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
|
||||
/* Returning from a successful sigreturn syscall.
|
||||
Avoid corrupting register state. */
|
||||
|
@ -2505,6 +2540,10 @@ done_syscall:
|
|||
env->active_tc.gpr[8], env->active_tc.gpr[9],
|
||||
env->active_tc.gpr[10], env->active_tc.gpr[11]);
|
||||
# endif /* O32 */
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->active_tc.PC -= 4;
|
||||
break;
|
||||
}
|
||||
if (ret == -TARGET_QEMU_ESIGRETURN) {
|
||||
/* Returning from a successful sigreturn syscall.
|
||||
Avoid clobbering register state. */
|
||||
|
@ -2685,6 +2724,7 @@ void cpu_loop(CPUOpenRISCState *env)
|
|||
{
|
||||
CPUState *cs = CPU(openrisc_env_get_cpu(env));
|
||||
int trapnr, gdbsig;
|
||||
abi_long ret;
|
||||
|
||||
for (;;) {
|
||||
cpu_exec_start(cs);
|
||||
|
@ -2730,14 +2770,19 @@ void cpu_loop(CPUOpenRISCState *env)
|
|||
break;
|
||||
case EXCP_SYSCALL:
|
||||
env->pc += 4; /* 0xc00; */
|
||||
env->gpr[11] = do_syscall(env,
|
||||
env->gpr[11], /* return value */
|
||||
env->gpr[3], /* r3 - r7 are params */
|
||||
env->gpr[4],
|
||||
env->gpr[5],
|
||||
env->gpr[6],
|
||||
env->gpr[7],
|
||||
env->gpr[8], 0, 0);
|
||||
ret = do_syscall(env,
|
||||
env->gpr[11], /* return value */
|
||||
env->gpr[3], /* r3 - r7 are params */
|
||||
env->gpr[4],
|
||||
env->gpr[5],
|
||||
env->gpr[6],
|
||||
env->gpr[7],
|
||||
env->gpr[8], 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->gpr[11] = ret;
|
||||
}
|
||||
break;
|
||||
case EXCP_FPE:
|
||||
qemu_log_mask(CPU_LOG_INT, "\nFloating point error\n");
|
||||
|
@ -2792,7 +2837,11 @@ void cpu_loop(CPUSH4State *env)
|
|||
env->gregs[0],
|
||||
env->gregs[1],
|
||||
0, 0);
|
||||
env->gregs[0] = ret;
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->gregs[0] = ret;
|
||||
}
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
|
@ -2865,7 +2914,11 @@ void cpu_loop(CPUCRISState *env)
|
|||
env->pregs[7],
|
||||
env->pregs[11],
|
||||
0, 0);
|
||||
env->regs[10] = ret;
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[10] = ret;
|
||||
}
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
{
|
||||
|
@ -2929,7 +2982,19 @@ void cpu_loop(CPUMBState *env)
|
|||
env->regs[9],
|
||||
env->regs[10],
|
||||
0, 0);
|
||||
env->regs[3] = ret;
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
/* Wind back to before the syscall. */
|
||||
env->sregs[SR_PC] -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[3] = ret;
|
||||
}
|
||||
/* All syscall exits result in guest r14 being equal to the
|
||||
* PC we return to, because the kernel syscall exit "rtbd" does
|
||||
* this. (This is true even for sigreturn(); note that r14 is
|
||||
* not a userspace-usable register, as the kernel may clobber it
|
||||
* at any point.)
|
||||
*/
|
||||
env->regs[14] = env->sregs[SR_PC];
|
||||
break;
|
||||
case EXCP_HW_EXCP:
|
||||
env->regs[17] = env->sregs[SR_PC] + 4;
|
||||
|
@ -3037,18 +3102,24 @@ void cpu_loop(CPUM68KState *env)
|
|||
break;
|
||||
case EXCP_TRAP0:
|
||||
{
|
||||
abi_long ret;
|
||||
ts->sim_syscalls = 0;
|
||||
n = env->dregs[0];
|
||||
env->pc += 2;
|
||||
env->dregs[0] = do_syscall(env,
|
||||
n,
|
||||
env->dregs[1],
|
||||
env->dregs[2],
|
||||
env->dregs[3],
|
||||
env->dregs[4],
|
||||
env->dregs[5],
|
||||
env->aregs[0],
|
||||
0, 0);
|
||||
ret = do_syscall(env,
|
||||
n,
|
||||
env->dregs[1],
|
||||
env->dregs[2],
|
||||
env->dregs[3],
|
||||
env->dregs[4],
|
||||
env->dregs[5],
|
||||
env->aregs[0],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->dregs[0] = ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
|
@ -3229,8 +3300,11 @@ void cpu_loop(CPUAlphaState *env)
|
|||
env->ir[IR_A2], env->ir[IR_A3],
|
||||
env->ir[IR_A4], env->ir[IR_A5],
|
||||
0, 0);
|
||||
if (trapnr == TARGET_NR_sigreturn
|
||||
|| trapnr == TARGET_NR_rt_sigreturn) {
|
||||
if (sysret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
break;
|
||||
}
|
||||
if (sysret == -TARGET_QEMU_ESIGRETURN) {
|
||||
break;
|
||||
}
|
||||
/* Syscall writes 0 to V0 to bypass error check, similar
|
||||
|
@ -3327,6 +3401,7 @@ void cpu_loop(CPUS390XState *env)
|
|||
int trapnr, n, sig;
|
||||
target_siginfo_t info;
|
||||
target_ulong addr;
|
||||
abi_long ret;
|
||||
|
||||
while (1) {
|
||||
cpu_exec_start(cs);
|
||||
|
@ -3344,9 +3419,14 @@ void cpu_loop(CPUS390XState *env)
|
|||
n = env->regs[1];
|
||||
}
|
||||
env->psw.addr += env->int_svc_ilen;
|
||||
env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7], 0, 0);
|
||||
ret = do_syscall(env, n, env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7], 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->psw.addr -= env->int_svc_ilen;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[2] = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCP_DEBUG:
|
||||
|
@ -3638,15 +3718,20 @@ void cpu_loop(CPUTLGState *env)
|
|||
cpu_exec_end(cs);
|
||||
switch (trapnr) {
|
||||
case TILEGX_EXCP_SYSCALL:
|
||||
env->regs[TILEGX_R_RE] = do_syscall(env, env->regs[TILEGX_R_NR],
|
||||
env->regs[0], env->regs[1],
|
||||
env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7]);
|
||||
env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(env->regs[TILEGX_R_RE])
|
||||
? - env->regs[TILEGX_R_RE]
|
||||
: 0;
|
||||
{
|
||||
abi_ulong ret = do_syscall(env, env->regs[TILEGX_R_NR],
|
||||
env->regs[0], env->regs[1],
|
||||
env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7]);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->pc -= 8;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->regs[TILEGX_R_RE] = ret;
|
||||
env->regs[TILEGX_R_ERR] = TILEGX_IS_ERRNO(ret) ? -ret : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TILEGX_EXCP_OPCODE_EXCH:
|
||||
do_exch(env, true, false);
|
||||
break;
|
||||
|
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUMBState *state)
|
|||
return state->regs[14];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
|
|||
return state->active_tc.gpr[29];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -222,10 +222,6 @@ struct target_pt_regs {
|
|||
#define TARGET_ENOTRECOVERABLE 166 /* State not recoverable */
|
||||
|
||||
|
||||
|
||||
/* Nasty hack: define a fake errno value for use by sigreturn. */
|
||||
#define TARGET_QEMU_ESIGRETURN 255
|
||||
|
||||
#define UNAME_MACHINE "mips"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
|
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
|
|||
return state->active_tc.gpr[29];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -219,10 +219,6 @@ struct target_pt_regs {
|
|||
#define TARGET_ENOTRECOVERABLE 166 /* State not recoverable */
|
||||
|
||||
|
||||
|
||||
/* Nasty hack: define a fake errno value for use by sigreturn. */
|
||||
#define TARGET_QEMU_ESIGRETURN 255
|
||||
|
||||
#define UNAME_MACHINE "mips64"
|
||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||
|
||||
|
|
|
@ -23,4 +23,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state)
|
|||
return state->gpr[1];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUPPCState *state)
|
|||
return state->gpr[1];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -53,8 +53,6 @@ struct target_revectored_struct {
|
|||
abi_ulong __map[8]; /* 256 bits */
|
||||
};
|
||||
|
||||
/* Nasty hack: define a fake errno value for use by sigreturn. */
|
||||
#define TARGET_QEMU_ESIGRETURN 255
|
||||
|
||||
/*
|
||||
* flags masks
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef QEMU_H
|
||||
#define QEMU_H
|
||||
|
||||
|
||||
#include "hostdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
|
@ -205,6 +205,131 @@ unsigned long init_guest_space(unsigned long host_start,
|
|||
|
||||
#include "qemu/log.h"
|
||||
|
||||
/* safe_syscall.S */
|
||||
|
||||
/**
|
||||
* safe_syscall:
|
||||
* @int number: number of system call to make
|
||||
* ...: arguments to the system call
|
||||
*
|
||||
* Call a system call if guest signal not pending.
|
||||
* This has the same API as the libc syscall() function, except that it
|
||||
* may return -1 with errno == TARGET_ERESTARTSYS if a signal was pending.
|
||||
*
|
||||
* Returns: the system call result, or -1 with an error code in errno
|
||||
* (Errnos are host errnos; we rely on TARGET_ERESTARTSYS not clashing
|
||||
* with any of the host errno values.)
|
||||
*/
|
||||
|
||||
/* A guide to using safe_syscall() to handle interactions between guest
|
||||
* syscalls and guest signals:
|
||||
*
|
||||
* Guest syscalls come in two flavours:
|
||||
*
|
||||
* (1) Non-interruptible syscalls
|
||||
*
|
||||
* These are guest syscalls that never get interrupted by signals and
|
||||
* so never return EINTR. They can be implemented straightforwardly in
|
||||
* QEMU: just make sure that if the implementation code has to make any
|
||||
* blocking calls that those calls are retried if they return EINTR.
|
||||
* It's also OK to implement these with safe_syscall, though it will be
|
||||
* a little less efficient if a signal is delivered at the 'wrong' moment.
|
||||
*
|
||||
* (2) Interruptible syscalls
|
||||
*
|
||||
* These are guest syscalls that can be interrupted by signals and
|
||||
* for which we need to either return EINTR or arrange for the guest
|
||||
* syscall to be restarted. This category includes both syscalls which
|
||||
* always restart (and in the kernel return -ERESTARTNOINTR), ones
|
||||
* which only restart if there is no handler (kernel returns -ERESTARTNOHAND
|
||||
* or -ERESTART_RESTARTBLOCK), and the most common kind which restart
|
||||
* if the handler was registered with SA_RESTART (kernel returns
|
||||
* -ERESTARTSYS). System calls which are only interruptible in some
|
||||
* situations (like 'open') also need to be handled this way.
|
||||
*
|
||||
* Here it is important that the host syscall is made
|
||||
* via this safe_syscall() function, and *not* via the host libc.
|
||||
* If the host libc is used then the implementation will appear to work
|
||||
* most of the time, but there will be a race condition where a
|
||||
* signal could arrive just before we make the host syscall inside libc,
|
||||
* and then then guest syscall will not correctly be interrupted.
|
||||
* Instead the implementation of the guest syscall can use the safe_syscall
|
||||
* function but otherwise just return the result or errno in the usual
|
||||
* way; the main loop code will take care of restarting the syscall
|
||||
* if appropriate.
|
||||
*
|
||||
* (If the implementation needs to make multiple host syscalls this is
|
||||
* OK; any which might really block must be via safe_syscall(); for those
|
||||
* which are only technically blocking (ie which we know in practice won't
|
||||
* stay in the host kernel indefinitely) it's OK to use libc if necessary.
|
||||
* You must be able to cope with backing out correctly if some safe_syscall
|
||||
* you make in the implementation returns either -TARGET_ERESTARTSYS or
|
||||
* EINTR though.)
|
||||
*
|
||||
*
|
||||
* How and why the safe_syscall implementation works:
|
||||
*
|
||||
* The basic setup is that we make the host syscall via a known
|
||||
* section of host native assembly. If a signal occurs, our signal
|
||||
* handler checks the interrupted host PC against the addresse of that
|
||||
* known section. If the PC is before or at the address of the syscall
|
||||
* instruction then we change the PC to point at a "return
|
||||
* -TARGET_ERESTARTSYS" code path instead, and then exit the signal handler
|
||||
* (causing the safe_syscall() call to immediately return that value).
|
||||
* Then in the main.c loop if we see this magic return value we adjust
|
||||
* the guest PC to wind it back to before the system call, and invoke
|
||||
* the guest signal handler as usual.
|
||||
*
|
||||
* This winding-back will happen in two cases:
|
||||
* (1) signal came in just before we took the host syscall (a race);
|
||||
* in this case we'll take the guest signal and have another go
|
||||
* at the syscall afterwards, and this is indistinguishable for the
|
||||
* guest from the timing having been different such that the guest
|
||||
* signal really did win the race
|
||||
* (2) signal came in while the host syscall was blocking, and the
|
||||
* host kernel decided the syscall should be restarted;
|
||||
* in this case we want to restart the guest syscall also, and so
|
||||
* rewinding is the right thing. (Note that "restart" semantics mean
|
||||
* "first call the signal handler, then reattempt the syscall".)
|
||||
* The other situation to consider is when a signal came in while the
|
||||
* host syscall was blocking, and the host kernel decided that the syscall
|
||||
* should not be restarted; in this case QEMU's host signal handler will
|
||||
* be invoked with the PC pointing just after the syscall instruction,
|
||||
* with registers indicating an EINTR return; the special code in the
|
||||
* handler will not kick in, and we will return EINTR to the guest as
|
||||
* we should.
|
||||
*
|
||||
* Notice that we can leave the host kernel to make the decision for
|
||||
* us about whether to do a restart of the syscall or not; we do not
|
||||
* need to check SA_RESTART flags in QEMU or distinguish the various
|
||||
* kinds of restartability.
|
||||
*/
|
||||
#ifdef HAVE_SAFE_SYSCALL
|
||||
/* The core part of this function is implemented in assembly */
|
||||
extern long safe_syscall_base(int *pending, long number, ...);
|
||||
|
||||
#define safe_syscall(...) \
|
||||
({ \
|
||||
long ret_; \
|
||||
int *psp_ = &((TaskState *)thread_cpu->opaque)->signal_pending; \
|
||||
ret_ = safe_syscall_base(psp_, __VA_ARGS__); \
|
||||
if (is_error(ret_)) { \
|
||||
errno = -ret_; \
|
||||
ret_ = -1; \
|
||||
} \
|
||||
ret_; \
|
||||
})
|
||||
|
||||
#else
|
||||
|
||||
/* Fallback for architectures which don't yet provide a safe-syscall assembly
|
||||
* fragment; note that this is racy!
|
||||
* This should go away when all host architectures have been updated.
|
||||
*/
|
||||
#define safe_syscall syscall
|
||||
|
||||
#endif
|
||||
|
||||
/* syscall.c */
|
||||
int host_to_target_waitstatus(int status);
|
||||
|
||||
|
|
|
@ -23,4 +23,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUS390XState *state)
|
|||
return state->regs[15];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* safe-syscall.S : include the host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
*
|
||||
* Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "hostdep.h"
|
||||
#include "errno_defs.h"
|
||||
|
||||
/* We have the correct host directory on our include path
|
||||
* so that this will pull in the right fragment for the architecture.
|
||||
*/
|
||||
#ifdef HAVE_SAFE_SYSCALL
|
||||
#include "safe-syscall.inc.S"
|
||||
#endif
|
||||
|
||||
/* We must specifically say that we're happy for the stack to not be
|
||||
* executable, otherwise the toolchain will default to assuming our
|
||||
* assembly needs an executable stack and the whole QEMU binary will
|
||||
* needlessly end up with one. This should be the last thing in this file.
|
||||
*/
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack, "", %progbits
|
||||
#endif
|
|
@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUSH4State *state)
|
|||
return state->gregs[15];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
1597
linux-user/signal.c
1597
linux-user/signal.c
File diff suppressed because it is too large
Load Diff
|
@ -33,4 +33,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
|
|||
return state->regwptr[UREG_FP];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -33,4 +33,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
|
|||
return state->regwptr[UREG_FP];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
|
@ -110,6 +110,10 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
|||
CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
|
||||
|
||||
//#define DEBUG
|
||||
/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
|
||||
* once. This exercises the codepaths for restart.
|
||||
*/
|
||||
//#define DEBUG_ERESTARTSYS
|
||||
|
||||
//#include <linux/msdos_fs.h>
|
||||
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
|
||||
|
@ -355,18 +359,6 @@ static int sys_getcwd1(char *buf, size_t size)
|
|||
return strlen(buf)+1;
|
||||
}
|
||||
|
||||
static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
/*
|
||||
* open(2) has extra parameter 'mode' when called with
|
||||
* flag O_CREAT.
|
||||
*/
|
||||
if ((flags & O_CREAT) != 0) {
|
||||
return (openat(dirfd, pathname, flags, mode));
|
||||
}
|
||||
return (openat(dirfd, pathname, flags));
|
||||
}
|
||||
|
||||
#ifdef TARGET_NR_utimensat
|
||||
#ifdef CONFIG_UTIMENSAT
|
||||
static int sys_utimensat(int dirfd, const char *pathname,
|
||||
|
@ -438,15 +430,6 @@ _syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
|
|||
size_t, sigsetsize)
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_pselect6)
|
||||
#ifndef __NR_pselect6
|
||||
# define __NR_pselect6 -1
|
||||
#endif
|
||||
#define __NR_sys_pselect6 __NR_pselect6
|
||||
_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
|
||||
fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_prlimit64)
|
||||
#ifndef __NR_prlimit64
|
||||
# define __NR_prlimit64 -1
|
||||
|
@ -619,15 +602,19 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
|
|||
|
||||
static inline int host_to_target_errno(int err)
|
||||
{
|
||||
if(host_to_target_errno_table[err])
|
||||
if (err >= 0 && err < ERRNO_TABLE_SIZE &&
|
||||
host_to_target_errno_table[err]) {
|
||||
return host_to_target_errno_table[err];
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int target_to_host_errno(int err)
|
||||
{
|
||||
if (target_to_host_errno_table[err])
|
||||
if (err >= 0 && err < ERRNO_TABLE_SIZE &&
|
||||
target_to_host_errno_table[err]) {
|
||||
return target_to_host_errno_table[err];
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -652,6 +639,67 @@ char *target_strerror(int err)
|
|||
return strerror(target_to_host_errno(err));
|
||||
}
|
||||
|
||||
#define safe_syscall0(type, name) \
|
||||
static type safe_##name(void) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name); \
|
||||
}
|
||||
|
||||
#define safe_syscall1(type, name, type1, arg1) \
|
||||
static type safe_##name(type1 arg1) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name, arg1); \
|
||||
}
|
||||
|
||||
#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
|
||||
static type safe_##name(type1 arg1, type2 arg2) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name, arg1, arg2); \
|
||||
}
|
||||
|
||||
#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
|
||||
static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name, arg1, arg2, arg3); \
|
||||
}
|
||||
|
||||
#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
|
||||
type4, arg4) \
|
||||
static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
|
||||
}
|
||||
|
||||
#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
|
||||
type4, arg4, type5, arg5) \
|
||||
static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
|
||||
type5 arg5) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
|
||||
}
|
||||
|
||||
#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
|
||||
type4, arg4, type5, arg5, type6, arg6) \
|
||||
static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
|
||||
type5 arg5, type6 arg6) \
|
||||
{ \
|
||||
return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
|
||||
}
|
||||
|
||||
safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
|
||||
safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
|
||||
safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
|
||||
int, flags, mode_t, mode)
|
||||
safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
|
||||
struct rusage *, rusage)
|
||||
safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
|
||||
int, options, struct rusage *, rusage)
|
||||
safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
|
||||
safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
|
||||
fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
|
||||
safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
|
||||
const struct timespec *,timeout,int *,uaddr2,int,val3)
|
||||
|
||||
static inline int host_to_target_sock_type(int host_type)
|
||||
{
|
||||
int target_type;
|
||||
|
@ -1062,7 +1110,8 @@ static abi_long do_select(int n,
|
|||
{
|
||||
fd_set rfds, wfds, efds;
|
||||
fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
|
||||
struct timeval tv, *tv_ptr;
|
||||
struct timeval tv;
|
||||
struct timespec ts, *ts_ptr;
|
||||
abi_long ret;
|
||||
|
||||
ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
|
||||
|
@ -1081,12 +1130,15 @@ static abi_long do_select(int n,
|
|||
if (target_tv_addr) {
|
||||
if (copy_from_user_timeval(&tv, target_tv_addr))
|
||||
return -TARGET_EFAULT;
|
||||
tv_ptr = &tv;
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
ts_ptr = &ts;
|
||||
} else {
|
||||
tv_ptr = NULL;
|
||||
ts_ptr = NULL;
|
||||
}
|
||||
|
||||
ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
|
||||
ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
|
||||
ts_ptr, NULL));
|
||||
|
||||
if (!is_error(ret)) {
|
||||
if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
|
||||
|
@ -1096,8 +1148,13 @@ static abi_long do_select(int n,
|
|||
if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
|
||||
return -TARGET_EFAULT;
|
||||
|
||||
if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
|
||||
return -TARGET_EFAULT;
|
||||
if (target_tv_addr) {
|
||||
tv.tv_sec = ts.tv_sec;
|
||||
tv.tv_usec = ts.tv_nsec / 1000;
|
||||
if (copy_to_user_timeval(target_tv_addr, &tv)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -3095,7 +3152,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
|
|||
}
|
||||
|
||||
static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
||||
unsigned int msgsz, abi_long msgtyp,
|
||||
ssize_t msgsz, abi_long msgtyp,
|
||||
int msgflg)
|
||||
{
|
||||
struct target_msgbuf *target_mb;
|
||||
|
@ -3103,10 +3160,18 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
|
|||
struct msgbuf *host_mb;
|
||||
abi_long ret = 0;
|
||||
|
||||
if (msgsz < 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
|
||||
return -TARGET_EFAULT;
|
||||
|
||||
host_mb = g_malloc(msgsz+sizeof(long));
|
||||
host_mb = g_try_malloc(msgsz + sizeof(long));
|
||||
if (!host_mb) {
|
||||
ret = -TARGET_ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
|
||||
|
||||
if (ret > 0) {
|
||||
|
@ -5034,6 +5099,40 @@ static inline int tswapid(int id)
|
|||
|
||||
#endif /* USE_UID16 */
|
||||
|
||||
/* We must do direct syscalls for setting UID/GID, because we want to
|
||||
* implement the Linux system call semantics of "change only for this thread",
|
||||
* not the libc/POSIX semantics of "change for all threads in process".
|
||||
* (See http://ewontfix.com/17/ for more details.)
|
||||
* We use the 32-bit version of the syscalls if present; if it is not
|
||||
* then either the host architecture supports 32-bit UIDs natively with
|
||||
* the standard syscall, or the 16-bit UID is the best we can do.
|
||||
*/
|
||||
#ifdef __NR_setuid32
|
||||
#define __NR_sys_setuid __NR_setuid32
|
||||
#else
|
||||
#define __NR_sys_setuid __NR_setuid
|
||||
#endif
|
||||
#ifdef __NR_setgid32
|
||||
#define __NR_sys_setgid __NR_setgid32
|
||||
#else
|
||||
#define __NR_sys_setgid __NR_setgid
|
||||
#endif
|
||||
#ifdef __NR_setresuid32
|
||||
#define __NR_sys_setresuid __NR_setresuid32
|
||||
#else
|
||||
#define __NR_sys_setresuid __NR_setresuid
|
||||
#endif
|
||||
#ifdef __NR_setresgid32
|
||||
#define __NR_sys_setresgid __NR_setresgid32
|
||||
#else
|
||||
#define __NR_sys_setresgid __NR_setresgid
|
||||
#endif
|
||||
|
||||
_syscall1(int, sys_setuid, uid_t, uid)
|
||||
_syscall1(int, sys_setgid, gid_t, gid)
|
||||
_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
|
||||
_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
|
||||
|
||||
void syscall_init(void)
|
||||
{
|
||||
IOCTLEntry *ie;
|
||||
|
@ -5137,8 +5236,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts,
|
|||
|
||||
if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
|
||||
return -TARGET_EFAULT;
|
||||
host_ts->tv_sec = tswapal(target_ts->tv_sec);
|
||||
host_ts->tv_nsec = tswapal(target_ts->tv_nsec);
|
||||
__get_user(host_ts->tv_sec, &target_ts->tv_sec);
|
||||
__get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
|
||||
unlock_user_struct(target_ts, target_addr, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -5150,8 +5249,8 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr,
|
|||
|
||||
if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
|
||||
return -TARGET_EFAULT;
|
||||
target_ts->tv_sec = tswapal(host_ts->tv_sec);
|
||||
target_ts->tv_nsec = tswapal(host_ts->tv_nsec);
|
||||
__put_user(host_ts->tv_sec, &target_ts->tv_sec);
|
||||
__put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
|
||||
unlock_user_struct(target_ts, target_addr, 1);
|
||||
return 0;
|
||||
}
|
||||
|
@ -5326,12 +5425,12 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
|
|||
} else {
|
||||
pts = NULL;
|
||||
}
|
||||
return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
|
||||
return get_errno(safe_futex(g2h(uaddr), op, tswap32(val),
|
||||
pts, NULL, val3));
|
||||
case FUTEX_WAKE:
|
||||
return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
|
||||
return get_errno(safe_futex(g2h(uaddr), op, val, NULL, NULL, 0));
|
||||
case FUTEX_FD:
|
||||
return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
|
||||
return get_errno(safe_futex(g2h(uaddr), op, val, NULL, NULL, 0));
|
||||
case FUTEX_REQUEUE:
|
||||
case FUTEX_CMP_REQUEUE:
|
||||
case FUTEX_WAKE_OP:
|
||||
|
@ -5341,11 +5440,11 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
|
|||
to satisfy the compiler. We do not need to tswap TIMEOUT
|
||||
since it's not compared to guest memory. */
|
||||
pts = (struct timespec *)(uintptr_t) timeout;
|
||||
return get_errno(sys_futex(g2h(uaddr), op, val, pts,
|
||||
g2h(uaddr2),
|
||||
(base_op == FUTEX_CMP_REQUEUE
|
||||
? tswap32(val3)
|
||||
: val3)));
|
||||
return get_errno(safe_futex(g2h(uaddr), op, val, pts,
|
||||
g2h(uaddr2),
|
||||
(base_op == FUTEX_CMP_REQUEUE
|
||||
? tswap32(val3)
|
||||
: val3)));
|
||||
default:
|
||||
return -TARGET_ENOSYS;
|
||||
}
|
||||
|
@ -5555,7 +5654,9 @@ static int open_self_cmdline(void *cpu_env, int fd)
|
|||
|
||||
nb_read = read(fd_orig, buf, sizeof(buf));
|
||||
if (nb_read < 0) {
|
||||
int e = errno;
|
||||
fd_orig = close(fd_orig);
|
||||
errno = e;
|
||||
return -1;
|
||||
} else if (nb_read == 0) {
|
||||
break;
|
||||
|
@ -5575,7 +5676,9 @@ static int open_self_cmdline(void *cpu_env, int fd)
|
|||
|
||||
if (word_skipped) {
|
||||
if (write(fd, cp_buf, nb_read) != nb_read) {
|
||||
int e = errno;
|
||||
close(fd_orig);
|
||||
errno = e;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -5595,7 +5698,7 @@ static int open_self_maps(void *cpu_env, int fd)
|
|||
|
||||
fp = fopen("/proc/self/maps", "r");
|
||||
if (fp == NULL) {
|
||||
return -EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
|
@ -5739,7 +5842,7 @@ static int open_net_route(void *cpu_env, int fd)
|
|||
|
||||
fp = fopen("/proc/net/route", "r");
|
||||
if (fp == NULL) {
|
||||
return -EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read header */
|
||||
|
@ -5789,7 +5892,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
|
|||
|
||||
if (is_proc_myself(pathname, "exe")) {
|
||||
int execfd = qemu_getauxval(AT_EXECFD);
|
||||
return execfd ? execfd : get_errno(sys_openat(dirfd, exec_path, flags, mode));
|
||||
return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
|
||||
}
|
||||
|
||||
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
||||
|
@ -5815,7 +5918,9 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
|
|||
unlink(filename);
|
||||
|
||||
if ((r = fake_open->fill(cpu_env, fd))) {
|
||||
int e = errno;
|
||||
close(fd);
|
||||
errno = e;
|
||||
return r;
|
||||
}
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
@ -5823,7 +5928,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
|
|||
return fd;
|
||||
}
|
||||
|
||||
return get_errno(sys_openat(dirfd, path(pathname), flags, mode));
|
||||
return safe_openat(dirfd, path(pathname), flags, mode);
|
||||
}
|
||||
|
||||
#define TIMER_MAGIC 0x0caf0000
|
||||
|
@ -5861,6 +5966,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
struct statfs stfs;
|
||||
void *p;
|
||||
|
||||
#if defined(DEBUG_ERESTARTSYS)
|
||||
/* Debug-only code for exercising the syscall-restart code paths
|
||||
* in the per-architecture cpu main loops: restart every syscall
|
||||
* the guest makes once before letting it through.
|
||||
*/
|
||||
{
|
||||
static int flag;
|
||||
|
||||
flag = !flag;
|
||||
if (flag) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
gemu_log("syscall %d", num);
|
||||
#endif
|
||||
|
@ -5907,7 +6027,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
else {
|
||||
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
|
||||
goto efault;
|
||||
ret = get_errno(read(arg1, p, arg3));
|
||||
ret = get_errno(safe_read(arg1, p, arg3));
|
||||
if (ret >= 0 &&
|
||||
fd_trans_host_to_target_data(arg1)) {
|
||||
ret = fd_trans_host_to_target_data(arg1)(p, ret);
|
||||
|
@ -5918,7 +6038,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
case TARGET_NR_write:
|
||||
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
|
||||
goto efault;
|
||||
ret = get_errno(write(arg1, p, arg3));
|
||||
ret = get_errno(safe_write(arg1, p, arg3));
|
||||
unlock_user(p, arg2, 0);
|
||||
break;
|
||||
#ifdef TARGET_NR_open
|
||||
|
@ -5968,7 +6088,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
case TARGET_NR_waitpid:
|
||||
{
|
||||
int status;
|
||||
ret = get_errno(waitpid(arg1, &status, arg3));
|
||||
ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
|
||||
if (!is_error(ret) && arg2 && ret
|
||||
&& put_user_s32(host_to_target_waitstatus(status), arg2))
|
||||
goto efault;
|
||||
|
@ -5980,7 +6100,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
{
|
||||
siginfo_t info;
|
||||
info.si_pid = 0;
|
||||
ret = get_errno(waitid(arg1, arg2, &info, arg4));
|
||||
ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
|
||||
if (!is_error(ret) && arg3 && info.si_pid != 0) {
|
||||
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
|
||||
goto efault;
|
||||
|
@ -6106,7 +6226,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
|
||||
if (!(p = lock_user_string(arg1)))
|
||||
goto execve_efault;
|
||||
ret = get_errno(execve(p, argp, envp));
|
||||
/* Although execve() is not an interruptible syscall it is
|
||||
* a special case where we must use the safe_syscall wrapper:
|
||||
* if we allow a signal to happen before we make the host
|
||||
* syscall then we will 'lose' it, because at the point of
|
||||
* execve the process leaves QEMU's control. So we use the
|
||||
* safe syscall wrapper to ensure that we either take the
|
||||
* signal as a guest signal, or else it does not happen
|
||||
* before the execve completes and makes it the other
|
||||
* program's problem.
|
||||
*/
|
||||
ret = get_errno(safe_execve(p, argp, envp));
|
||||
unlock_user(p, arg1, 0);
|
||||
|
||||
goto execve_end;
|
||||
|
@ -6930,12 +7060,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
break;
|
||||
#ifdef TARGET_NR_sigreturn
|
||||
case TARGET_NR_sigreturn:
|
||||
/* NOTE: ret is eax, so not transcoding must be done */
|
||||
ret = do_sigreturn(cpu_env);
|
||||
break;
|
||||
#endif
|
||||
case TARGET_NR_rt_sigreturn:
|
||||
/* NOTE: ret is eax, so not transcoding must be done */
|
||||
ret = do_rt_sigreturn(cpu_env);
|
||||
break;
|
||||
case TARGET_NR_sethostname:
|
||||
|
@ -7124,8 +7252,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
sig_ptr = NULL;
|
||||
}
|
||||
|
||||
ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
|
||||
ts_ptr, sig_ptr));
|
||||
ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
|
||||
ts_ptr, sig_ptr));
|
||||
|
||||
if (!is_error(ret)) {
|
||||
if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
|
||||
|
@ -7694,7 +7822,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
rusage_ptr = &rusage;
|
||||
else
|
||||
rusage_ptr = NULL;
|
||||
ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
|
||||
ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
|
||||
if (!is_error(ret)) {
|
||||
if (status_ptr && ret) {
|
||||
status = host_to_target_waitstatus(status);
|
||||
|
@ -8740,9 +8868,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
#ifdef TARGET_NR_setresuid
|
||||
case TARGET_NR_setresuid:
|
||||
ret = get_errno(setresuid(low2highuid(arg1),
|
||||
low2highuid(arg2),
|
||||
low2highuid(arg3)));
|
||||
ret = get_errno(sys_setresuid(low2highuid(arg1),
|
||||
low2highuid(arg2),
|
||||
low2highuid(arg3)));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_getresuid
|
||||
|
@ -8761,9 +8889,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
#ifdef TARGET_NR_getresgid
|
||||
case TARGET_NR_setresgid:
|
||||
ret = get_errno(setresgid(low2highgid(arg1),
|
||||
low2highgid(arg2),
|
||||
low2highgid(arg3)));
|
||||
ret = get_errno(sys_setresgid(low2highgid(arg1),
|
||||
low2highgid(arg2),
|
||||
low2highgid(arg3)));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_getresgid
|
||||
|
@ -8789,10 +8917,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
break;
|
||||
#endif
|
||||
case TARGET_NR_setuid:
|
||||
ret = get_errno(setuid(low2highuid(arg1)));
|
||||
ret = get_errno(sys_setuid(low2highuid(arg1)));
|
||||
break;
|
||||
case TARGET_NR_setgid:
|
||||
ret = get_errno(setgid(low2highgid(arg1)));
|
||||
ret = get_errno(sys_setgid(low2highgid(arg1)));
|
||||
break;
|
||||
case TARGET_NR_setfsuid:
|
||||
ret = get_errno(setfsuid(arg1));
|
||||
|
@ -9074,7 +9202,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
#ifdef TARGET_NR_setresuid32
|
||||
case TARGET_NR_setresuid32:
|
||||
ret = get_errno(setresuid(arg1, arg2, arg3));
|
||||
ret = get_errno(sys_setresuid(arg1, arg2, arg3));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_getresuid32
|
||||
|
@ -9093,7 +9221,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
#ifdef TARGET_NR_setresgid32
|
||||
case TARGET_NR_setresgid32:
|
||||
ret = get_errno(setresgid(arg1, arg2, arg3));
|
||||
ret = get_errno(sys_setresgid(arg1, arg2, arg3));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_getresgid32
|
||||
|
@ -9120,12 +9248,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
#endif
|
||||
#ifdef TARGET_NR_setuid32
|
||||
case TARGET_NR_setuid32:
|
||||
ret = get_errno(setuid(arg1));
|
||||
ret = get_errno(sys_setuid(arg1));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_setgid32
|
||||
case TARGET_NR_setgid32:
|
||||
ret = get_errno(setgid(arg1));
|
||||
ret = get_errno(sys_setgid(arg1));
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_setfsuid32
|
||||
|
|
|
@ -55,7 +55,8 @@
|
|||
#define TARGET_IOC_NRBITS 8
|
||||
#define TARGET_IOC_TYPEBITS 8
|
||||
|
||||
#if defined(TARGET_I386) || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|
||||
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \
|
||||
|| (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|
||||
|| defined(TARGET_SPARC) \
|
||||
|| defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
|
||||
/* 16 bit uid wrappers emulation */
|
||||
|
|
|
@ -25,4 +25,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUTLGState *state)
|
|||
return state->regs[TILEGX_R_SP];
|
||||
}
|
||||
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
||||
|
|
Loading…
Reference in New Issue