This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: IA64 INLINE_SYSCALL Support
- From: Ian Wienand <ianw at gelato dot unsw dot edu dot au>
- To: libc-alpha at sources dot redhat dot com
- Date: Thu, 12 Dec 2002 16:16:01 +1100
- Subject: Re: IA64 INLINE_SYSCALL Support
- References: <20021204010849.GA32269@cse.unsw.edu.au>
Hi,
Did anyone get a chance to review this? Are there any problems with
the code?
After speaking with some colleagues they have suggested that the
problem of strange values appearing is a common ia64 pitfall, as gcc
doesn't treat non-stacked registers (r8,r10,etc) like normal
registers, so even if you tell it they are clobbered it doesn't really
guarantee you anything.
-i
ianw@gelato.unsw.edu.au
On Wed, Dec 04, 2002 at 12:08:49PM +1100, Ian Wienand wrote:
> I found this patch
> http://sources.redhat.com/ml/libc-hacker/2001-03/msg00061.html which I
> have modified.
>
> The most obvious problem with that patch is that on IA64 the returned
> errno is not negative. on a syscall return, r10 is set to -1 to
> flag an error, and r8 then contains the return value or the positive
> errno (this is not the case for internal kernel errors though, where
> the errno convention follows the single value return for error and
> errno, it's just de-multiplexed for return to userspace).
>
> The less obvious problem is that using register variables (_r8 and
> _r10 in the original) doesn't really work. It seems to work some of
> the time, but other times r8 manages to get it's self corrupted
> somewhere between returning and going back to the calling function.
>
> At any rate the attached modified patch works for me.
>
> -i
> ianw@gelato.unsw.edu.au
>
> --- sysdeps/unix/sysv/linux/ia64/sysdep.h.old 2002-12-04 11:59:33.000000000 +1100
> +++ sysdeps/unix/sysv/linux/ia64/sysdep.h 2002-12-03 16:35:24.000000000 +1100
> @@ -102,11 +102,74 @@
>
> #else /* not __ASSEMBLER__ */
>
> -/* Define a macro which expands into the inline wrapper code for a system
> - call. */
> -#if 0
> -#undef INLINE_SYSCALL
> -#define INLINE_SYSCALL(name, nr, args...) __##name (args)
> -#endif
> +/* On IA-64 we have stacked registers for passing arguments. The
> + "out" registers end up being the called function's "in"
> + registers.
>
> + Also, since we have plenty of registers we have two return values
> + from a syscall. r10 is set to -1 on error, whilst r8 contains the
> + (non-negative) errno on error or the return value on success.
> +*/
> +#define INLINE_SYSCALL(name, nr, args...) \
> + ({ \
> + int syscall = __NR_##name; /* r15 */ \
> + int retval; /* r8 */ \
> + int error; /* r10 */ \
> + LOAD_ARGS_##nr (args); \
> + asm volatile ( "mov r15=%2\n\t" \
> + "break %3;;\n\t" \
> + "mov %0=r8\n\t" \
> + "mov %1=r10\n\t" \
> + : "=r" (retval), "=r" (error) \
> + : "r"(syscall) , "i" (__BREAK_SYSCALL) \
> + ASM_ARGS_##nr \
> + : "memory" ASM_CLOBBERS_##nr); \
> + if (error == (long) -1) \
> + { \
> + __set_errno (retval); \
> + retval = (long) -1; \
> + } \
> + (int) retval; })
> +
> +#define LOAD_ARGS_0() do { } while (0)
> +#define LOAD_ARGS_1(out0) \
> + register long _out0 asm ("out0") = (long) (out0); \
> + LOAD_ARGS_0 ()
> +#define LOAD_ARGS_2(out0, out1) \
> + register long _out1 asm ("out1") = (long) (out1); \
> + LOAD_ARGS_1 (out0)
> +#define LOAD_ARGS_3(out0, out1, out2) \
> + register long _out2 asm ("out2") = (long) (out2); \
> + LOAD_ARGS_2 (out0, out1)
> +#define LOAD_ARGS_4(out0, out1, out2, out3) \
> + register long _out3 asm ("out3") = (long) (out3); \
> + LOAD_ARGS_3 (out0, out1, out2)
> +#define LOAD_ARGS_5(out0, out1, out2, out3, out4) \
> + register long _out4 asm ("out4") = (long) (out4); \
> + LOAD_ARGS_4 (out0, out1, out2, out3)
> +
> +#define ASM_ARGS_0
> +#define ASM_ARGS_1 ASM_ARGS_0, "r" (_out0)
> +#define ASM_ARGS_2 ASM_ARGS_1, "r" (_out1)
> +#define ASM_ARGS_3 ASM_ARGS_2, "r" (_out2)
> +#define ASM_ARGS_4 ASM_ARGS_3, "r" (_out3)
> +#define ASM_ARGS_5 ASM_ARGS_4, "r" (_out4)
> +
> +#define ASM_CLOBBERS_0 ASM_CLOBBERS_1, "out0"
> +#define ASM_CLOBBERS_1 ASM_CLOBBERS_2, "out1"
> +#define ASM_CLOBBERS_2 ASM_CLOBBERS_3, "out2"
> +#define ASM_CLOBBERS_3 ASM_CLOBBERS_4, "out3"
> +#define ASM_CLOBBERS_4 ASM_CLOBBERS_5, "out4"
> +#define ASM_CLOBBERS_5 , "out5", "out6", "out7", \
> + /* Non-stacked integer registers, minus r8, r10, r15. */ \
> + "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \
> + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \
> + "r28", "r29", "r30", "r31", \
> + /* Predicate registers. */ \
> + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \
> + /* Non-rotating fp registers. */ \
> + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
> + /* Branch registers. */ \
> + "b6", "b7"
> +
> #endif /* not __ASSEMBLER__ */