Subject: Re: Signal handling changes
To: Charles M. Hannum <mycroft@mit.edu>
From: None <rvb@sicily.odyssey.cs.cmu.edu>
List: tech-kern
Date: 08/29/1998 16:06:14
"Charles M. Hannum" <mycroft@mit.edu> writes:

> 2) I have to make a lot of changes to emulation code (sys/compat) to
>    properly handle signal set conversion.  In particular, the way
>    signal contexts are handled is really broken; I will be introducing
>    a per-CPU, per-emulation version of sigreturn, and modifying the
>    existing implementations of sendsig to use the correct signal
>    context format for the emulation in question.

I'm happy to see that someone is revisiting this issue.  I have
probably a slightly different problem that you should look at
regarding signals and emulation.  I can give you code in the context
of a 1.3 kernel but I've not merged it into current yet.  The basic
problem is simple.  When you decide to deliver a signal, you use the
emulated delivery method.  But very often you deliver the wrong info.
Supposed you get a page fault and need to deliver it to a Linux
process.   Is it a SIGBUS or SIGSEGV? and what args does it get
(think cr2 here).

I am forced to code like:

int trapno_to_x86vec[] = {
                6,              /*  0 T_PRIVINFLT */
                3,              /*  1 T_BPTFLT */
                16,             /*  2 T_ARITHTRAP */
                254,            /*  3 T_ASTFLT */
                13,             /*  4 T_PROTFLT */
                1,              /*  5 T_TRCTRAP */
                14,             /*  6 T_PAGEFLT */
                17,             /*  7 T_ALIGNFLT */
                0,              /*  8 T_DIVIDE */
                2,              /*  9 T_NMI */
                4,              /* 10 T_OFLOW */
                5,              /* 11 T_BOUND */
                7,              /* 12 T_DNA */
                8,              /* 13 T_DOUBLEFLT */
                9,              /* 14 T_FPOPFLT */
                10,             /* 15 T_TSSFLT */
                11,             /* 16 T_SEGNPFLT */
                12,             /* 17 T_STKFLT */
                255             /* 18 T_RESERVED */
};

/* For the nmi and reserved below linux does not post a signal. */
int x86vec_to_linux_sig[] = {
        SIGFPE,  SIGTRAP, /*nmi*/ SIGSEGV, SIGTRAP,
        SIGSEGV, SIGSEGV, SIGILL,          SIGSEGV,
        SIGSEGV, SIGFPE,  SIGSEGV,         SIGBUS,
        SIGBUS,  SIGSEGV, SIGSEGV,         /* reserved */ SIGSEGV,
        SIGFPE,  SIGSEGV
};

/*
 * Translate a NetBSD hardware signal to the corresponding
 * linux signal.
 */
void
linux_translate_signal(struct proc *p, int *signum, u_long *code);

void
linux_translate_signal(p, signum, code)
        struct proc *p;
        int *signum;
        u_long *code;
{
        register struct trapframe *tf = p->p_md.md_regs;

#define SIGHDW ((1<<SIGILL)|(1<<SIGTRAP)|(1<<SIGIOT)|(1<<SIGBUS)|(1<<SIGFPE)|(1<<SIGSEG\
V))

        if (SIGHDW & (1<<*signum)) {
                tf->tf_trapno = trapno_to_x86vec[tf->tf_trapno];
                *code = tf->tf_trapno;
                *signum=x86vec_to_linux_sig[tf->tf_trapno];
        }
}

------------
------------
Then trap() calls emul_trapsignal rather than trapsignal as defined below:

void
emul_trapsignal(p, signum, code)
        struct proc *p;
        int signum;
        u_long code;
{

#ifdef COMPAT_LINUX
        if (p->p_emul == &emul_linux_aout || p->p_emul == &emul_linux_elf)
                linux_translate_signal(p, &signum, &code);
#endif
        trapsignal(p, signum, code);
}