* [Qemu-devel] [PULL 00/38] linux-user update
@ 2016-05-25 5:27 riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 01/38] linux-user: Check array bounds in errno conversion riku.voipio
` (38 more replies)
0 siblings, 39 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Riku Voipio
From: Riku Voipio <riku.voipio@linaro.org>
The following changes since commit b0f6ef8915247f3230ffd9b71af9c3dadb6082c7:
Merge remote-tracking branch 'remotes/amit-virtio-rng/tags/rng-2.7-1' into staging (2016-05-24 11:38:22 +0100)
are available in the git repository at:
git://git.linaro.org/people/riku.voipio/qemu.git tags/pull-linux-user-20160525
for you to fetch changes up to 210a7201d1bd9e25eec01d23edb713f181eabb23:
linux-user,target-ppc: fix use of MSR_LE (2016-05-24 15:45:46 +0300)
----------------------------------------------------------------
Linux user update for May 2016
----------------------------------------------------------------
Chen Gang (3):
linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame
linux-user/signal.c: Use target address instead of host address for microblaze restorer
linux-user/signal.c: Use s390 target space address instead of host space
Laurent Vivier (1):
linux-user,target-ppc: fix use of MSR_LE
Peter Maydell (11):
linux-user: Consistently return host errnos from do_openat()
linux-user: Support for restarting system calls for tilegx targets
linux-user: Set r14 on exit from microblaze syscall
linux-user: Use safe_syscall for pselect, select syscalls
linux-user: Use safe_syscall for futex syscall
linux-user: Handle negative values in timespec conversion
linux-user: Handle msgrcv error case correctly
linux-user: Use g_try_malloc() in do_msgrcv()
linux-user: x86_64: Don't use 16-bit UIDs
linux-user: Use direct syscalls for setuid(), etc
linux-user: arm: Remove ARM_cpsr and similar #defines
Timothy E Baldwin (23):
linux-user: Check array bounds in errno conversion
linux-user: Reindent signal handling
linux-user: Define TARGET_ERESTART* errno values
linux-user: Renumber TARGET_QEMU_ESIGRETURN, make it not arch-specific
linux-user: Support for restarting system calls for x86 targets
linux-user: Support for restarting system calls for ARM targets
linux-user: Support for restarting system calls for MIPS targets
linux-user: Support for restarting system calls for PPC targets
linux-user: Support for restarting system calls for SPARC targets
linux-user: Support for restarting system calls for SH4 targets
linux-user: Support for restarting system calls for Alpha targets
linux-user: Support for restarting system calls for UniCore32 targets
linux-user: Support for restarting system calls for OpenRISC targets
linux-user: Support for restarting system calls for M68K targets
linux-user: Support for restarting system calls for S390 targets
linux-user: Support for restarting system calls for CRIS targets
linux-user: Support for restarting system calls for Microblaze targets
linux-user: Add debug code to exercise restarting system calls
linux-user: Provide safe_syscall for fixing races between signals and syscalls
linux-user: Use safe_syscall for read and write system calls
linux-user: Use safe_syscall for open and openat system calls
linux-user: Use safe_syscall for wait system calls
linux-user: Use safe_syscall for execve syscall
Makefile.target | 4 +-
linux-user/Makefile.objs | 3 +-
linux-user/alpha/target_signal.h | 1 +
linux-user/arm/target_signal.h | 1 +
linux-user/arm/target_syscall.h | 20 +-
linux-user/cris/target_signal.h | 1 +
linux-user/elfload.c | 19 +-
linux-user/errno_defs.h | 17 +
linux-user/host/x86_64/hostdep.h | 38 +
linux-user/host/x86_64/safe-syscall.inc.S | 81 +++
linux-user/m68k/target_signal.h | 1 +
linux-user/main.c | 225 ++++--
linux-user/microblaze/target_signal.h | 1 +
linux-user/mips/target_signal.h | 1 +
linux-user/mips/target_syscall.h | 4 -
linux-user/mips64/target_signal.h | 1 +
linux-user/mips64/target_syscall.h | 4 -
linux-user/openrisc/target_signal.h | 1 +
linux-user/ppc/target_signal.h | 1 +
linux-user/ppc/target_syscall.h | 2 -
linux-user/qemu.h | 127 +++-
linux-user/s390x/target_signal.h | 1 +
linux-user/safe-syscall.S | 30 +
linux-user/sh4/target_signal.h | 1 +
linux-user/signal.c | 1631 ++++++++++++++++++++++---------------------
linux-user/sparc/target_signal.h | 1 +
linux-user/sparc64/target_signal.h | 1 +
linux-user/syscall.c | 266 +++++--
linux-user/syscall_defs.h | 3 +-
linux-user/tilegx/target_signal.h | 1 +
30 files changed, 1516 insertions(+), 972 deletions(-)
create mode 100644 linux-user/host/x86_64/hostdep.h
create mode 100644 linux-user/host/x86_64/safe-syscall.inc.S
create mode 100644 linux-user/safe-syscall.S
^ permalink raw reply [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 01/38] linux-user: Check array bounds in errno conversion
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 02/38] linux-user: Consistently return host errnos from do_openat() riku.voipio
` (37 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Check array bounds in host_to_target_errno() and target_to_host_errno().
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-2-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: Add a lower-bound check, use braces on if(), tweak commit message]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
---
linux-user/syscall.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 032d338..5246f36 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -619,15 +619,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;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 02/38] linux-user: Consistently return host errnos from do_openat()
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 01/38] linux-user: Check array bounds in errno conversion riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 03/38] linux-user: Reindent signal handling riku.voipio
` (36 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
The function do_openat() is not consistent about whether it is
returning a host errno or a guest errno in case of failure.
Standardise on returning -1 with errno set (ie caller has
to call get_errno()).
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
---
linux-user/syscall.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 5246f36..f4c2e19 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5559,7 +5559,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;
@@ -5579,7 +5581,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;
}
}
@@ -5599,7 +5603,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) {
@@ -5743,7 +5747,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 */
@@ -5793,7 +5797,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 : sys_openat(dirfd, exec_path, flags, mode);
}
for (fake_open = fakes; fake_open->filename; fake_open++) {
@@ -5819,7 +5823,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);
@@ -5827,7 +5833,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 sys_openat(dirfd, path(pathname), flags, mode);
}
#define TIMER_MAGIC 0x0caf0000
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 03/38] linux-user: Reindent signal handling
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 01/38] linux-user: Check array bounds in errno conversion riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 02/38] linux-user: Consistently return host errnos from do_openat() riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 04/38] linux-user: Define TARGET_ERESTART* errno values riku.voipio
` (35 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Some of the signal handling was a mess with a mixture of tabs and 8 space
indents.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-3-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: just rebased]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/signal.c | 1543 ++++++++++++++++++++++++++-------------------------
1 file changed, 791 insertions(+), 752 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 96e86c0..04c21d0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -157,7 +157,7 @@ static void target_to_host_sigset_internal(sigset_t *d,
if (target_sigismember(s, i)) {
sigaddset(d, target_to_host_signal(i));
}
- }
+ }
}
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
@@ -250,18 +250,18 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
tinfo->si_code = info->si_code;
if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
- || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
+ || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
/* Should never come here, but who knows. The information for
the target is irrelevant. */
tinfo->_sifields._sigfault._addr = 0;
} 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);
+ = 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) {
@@ -269,7 +269,7 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
tinfo->_sifields._rt._uid = info->si_uid;
/* XXX: potential problem if 64 bit */
tinfo->_sifields._rt._sigval.sival_ptr
- = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
+ = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
}
}
@@ -723,75 +723,75 @@ int do_sigaction(int sig, const struct target_sigaction *act,
/* from the Linux kernel */
struct target_fpreg {
- uint16_t significand[4];
- uint16_t exponent;
+ uint16_t significand[4];
+ uint16_t exponent;
};
struct target_fpxreg {
- uint16_t significand[4];
- uint16_t exponent;
- uint16_t padding[3];
+ uint16_t significand[4];
+ uint16_t exponent;
+ uint16_t padding[3];
};
struct target_xmmreg {
- abi_ulong element[4];
+ abi_ulong element[4];
};
struct target_fpstate {
- /* Regular FPU environment */
- abi_ulong cw;
- abi_ulong sw;
- abi_ulong tag;
- abi_ulong ipoff;
- abi_ulong cssel;
- abi_ulong dataoff;
- abi_ulong datasel;
- struct target_fpreg _st[8];
- uint16_t status;
- uint16_t magic; /* 0xffff = regular FPU data only */
-
- /* FXSR FPU environment */
- abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
- abi_ulong mxcsr;
- abi_ulong reserved;
- struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
- struct target_xmmreg _xmm[8];
- abi_ulong padding[56];
+ /* Regular FPU environment */
+ abi_ulong cw;
+ abi_ulong sw;
+ abi_ulong tag;
+ abi_ulong ipoff;
+ abi_ulong cssel;
+ abi_ulong dataoff;
+ abi_ulong datasel;
+ struct target_fpreg _st[8];
+ uint16_t status;
+ uint16_t magic; /* 0xffff = regular FPU data only */
+
+ /* FXSR FPU environment */
+ abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */
+ abi_ulong mxcsr;
+ abi_ulong reserved;
+ struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
+ struct target_xmmreg _xmm[8];
+ abi_ulong padding[56];
};
#define X86_FXSR_MAGIC 0x0000
struct target_sigcontext {
- uint16_t gs, __gsh;
- uint16_t fs, __fsh;
- uint16_t es, __esh;
- uint16_t ds, __dsh;
- abi_ulong edi;
- abi_ulong esi;
- abi_ulong ebp;
- abi_ulong esp;
- abi_ulong ebx;
- abi_ulong edx;
- abi_ulong ecx;
- abi_ulong eax;
- abi_ulong trapno;
- abi_ulong err;
- abi_ulong eip;
- uint16_t cs, __csh;
- abi_ulong eflags;
- abi_ulong esp_at_signal;
- uint16_t ss, __ssh;
- abi_ulong fpstate; /* pointer */
- abi_ulong oldmask;
- abi_ulong cr2;
+ uint16_t gs, __gsh;
+ uint16_t fs, __fsh;
+ uint16_t es, __esh;
+ uint16_t ds, __dsh;
+ abi_ulong edi;
+ abi_ulong esi;
+ abi_ulong ebp;
+ abi_ulong esp;
+ abi_ulong ebx;
+ abi_ulong edx;
+ abi_ulong ecx;
+ abi_ulong eax;
+ abi_ulong trapno;
+ abi_ulong err;
+ abi_ulong eip;
+ uint16_t cs, __csh;
+ abi_ulong eflags;
+ abi_ulong esp_at_signal;
+ uint16_t ss, __ssh;
+ abi_ulong fpstate; /* pointer */
+ abi_ulong oldmask;
+ abi_ulong cr2;
};
struct target_ucontext {
- abi_ulong tuc_flags;
- abi_ulong tuc_link;
- target_stack_t tuc_stack;
- struct target_sigcontext tuc_mcontext;
- target_sigset_t tuc_sigmask; /* mask last for extensibility */
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
+ target_stack_t tuc_stack;
+ struct target_sigcontext tuc_mcontext;
+ target_sigset_t tuc_sigmask; /* mask last for extensibility */
};
struct sigframe
@@ -828,7 +828,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
CPUState *cs = CPU(x86_env_get_cpu(env));
uint16_t magic;
- /* already locked in setup_frame() */
+ /* already locked in setup_frame() */
__put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
__put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
__put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
@@ -849,13 +849,13 @@ static void setup_sigcontext(struct target_sigcontext *sc,
__put_user(env->regs[R_ESP], &sc->esp_at_signal);
__put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
- cpu_x86_fsave(env, fpstate_addr, 1);
- fpstate->status = fpstate->sw;
- magic = 0xffff;
+ cpu_x86_fsave(env, fpstate_addr, 1);
+ fpstate->status = fpstate->sw;
+ magic = 0xffff;
__put_user(magic, &fpstate->magic);
__put_user(fpstate_addr, &sc->fpstate);
- /* non-iBCS2 extensions.. */
+ /* non-iBCS2 extensions.. */
__put_user(mask, &sc->oldmask);
__put_user(env->cr[2], &sc->cr2);
}
@@ -867,110 +867,112 @@ static void setup_sigcontext(struct target_sigcontext *sc,
static inline abi_ulong
get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
{
- unsigned long esp;
+ unsigned long esp;
- /* Default to using normal stack */
- esp = env->regs[R_ESP];
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa_flags & TARGET_SA_ONSTACK) {
- if (sas_ss_flags(esp) == 0)
- esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ /* Default to using normal stack */
+ esp = env->regs[R_ESP];
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa_flags & TARGET_SA_ONSTACK) {
+ if (sas_ss_flags(esp) == 0) {
+ esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
}
+ } else {
- /* This is the legacy signal stack switching. */
- else
+ /* This is the legacy signal stack switching. */
if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
- !(ka->sa_flags & TARGET_SA_RESTORER) &&
- ka->sa_restorer) {
+ !(ka->sa_flags & TARGET_SA_RESTORER) &&
+ ka->sa_restorer) {
esp = (unsigned long) ka->sa_restorer;
- }
- return (esp - frame_size) & -8ul;
+ }
+ }
+ return (esp - frame_size) & -8ul;
}
/* compare linux/arch/i386/kernel/signal.c:setup_frame() */
static void setup_frame(int sig, struct target_sigaction *ka,
- target_sigset_t *set, CPUX86State *env)
+ target_sigset_t *set, CPUX86State *env)
{
- abi_ulong frame_addr;
- struct sigframe *frame;
- int i;
+ abi_ulong frame_addr;
+ struct sigframe *frame;
+ int i;
- frame_addr = get_sigframe(ka, env, sizeof(*frame));
- trace_user_setup_frame(env, frame_addr);
+ frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ trace_user_setup_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+ goto give_sigsegv;
__put_user(sig, &frame->sig);
- setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
- frame_addr + offsetof(struct sigframe, fpstate));
+ setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
+ frame_addr + offsetof(struct sigframe, fpstate));
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &frame->extramask[i - 1]);
}
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- if (ka->sa_flags & TARGET_SA_RESTORER) {
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa_flags & TARGET_SA_RESTORER) {
__put_user(ka->sa_restorer, &frame->pretcode);
- } else {
- uint16_t val16;
- abi_ulong retcode_addr;
- retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
+ } else {
+ uint16_t val16;
+ abi_ulong retcode_addr;
+ retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
__put_user(retcode_addr, &frame->pretcode);
- /* This is popl %eax ; movl $,%eax ; int $0x80 */
- val16 = 0xb858;
+ /* This is popl %eax ; movl $,%eax ; int $0x80 */
+ val16 = 0xb858;
__put_user(val16, (uint16_t *)(frame->retcode+0));
__put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
- val16 = 0x80cd;
+ val16 = 0x80cd;
__put_user(val16, (uint16_t *)(frame->retcode+6));
- }
+ }
- /* Set up registers for signal handler */
- env->regs[R_ESP] = frame_addr;
- env->eip = ka->_sa_handler;
+ /* Set up registers for signal handler */
+ env->regs[R_ESP] = frame_addr;
+ env->eip = ka->_sa_handler;
- cpu_x86_load_seg(env, R_DS, __USER_DS);
- cpu_x86_load_seg(env, R_ES, __USER_DS);
- cpu_x86_load_seg(env, R_SS, __USER_DS);
- cpu_x86_load_seg(env, R_CS, __USER_CS);
- env->eflags &= ~TF_MASK;
+ cpu_x86_load_seg(env, R_DS, __USER_DS);
+ cpu_x86_load_seg(env, R_ES, __USER_DS);
+ cpu_x86_load_seg(env, R_SS, __USER_DS);
+ cpu_x86_load_seg(env, R_CS, __USER_CS);
+ env->eflags &= ~TF_MASK;
- unlock_user_struct(frame, frame_addr, 1);
+ unlock_user_struct(frame, frame_addr, 1);
- return;
+ return;
give_sigsegv:
- if (sig == TARGET_SIGSEGV)
- ka->_sa_handler = TARGET_SIG_DFL;
- force_sig(TARGET_SIGSEGV /* , current */);
+ if (sig == TARGET_SIGSEGV) {
+ ka->_sa_handler = TARGET_SIG_DFL;
+ }
+ force_sig(TARGET_SIGSEGV /* , current */);
}
/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
static void setup_rt_frame(int sig, struct target_sigaction *ka,
target_siginfo_t *info,
- target_sigset_t *set, CPUX86State *env)
+ target_sigset_t *set, CPUX86State *env)
{
- abi_ulong frame_addr, addr;
- struct rt_sigframe *frame;
- int i;
+ abi_ulong frame_addr, addr;
+ struct rt_sigframe *frame;
+ int i;
- frame_addr = get_sigframe(ka, env, sizeof(*frame));
- trace_user_setup_rt_frame(env, frame_addr);
+ frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ trace_user_setup_rt_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+ goto give_sigsegv;
__put_user(sig, &frame->sig);
- addr = frame_addr + offsetof(struct rt_sigframe, info);
+ addr = frame_addr + offsetof(struct rt_sigframe, info);
__put_user(addr, &frame->pinfo);
- addr = frame_addr + offsetof(struct rt_sigframe, uc);
+ addr = frame_addr + offsetof(struct rt_sigframe, uc);
__put_user(addr, &frame->puc);
tswap_siginfo(&frame->info, info);
- /* Create the ucontext. */
+ /* Create the ucontext. */
__put_user(0, &frame->uc.tuc_flags);
__put_user(0, &frame->uc.tuc_link);
__put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
@@ -985,81 +987,82 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
}
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- if (ka->sa_flags & TARGET_SA_RESTORER) {
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa_flags & TARGET_SA_RESTORER) {
__put_user(ka->sa_restorer, &frame->pretcode);
- } else {
- uint16_t val16;
- addr = frame_addr + offsetof(struct rt_sigframe, retcode);
+ } else {
+ uint16_t val16;
+ addr = frame_addr + offsetof(struct rt_sigframe, retcode);
__put_user(addr, &frame->pretcode);
- /* This is movl $,%eax ; int $0x80 */
+ /* This is movl $,%eax ; int $0x80 */
__put_user(0xb8, (char *)(frame->retcode+0));
__put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
- val16 = 0x80cd;
+ val16 = 0x80cd;
__put_user(val16, (uint16_t *)(frame->retcode+5));
- }
+ }
- /* Set up registers for signal handler */
- env->regs[R_ESP] = frame_addr;
- env->eip = ka->_sa_handler;
+ /* Set up registers for signal handler */
+ env->regs[R_ESP] = frame_addr;
+ env->eip = ka->_sa_handler;
- cpu_x86_load_seg(env, R_DS, __USER_DS);
- cpu_x86_load_seg(env, R_ES, __USER_DS);
- cpu_x86_load_seg(env, R_SS, __USER_DS);
- cpu_x86_load_seg(env, R_CS, __USER_CS);
- env->eflags &= ~TF_MASK;
+ cpu_x86_load_seg(env, R_DS, __USER_DS);
+ cpu_x86_load_seg(env, R_ES, __USER_DS);
+ cpu_x86_load_seg(env, R_SS, __USER_DS);
+ cpu_x86_load_seg(env, R_CS, __USER_CS);
+ env->eflags &= ~TF_MASK;
- unlock_user_struct(frame, frame_addr, 1);
+ unlock_user_struct(frame, frame_addr, 1);
- return;
+ return;
give_sigsegv:
- if (sig == TARGET_SIGSEGV)
- ka->_sa_handler = TARGET_SIG_DFL;
- force_sig(TARGET_SIGSEGV /* , current */);
+ if (sig == TARGET_SIGSEGV) {
+ ka->_sa_handler = TARGET_SIG_DFL;
+ }
+ force_sig(TARGET_SIGSEGV /* , current */);
}
static int
restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
{
- unsigned int err = 0;
- abi_ulong fpstate_addr;
- unsigned int tmpflags;
-
- cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
- cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
- cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
- cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
-
- env->regs[R_EDI] = tswapl(sc->edi);
- env->regs[R_ESI] = tswapl(sc->esi);
- env->regs[R_EBP] = tswapl(sc->ebp);
- env->regs[R_ESP] = tswapl(sc->esp);
- env->regs[R_EBX] = tswapl(sc->ebx);
- env->regs[R_EDX] = tswapl(sc->edx);
- env->regs[R_ECX] = tswapl(sc->ecx);
- env->eip = tswapl(sc->eip);
-
- cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
- cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
-
- tmpflags = tswapl(sc->eflags);
- env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
- // regs->orig_eax = -1; /* disable syscall checks */
-
- fpstate_addr = tswapl(sc->fpstate);
- if (fpstate_addr != 0) {
- if (!access_ok(VERIFY_READ, fpstate_addr,
- sizeof(struct target_fpstate)))
- goto badframe;
- cpu_x86_frstor(env, fpstate_addr, 1);
- }
+ unsigned int err = 0;
+ abi_ulong fpstate_addr;
+ unsigned int tmpflags;
+
+ cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
+ cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
+ cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
+ cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
+
+ env->regs[R_EDI] = tswapl(sc->edi);
+ env->regs[R_ESI] = tswapl(sc->esi);
+ env->regs[R_EBP] = tswapl(sc->ebp);
+ env->regs[R_ESP] = tswapl(sc->esp);
+ env->regs[R_EBX] = tswapl(sc->ebx);
+ env->regs[R_EDX] = tswapl(sc->edx);
+ env->regs[R_ECX] = tswapl(sc->ecx);
+ env->eip = tswapl(sc->eip);
+
+ cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
+ cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
+
+ tmpflags = tswapl(sc->eflags);
+ env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
+ // regs->orig_eax = -1; /* disable syscall checks */
+
+ fpstate_addr = tswapl(sc->fpstate);
+ if (fpstate_addr != 0) {
+ if (!access_ok(VERIFY_READ, fpstate_addr,
+ sizeof(struct target_fpstate)))
+ goto badframe;
+ cpu_x86_frstor(env, fpstate_addr, 1);
+ }
- *peax = tswapl(sc->eax);
- return err;
+ *peax = tswapl(sc->eax);
+ return err;
badframe:
- return 1;
+ return 1;
}
long do_sigreturn(CPUX86State *env)
@@ -1096,32 +1099,34 @@ badframe:
long do_rt_sigreturn(CPUX86State *env)
{
- abi_ulong frame_addr;
- struct rt_sigframe *frame;
- sigset_t set;
- int eax;
+ abi_ulong frame_addr;
+ struct rt_sigframe *frame;
+ sigset_t set;
+ int eax;
- frame_addr = env->regs[R_ESP] - 4;
- trace_user_do_rt_sigreturn(env, frame_addr);
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
- target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- do_sigprocmask(SIG_SETMASK, &set, NULL);
+ frame_addr = env->regs[R_ESP] - 4;
+ trace_user_do_rt_sigreturn(env, frame_addr);
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+ goto badframe;
+ target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
+ do_sigprocmask(SIG_SETMASK, &set, NULL);
- if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
- goto badframe;
+ if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) {
+ goto badframe;
+ }
- if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
- get_sp_from_cpustate(env)) == -EFAULT)
- goto badframe;
+ if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
+ get_sp_from_cpustate(env)) == -EFAULT) {
+ goto badframe;
+ }
- unlock_user_struct(frame, frame_addr, 0);
- return eax;
+ unlock_user_struct(frame, frame_addr, 0);
+ return eax;
badframe:
- unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
- return 0;
+ unlock_user_struct(frame, frame_addr, 0);
+ force_sig(TARGET_SIGSEGV);
+ return 0;
}
#elif defined(TARGET_AARCH64)
@@ -1402,27 +1407,27 @@ long do_sigreturn(CPUARMState *env)
#elif defined(TARGET_ARM)
struct target_sigcontext {
- abi_ulong trap_no;
- abi_ulong error_code;
- abi_ulong oldmask;
- abi_ulong arm_r0;
- abi_ulong arm_r1;
- abi_ulong arm_r2;
- abi_ulong arm_r3;
- abi_ulong arm_r4;
- abi_ulong arm_r5;
- abi_ulong arm_r6;
- abi_ulong arm_r7;
- abi_ulong arm_r8;
- abi_ulong arm_r9;
- abi_ulong arm_r10;
- abi_ulong arm_fp;
- abi_ulong arm_ip;
- abi_ulong arm_sp;
- abi_ulong arm_lr;
- abi_ulong arm_pc;
- abi_ulong arm_cpsr;
- abi_ulong fault_address;
+ abi_ulong trap_no;
+ abi_ulong error_code;
+ abi_ulong oldmask;
+ abi_ulong arm_r0;
+ abi_ulong arm_r1;
+ abi_ulong arm_r2;
+ abi_ulong arm_r3;
+ abi_ulong arm_r4;
+ abi_ulong arm_r5;
+ abi_ulong arm_r6;
+ abi_ulong arm_r7;
+ abi_ulong arm_r8;
+ abi_ulong arm_r9;
+ abi_ulong arm_r10;
+ abi_ulong arm_fp;
+ abi_ulong arm_ip;
+ abi_ulong arm_sp;
+ abi_ulong arm_lr;
+ abi_ulong arm_pc;
+ abi_ulong arm_cpsr;
+ abi_ulong fault_address;
};
struct target_ucontext_v1 {
@@ -1581,7 +1586,7 @@ get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
static void
setup_return(CPUARMState *env, struct target_sigaction *ka,
- abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
+ abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
{
abi_ulong handler = ka->_sa_handler;
abi_ulong retcode;
@@ -1691,42 +1696,44 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
static void setup_frame_v1(int usig, struct target_sigaction *ka,
target_sigset_t *set, CPUARMState *regs)
{
- struct sigframe_v1 *frame;
- abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
- int i;
+ struct sigframe_v1 *frame;
+ abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+ int i;
- trace_user_setup_frame(regs, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- return;
+ trace_user_setup_frame(regs, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ return;
+ }
- setup_sigcontext(&frame->sc, regs, set->sig[0]);
+ setup_sigcontext(&frame->sc, regs, set->sig[0]);
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &frame->extramask[i - 1]);
}
- setup_return(regs, ka, &frame->retcode, frame_addr, usig,
- frame_addr + offsetof(struct sigframe_v1, retcode));
+ setup_return(regs, ka, &frame->retcode, frame_addr, usig,
+ frame_addr + offsetof(struct sigframe_v1, retcode));
- unlock_user_struct(frame, frame_addr, 1);
+ unlock_user_struct(frame, frame_addr, 1);
}
static void setup_frame_v2(int usig, struct target_sigaction *ka,
target_sigset_t *set, CPUARMState *regs)
{
- struct sigframe_v2 *frame;
- abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+ struct sigframe_v2 *frame;
+ abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
- trace_user_setup_frame(regs, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- return;
+ trace_user_setup_frame(regs, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ return;
+ }
- setup_sigframe_v2(&frame->uc, set, regs);
+ setup_sigframe_v2(&frame->uc, set, regs);
- setup_return(regs, ka, &frame->retcode, frame_addr, usig,
- frame_addr + offsetof(struct sigframe_v2, retcode));
+ setup_return(regs, ka, &frame->retcode, frame_addr, usig,
+ frame_addr + offsetof(struct sigframe_v2, retcode));
- unlock_user_struct(frame, frame_addr, 1);
+ unlock_user_struct(frame, frame_addr, 1);
}
static void setup_frame(int usig, struct target_sigaction *ka,
@@ -1744,70 +1751,72 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
target_siginfo_t *info,
target_sigset_t *set, CPUARMState *env)
{
- struct rt_sigframe_v1 *frame;
- abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
- struct target_sigaltstack stack;
- int i;
- abi_ulong info_addr, uc_addr;
+ struct rt_sigframe_v1 *frame;
+ abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ struct target_sigaltstack stack;
+ int i;
+ abi_ulong info_addr, uc_addr;
- trace_user_setup_rt_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- return /* 1 */;
+ trace_user_setup_rt_frame(env, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ return /* 1 */;
+ }
- info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
- __put_user(info_addr, &frame->pinfo);
- uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
- __put_user(uc_addr, &frame->puc);
- tswap_siginfo(&frame->info, info);
+ info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
+ __put_user(info_addr, &frame->pinfo);
+ uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
+ __put_user(uc_addr, &frame->puc);
+ tswap_siginfo(&frame->info, info);
- /* Clear all the bits of the ucontext we don't use. */
- memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
+ /* Clear all the bits of the ucontext we don't use. */
+ memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
- memset(&stack, 0, sizeof(stack));
- __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
- __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
- __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
- memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
+ memset(&stack, 0, sizeof(stack));
+ __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
+ __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
+ __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
+ memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
- setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
- for(i = 0; i < TARGET_NSIG_WORDS; i++) {
- __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
- }
+ setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
+ for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+ __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
+ }
- setup_return(env, ka, &frame->retcode, frame_addr, usig,
- frame_addr + offsetof(struct rt_sigframe_v1, retcode));
+ setup_return(env, ka, &frame->retcode, frame_addr, usig,
+ frame_addr + offsetof(struct rt_sigframe_v1, retcode));
- env->regs[1] = info_addr;
- env->regs[2] = uc_addr;
+ env->regs[1] = info_addr;
+ env->regs[2] = uc_addr;
- unlock_user_struct(frame, frame_addr, 1);
+ unlock_user_struct(frame, frame_addr, 1);
}
static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
target_siginfo_t *info,
target_sigset_t *set, CPUARMState *env)
{
- struct rt_sigframe_v2 *frame;
- abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
- abi_ulong info_addr, uc_addr;
+ struct rt_sigframe_v2 *frame;
+ abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+ abi_ulong info_addr, uc_addr;
- trace_user_setup_rt_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- return /* 1 */;
+ trace_user_setup_rt_frame(env, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ return /* 1 */;
+ }
- info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
- uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
- tswap_siginfo(&frame->info, info);
+ info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
+ uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
+ tswap_siginfo(&frame->info, info);
- setup_sigframe_v2(&frame->uc, set, env);
+ setup_sigframe_v2(&frame->uc, set, env);
- setup_return(env, ka, &frame->retcode, frame_addr, usig,
- frame_addr + offsetof(struct rt_sigframe_v2, retcode));
+ setup_return(env, ka, &frame->retcode, frame_addr, usig,
+ frame_addr + offsetof(struct rt_sigframe_v2, retcode));
- env->regs[1] = info_addr;
- env->regs[2] = uc_addr;
+ env->regs[1] = info_addr;
+ env->regs[2] = uc_addr;
- unlock_user_struct(frame, frame_addr, 1);
+ unlock_user_struct(frame, frame_addr, 1);
}
static void setup_rt_frame(int usig, struct target_sigaction *ka,
@@ -1824,8 +1833,8 @@ static void setup_rt_frame(int usig, struct target_sigaction *ka,
static int
restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
{
- int err = 0;
- uint32_t cpsr;
+ int err = 0;
+ uint32_t cpsr;
__get_user(env->regs[0], &sc->arm_r0);
__get_user(env->regs[1], &sc->arm_r1);
@@ -1848,55 +1857,57 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
#endif
- err |= !valid_user_regs(env);
+ err |= !valid_user_regs(env);
- return err;
+ return err;
}
static long do_sigreturn_v1(CPUARMState *env)
{
- abi_ulong frame_addr;
- struct sigframe_v1 *frame = NULL;
- target_sigset_t set;
- sigset_t host_set;
- int i;
-
- /*
- * Since we stacked the signal on a 64-bit boundary,
- * then 'sp' should be word aligned here. If it's
- * not, then the user is trying to mess with us.
- */
- frame_addr = env->regs[13];
- trace_user_do_sigreturn(env, frame_addr);
- if (frame_addr & 7) {
- goto badframe;
- }
+ abi_ulong frame_addr;
+ struct sigframe_v1 *frame = NULL;
+ target_sigset_t set;
+ sigset_t host_set;
+ int i;
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ /*
+ * Since we stacked the signal on a 64-bit boundary,
+ * then 'sp' should be word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ frame_addr = env->regs[13];
+ trace_user_do_sigreturn(env, frame_addr);
+ if (frame_addr & 7) {
+ goto badframe;
+ }
+
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
__get_user(set.sig[0], &frame->sc.oldmask);
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
__get_user(set.sig[i], &frame->extramask[i - 1]);
}
- target_to_host_sigset_internal(&host_set, &set);
- do_sigprocmask(SIG_SETMASK, &host_set, NULL);
+ target_to_host_sigset_internal(&host_set, &set);
+ do_sigprocmask(SIG_SETMASK, &host_set, NULL);
- if (restore_sigcontext(env, &frame->sc))
- goto badframe;
+ if (restore_sigcontext(env, &frame->sc)) {
+ goto badframe;
+ }
#if 0
- /* Send SIGTRAP if we're single-stepping */
- if (ptrace_cancel_bpt(current))
- send_sig(SIGTRAP, current, 1);
+ /* Send SIGTRAP if we're single-stepping */
+ if (ptrace_cancel_bpt(current))
+ send_sig(SIGTRAP, current, 1);
#endif
- unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ unlock_user_struct(frame, frame_addr, 0);
+ return env->regs[0];
badframe:
- force_sig(TARGET_SIGSEGV /* , current */);
- return 0;
+ force_sig(TARGET_SIGSEGV /* , current */);
+ return 0;
}
static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
@@ -1987,7 +1998,7 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
#if 0
/* Send SIGTRAP if we're single-stepping */
if (ptrace_cancel_bpt(current))
- send_sig(SIGTRAP, current, 1);
+ send_sig(SIGTRAP, current, 1);
#endif
return 0;
@@ -1995,33 +2006,35 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
static long do_sigreturn_v2(CPUARMState *env)
{
- abi_ulong frame_addr;
- struct sigframe_v2 *frame = NULL;
-
- /*
- * Since we stacked the signal on a 64-bit boundary,
- * then 'sp' should be word aligned here. If it's
- * not, then the user is trying to mess with us.
- */
- frame_addr = env->regs[13];
- trace_user_do_sigreturn(env, frame_addr);
- if (frame_addr & 7) {
- goto badframe;
- }
+ abi_ulong frame_addr;
+ struct sigframe_v2 *frame = NULL;
+
+ /*
+ * Since we stacked the signal on a 64-bit boundary,
+ * then 'sp' should be word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ frame_addr = env->regs[13];
+ trace_user_do_sigreturn(env, frame_addr);
+ if (frame_addr & 7) {
+ goto badframe;
+ }
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
- if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
- goto badframe;
+ if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
+ goto badframe;
+ }
- unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ unlock_user_struct(frame, frame_addr, 0);
+ return env->regs[0];
badframe:
- unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV /* , current */);
- return 0;
+ unlock_user_struct(frame, frame_addr, 0);
+ force_sig(TARGET_SIGSEGV /* , current */);
+ return 0;
}
long do_sigreturn(CPUARMState *env)
@@ -2035,76 +2048,80 @@ long do_sigreturn(CPUARMState *env)
static long do_rt_sigreturn_v1(CPUARMState *env)
{
- abi_ulong frame_addr;
- struct rt_sigframe_v1 *frame = NULL;
- sigset_t host_set;
-
- /*
- * Since we stacked the signal on a 64-bit boundary,
- * then 'sp' should be word aligned here. If it's
- * not, then the user is trying to mess with us.
- */
- frame_addr = env->regs[13];
- trace_user_do_rt_sigreturn(env, frame_addr);
- if (frame_addr & 7) {
- goto badframe;
- }
+ abi_ulong frame_addr;
+ struct rt_sigframe_v1 *frame = NULL;
+ sigset_t host_set;
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ /*
+ * Since we stacked the signal on a 64-bit boundary,
+ * then 'sp' should be word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ frame_addr = env->regs[13];
+ trace_user_do_rt_sigreturn(env, frame_addr);
+ if (frame_addr & 7) {
+ goto badframe;
+ }
- target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
- do_sigprocmask(SIG_SETMASK, &host_set, NULL);
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
+
+ target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
+ do_sigprocmask(SIG_SETMASK, &host_set, NULL);
- if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
- goto badframe;
+ if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
+ goto badframe;
+ }
- if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
- goto badframe;
+ if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
+ goto badframe;
#if 0
- /* Send SIGTRAP if we're single-stepping */
- if (ptrace_cancel_bpt(current))
- send_sig(SIGTRAP, current, 1);
+ /* Send SIGTRAP if we're single-stepping */
+ if (ptrace_cancel_bpt(current))
+ send_sig(SIGTRAP, current, 1);
#endif
- unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ unlock_user_struct(frame, frame_addr, 0);
+ return env->regs[0];
badframe:
- unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV /* , current */);
- return 0;
+ unlock_user_struct(frame, frame_addr, 0);
+ force_sig(TARGET_SIGSEGV /* , current */);
+ return 0;
}
static long do_rt_sigreturn_v2(CPUARMState *env)
{
- abi_ulong frame_addr;
- struct rt_sigframe_v2 *frame = NULL;
-
- /*
- * Since we stacked the signal on a 64-bit boundary,
- * then 'sp' should be word aligned here. If it's
- * not, then the user is trying to mess with us.
- */
- frame_addr = env->regs[13];
- trace_user_do_rt_sigreturn(env, frame_addr);
- if (frame_addr & 7) {
- goto badframe;
- }
+ abi_ulong frame_addr;
+ struct rt_sigframe_v2 *frame = NULL;
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ /*
+ * Since we stacked the signal on a 64-bit boundary,
+ * then 'sp' should be word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ frame_addr = env->regs[13];
+ trace_user_do_rt_sigreturn(env, frame_addr);
+ if (frame_addr & 7) {
+ goto badframe;
+ }
+
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
- if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
- goto badframe;
+ if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
+ goto badframe;
+ }
- unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ unlock_user_struct(frame, frame_addr, 0);
+ return env->regs[0];
badframe:
- unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV /* , current */);
- return 0;
+ unlock_user_struct(frame, frame_addr, 0);
+ force_sig(TARGET_SIGSEGV /* , current */);
+ return 0;
}
long do_rt_sigreturn(CPUARMState *env)
@@ -2122,83 +2139,83 @@ long do_rt_sigreturn(CPUARMState *env)
/* This is what SunOS does, so shall I. */
struct target_sigcontext {
- abi_ulong sigc_onstack; /* state to restore */
+ abi_ulong sigc_onstack; /* state to restore */
- abi_ulong sigc_mask; /* sigmask to restore */
- abi_ulong sigc_sp; /* stack pointer */
- abi_ulong sigc_pc; /* program counter */
- abi_ulong sigc_npc; /* next program counter */
- abi_ulong sigc_psr; /* for condition codes etc */
- abi_ulong sigc_g1; /* User uses these two registers */
- abi_ulong sigc_o0; /* within the trampoline code. */
+ abi_ulong sigc_mask; /* sigmask to restore */
+ abi_ulong sigc_sp; /* stack pointer */
+ abi_ulong sigc_pc; /* program counter */
+ abi_ulong sigc_npc; /* next program counter */
+ abi_ulong sigc_psr; /* for condition codes etc */
+ abi_ulong sigc_g1; /* User uses these two registers */
+ abi_ulong sigc_o0; /* within the trampoline code. */
- /* Now comes information regarding the users window set
+ /* Now comes information regarding the users window set
* at the time of the signal.
*/
- abi_ulong sigc_oswins; /* outstanding windows */
+ abi_ulong sigc_oswins; /* outstanding windows */
- /* stack ptrs for each regwin buf */
- char *sigc_spbuf[__SUNOS_MAXWIN];
+ /* stack ptrs for each regwin buf */
+ char *sigc_spbuf[__SUNOS_MAXWIN];
- /* Windows to restore after signal */
- struct {
- abi_ulong locals[8];
- abi_ulong ins[8];
- } sigc_wbuf[__SUNOS_MAXWIN];
+ /* Windows to restore after signal */
+ struct {
+ abi_ulong locals[8];
+ abi_ulong ins[8];
+ } sigc_wbuf[__SUNOS_MAXWIN];
};
/* A Sparc stack frame */
struct sparc_stackf {
- abi_ulong locals[8];
- abi_ulong ins[8];
- /* It's simpler to treat fp and callers_pc as elements of ins[]
+ abi_ulong locals[8];
+ abi_ulong ins[8];
+ /* It's simpler to treat fp and callers_pc as elements of ins[]
* since we never need to access them ourselves.
*/
- char *structptr;
- abi_ulong xargs[6];
- abi_ulong xxargs[1];
+ char *structptr;
+ abi_ulong xargs[6];
+ abi_ulong xxargs[1];
};
typedef struct {
- struct {
- abi_ulong psr;
- abi_ulong pc;
- abi_ulong npc;
- abi_ulong y;
- abi_ulong u_regs[16]; /* globals and ins */
- } si_regs;
- int si_mask;
+ struct {
+ abi_ulong psr;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong u_regs[16]; /* globals and ins */
+ } si_regs;
+ int si_mask;
} __siginfo_t;
typedef struct {
- abi_ulong si_float_regs[32];
- unsigned long si_fsr;
- unsigned long si_fpqdepth;
- struct {
- unsigned long *insn_addr;
- unsigned long insn;
- } si_fpqueue [16];
+ abi_ulong si_float_regs[32];
+ unsigned long si_fsr;
+ unsigned long si_fpqdepth;
+ struct {
+ unsigned long *insn_addr;
+ unsigned long insn;
+ } si_fpqueue [16];
} qemu_siginfo_fpu_t;
struct target_signal_frame {
- struct sparc_stackf ss;
- __siginfo_t info;
- abi_ulong fpu_save;
- abi_ulong insns[2] __attribute__ ((aligned (8)));
- abi_ulong extramask[TARGET_NSIG_WORDS - 1];
- abi_ulong extra_size; /* Should be 0 */
- qemu_siginfo_fpu_t fpu_state;
+ struct sparc_stackf ss;
+ __siginfo_t info;
+ abi_ulong fpu_save;
+ abi_ulong insns[2] __attribute__ ((aligned (8)));
+ abi_ulong extramask[TARGET_NSIG_WORDS - 1];
+ abi_ulong extra_size; /* Should be 0 */
+ qemu_siginfo_fpu_t fpu_state;
};
struct target_rt_signal_frame {
- struct sparc_stackf ss;
- siginfo_t info;
- abi_ulong regs[20];
- sigset_t mask;
- abi_ulong fpu_save;
- unsigned int insns[2];
- stack_t stack;
- unsigned int extra_size; /* Should be 0 */
- qemu_siginfo_fpu_t fpu_state;
+ struct sparc_stackf ss;
+ siginfo_t info;
+ abi_ulong regs[20];
+ sigset_t mask;
+ abi_ulong fpu_save;
+ unsigned int insns[2];
+ stack_t stack;
+ unsigned int extra_size; /* Should be 0 */
+ qemu_siginfo_fpu_t fpu_state;
};
#define UREG_O0 16
@@ -2219,36 +2236,37 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa,
CPUSPARCState *env,
unsigned long framesize)
{
- abi_ulong sp;
+ abi_ulong sp;
- sp = env->regwptr[UREG_FP];
+ sp = env->regwptr[UREG_FP];
- /* This is the X/Open sanctioned signal stack switching. */
- if (sa->sa_flags & TARGET_SA_ONSTACK) {
- if (!on_sig_stack(sp)
- && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
- sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
- }
- return sp - framesize;
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (sa->sa_flags & TARGET_SA_ONSTACK) {
+ if (!on_sig_stack(sp)
+ && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
+ }
+ return sp - framesize;
}
static int
setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
{
- int err = 0, i;
+ int err = 0, i;
__put_user(env->psr, &si->si_regs.psr);
__put_user(env->pc, &si->si_regs.pc);
__put_user(env->npc, &si->si_regs.npc);
__put_user(env->y, &si->si_regs.y);
- for (i=0; i < 8; i++) {
+ for (i=0; i < 8; i++) {
__put_user(env->gregs[i], &si->si_regs.u_regs[i]);
- }
- for (i=0; i < 8; i++) {
+ }
+ for (i=0; i < 8; i++) {
__put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
- }
+ }
__put_user(mask, &si->si_mask);
- return err;
+ return err;
}
#if 0
@@ -2256,7 +2274,7 @@ static int
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
CPUSPARCState *env, unsigned long mask)
{
- int err = 0;
+ int err = 0;
__put_user(mask, &sc->sigc_mask);
__put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
@@ -2266,7 +2284,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
__put_user(env->gregs[1], &sc->sigc_g1);
__put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
- return err;
+ return err;
}
#endif
#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
@@ -2274,90 +2292,90 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
static void setup_frame(int sig, struct target_sigaction *ka,
target_sigset_t *set, CPUSPARCState *env)
{
- abi_ulong sf_addr;
- struct target_signal_frame *sf;
- int sigframe_size, err, i;
+ abi_ulong sf_addr;
+ struct target_signal_frame *sf;
+ int sigframe_size, err, i;
- /* 1. Make sure everything is clean */
- //synchronize_user_stack();
+ /* 1. Make sure everything is clean */
+ //synchronize_user_stack();
- sigframe_size = NF_ALIGNEDSZ;
- sf_addr = get_sigframe(ka, env, sigframe_size);
- trace_user_setup_frame(env, sf_addr);
+ sigframe_size = NF_ALIGNEDSZ;
+ sf_addr = get_sigframe(ka, env, sigframe_size);
+ trace_user_setup_frame(env, sf_addr);
- sf = lock_user(VERIFY_WRITE, sf_addr,
- sizeof(struct target_signal_frame), 0);
- if (!sf)
- goto sigsegv;
-
+ sf = lock_user(VERIFY_WRITE, sf_addr,
+ sizeof(struct target_signal_frame), 0);
+ if (!sf) {
+ goto sigsegv;
+ }
#if 0
- if (invalid_frame_pointer(sf, sigframe_size))
- goto sigill_and_return;
+ if (invalid_frame_pointer(sf, sigframe_size))
+ goto sigill_and_return;
#endif
- /* 2. Save the current process state */
- err = setup___siginfo(&sf->info, env, set->sig[0]);
+ /* 2. Save the current process state */
+ err = setup___siginfo(&sf->info, env, set->sig[0]);
__put_user(0, &sf->extra_size);
- //save_fpu_state(regs, &sf->fpu_state);
- //__put_user(&sf->fpu_state, &sf->fpu_save);
+ //save_fpu_state(regs, &sf->fpu_state);
+ //__put_user(&sf->fpu_state, &sf->fpu_save);
__put_user(set->sig[0], &sf->info.si_mask);
- for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
+ for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
__put_user(set->sig[i + 1], &sf->extramask[i]);
- }
+ }
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
__put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
- }
- for (i = 0; i < 8; i++) {
+ }
+ for (i = 0; i < 8; i++) {
__put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
- }
- if (err)
- goto sigsegv;
-
- /* 3. signal handler back-trampoline and parameters */
- env->regwptr[UREG_FP] = sf_addr;
- env->regwptr[UREG_I0] = sig;
- env->regwptr[UREG_I1] = sf_addr +
- offsetof(struct target_signal_frame, info);
- env->regwptr[UREG_I2] = sf_addr +
- offsetof(struct target_signal_frame, info);
-
- /* 4. signal handler */
- env->pc = ka->_sa_handler;
- env->npc = (env->pc + 4);
- /* 5. return to kernel instructions */
- if (ka->sa_restorer)
- env->regwptr[UREG_I7] = ka->sa_restorer;
- else {
- uint32_t val32;
-
- env->regwptr[UREG_I7] = sf_addr +
- offsetof(struct target_signal_frame, insns) - 2 * 4;
-
- /* mov __NR_sigreturn, %g1 */
- val32 = 0x821020d8;
+ }
+ if (err)
+ goto sigsegv;
+
+ /* 3. signal handler back-trampoline and parameters */
+ env->regwptr[UREG_FP] = sf_addr;
+ env->regwptr[UREG_I0] = sig;
+ env->regwptr[UREG_I1] = sf_addr +
+ offsetof(struct target_signal_frame, info);
+ env->regwptr[UREG_I2] = sf_addr +
+ offsetof(struct target_signal_frame, info);
+
+ /* 4. signal handler */
+ env->pc = ka->_sa_handler;
+ env->npc = (env->pc + 4);
+ /* 5. return to kernel instructions */
+ if (ka->sa_restorer) {
+ env->regwptr[UREG_I7] = ka->sa_restorer;
+ } else {
+ uint32_t val32;
+
+ env->regwptr[UREG_I7] = sf_addr +
+ offsetof(struct target_signal_frame, insns) - 2 * 4;
+
+ /* mov __NR_sigreturn, %g1 */
+ val32 = 0x821020d8;
__put_user(val32, &sf->insns[0]);
- /* t 0x10 */
- val32 = 0x91d02010;
+ /* t 0x10 */
+ val32 = 0x91d02010;
__put_user(val32, &sf->insns[1]);
- if (err)
- goto sigsegv;
+ if (err)
+ goto sigsegv;
- /* Flush instruction space. */
- //flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
- // tb_flush(CPU(sparc_env_get_cpu(env)));
- }
- unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
- return;
+ /* Flush instruction space. */
+ // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
+ // tb_flush(env);
+ }
+ unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
+ return;
#if 0
sigill_and_return:
- force_sig(TARGET_SIGILL);
+ force_sig(TARGET_SIGILL);
#endif
sigsegv:
- unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
- force_sig(TARGET_SIGSEGV);
+ unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
+ force_sig(TARGET_SIGSEGV);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -2369,71 +2387,74 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
long do_sigreturn(CPUSPARCState *env)
{
- abi_ulong sf_addr;
- struct target_signal_frame *sf;
- uint32_t up_psr, pc, npc;
- target_sigset_t set;
- sigset_t host_set;
- int err=0, i;
+ abi_ulong sf_addr;
+ struct target_signal_frame *sf;
+ uint32_t up_psr, pc, npc;
+ target_sigset_t set;
+ sigset_t host_set;
+ int err=0, i;
- sf_addr = env->regwptr[UREG_FP];
- trace_user_do_sigreturn(env, sf_addr);
- if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
- goto segv_and_exit;
+ sf_addr = env->regwptr[UREG_FP];
+ trace_user_do_sigreturn(env, sf_addr);
+ if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
+ goto segv_and_exit;
+ }
- /* 1. Make sure we are not getting garbage from the user */
+ /* 1. Make sure we are not getting garbage from the user */
- if (sf_addr & 3)
- goto segv_and_exit;
+ if (sf_addr & 3)
+ goto segv_and_exit;
- __get_user(pc, &sf->info.si_regs.pc);
- __get_user(npc, &sf->info.si_regs.npc);
+ __get_user(pc, &sf->info.si_regs.pc);
+ __get_user(npc, &sf->info.si_regs.npc);
- if ((pc | npc) & 3)
- goto segv_and_exit;
+ if ((pc | npc) & 3) {
+ goto segv_and_exit;
+ }
- /* 2. Restore the state */
- __get_user(up_psr, &sf->info.si_regs.psr);
+ /* 2. Restore the state */
+ __get_user(up_psr, &sf->info.si_regs.psr);
- /* User can only change condition codes and FPU enabling in %psr. */
- env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
- | (env->psr & ~(PSR_ICC /* | PSR_EF */));
+ /* User can only change condition codes and FPU enabling in %psr. */
+ env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
+ | (env->psr & ~(PSR_ICC /* | PSR_EF */));
- env->pc = pc;
- env->npc = npc;
- __get_user(env->y, &sf->info.si_regs.y);
- for (i=0; i < 8; i++) {
- __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
- }
- for (i=0; i < 8; i++) {
- __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
- }
+ env->pc = pc;
+ env->npc = npc;
+ __get_user(env->y, &sf->info.si_regs.y);
+ for (i=0; i < 8; i++) {
+ __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
+ }
+ for (i=0; i < 8; i++) {
+ __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
+ }
- /* FIXME: implement FPU save/restore:
+ /* FIXME: implement FPU save/restore:
* __get_user(fpu_save, &sf->fpu_save);
* if (fpu_save)
* err |= restore_fpu_state(env, fpu_save);
*/
- /* This is pretty much atomic, no amount locking would prevent
+ /* This is pretty much atomic, no amount locking would prevent
* the races which exist anyways.
*/
- __get_user(set.sig[0], &sf->info.si_mask);
- for(i = 1; i < TARGET_NSIG_WORDS; i++) {
- __get_user(set.sig[i], &sf->extramask[i - 1]);
- }
+ __get_user(set.sig[0], &sf->info.si_mask);
+ for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+ __get_user(set.sig[i], &sf->extramask[i - 1]);
+ }
- target_to_host_sigset_internal(&host_set, &set);
- do_sigprocmask(SIG_SETMASK, &host_set, NULL);
+ target_to_host_sigset_internal(&host_set, &set);
+ do_sigprocmask(SIG_SETMASK, &host_set, NULL);
- if (err)
- goto segv_and_exit;
- unlock_user_struct(sf, sf_addr, 0);
- return env->regwptr[0];
+ if (err) {
+ goto segv_and_exit;
+ }
+ unlock_user_struct(sf, sf_addr, 0);
+ return env->regwptr[0];
segv_and_exit:
- unlock_user_struct(sf, sf_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ unlock_user_struct(sf, sf_addr, 0);
+ force_sig(TARGET_SIGSEGV);
}
long do_rt_sigreturn(CPUSPARCState *env)
@@ -2522,13 +2543,15 @@ void sparc64_set_context(CPUSPARCState *env)
unsigned int i;
ucp_addr = env->regwptr[UREG_I0];
- if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
+ if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
goto do_sigsegv;
+ }
grp = &ucp->tuc_mcontext.mc_gregs;
__get_user(pc, &((*grp)[MC_PC]));
__get_user(npc, &((*grp)[MC_NPC]));
- if ((pc | npc) & 3)
+ if ((pc | npc) & 3) {
goto do_sigsegv;
+ }
if (env->regwptr[UREG_I1]) {
target_sigset_t target_set;
sigset_t set;
@@ -2573,12 +2596,14 @@ void sparc64_set_context(CPUSPARCState *env)
__get_user(i7, &(ucp->tuc_mcontext.mc_i7));
w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
- if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
- abi_ulong) != 0)
+ if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
+ abi_ulong) != 0) {
goto do_sigsegv;
- if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
- abi_ulong) != 0)
+ }
+ if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
+ abi_ulong) != 0) {
goto do_sigsegv;
+ }
/* FIXME this does not match how the kernel handles the FPU in
* its sparc64_set_context implementation. In particular the FPU
* is only restored if fenab is non-zero in:
@@ -2601,7 +2626,7 @@ void sparc64_set_context(CPUSPARCState *env)
&(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
unlock_user_struct(ucp, ucp_addr, 0);
return;
- do_sigsegv:
+do_sigsegv:
unlock_user_struct(ucp, ucp_addr, 0);
force_sig(TARGET_SIGSEGV);
}
@@ -2619,8 +2644,9 @@ void sparc64_get_context(CPUSPARCState *env)
sigset_t set;
ucp_addr = env->regwptr[UREG_I0];
- if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
+ if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
goto do_sigsegv;
+ }
mcp = &ucp->tuc_mcontext;
grp = &mcp->mc_gregs;
@@ -2670,12 +2696,14 @@ void sparc64_get_context(CPUSPARCState *env)
w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
fp = i7 = 0;
- if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
- abi_ulong) != 0)
+ if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
+ abi_ulong) != 0) {
goto do_sigsegv;
- if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
- abi_ulong) != 0)
+ }
+ if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
+ abi_ulong) != 0) {
goto do_sigsegv;
+ }
__put_user(fp, &(mcp->mc_fp));
__put_user(i7, &(mcp->mc_i7));
@@ -2697,7 +2725,7 @@ void sparc64_get_context(CPUSPARCState *env)
goto do_sigsegv;
unlock_user_struct(ucp, ucp_addr, 1);
return;
- do_sigsegv:
+do_sigsegv:
unlock_user_struct(ucp, ucp_addr, 1);
force_sig(TARGET_SIGSEGV);
}
@@ -2787,7 +2815,7 @@ static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
}
static inline void setup_sigcontext(CPUMIPSState *regs,
- struct target_sigcontext *sc)
+ struct target_sigcontext *sc)
{
int i;
@@ -2899,8 +2927,9 @@ static void setup_frame(int sig, struct target_sigaction * ka,
frame_addr = get_sigframe(ka, regs, sizeof(*frame));
trace_user_setup_frame(regs, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
@@ -2948,7 +2977,7 @@ long do_sigreturn(CPUMIPSState *regs)
frame_addr = regs->active_tc.gpr[29];
trace_user_do_sigreturn(regs, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ goto badframe;
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
__get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
@@ -2994,8 +3023,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
frame_addr = get_sigframe(ka, env, sizeof(*frame));
trace_user_setup_rt_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
@@ -3053,8 +3083,9 @@ long do_rt_sigreturn(CPUMIPSState *env)
frame_addr = env->active_tc.gpr[29];
trace_user_do_rt_sigreturn(env, frame_addr);
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
@@ -3062,8 +3093,8 @@ long do_rt_sigreturn(CPUMIPSState *env)
restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
if (do_sigaltstack(frame_addr +
- offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
- 0, get_sp_from_cpustate(env)) == -EFAULT)
+ offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
+ 0, get_sp_from_cpustate(env)) == -EFAULT)
goto badframe;
env->active_tc.PC = env->CP0_EPC;
@@ -3134,7 +3165,7 @@ struct target_rt_sigframe
#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */
static abi_ulong get_sigframe(struct target_sigaction *ka,
- unsigned long sp, size_t frame_size)
+ unsigned long sp, size_t frame_size)
{
if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
@@ -3144,7 +3175,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka,
}
static void setup_sigcontext(struct target_sigcontext *sc,
- CPUSH4State *regs, unsigned long mask)
+ CPUSH4State *regs, unsigned long mask)
{
int i;
@@ -3173,7 +3204,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
}
static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
- target_ulong *r0_p)
+ target_ulong *r0_p)
{
int i;
@@ -3210,8 +3241,9 @@ static void setup_frame(int sig, struct target_sigaction *ka,
frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
trace_user_setup_frame(regs, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
setup_sigcontext(&frame->sc, regs, set->sig[0]);
@@ -3258,8 +3290,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
trace_user_setup_rt_frame(regs, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
tswap_siginfo(&frame->info, info);
@@ -3273,7 +3306,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(target_sigaltstack_used.ss_size,
&frame->uc.tuc_stack.ss_size);
setup_sigcontext(&frame->uc.tuc_mcontext,
- regs, set->sig[0]);
+ regs, set->sig[0]);
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
}
@@ -3319,8 +3352,9 @@ long do_sigreturn(CPUSH4State *regs)
frame_addr = regs->gregs[15];
trace_user_do_sigreturn(regs, frame_addr);
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
__get_user(target_set.sig[0], &frame->sc.oldmask);
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
@@ -3353,8 +3387,9 @@ long do_rt_sigreturn(CPUSH4State *regs)
frame_addr = regs->gregs[15];
trace_user_do_rt_sigreturn(regs, frame_addr);
- if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
- goto badframe;
+ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+ goto badframe;
+ }
target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
@@ -3362,9 +3397,10 @@ long do_rt_sigreturn(CPUSH4State *regs)
restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
if (do_sigaltstack(frame_addr +
- offsetof(struct target_rt_sigframe, uc.tuc_stack),
- 0, get_sp_from_cpustate(regs)) == -EFAULT)
+ offsetof(struct target_rt_sigframe, uc.tuc_stack),
+ 0, get_sp_from_cpustate(regs)) == -EFAULT) {
goto badframe;
+ }
unlock_user_struct(frame, frame_addr, 0);
return r0;
@@ -3548,7 +3584,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
- badframe:
+badframe:
force_sig(TARGET_SIGSEGV);
}
@@ -3576,7 +3612,7 @@ long do_sigreturn(CPUMBState *env)
/* Restore blocked signals */
__get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
- __get_user(target_set.sig[i], &frame->extramask[i - 1]);
+ __get_user(target_set.sig[i], &frame->extramask[i - 1]);
}
target_to_host_sigset_internal(&set, &target_set);
do_sigprocmask(SIG_SETMASK, &set, NULL);
@@ -3585,10 +3621,10 @@ long do_sigreturn(CPUMBState *env)
/* We got here through a sigreturn syscall, our path back is via an
rtb insn so setup r14 for that. */
env->regs[14] = env->sregs[SR_PC];
-
+
unlock_user_struct(frame, frame_addr, 0);
return env->regs[10];
- badframe:
+badframe:
force_sig(TARGET_SIGSEGV);
}
@@ -3602,124 +3638,124 @@ long do_rt_sigreturn(CPUMBState *env)
#elif defined(TARGET_CRIS)
struct target_sigcontext {
- struct target_pt_regs regs; /* needs to be first */
- uint32_t oldmask;
- uint32_t usp; /* usp before stacking this gunk on it */
+ struct target_pt_regs regs; /* needs to be first */
+ uint32_t oldmask;
+ uint32_t usp; /* usp before stacking this gunk on it */
};
/* Signal frames. */
struct target_signal_frame {
- struct target_sigcontext sc;
- uint32_t extramask[TARGET_NSIG_WORDS - 1];
- uint16_t retcode[4]; /* Trampoline code. */
+ struct target_sigcontext sc;
+ uint32_t extramask[TARGET_NSIG_WORDS - 1];
+ uint16_t retcode[4]; /* Trampoline code. */
};
struct rt_signal_frame {
- siginfo_t *pinfo;
- void *puc;
- siginfo_t info;
- struct ucontext uc;
- uint16_t retcode[4]; /* Trampoline code. */
+ siginfo_t *pinfo;
+ void *puc;
+ siginfo_t info;
+ struct ucontext uc;
+ uint16_t retcode[4]; /* Trampoline code. */
};
static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
{
- __put_user(env->regs[0], &sc->regs.r0);
- __put_user(env->regs[1], &sc->regs.r1);
- __put_user(env->regs[2], &sc->regs.r2);
- __put_user(env->regs[3], &sc->regs.r3);
- __put_user(env->regs[4], &sc->regs.r4);
- __put_user(env->regs[5], &sc->regs.r5);
- __put_user(env->regs[6], &sc->regs.r6);
- __put_user(env->regs[7], &sc->regs.r7);
- __put_user(env->regs[8], &sc->regs.r8);
- __put_user(env->regs[9], &sc->regs.r9);
- __put_user(env->regs[10], &sc->regs.r10);
- __put_user(env->regs[11], &sc->regs.r11);
- __put_user(env->regs[12], &sc->regs.r12);
- __put_user(env->regs[13], &sc->regs.r13);
- __put_user(env->regs[14], &sc->usp);
- __put_user(env->regs[15], &sc->regs.acr);
- __put_user(env->pregs[PR_MOF], &sc->regs.mof);
- __put_user(env->pregs[PR_SRP], &sc->regs.srp);
- __put_user(env->pc, &sc->regs.erp);
+ __put_user(env->regs[0], &sc->regs.r0);
+ __put_user(env->regs[1], &sc->regs.r1);
+ __put_user(env->regs[2], &sc->regs.r2);
+ __put_user(env->regs[3], &sc->regs.r3);
+ __put_user(env->regs[4], &sc->regs.r4);
+ __put_user(env->regs[5], &sc->regs.r5);
+ __put_user(env->regs[6], &sc->regs.r6);
+ __put_user(env->regs[7], &sc->regs.r7);
+ __put_user(env->regs[8], &sc->regs.r8);
+ __put_user(env->regs[9], &sc->regs.r9);
+ __put_user(env->regs[10], &sc->regs.r10);
+ __put_user(env->regs[11], &sc->regs.r11);
+ __put_user(env->regs[12], &sc->regs.r12);
+ __put_user(env->regs[13], &sc->regs.r13);
+ __put_user(env->regs[14], &sc->usp);
+ __put_user(env->regs[15], &sc->regs.acr);
+ __put_user(env->pregs[PR_MOF], &sc->regs.mof);
+ __put_user(env->pregs[PR_SRP], &sc->regs.srp);
+ __put_user(env->pc, &sc->regs.erp);
}
static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
{
- __get_user(env->regs[0], &sc->regs.r0);
- __get_user(env->regs[1], &sc->regs.r1);
- __get_user(env->regs[2], &sc->regs.r2);
- __get_user(env->regs[3], &sc->regs.r3);
- __get_user(env->regs[4], &sc->regs.r4);
- __get_user(env->regs[5], &sc->regs.r5);
- __get_user(env->regs[6], &sc->regs.r6);
- __get_user(env->regs[7], &sc->regs.r7);
- __get_user(env->regs[8], &sc->regs.r8);
- __get_user(env->regs[9], &sc->regs.r9);
- __get_user(env->regs[10], &sc->regs.r10);
- __get_user(env->regs[11], &sc->regs.r11);
- __get_user(env->regs[12], &sc->regs.r12);
- __get_user(env->regs[13], &sc->regs.r13);
- __get_user(env->regs[14], &sc->usp);
- __get_user(env->regs[15], &sc->regs.acr);
- __get_user(env->pregs[PR_MOF], &sc->regs.mof);
- __get_user(env->pregs[PR_SRP], &sc->regs.srp);
- __get_user(env->pc, &sc->regs.erp);
+ __get_user(env->regs[0], &sc->regs.r0);
+ __get_user(env->regs[1], &sc->regs.r1);
+ __get_user(env->regs[2], &sc->regs.r2);
+ __get_user(env->regs[3], &sc->regs.r3);
+ __get_user(env->regs[4], &sc->regs.r4);
+ __get_user(env->regs[5], &sc->regs.r5);
+ __get_user(env->regs[6], &sc->regs.r6);
+ __get_user(env->regs[7], &sc->regs.r7);
+ __get_user(env->regs[8], &sc->regs.r8);
+ __get_user(env->regs[9], &sc->regs.r9);
+ __get_user(env->regs[10], &sc->regs.r10);
+ __get_user(env->regs[11], &sc->regs.r11);
+ __get_user(env->regs[12], &sc->regs.r12);
+ __get_user(env->regs[13], &sc->regs.r13);
+ __get_user(env->regs[14], &sc->usp);
+ __get_user(env->regs[15], &sc->regs.acr);
+ __get_user(env->pregs[PR_MOF], &sc->regs.mof);
+ __get_user(env->pregs[PR_SRP], &sc->regs.srp);
+ __get_user(env->pc, &sc->regs.erp);
}
static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
{
- abi_ulong sp;
- /* Align the stack downwards to 4. */
- sp = (env->regs[R_SP] & ~3);
- return sp - framesize;
+ abi_ulong sp;
+ /* Align the stack downwards to 4. */
+ sp = (env->regs[R_SP] & ~3);
+ return sp - framesize;
}
static void setup_frame(int sig, struct target_sigaction *ka,
target_sigset_t *set, CPUCRISState *env)
{
- struct target_signal_frame *frame;
- abi_ulong frame_addr;
- int i;
-
- frame_addr = get_sigframe(env, sizeof *frame);
- trace_user_setup_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto badframe;
-
- /*
- * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
- * use this trampoline anymore but it sets it up for GDB.
- * In QEMU, using the trampoline simplifies things a bit so we use it.
- *
- * This is movu.w __NR_sigreturn, r9; break 13;
- */
+ struct target_signal_frame *frame;
+ abi_ulong frame_addr;
+ int i;
+
+ frame_addr = get_sigframe(env, sizeof *frame);
+ trace_user_setup_frame(env, frame_addr);
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+ goto badframe;
+
+ /*
+ * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
+ * use this trampoline anymore but it sets it up for GDB.
+ * In QEMU, using the trampoline simplifies things a bit so we use it.
+ *
+ * This is movu.w __NR_sigreturn, r9; break 13;
+ */
__put_user(0x9c5f, frame->retcode+0);
__put_user(TARGET_NR_sigreturn,
frame->retcode + 1);
__put_user(0xe93d, frame->retcode + 2);
- /* Save the mask. */
+ /* Save the mask. */
__put_user(set->sig[0], &frame->sc.oldmask);
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &frame->extramask[i - 1]);
}
- setup_sigcontext(&frame->sc, env);
+ setup_sigcontext(&frame->sc, env);
- /* Move the stack and setup the arguments for the handler. */
- env->regs[R_SP] = frame_addr;
- env->regs[10] = sig;
- env->pc = (unsigned long) ka->_sa_handler;
- /* Link SRP so the guest returns through the trampoline. */
- env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
+ /* Move the stack and setup the arguments for the handler. */
+ env->regs[R_SP] = frame_addr;
+ env->regs[10] = sig;
+ env->pc = (unsigned long) ka->_sa_handler;
+ /* Link SRP so the guest returns through the trampoline. */
+ env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
- unlock_user_struct(frame, frame_addr, 1);
- return;
- badframe:
- force_sig(TARGET_SIGSEGV);
+ unlock_user_struct(frame, frame_addr, 1);
+ return;
+badframe:
+ force_sig(TARGET_SIGSEGV);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3731,31 +3767,32 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
long do_sigreturn(CPUCRISState *env)
{
- struct target_signal_frame *frame;
- abi_ulong frame_addr;
- target_sigset_t target_set;
- sigset_t set;
- int i;
+ struct target_signal_frame *frame;
+ abi_ulong frame_addr;
+ target_sigset_t target_set;
+ sigset_t set;
+ int i;
- frame_addr = env->regs[R_SP];
- trace_user_do_sigreturn(env, frame_addr);
- /* Make sure the guest isn't playing games. */
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
- goto badframe;
+ frame_addr = env->regs[R_SP];
+ trace_user_do_sigreturn(env, frame_addr);
+ /* Make sure the guest isn't playing games. */
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
+ goto badframe;
+ }
- /* Restore blocked signals */
+ /* Restore blocked signals */
__get_user(target_set.sig[0], &frame->sc.oldmask);
- for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+ for(i = 1; i < TARGET_NSIG_WORDS; i++) {
__get_user(target_set.sig[i], &frame->extramask[i - 1]);
- }
- target_to_host_sigset_internal(&set, &target_set);
- do_sigprocmask(SIG_SETMASK, &set, NULL);
+ }
+ target_to_host_sigset_internal(&set, &target_set);
+ do_sigprocmask(SIG_SETMASK, &set, NULL);
- restore_sigcontext(&frame->sc, env);
- unlock_user_struct(frame, frame_addr, 0);
- return env->regs[10];
- badframe:
- force_sig(TARGET_SIGSEGV);
+ restore_sigcontext(&frame->sc, env);
+ unlock_user_struct(frame, frame_addr, 0);
+ return env->regs[10];
+badframe:
+ force_sig(TARGET_SIGSEGV);
}
long do_rt_sigreturn(CPUCRISState *env)
@@ -3841,8 +3878,8 @@ badframe:
/* Set up a signal frame. */
static void setup_sigcontext(struct target_sigcontext *sc,
- CPUOpenRISCState *regs,
- unsigned long mask)
+ CPUOpenRISCState *regs,
+ unsigned long mask)
{
unsigned long usp = regs->gpr[1];
@@ -4100,7 +4137,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
frame_addr = get_sigframe(ka, env, sizeof(*frame));
trace_user_setup_frame(env, frame_addr);
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
- goto give_sigsegv;
+ goto give_sigsegv;
}
__put_user(set->sig[0], &frame->sc.oldmask[0]);
@@ -4113,13 +4150,13 @@ static void setup_frame(int sig, struct target_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa_flags & TARGET_SA_RESTORER) {
- env->regs[14] = (unsigned long)
- ka->sa_restorer | PSW_ADDR_AMODE;
+ env->regs[14] = (unsigned long)
+ ka->sa_restorer | PSW_ADDR_AMODE;
} else {
- env->regs[14] = (unsigned long)
- frame->retcode | PSW_ADDR_AMODE;
- __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
- (uint16_t *)(frame->retcode));
+ env->regs[14] = (unsigned long)
+ frame->retcode | PSW_ADDR_AMODE;
+ __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
+ (uint16_t *)(frame->retcode));
}
/* Set up backchain. */
@@ -4167,12 +4204,12 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
__put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
__put_user(sas_ss_flags(get_sp_from_cpustate(env)),
- &frame->uc.tuc_stack.ss_flags);
+ &frame->uc.tuc_stack.ss_flags);
__put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
save_sigregs(env, &frame->uc.tuc_mcontext);
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
__put_user((abi_ulong)set->sig[i],
- (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
+ (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
}
/* Set up to return from userspace. If provided, use a stub
@@ -4423,15 +4460,15 @@ struct target_sigframe {
#define TARGET_TRAMP_SIZE 6
struct target_rt_sigframe {
- /* sys_rt_sigreturn requires the ucontext be the first field */
- struct target_ucontext uc;
- target_ulong _unused[2];
- uint32_t trampoline[TARGET_TRAMP_SIZE];
- target_ulong pinfo; /* struct siginfo __user * */
- target_ulong puc; /* void __user * */
- struct target_siginfo info;
- /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
- char abigap[288];
+ /* sys_rt_sigreturn requires the ucontext be the first field */
+ struct target_ucontext uc;
+ target_ulong _unused[2];
+ uint32_t trampoline[TARGET_TRAMP_SIZE];
+ target_ulong pinfo; /* struct siginfo __user * */
+ target_ulong puc; /* void __user * */
+ struct target_siginfo info;
+ /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
+ char abigap[288];
} __attribute__((aligned(16)));
#else
@@ -4466,7 +4503,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
oldsp = env->gpr[1];
if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
- (sas_ss_flags(oldsp) == 0)) {
+ (sas_ss_flags(oldsp) == 0)) {
oldsp = (target_sigaltstack_used.ss_sp
+ target_sigaltstack_used.ss_size);
}
@@ -4488,7 +4525,7 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
/* Save general registers. */
for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
- __put_user(env->gpr[i], &frame->mc_gregs[i]);
+ __put_user(env->gpr[i], &frame->mc_gregs[i]);
}
__put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
__put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
@@ -4925,7 +4962,7 @@ struct target_sigframe
abi_ulong extramask[TARGET_NSIG_WORDS-1];
struct target_sigcontext sc;
};
-
+
typedef int target_greg_t;
#define TARGET_NGREG 18
typedef target_greg_t target_gregset_t[TARGET_NGREG];
@@ -4964,7 +5001,7 @@ struct target_rt_sigframe
};
static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
- abi_ulong mask)
+ abi_ulong mask)
{
__put_user(mask, &sc->sc_mask);
__put_user(env->aregs[7], &sc->sc_usp);
@@ -5022,8 +5059,9 @@ static void setup_frame(int sig, struct target_sigaction *ka,
frame_addr = get_sigframe(ka, env, sizeof *frame);
trace_user_setup_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
__put_user(sig, &frame->sig);
@@ -5044,7 +5082,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
/* moveq #,d0; trap #0 */
__put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
- (uint32_t *)(frame->retcode));
+ (uint32_t *)(frame->retcode));
/* Set up to return from userspace */
@@ -5085,7 +5123,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
return 0;
}
-
+
static inline int target_rt_restore_ucontext(CPUM68KState *env,
struct target_ucontext *uc,
int *pd0)
@@ -5139,8 +5177,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
frame_addr = get_sigframe(ka, env, sizeof *frame);
trace_user_setup_rt_frame(env, frame_addr);
- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
- goto give_sigsegv;
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
__put_user(sig, &frame->sig);
@@ -5159,13 +5198,13 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(target_sigaltstack_used.ss_sp,
&frame->uc.tuc_stack.ss_sp);
__put_user(sas_ss_flags(env->aregs[7]),
- &frame->uc.tuc_stack.ss_flags);
+ &frame->uc.tuc_stack.ss_flags);
__put_user(target_sigaltstack_used.ss_size,
&frame->uc.tuc_stack.ss_size);
err |= target_rt_setup_ucontext(&frame->uc, env);
if (err)
- goto give_sigsegv;
+ goto give_sigsegv;
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
@@ -5316,7 +5355,7 @@ struct target_rt_sigframe {
#define INSN_CALLSYS 0x00000083
static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
- abi_ulong frame_addr, target_sigset_t *set)
+ abi_ulong frame_addr, target_sigset_t *set)
{
int i;
@@ -5342,7 +5381,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
}
static void restore_sigcontext(CPUAlphaState *env,
- struct target_sigcontext *sc)
+ struct target_sigcontext *sc)
{
uint64_t fpcr;
int i;
@@ -5402,7 +5441,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
if (err) {
- give_sigsegv:
+give_sigsegv:
if (sig == TARGET_SIGSEGV) {
ka->_sa_handler = TARGET_SIG_DFL;
}
@@ -5459,8 +5498,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
}
if (err) {
- give_sigsegv:
- if (sig == TARGET_SIGSEGV) {
+give_sigsegv:
+ if (sig == TARGET_SIGSEGV) {
ka->_sa_handler = TARGET_SIG_DFL;
}
force_sig(TARGET_SIGSEGV);
@@ -5495,7 +5534,7 @@ long do_sigreturn(CPUAlphaState *env)
unlock_user_struct(sc, sc_addr, 0);
return env->ir[IR_V0];
- badframe:
+badframe:
force_sig(TARGET_SIGSEGV);
}
@@ -5523,7 +5562,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
return env->ir[IR_V0];
- badframe:
+badframe:
unlock_user_struct(frame, frame_addr, 0);
force_sig(TARGET_SIGSEGV);
}
@@ -5690,14 +5729,14 @@ long do_rt_sigreturn(CPUTLGState *env)
#else
static void setup_frame(int sig, struct target_sigaction *ka,
- target_sigset_t *set, CPUArchState *env)
+ target_sigset_t *set, CPUArchState *env)
{
fprintf(stderr, "setup_frame: not implemented\n");
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
target_siginfo_t *info,
- target_sigset_t *set, CPUArchState *env)
+ target_sigset_t *set, CPUArchState *env)
{
fprintf(stderr, "setup_rt_frame: not implemented\n");
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 04/38] linux-user: Define TARGET_ERESTART* errno values
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (2 preceding siblings ...)
2016-05-25 5:27 ` [Qemu-devel] [PULL 03/38] linux-user: Reindent signal handling riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 05/38] linux-user: Renumber TARGET_QEMU_ESIGRETURN, make it not arch-specific riku.voipio
` (34 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Define TARGET_ERESTARTSYS; like the kernel, we will use this to
indicate that a guest system call should be restarted. We use
the same value the kernel does for this, 512.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
[PMM: split out from the patch which moves and renumbers
TARGET_QEMU_ESIGRETURN, add comment on usage]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/errno_defs.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/linux-user/errno_defs.h b/linux-user/errno_defs.h
index 8a1cf76..b7a8c9f 100644
--- a/linux-user/errno_defs.h
+++ b/linux-user/errno_defs.h
@@ -139,3 +139,11 @@
/* 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) */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 05/38] linux-user: Renumber TARGET_QEMU_ESIGRETURN, make it not arch-specific
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (3 preceding siblings ...)
2016-05-25 5:27 ` [Qemu-devel] [PULL 04/38] linux-user: Define TARGET_ERESTART* errno values riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 06/38] linux-user: Support for restarting system calls for x86 targets riku.voipio
` (33 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Currently we define a QEMU-internal errno TARGET_QEMU_ESIGRETURN
only on the MIPS and PPC targets; move this to errno_defs.h
so it is available for all architectures, and renumber it to 513.
We pick 513 because this is safe from future use as a system call return
value: Linux uses it as ERESTART_NOINTR internally and never allows that
errno to escape to userspace.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-4-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: TARGET_ERESTARTSYS split out into preceding patch, add comment]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/errno_defs.h | 9 +++++++++
linux-user/mips/target_syscall.h | 4 ----
linux-user/mips64/target_syscall.h | 4 ----
linux-user/ppc/target_syscall.h | 2 --
4 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/linux-user/errno_defs.h b/linux-user/errno_defs.h
index b7a8c9f..65522c4 100644
--- a/linux-user/errno_defs.h
+++ b/linux-user/errno_defs.h
@@ -147,3 +147,12 @@
* 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 */
diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h
index 68db160..e8e305c 100644
--- a/linux-user/mips/target_syscall.h
+++ b/linux-user/mips/target_syscall.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"
diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h
index 0e0c2d2..5789e86 100644
--- a/linux-user/mips64/target_syscall.h
+++ b/linux-user/mips64/target_syscall.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"
diff --git a/linux-user/ppc/target_syscall.h b/linux-user/ppc/target_syscall.h
index 35cab59..7ca83c2 100644
--- a/linux-user/ppc/target_syscall.h
+++ b/linux-user/ppc/target_syscall.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
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 06/38] linux-user: Support for restarting system calls for x86 targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (4 preceding siblings ...)
2016-05-25 5:27 ` [Qemu-devel] [PULL 05/38] linux-user: Renumber TARGET_QEMU_ESIGRETURN, make it not arch-specific riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 07/38] linux-user: Support for restarting system calls for ARM targets riku.voipio
` (32 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the x86 main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code rather than passing it
back out as the "return code" from do_sigreturn()
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch EAX
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-5-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: Commit message tweaks; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 47 +++++++++++++++++++++++++++++------------------
linux-user/signal.c | 15 +++++++--------
linux-user/syscall.c | 2 --
3 files changed, 36 insertions(+), 28 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index ba38aed..57ae76e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -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:
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 04c21d0..11ddd05 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1024,7 +1024,7 @@ give_sigsegv:
}
static int
-restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
+restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
{
unsigned int err = 0;
abi_ulong fpstate_addr;
@@ -1042,6 +1042,7 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
env->regs[R_EBX] = tswapl(sc->ebx);
env->regs[R_EDX] = tswapl(sc->edx);
env->regs[R_ECX] = tswapl(sc->ecx);
+ env->regs[R_EAX] = tswapl(sc->eax);
env->eip = tswapl(sc->eip);
cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
@@ -1059,7 +1060,6 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
cpu_x86_frstor(env, fpstate_addr, 1);
}
- *peax = tswapl(sc->eax);
return err;
badframe:
return 1;
@@ -1071,7 +1071,7 @@ long do_sigreturn(CPUX86State *env)
abi_ulong frame_addr = env->regs[R_ESP] - 8;
target_sigset_t target_set;
sigset_t set;
- int eax, i;
+ int i;
trace_user_do_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
@@ -1086,10 +1086,10 @@ long do_sigreturn(CPUX86State *env)
do_sigprocmask(SIG_SETMASK, &set, NULL);
/* restore registers */
- if (restore_sigcontext(env, &frame->sc, &eax))
+ if (restore_sigcontext(env, &frame->sc))
goto badframe;
unlock_user_struct(frame, frame_addr, 0);
- return eax;
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
@@ -1102,7 +1102,6 @@ long do_rt_sigreturn(CPUX86State *env)
abi_ulong frame_addr;
struct rt_sigframe *frame;
sigset_t set;
- int eax;
frame_addr = env->regs[R_ESP] - 4;
trace_user_do_rt_sigreturn(env, frame_addr);
@@ -1111,7 +1110,7 @@ long do_rt_sigreturn(CPUX86State *env)
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
do_sigprocmask(SIG_SETMASK, &set, NULL);
- if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) {
+ if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
goto badframe;
}
@@ -1121,7 +1120,7 @@ long do_rt_sigreturn(CPUX86State *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return eax;
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f4c2e19..a4a1af7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6940,12 +6940,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:
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 07/38] linux-user: Support for restarting system calls for ARM targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (5 preceding siblings ...)
2016-05-25 5:27 ` [Qemu-devel] [PULL 06/38] linux-user: Support for restarting system calls for x86 targets riku.voipio
@ 2016-05-25 5:27 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 08/38] linux-user: Support for restarting system calls for MIPS targets riku.voipio
` (31 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 5:27 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the 32-bit and 64-bit ARM main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-6-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/arm/target_signal.h | 1 +
linux-user/main.c | 48 ++++++++++++++++++++++++++----------------
linux-user/signal.c | 10 ++++-----
3 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h
index 2b32813..fb31f4c 100644
--- a/linux-user/arm/target_signal.h
+++ b/linux-user/arm/target_signal.h
@@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
return state->regs[13];
}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/main.c b/linux-user/main.c
index 57ae76e..0e3da58 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -727,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);
@@ -865,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;
@@ -1056,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 (;;) {
@@ -1065,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 */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 11ddd05..14e58b0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1390,7 +1390,7 @@ long do_rt_sigreturn(CPUARMState *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return env->xregs[0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
@@ -1902,7 +1902,7 @@ static long do_sigreturn_v1(CPUARMState *env)
send_sig(SIGTRAP, current, 1);
#endif
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV /* , current */);
@@ -2028,7 +2028,7 @@ static long do_sigreturn_v2(CPUARMState *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
@@ -2082,7 +2082,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env)
send_sig(SIGTRAP, current, 1);
#endif
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
@@ -2115,7 +2115,7 @@ static long do_rt_sigreturn_v2(CPUARMState *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 08/38] linux-user: Support for restarting system calls for MIPS targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (6 preceding siblings ...)
2016-05-25 5:27 ` [Qemu-devel] [PULL 07/38] linux-user: Support for restarting system calls for ARM targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 09/38] linux-user: Support for restarting system calls for PPC targets riku.voipio
` (30 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the MIPS main loop code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
(We already handle TARGET_QEMU_ESIGRETURN.)
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-7-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 4 ++++
linux-user/mips/target_signal.h | 1 +
linux-user/mips64/target_signal.h | 1 +
3 files changed, 6 insertions(+)
diff --git a/linux-user/main.c b/linux-user/main.c
index 0e3da58..3b47045 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2528,6 +2528,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. */
diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h
index 6e1dc8b..460cc9f 100644
--- a/linux-user/mips/target_signal.h
+++ b/linux-user/mips/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 */
diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h
index 5fb6a2c..a2dc514 100644
--- a/linux-user/mips64/target_signal.h
+++ b/linux-user/mips64/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 */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 09/38] linux-user: Support for restarting system calls for PPC targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (7 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 08/38] linux-user: Support for restarting system calls for MIPS targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 10/38] linux-user: Support for restarting system calls for SPARC targets riku.voipio
` (29 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the PPC main loop code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
(We already handle TARGET_QEMU_ESIGRETURN.)
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-8-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 4 ++++
linux-user/ppc/target_signal.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/linux-user/main.c b/linux-user/main.c
index 3b47045..f53cf9d 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1987,6 +1987,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. */
diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h
index a93b5cf..4f01dd4 100644
--- a/linux-user/ppc/target_signal.h
+++ b/linux-user/ppc/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 */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 10/38] linux-user: Support for restarting system calls for SPARC targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (8 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 09/38] linux-user: Support for restarting system calls for PPC targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 11/38] linux-user: Support for restarting system calls for SH4 targets riku.voipio
` (28 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the SPARC main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-9-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: Commit message tweaks; drop TARGET_USE_ERESTARTSYS define]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 3 +++
linux-user/signal.c | 2 +-
linux-user/sparc/target_signal.h | 1 +
linux-user/sparc64/target_signal.h | 1 +
4 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index f53cf9d..95655df 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1376,6 +1376,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;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 14e58b0..e742347 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2449,7 +2449,7 @@ long do_sigreturn(CPUSPARCState *env)
goto segv_and_exit;
}
unlock_user_struct(sf, sf_addr, 0);
- return env->regwptr[0];
+ return -TARGET_QEMU_ESIGRETURN;
segv_and_exit:
unlock_user_struct(sf, sf_addr, 0);
diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h
index c7de300..2df38c8 100644
--- a/linux-user/sparc/target_signal.h
+++ b/linux-user/sparc/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 */
diff --git a/linux-user/sparc64/target_signal.h b/linux-user/sparc64/target_signal.h
index c7de300..2df38c8 100644
--- a/linux-user/sparc64/target_signal.h
+++ b/linux-user/sparc64/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 */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 11/38] linux-user: Support for restarting system calls for SH4 targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (9 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 10/38] linux-user: Support for restarting system calls for SPARC targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 12/38] linux-user: Support for restarting system calls for Alpha targets riku.voipio
` (27 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the SH4 main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-12-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 6 +++++-
linux-user/sh4/target_signal.h | 1 +
linux-user/signal.c | 16 ++++++----------
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 95655df..838d9b3 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2826,7 +2826,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 */
diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h
index e148da0..f9911aa 100644
--- a/linux-user/sh4/target_signal.h
+++ b/linux-user/sh4/target_signal.h
@@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUSH4State *state)
return state->gregs[15];
}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index e742347..8b5ddf2 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3202,13 +3202,12 @@ static void setup_sigcontext(struct target_sigcontext *sc,
__put_user(mask, &sc->oldmask);
}
-static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
- target_ulong *r0_p)
+static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
{
int i;
#define COPY(x) __get_user(regs->x, &sc->sc_##x)
- COPY(gregs[1]);
+ COPY(gregs[0]); COPY(gregs[1]);
COPY(gregs[2]); COPY(gregs[3]);
COPY(gregs[4]); COPY(gregs[5]);
COPY(gregs[6]); COPY(gregs[7]);
@@ -3228,7 +3227,6 @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
__get_user(regs->fpul, &sc->sc_fpul);
regs->tra = -1; /* disable syscall checks */
- __get_user(*r0_p, &sc->sc_gregs[0]);
}
static void setup_frame(int sig, struct target_sigaction *ka,
@@ -3345,7 +3343,6 @@ long do_sigreturn(CPUSH4State *regs)
abi_ulong frame_addr;
sigset_t blocked;
target_sigset_t target_set;
- target_ulong r0;
int i;
int err = 0;
@@ -3366,10 +3363,10 @@ long do_sigreturn(CPUSH4State *regs)
target_to_host_sigset_internal(&blocked, &target_set);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
- restore_sigcontext(regs, &frame->sc, &r0);
+ restore_sigcontext(regs, &frame->sc);
unlock_user_struct(frame, frame_addr, 0);
- return r0;
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
@@ -3382,7 +3379,6 @@ long do_rt_sigreturn(CPUSH4State *regs)
struct target_rt_sigframe *frame;
abi_ulong frame_addr;
sigset_t blocked;
- target_ulong r0;
frame_addr = regs->gregs[15];
trace_user_do_rt_sigreturn(regs, frame_addr);
@@ -3393,7 +3389,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
do_sigprocmask(SIG_SETMASK, &blocked, NULL);
- restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
+ restore_sigcontext(regs, &frame->uc.tuc_mcontext);
if (do_sigaltstack(frame_addr +
offsetof(struct target_rt_sigframe, uc.tuc_stack),
@@ -3402,7 +3398,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
}
unlock_user_struct(frame, frame_addr, 0);
- return r0;
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 12/38] linux-user: Support for restarting system calls for Alpha targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (10 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 11/38] linux-user: Support for restarting system calls for SH4 targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 13/38] linux-user: Support for restarting system calls for UniCore32 targets riku.voipio
` (26 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the Alpha main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-13-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define;
PC is env->pc, not env->ir[IR_PV]]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/alpha/target_signal.h | 1 +
linux-user/main.c | 7 +++++--
linux-user/signal.c | 4 ++--
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h
index d3822da..4c78319 100644
--- a/linux-user/alpha/target_signal.h
+++ b/linux-user/alpha/target_signal.h
@@ -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 */
diff --git a/linux-user/main.c b/linux-user/main.c
index 838d9b3..eeea8f5 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3267,8 +3267,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
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 8b5ddf2..559e764 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5527,7 +5527,7 @@ long do_sigreturn(CPUAlphaState *env)
restore_sigcontext(env, sc);
unlock_user_struct(sc, sc_addr, 0);
- return env->ir[IR_V0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV);
@@ -5554,7 +5554,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return env->ir[IR_V0];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 13/38] linux-user: Support for restarting system calls for UniCore32 targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (11 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 12/38] linux-user: Support for restarting system calls for Alpha targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 14/38] linux-user: Support for restarting system calls for OpenRISC targets riku.voipio
` (25 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the UniCore32 main loop code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
(We don't support signals on this target so there is no sigreturn code
to update.)
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-30-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index eeea8f5..2d7e700 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1171,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],
@@ -1180,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;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 14/38] linux-user: Support for restarting system calls for OpenRISC targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (12 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 13/38] linux-user: Support for restarting system calls for UniCore32 targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 15/38] linux-user: Support for restarting system calls for M68K targets riku.voipio
` (24 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the OpenRISC main loop code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
(We don't implement sigreturn on this target so there is no
code there to update.)
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-31-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 22 ++++++++++++++--------
linux-user/openrisc/target_signal.h | 1 +
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 2d7e700..14a7826 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2724,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);
@@ -2769,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");
diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h
index 964aed6..f600501 100644
--- a/linux-user/openrisc/target_signal.h
+++ b/linux-user/openrisc/target_signal.h
@@ -23,4 +23,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state)
return state->gpr[1];
}
+
#endif /* TARGET_SIGNAL_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 15/38] linux-user: Support for restarting system calls for M68K targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (13 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 14/38] linux-user: Support for restarting system calls for OpenRISC targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 16/38] linux-user: Support for restarting system calls for S390 targets riku.voipio
` (23 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the M68K main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-32-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/m68k/target_signal.h | 1 +
linux-user/main.c | 24 +++++++++++++++---------
linux-user/signal.c | 20 ++++++++------------
3 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/linux-user/m68k/target_signal.h b/linux-user/m68k/target_signal.h
index 479758a..9deaa89 100644
--- a/linux-user/m68k/target_signal.h
+++ b/linux-user/m68k/target_signal.h
@@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUM68KState *state)
return state->aregs[7];
}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/main.c b/linux-user/main.c
index 14a7826..05a44ea 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3086,18 +3086,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:
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 559e764..3eea6b7 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5009,19 +5009,18 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
}
static void
-restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
+restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
{
int temp;
__get_user(env->aregs[7], &sc->sc_usp);
+ __get_user(env->dregs[0], &sc->sc_d0);
__get_user(env->dregs[1], &sc->sc_d1);
__get_user(env->aregs[0], &sc->sc_a0);
__get_user(env->aregs[1], &sc->sc_a1);
__get_user(env->pc, &sc->sc_pc);
__get_user(temp, &sc->sc_sr);
env->sr = (env->sr & 0xff00) | (temp & 0xff);
-
- *pd0 = tswapl(sc->sc_d0);
}
/*
@@ -5120,8 +5119,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
}
static inline int target_rt_restore_ucontext(CPUM68KState *env,
- struct target_ucontext *uc,
- int *pd0)
+ struct target_ucontext *uc)
{
int temp;
target_greg_t *gregs = uc->tuc_mcontext.gregs;
@@ -5151,7 +5149,6 @@ static inline int target_rt_restore_ucontext(CPUM68KState *env,
__get_user(temp, &gregs[17]);
env->sr = (env->sr & 0xff00) | (temp & 0xff);
- *pd0 = env->dregs[0];
return 0;
badframe:
@@ -5238,7 +5235,7 @@ long do_sigreturn(CPUM68KState *env)
abi_ulong frame_addr = env->aregs[7] - 4;
target_sigset_t target_set;
sigset_t set;
- int d0, i;
+ int i;
trace_user_do_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
@@ -5257,10 +5254,10 @@ long do_sigreturn(CPUM68KState *env)
/* restore registers */
- restore_sigcontext(env, &frame->sc, &d0);
+ restore_sigcontext(env, &frame->sc);
unlock_user_struct(frame, frame_addr, 0);
- return d0;
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV);
@@ -5273,7 +5270,6 @@ long do_rt_sigreturn(CPUM68KState *env)
abi_ulong frame_addr = env->aregs[7] - 4;
target_sigset_t target_set;
sigset_t set;
- int d0;
trace_user_do_rt_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
@@ -5284,7 +5280,7 @@ long do_rt_sigreturn(CPUM68KState *env)
/* restore registers */
- if (target_rt_restore_ucontext(env, &frame->uc, &d0))
+ if (target_rt_restore_ucontext(env, &frame->uc))
goto badframe;
if (do_sigaltstack(frame_addr +
@@ -5293,7 +5289,7 @@ long do_rt_sigreturn(CPUM68KState *env)
goto badframe;
unlock_user_struct(frame, frame_addr, 0);
- return d0;
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 16/38] linux-user: Support for restarting system calls for S390 targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (14 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 15/38] linux-user: Support for restarting system calls for M68K targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 17/38] linux-user: Support for restarting system calls for CRIS targets riku.voipio
` (22 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the S390 main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-33-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: tweak commit message; remove stray double semicolon; drop
TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 12 +++++++++---
linux-user/s390x/target_signal.h | 1 +
linux-user/signal.c | 4 ++--
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 05a44ea..2bd620c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3385,6 +3385,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);
@@ -3402,9 +3403,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:
diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h
index b4816b0..a6fb287 100644
--- a/linux-user/s390x/target_signal.h
+++ b/linux-user/s390x/target_signal.h
@@ -23,4 +23,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUS390XState *state)
return state->regs[15];
}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 3eea6b7..51e11c1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4280,7 +4280,7 @@ long do_sigreturn(CPUS390XState *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[2];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV);
@@ -4310,7 +4310,7 @@ long do_rt_sigreturn(CPUS390XState *env)
goto badframe;
}
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[2];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
unlock_user_struct(frame, frame_addr, 0);
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 17/38] linux-user: Support for restarting system calls for CRIS targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (15 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 16/38] linux-user: Support for restarting system calls for S390 targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 18/38] linux-user: Support for restarting system calls for tilegx targets riku.voipio
` (21 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the CRIS main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-34-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
[PMM: tweak commit message; drop TARGET_USE_ERESTARTSYS define]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/cris/target_signal.h | 1 +
linux-user/main.c | 6 +++++-
linux-user/signal.c | 2 +-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/linux-user/cris/target_signal.h b/linux-user/cris/target_signal.h
index 5611840..e0f1382 100644
--- a/linux-user/cris/target_signal.h
+++ b/linux-user/cris/target_signal.h
@@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUCRISState *state)
return state->regs[14];
}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/main.c b/linux-user/main.c
index 2bd620c..834974a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2914,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:
{
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 51e11c1..71a8e2a 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3785,7 +3785,7 @@ long do_sigreturn(CPUCRISState *env)
restore_sigcontext(&frame->sc, env);
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[10];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV);
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 18/38] linux-user: Support for restarting system calls for tilegx targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (16 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 17/38] linux-user: Support for restarting system calls for CRIS targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 19/38] linux-user: Set r14 on exit from microblaze syscall riku.voipio
` (20 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
Update the tilegx main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* return -TARGET_QEMU_ESIGRETURN from sigreturn rather than current R_RE
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Note that this fixes a bug where a sigreturn which happened to have
an errno value in TILEGX_R_RE would incorrectly cause TILEGX_R_ERR
to get set.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 21 +++++++++++++--------
linux-user/signal.c | 2 +-
linux-user/tilegx/target_signal.h | 1 +
3 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 834974a..1f604a7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3706,15 +3706,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;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 71a8e2a..b4641df 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5709,7 +5709,7 @@ long do_rt_sigreturn(CPUTLGState *env)
}
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[TILEGX_R_RE];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
diff --git a/linux-user/tilegx/target_signal.h b/linux-user/tilegx/target_signal.h
index b595f98..fcf1040 100644
--- a/linux-user/tilegx/target_signal.h
+++ b/linux-user/tilegx/target_signal.h
@@ -25,4 +25,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUTLGState *state)
return state->regs[TILEGX_R_SP];
}
+
#endif /* TARGET_SIGNAL_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 19/38] linux-user: Set r14 on exit from microblaze syscall
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (17 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 18/38] linux-user: Support for restarting system calls for tilegx targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 20/38] linux-user: Support for restarting system calls for Microblaze targets riku.voipio
` (19 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
All syscall exits on microblaze result in r14 being equal to the
PC we return to, because the kernel syscall exit instruction "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.)
Emulate the setting of r14 on exit; this isn't really a guest
visible change for valid guest code because r14 isn't reliably
observable anyway. However having the code and the comment helps
to explain why it's ok for the ERESTARTSYS handling not to undo
the changes to r14 that happen on syscall entry.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/linux-user/main.c b/linux-user/main.c
index 1f604a7..aa6b414 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2983,6 +2983,13 @@ void cpu_loop(CPUMBState *env)
env->regs[10],
0, 0);
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;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 20/38] linux-user: Support for restarting system calls for Microblaze targets
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (18 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 19/38] linux-user: Set r14 on exit from microblaze syscall riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 21/38] linux-user: Add debug code to exercise restarting system calls riku.voipio
` (18 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Update the Microblaze main loop and sigreturn code:
* on TARGET_ERESTARTSYS, wind guest PC backwards to repeat syscall insn
* set all guest CPU state within signal.c code on sigreturn
* handle TARGET_QEMU_ESIGRETURN in the main loop as the indication
that the main loop should not touch any guest CPU state
Note that this in passing fixes a bug where we were corrupting
the guest r[3] on sigreturn with the guest's r[10] because
do_sigreturn() was returning env->regs[10] but the register for
syscall return values is env->regs[3].
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-11-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
[PMM: Commit message tweaks; drop TARGET_USE_ERESTARTSYS define;
drop whitespace changes]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/main.c | 7 ++++++-
linux-user/microblaze/target_signal.h | 1 +
linux-user/signal.c | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index aa6b414..40aea6e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2982,7 +2982,12 @@ 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
diff --git a/linux-user/microblaze/target_signal.h b/linux-user/microblaze/target_signal.h
index 3d1f7a7..acdf3b5 100644
--- a/linux-user/microblaze/target_signal.h
+++ b/linux-user/microblaze/target_signal.h
@@ -26,4 +26,5 @@ static inline abi_ulong get_sp_from_cpustate(CPUMBState *state)
return state->regs[14];
}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b4641df..9e85550 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3618,7 +3618,7 @@ long do_sigreturn(CPUMBState *env)
env->regs[14] = env->sregs[SR_PC];
unlock_user_struct(frame, frame_addr, 0);
- return env->regs[10];
+ return -TARGET_QEMU_ESIGRETURN;
badframe:
force_sig(TARGET_SIGSEGV);
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 21/38] linux-user: Add debug code to exercise restarting system calls
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (19 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 20/38] linux-user: Support for restarting system calls for Microblaze targets riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 22/38] linux-user: Provide safe_syscall for fixing races between signals and syscalls riku.voipio
` (17 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
If DEBUG_ERESTARTSYS is set restart all system calls once. This
is pure debug code for exercising the syscall restart code paths
in the per-architecture cpu main loops.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-10-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: Add comment and a commented-out #define next to the commented-out
generic DEBUG #define; remove the check on TARGET_USE_ERESTARTSYS;
tweak comment message]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a4a1af7..ced519d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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])
@@ -5871,6 +5875,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
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 22/38] linux-user: Provide safe_syscall for fixing races between signals and syscalls
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (20 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 21/38] linux-user: Add debug code to exercise restarting system calls riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 23/38] linux-user: Use safe_syscall for read and write system calls riku.voipio
` (16 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
If a signal is delivered immediately before a blocking system call the
handler will only be called after the system call returns, which may be a
long time later or never.
This is fixed by using a function (safe_syscall) that checks if a guest
signal is pending prior to making a system call, and if so does not call the
system call and returns -TARGET_ERESTARTSYS. If a signal is received between
the check and the system call host_signal_handler() rewinds execution to
before the check. This rewinding has the effect of closing the race window
so that safe_syscall will reliably either (a) go into the host syscall
with no unprocessed guest signals pending or or (b) return
-TARGET_ERESTARTSYS so that the caller can deal with the signals.
Implementing this requires a per-host-architecture assembly language
fragment.
This will also resolve the mishandling of the SA_RESTART flag where
we would restart a host system call and not call the guest signal handler
until the syscall finally completed -- syscall restarting now always
happens at the guest syscall level so the guest signal handler will run.
(The host syscall will never be restarted because if the host kernel
rewinds the PC to point at the syscall insn for a restart then our
host_signal_handler() will see this and arrange the guest PC rewind.)
This commit contains the infrastructure for implementing safe_syscall
and the assembly language fragment for x86-64, but does not change any
syscalls to use it.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-14-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM:
* Avoid having an architecture if-ladder in configure by putting
linux-user/host/$(ARCH) on the include path and including
safe-syscall.inc.S from it
* Avoid ifdef ladder in signal.c by creating new hostdep.h to hold
host-architecture-specific things
* Added copyright/license header to safe-syscall.inc.S
* Rewrote commit message
* Added comments to safe-syscall.inc.S
* Changed calling convention of safe_syscall() to match syscall()
(returns -1 and host error in errno on failure)
* Added a long comment in qemu.h about how to use safe_syscall()
to implement guest syscalls.
]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
Makefile.target | 4 +-
linux-user/Makefile.objs | 3 +-
linux-user/host/x86_64/hostdep.h | 38 +++++++++
linux-user/host/x86_64/safe-syscall.inc.S | 81 +++++++++++++++++++
linux-user/qemu.h | 127 +++++++++++++++++++++++++++++-
linux-user/safe-syscall.S | 30 +++++++
linux-user/signal.c | 10 +++
linux-user/syscall.c | 47 +++++++++++
8 files changed, 337 insertions(+), 3 deletions(-)
create mode 100644 linux-user/host/x86_64/hostdep.h
create mode 100644 linux-user/host/x86_64/safe-syscall.inc.S
create mode 100644 linux-user/safe-syscall.S
diff --git a/Makefile.target b/Makefile.target
index 34ddb7e..c83d7ef 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -108,7 +108,9 @@ 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
+QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \
+ -I$(SRC_PATH)/linux-user/host/$(ARCH) \
+ -I$(SRC_PATH)/linux-user
obj-y += linux-user/
obj-y += gdbstub.o thunk.o user-exec.o
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
index fd50217..8c93058 100644
--- a/linux-user/Makefile.objs
+++ b/linux-user/Makefile.objs
@@ -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
diff --git a/linux-user/host/x86_64/hostdep.h b/linux-user/host/x86_64/hostdep.h
new file mode 100644
index 0000000..9dfbf3a
--- /dev/null
+++ b/linux-user/host/x86_64/hostdep.h
@@ -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
diff --git a/linux-user/host/x86_64/safe-syscall.inc.S b/linux-user/host/x86_64/safe-syscall.inc.S
new file mode 100644
index 0000000..dde434c
--- /dev/null
+++ b/linux-user/host/x86_64/safe-syscall.inc.S
@@ -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
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 208c63e..f09b750 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -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);
diff --git a/linux-user/safe-syscall.S b/linux-user/safe-syscall.S
new file mode 100644
index 0000000..b5df625
--- /dev/null
+++ b/linux-user/safe-syscall.S
@@ -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
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9e85550..ff4de4f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -561,6 +561,13 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
}
}
+#ifndef HAVE_SAFE_SYSCALL
+static inline void rewind_if_in_safe_syscall(void *puc)
+{
+ /* Default version: never rewind */
+}
+#endif
+
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
@@ -581,6 +588,9 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
if (sig < 1 || sig > TARGET_NSIG)
return;
trace_user_host_signal(env, host_signum, sig);
+
+ rewind_if_in_safe_syscall(puc);
+
host_to_target_siginfo_noswap(&tinfo, info);
if (queue_signal(env, sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ced519d..b6a8ed6 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -660,6 +660,53 @@ 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); \
+}
+
static inline int host_to_target_sock_type(int host_type)
{
int target_type;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 23/38] linux-user: Use safe_syscall for read and write system calls
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (21 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 22/38] linux-user: Provide safe_syscall for fixing races between signals and syscalls riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 24/38] linux-user: Use safe_syscall for open and openat " riku.voipio
` (15 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Restart read() and write() if signals occur before, or during with SA_RESTART
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-15-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: Update to new safe_syscall() convention of setting errno]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b6a8ed6..bee1360 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -707,6 +707,9 @@ static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
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)
+
static inline int host_to_target_sock_type(int host_type)
{
int target_type;
@@ -5983,7 +5986,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);
@@ -5994,7 +5997,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
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 24/38] linux-user: Use safe_syscall for open and openat system calls
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (22 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 23/38] linux-user: Use safe_syscall for read and write system calls riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 25/38] linux-user: Use safe_syscall for wait " riku.voipio
` (14 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Restart open() and openat() if signals occur before,
or during with SA_RESTART.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-17-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: Adjusted to follow new -1-and-set-errno safe_syscall convention]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bee1360..0037ee7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -359,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,
@@ -709,6 +697,8 @@ static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
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)
static inline int host_to_target_sock_type(int host_type)
{
@@ -5851,7 +5841,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 : 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++) {
@@ -5887,7 +5877,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
return fd;
}
- return sys_openat(dirfd, path(pathname), flags, mode);
+ return safe_openat(dirfd, path(pathname), flags, mode);
}
#define TIMER_MAGIC 0x0caf0000
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 25/38] linux-user: Use safe_syscall for wait system calls
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (23 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 24/38] linux-user: Use safe_syscall for open and openat " riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 26/38] linux-user: Use safe_syscall for execve syscall riku.voipio
` (13 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Use safe_syscall for waitpid, waitid and wait4 syscalls. Note that this
change allows us to implement support for waitid's fifth (rusage) argument
in future; for the moment we ignore it as we have done up til now.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-18-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: Adjust to new safe_syscall convention. Add fifth waitid syscall argument
(which isn't present in the libc interface but is in the syscall ABI)]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0037ee7..d9f4695 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -699,6 +699,10 @@ 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)
static inline int host_to_target_sock_type(int host_type)
{
@@ -6037,7 +6041,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;
@@ -6049,7 +6053,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;
@@ -7761,7 +7765,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);
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 26/38] linux-user: Use safe_syscall for execve syscall
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (24 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 25/38] linux-user: Use safe_syscall for wait " riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 27/38] linux-user: Use safe_syscall for pselect, select syscalls riku.voipio
` (12 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Timothy E Baldwin
From: Timothy E Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Wrap execve() in the safe-syscall handling. Although execve() is not
an interruptible syscall, it is a special case: 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.
The practical upshot is that without this SIGTERM could fail to
terminate the process.
Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Message-id: 1441497448-32489-25-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
[PMM: expanded commit message to explain in more detail why this is
needed, and add comment about it too]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d9f4695..dea827f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -703,6 +703,7 @@ 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)
static inline int host_to_target_sock_type(int host_type)
{
@@ -6179,7 +6180,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;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 27/38] linux-user: Use safe_syscall for pselect, select syscalls
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (25 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 26/38] linux-user: Use safe_syscall for execve syscall riku.voipio
@ 2016-05-25 10:31 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 28/38] linux-user: Use safe_syscall for futex syscall riku.voipio
` (11 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
Use the safe_syscall wrapper for the pselect and select syscalls.
Since not every architecture has the select syscall, we now
have to implement select in terms of pselect, which means doing
timeval<->timespec conversion.
(Five years on from the initial patch that added pselect support
to QEMU and a decade after pselect6 went into the kernel, it seems
safe to not try to support hosts with header files which don't
define __NR_pselect6.)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index dea827f..c9c2ae9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -430,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
@@ -704,6 +695,8 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
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)
static inline int host_to_target_sock_type(int host_type)
{
@@ -1115,7 +1108,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);
@@ -1134,12 +1128,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))
@@ -1149,8 +1146,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;
@@ -7206,8 +7208,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))
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 28/38] linux-user: Use safe_syscall for futex syscall
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (26 preceding siblings ...)
2016-05-25 10:31 ` [Qemu-devel] [PULL 27/38] linux-user: Use safe_syscall for pselect, select syscalls riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 29/38] linux-user: Handle negative values in timespec conversion riku.voipio
` (10 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
Use the safe_syscall wrapper for the futex syscall.
In particular, this fixes hangs when using programs that link
against the Boehm garbage collector, including the Mono runtime.
(We don't change the sys_futex() call in the implementation of
the exit syscall, because as the FIXME comment there notes
that should be handled by disabling signals, since we can't
easily back out if the futex were to return ERESTARTSYS.)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c9c2ae9..4e419fb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -697,6 +697,8 @@ safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
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)
{
@@ -5381,12 +5383,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:
@@ -5396,11 +5398,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;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 29/38] linux-user: Handle negative values in timespec conversion
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (27 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 28/38] linux-user: Use safe_syscall for futex syscall riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 30/38] linux-user: Handle msgrcv error case correctly riku.voipio
` (9 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
In a struct timespec, both fields are signed longs. Converting
them from guest to host with code like
host_ts->tv_sec = tswapal(target_ts->tv_sec);
mishandles negative values if the guest has 32-bit longs and
the host has 64-bit longs because tswapal()'s return type is
abi_ulong: the assignment will zero-extend into the host long
type rather than sign-extending it.
Make the conversion routines use __get_user() and __set_user()
instead: this automatically picks up the signedness of the
field type and does the correct kind of sign or zero extension.
It also handles the possibility that the target struct is not
sufficiently aligned for the host's requirements.
In particular, this fixes a hang when running the Linux Test Project
mq_timedsend01 and mq_timedreceive01 tests: one of the test cases
sets the timeout to -1 and expects an EINVAL failure, but we were
setting a very long timeout instead.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4e419fb..6c4f5c6 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5194,8 +5194,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;
}
@@ -5207,8 +5207,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;
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 30/38] linux-user: Handle msgrcv error case correctly
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (28 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 29/38] linux-user: Handle negative values in timespec conversion riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 31/38] linux-user: Use g_try_malloc() in do_msgrcv() riku.voipio
` (8 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
The msgrcv ABI is a bit odd -- the msgsz argument is a size_t, which is
unsigned, but it must fail EINVAL if the value is negative when cast
to a long. We were incorrectly passing the value through an
"unsigned int", which meant that if the guest was 32-bit longs and
the host was 64-bit longs an input of 0xffffffff (which should trigger
EINVAL) would simply be passed to the host msgrcv() as 0xffffffff,
where it does not cause the host kernel to reject it.
Follow the same approach as do_msgsnd() in using a ssize_t and
doing the check for negative values by hand, so we correctly fail
in this corner case.
This fixes the msgrcv03 Linux Test Project test case, which otherwise
hangs.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6c4f5c6..cec5b80 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3152,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;
@@ -3160,6 +3160,10 @@ 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;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 31/38] linux-user: Use g_try_malloc() in do_msgrcv()
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (29 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 30/38] linux-user: Handle msgrcv error case correctly riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 32/38] linux-user: x86_64: Don't use 16-bit UIDs riku.voipio
` (7 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
In do_msgrcv() we want to allocate a message buffer, whose size
is passed to us by the guest. That means we could legitimately
fail, so use g_try_malloc() and handle the error case, in the same
way that do_msgsnd() does.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cec5b80..40e8742 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3167,7 +3167,11 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
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) {
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 32/38] linux-user: x86_64: Don't use 16-bit UIDs
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (30 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 31/38] linux-user: Use g_try_malloc() in do_msgrcv() riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 33/38] linux-user: Use direct syscalls for setuid(), etc riku.voipio
` (6 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
The 64-bit x86 syscall ABI uses 32-bit UIDs; only define
USE_UID16 for 32-bit x86.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall_defs.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 9e2b3c2..34af15a 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -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 */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 33/38] linux-user: Use direct syscalls for setuid(), etc
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (31 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 32/38] linux-user: x86_64: Don't use 16-bit UIDs riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 34/38] linux-user: arm: Remove ARM_cpsr and similar #defines riku.voipio
` (5 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
On Linux the setuid(), setgid(), etc system calls have different semantics
from the libc functions. The libc functions follow POSIX and update the
credentials for all threads in the process; the system calls update only
the thread which makes the call. (This impedance mismatch is worked around
in libc by signalling all threads to tell them to do a syscall, in a
byzantine and fragile way; see http://ewontfix.com/17/.)
Since in linux-user we are trying to emulate the system call semantics,
we must implement all these syscalls to directly call the underlying
host syscall, rather than calling the host libc function.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/syscall.c | 58 +++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 46 insertions(+), 12 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 40e8742..df70255 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5099,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;
@@ -8834,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
@@ -8855,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
@@ -8883,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));
@@ -9168,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
@@ -9187,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
@@ -9214,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
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 34/38] linux-user: arm: Remove ARM_cpsr and similar #defines
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (32 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 33/38] linux-user: Use direct syscalls for setuid(), etc riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 35/38] linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame riku.voipio
` (4 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
The #defines of ARM_cpsr and friends in linux-user/arm/target-syscall.h
can clash with versions in the system headers if building on an
ARM or AArch64 build (though this seems to be dependent on the version
of the system headers). The QEMU defines are not very useful (it's
not clear that they're intended for use with the target_pt_regs struct
rather than (say) the CPUARMState structure) and we only use them in one
function in elfload.c anyway. So just remove the #defines and directly
access regs->uregs[].
Reported-by: Christopher Covington <cov@codeaurora.org>
Tested-by: Christopher Covington <cov@codeaurora.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/arm/target_syscall.h | 20 +-------------------
linux-user/elfload.c | 19 ++++++++++---------
2 files changed, 11 insertions(+), 28 deletions(-)
diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h
index ea863db..11077b7 100644
--- a/linux-user/arm/target_syscall.h
+++ b/linux-user/arm/target_syscall.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
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index e47caff..bb2558f 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -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
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 35/38] linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (33 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 34/38] linux-user: arm: Remove ARM_cpsr and similar #defines riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 36/38] linux-user/signal.c: Use target address instead of host address for microblaze restorer riku.voipio
` (3 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Chen Gang
From: Chen Gang <chengang@emindsoft.com.cn>
Original implementation uses do_rt_sigreturn directly in host space,
when a guest program is in unwind procedure in guest space, it will get
an incorrect restore address, then causes unwind failure.
Also cleanup the original incorrect indentation.
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/signal.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index ff4de4f..a072fa6 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5599,8 +5599,13 @@ struct target_rt_sigframe {
unsigned char save_area[16]; /* caller save area */
struct target_siginfo info;
struct target_ucontext uc;
+ abi_ulong retcode[2];
};
+#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
+#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
+
+
static void setup_sigcontext(struct target_sigcontext *sc,
CPUArchState *env, int signo)
{
@@ -5676,9 +5681,12 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
- restorer = (unsigned long) do_rt_sigreturn;
if (ka->sa_flags & TARGET_SA_RESTORER) {
- restorer = (unsigned long) ka->sa_restorer;
+ restorer = (unsigned long) ka->sa_restorer;
+ } else {
+ __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
+ __put_user(INSN_SWINT1, &frame->retcode[1]);
+ restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
}
env->pc = (unsigned long) ka->_sa_handler;
env->regs[TILEGX_R_SP] = (unsigned long) frame;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 36/38] linux-user/signal.c: Use target address instead of host address for microblaze restorer
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (34 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 35/38] linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 37/38] linux-user/signal.c: Use s390 target space address instead of host space riku.voipio
` (2 subsequent siblings)
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Chen Gang
From: Chen Gang <chengang@emindsoft.com.cn>
The return address is in target space, so the restorer address needs to
be target space, too.
Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/signal.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index a072fa6..c75fb48 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3573,7 +3573,8 @@ static void setup_frame(int sig, struct target_sigaction *ka,
/* Return from sighandler will jump to the tramp.
Negative 8 offset because return is rtsd r15, 8 */
- env->regs[15] = ((unsigned long)frame->tramp) - 8;
+ env->regs[15] = frame_addr + offsetof(struct target_signal_frame, tramp)
+ - 8;
}
/* Set up registers for signal handler */
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 37/38] linux-user/signal.c: Use s390 target space address instead of host space
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (35 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 36/38] linux-user/signal.c: Use target address instead of host address for microblaze restorer riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 38/38] linux-user, target-ppc: fix use of MSR_LE riku.voipio
2016-05-25 16:33 ` [Qemu-devel] [PULL 00/38] linux-user update Peter Maydell
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Chen Gang
From: Chen Gang <chengang@emindsoft.com.cn>
The return address is in target space, so the restorer address needs to
be target space, too.
Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
---
linux-user/signal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c75fb48..28ce921 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4159,8 +4159,8 @@ static void setup_frame(int sig, struct target_sigaction *ka,
env->regs[14] = (unsigned long)
ka->sa_restorer | PSW_ADDR_AMODE;
} else {
- env->regs[14] = (unsigned long)
- frame->retcode | PSW_ADDR_AMODE;
+ env->regs[14] = (frame_addr + offsetof(sigframe, retcode))
+ | PSW_ADDR_AMODE;
__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
(uint16_t *)(frame->retcode));
}
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [Qemu-devel] [PULL 38/38] linux-user, target-ppc: fix use of MSR_LE
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (36 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 37/38] linux-user/signal.c: Use s390 target space address instead of host space riku.voipio
@ 2016-05-25 10:32 ` riku.voipio
2016-05-25 16:33 ` [Qemu-devel] [PULL 00/38] linux-user update Peter Maydell
38 siblings, 0 replies; 41+ messages in thread
From: riku.voipio @ 2016-05-25 10:32 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
From: Laurent Vivier <laurent@vivier.eu>
setup_frame()/setup_rt_frame()/restore_user_regs() are using
MSR_LE as the similar kernel functions do: as a bitmask.
But in QEMU, MSR_LE is a bit position, so change this
accordingly.
The previous code was doing nothing as MSR_LE is 0,
and "env->msr &= ~MSR_LE" doesn't change the value of msr.
And yes, a user process can change its endianness,
see linux kernel commit:
fab5db9 [PATCH] powerpc: Implement support for setting little-endian mode via prctl
and prctl(2): PR_SET_ENDIAN, PR_GET_ENDIAN
Reviewed-by: Thomas Huth <huth@tuxfamily.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
---
linux-user/signal.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 28ce921..8090b4d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4632,7 +4632,7 @@ static void restore_user_regs(CPUPPCState *env,
/* If doing signal return, restore the previous little-endian mode. */
if (sig)
- env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE);
+ env->msr = (env->msr & ~(1ull << MSR_LE)) | (msr & (1ull << MSR_LE));
/* Restore Altivec registers if necessary. */
if (env->insns_flags & PPC_ALTIVEC) {
@@ -4747,7 +4747,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
#endif
/* Signal handlers are entered in big-endian mode. */
- env->msr &= ~MSR_LE;
+ env->msr &= ~(1ull << MSR_LE);
unlock_user_struct(frame, frame_addr, 1);
return;
@@ -4842,7 +4842,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
#endif
/* Signal handlers are entered in big-endian mode. */
- env->msr &= ~MSR_LE;
+ env->msr &= ~(1ull << MSR_LE);
unlock_user_struct(rt_sf, rt_sf_addr, 1);
return;
--
2.1.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PULL 00/38] linux-user update
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
` (37 preceding siblings ...)
2016-05-25 10:32 ` [Qemu-devel] [PULL 38/38] linux-user, target-ppc: fix use of MSR_LE riku.voipio
@ 2016-05-25 16:33 ` Peter Maydell
2016-05-26 12:00 ` Peter Maydell
38 siblings, 1 reply; 41+ messages in thread
From: Peter Maydell @ 2016-05-25 16:33 UTC (permalink / raw)
To: Riku Voipio; +Cc: QEMU Developers
On 25 May 2016 at 06:27, <riku.voipio@linaro.org> wrote:
> From: Riku Voipio <riku.voipio@linaro.org>
>
> The following changes since commit b0f6ef8915247f3230ffd9b71af9c3dadb6082c7:
>
> Merge remote-tracking branch 'remotes/amit-virtio-rng/tags/rng-2.7-1' into staging (2016-05-24 11:38:22 +0100)
>
> are available in the git repository at:
>
> git://git.linaro.org/people/riku.voipio/qemu.git tags/pull-linux-user-20160525
>
> for you to fetch changes up to 210a7201d1bd9e25eec01d23edb713f181eabb23:
>
> linux-user,target-ppc: fix use of MSR_LE (2016-05-24 15:45:46 +0300)
>
> ----------------------------------------------------------------
> Linux user update for May 2016
Oops, this doesn't build on non-x86 hosts:
cc -I/home/petmay01/qemu/tcg -I/home/petmay01/qemu/tcg/aarch64
-I/home/petmay01/qemu/linux-headers
-I/home/petmay01/qemu/build/all-a64/linux-headers -I.
-I/home/petmay01/qemu -I/home/petmay01/qemu/include
-I/home/petmay01/qemu -I. -I/usr/include/pixman-1 -Werror
-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings
-Wmissing-prototypes -fno-strict-aliasing -fno-common -Wendif-labels
-Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security
-Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration
-Wold-style-definition -Wtype-limits -fstack-protector-all
-I/usr/include/p11-kit-1 -I/usr/include/libpng12
-I/usr/include/libusb-1.0 -I../linux-headers -I..
-I/home/petmay01/qemu/target-arm -DNEED_CPU_H
-I/home/petmay01/qemu/include -I/home/petmay01/qemu/linux-user/aarch64
-I/home/petmay01/qemu/linux-user/host/aarch64
-I/home/petmay01/qemu/linux-user -MMD -MP -MT exec.o -MF ./exec.d -O2
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -pthread -I/usr/include/glib-2.0
-I/usr/lib/aarch64-linux-gnu/glib-2.0/include -g -c -o exec.o
/home/petmay01/qemu/exec.c
cc1: error: /home/petmay01/qemu/linux-user/host/aarch64: No such file
or directory [-Werror]
Looks like the C compiler doesn't like nonexistent -I directories.
I thought I'd tested "does this still build without the host-specific
.S file", but I guess I must have had the directory floating around
in my working tree.
I'll sort out a fixup patch tomorrow...
thanks
-- PMM
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [Qemu-devel] [PULL 00/38] linux-user update
2016-05-25 16:33 ` [Qemu-devel] [PULL 00/38] linux-user update Peter Maydell
@ 2016-05-26 12:00 ` Peter Maydell
0 siblings, 0 replies; 41+ messages in thread
From: Peter Maydell @ 2016-05-26 12:00 UTC (permalink / raw)
To: Riku Voipio; +Cc: QEMU Developers
On 25 May 2016 at 17:33, Peter Maydell <peter.maydell@linaro.org> wrote:
> Looks like the C compiler doesn't like nonexistent -I directories.
> I thought I'd tested "does this still build without the host-specific
> .S file", but I guess I must have had the directory floating around
> in my working tree.
>
> I'll sort out a fixup patch tomorrow...
Fixup patch: http://patchwork.ozlabs.org/patch/626643/
thanks
-- PMM
^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2016-05-26 12:00 UTC | newest]
Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-25 5:27 [Qemu-devel] [PULL 00/38] linux-user update riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 01/38] linux-user: Check array bounds in errno conversion riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 02/38] linux-user: Consistently return host errnos from do_openat() riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 03/38] linux-user: Reindent signal handling riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 04/38] linux-user: Define TARGET_ERESTART* errno values riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 05/38] linux-user: Renumber TARGET_QEMU_ESIGRETURN, make it not arch-specific riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 06/38] linux-user: Support for restarting system calls for x86 targets riku.voipio
2016-05-25 5:27 ` [Qemu-devel] [PULL 07/38] linux-user: Support for restarting system calls for ARM targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 08/38] linux-user: Support for restarting system calls for MIPS targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 09/38] linux-user: Support for restarting system calls for PPC targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 10/38] linux-user: Support for restarting system calls for SPARC targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 11/38] linux-user: Support for restarting system calls for SH4 targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 12/38] linux-user: Support for restarting system calls for Alpha targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 13/38] linux-user: Support for restarting system calls for UniCore32 targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 14/38] linux-user: Support for restarting system calls for OpenRISC targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 15/38] linux-user: Support for restarting system calls for M68K targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 16/38] linux-user: Support for restarting system calls for S390 targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 17/38] linux-user: Support for restarting system calls for CRIS targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 18/38] linux-user: Support for restarting system calls for tilegx targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 19/38] linux-user: Set r14 on exit from microblaze syscall riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 20/38] linux-user: Support for restarting system calls for Microblaze targets riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 21/38] linux-user: Add debug code to exercise restarting system calls riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 22/38] linux-user: Provide safe_syscall for fixing races between signals and syscalls riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 23/38] linux-user: Use safe_syscall for read and write system calls riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 24/38] linux-user: Use safe_syscall for open and openat " riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 25/38] linux-user: Use safe_syscall for wait " riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 26/38] linux-user: Use safe_syscall for execve syscall riku.voipio
2016-05-25 10:31 ` [Qemu-devel] [PULL 27/38] linux-user: Use safe_syscall for pselect, select syscalls riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 28/38] linux-user: Use safe_syscall for futex syscall riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 29/38] linux-user: Handle negative values in timespec conversion riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 30/38] linux-user: Handle msgrcv error case correctly riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 31/38] linux-user: Use g_try_malloc() in do_msgrcv() riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 32/38] linux-user: x86_64: Don't use 16-bit UIDs riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 33/38] linux-user: Use direct syscalls for setuid(), etc riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 34/38] linux-user: arm: Remove ARM_cpsr and similar #defines riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 35/38] linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 36/38] linux-user/signal.c: Use target address instead of host address for microblaze restorer riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 37/38] linux-user/signal.c: Use s390 target space address instead of host space riku.voipio
2016-05-25 10:32 ` [Qemu-devel] [PULL 38/38] linux-user, target-ppc: fix use of MSR_LE riku.voipio
2016-05-25 16:33 ` [Qemu-devel] [PULL 00/38] linux-user update Peter Maydell
2016-05-26 12:00 ` Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).