Subject: Linux RT signals emulation (PowerPC vs i386)
To: None <tech-kern@netbsd.org, port-i386@netbsd.org, port-powerpc@netbsd.org>
From: Emmanuel Dreyfus <p99dreyf@criens.u-psud.fr>
List: tech-kern
Date: 03/18/2001 13:22:05
Background: NetBSD/PowerPC emulation of Linux binaries is broken when
dealing with RT signals: on return from the signal handler, sigreturn()
is called instead of rt_sigreturn().

Here is some code from the Linux kernel, on syscall entry (PowerPC
version):

linux/arch/ppc/kernel/entry.S:
#endif /* SHOW_SYSCALLS */
        cmpi    0,r0,0x7777     /* Special case for 'sys_sigreturn' */
        beq-    10f
        cmpi    0,r0,0x6666     /* Special case for 'sys_rt_sigreturn'*/
        beq-    16f
        lwz     r10,TASK_FLAGS(r2)

What I understand here is that there is a special case when entering the
kernel on sigreturn or rt_sigreturn call. I'm not sure we really care
about this, our problem yet is that sigreturn is called where
rt_sigreturn should be called.

The signal trampoline is built in linux/arch/ppc/kernel/signal.c, in
setup_frame() and setup_rt_frame(), depending if we are doing a standard
signal or a RT signal.

linux/arch/ppc/kernel/signal.c:setup_frame()
    || __put_user(0x38007777UL, &frame->tramp[0])    /* li r0,0x7777 */
    || __put_user(0x44000002UL, &frame->tramp[1]))   /* sc */

linux/arch/ppc/kernel/signal.c:setup_rt_frame()
    || __put_user(0x38006666UL, &frame->tramp[0])  /* li r0,0x6666 */
    || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */

Decision on which function to use is made here:
linux/arch/ppc/kernel/signal.c:do_signal()
   if (ka->sa.sa_flags & SA_SIGINFO)
      setup_rt_frame(regs, (struct sigregs *) frame, newsp);
   else 
      setup_frame(regs, (struct sigregs *) frame, newsp);

In a nutshell, Linux has two functions to setup the stack and two
different trampoline codes. What is wrong in the emulation on the
PowerPC now is that I only have one trampoline code, for sigreturn().
It's in sys/arch/powerpc/powerpc/linux_sigcode.s, and it is called
linux_sigcode.

And more, I do not make any decision on the SA_SIGINFO flag when I'm
building the signal stack, in
sys/compat/linux/arch/powerpc/linux_machdep.c:sendsig()

NetBSD/i386 has two signal trampolines in
sys/arch/i386/i386/linux_sigcode.s. One for sigreturn(), and the other
for rt_sigreturn(). They are called linux_sigcode and linux_rt_sigcode 

Both linux_sigcode goes into the emulation switch in
sys/compat/linux/common/linux_exec.c. What surprises me is that
linux_rt_sigcode does not seems to be used anywhere in the i386
emulation.

Hence the question: do NetBSD/i386 make any use of Linux RT signals? It
seems to me that it does treat all signals as been standards signals,
not RT signals. If this is true, is it because of the lack of RT signals
support from NetBSD? And it seems that NetBSD/i386 emulation is able to
run Linux's JDK-1.3.0, hence emulation of RT signals as standard signals
does not seems to be a real problem. Is it? I remember I've readen
something like glibc does not use RT signal because of the kernel
version returned by emulated uname(). Is it true? (ie: does Linux i386
binaries avoid using RT signals on NetBSD because of the kernel version
returned by uname?)

-- 
Emmanuel Dreyfus.  
p99dreyf@criens.u-psud.fr