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);
}