This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: IA64 INLINE_SYSCALL Support


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__ */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]