On 13 June 2016 at 22:45, Richard Henderson <r...@twiddle.net> wrote: > Signed-off-by: Richard Henderson <r...@twiddle.net> > --- > linux-user/host/aarch64/hostdep.h | 34 ++++++++++++++ > linux-user/host/aarch64/safe-syscall.inc.S | 72 > ++++++++++++++++++++++++++++++ > 2 files changed, 106 insertions(+) > create mode 100644 linux-user/host/aarch64/hostdep.h > create mode 100644 linux-user/host/aarch64/safe-syscall.inc.S > > diff --git a/linux-user/host/aarch64/hostdep.h > b/linux-user/host/aarch64/hostdep.h > new file mode 100644 > index 0000000..0ff7985 > --- /dev/null > +++ b/linux-user/host/aarch64/hostdep.h > @@ -0,0 +1,34 @@ > +/* > + * hostdep.h : things which are dependent on the host architecture > + * > + * 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; > + __u64 *pcreg = &uc->uc_mcontext.pc; > + > + 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/aarch64/safe-syscall.inc.S > b/linux-user/host/aarch64/safe-syscall.inc.S > new file mode 100644 > index 0000000..5416b90 > --- /dev/null > +++ b/linux-user/host/aarch64/safe-syscall.inc.S > @@ -0,0 +1,72 @@ > +/* > + * 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 > + * > + * 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 > + .type safe_syscall_start, #function > + .type safe_syscall_end, #function
_start and _end aren't function entry points, so is it OK to mark them as functions? (The 'as' manual doesn't document what setting .type does in much detail...) > + > + /* 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: > + .cfi_startproc > + /* The syscall calling convention isn't the same as the > + * C one: > + * we enter with x0 == *signal_pending > + * x1 == syscall number > + * x2 ... x7, (stack) == syscall arguments > + * and return the result in x0 > + * and the syscall instruction needs > + * x8 == syscall number > + * x0 ... x6 == syscall arguments > + * and returns the result in x0 > + * Shuffle everything around appropriately. > + */ http://man7.org/linux/man-pages/man2/syscall.2.html doesn't mention a syscall argument in x7, just x0..x5. > + mov x9, x0 /* signal_pending pointer */ > + mov w8, w1 /* syscall number */ Seems a bit odd to use a 32-bit move for this when our input calling convention has it as 64 bits and the kernel's calling convention has it as 64 bits. > + mov x0, x2 /* syscall arguments */ > + mov x1, x3 > + mov x2, x4 > + mov x3, x5 > + mov x4, x6 > + mov x6, x7 > + ldr x7, [sp] > + > + /* 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 */ > + ldr w10, [x9] > + cbnz w10, 0f > + svc 0x0 > +safe_syscall_end: > + /* code path for having successfully executed the syscall */ > + ret > + > +0: > + /* code path when we didn't execute the syscall */ > + mov x0, #-TARGET_ERESTARTSYS > + ret > + .cfi_endproc > + > + .size safe_syscall_base, .-safe_syscall_base > -- > 2.5.5 > thanks -- PMM