[RFC] RT signals

Jakub Jelinek (jj@sunsite.ms.mff.cuni.cz)
Wed, 28 Jul 1999 17:35:15 +0200


Hi!

The implementation of POSIX timers which made it into 2.3.12pre adds a
siginfo_t nrt_info[SIGRTMIN] array to task structure. That's 4K if I count
well, which seems a little bit dangerous to me. So I wonder whether a
patch like the one below would not be useful.
Basically, it leaves the padding (the only huge thing in siginfo_t) only for
userland and works only with the known field in the union. At least from
what I understood about rt signals, user should not stand up and create his
own new siginfo format and pass it through signals because the kernel would
not understand that at all, meaning e.g. on sparc that you cannot do that
between 32bit and 64bit task. I checked Solaris and it seems at least from
their siginfo.h that they user internally only the know fields and the
padding is for userland only. It could also speed things up, because kernel
will no longer have to copy 128 bytes here and there when about 3/4 of that
is padding.
This patch also changes the si_uid type on sparc32 to int. I doubt it will
matter for any application in the field, because glibc defines that si_uid
field to int, no conversion is done, we are big endian and nobody noticed.
It is IMHO better than making glibc translate siginfo_t whenever
encountered.
This patch also removes tss.sig_address and tss.sig_desc because it is
obsoleted now when one can send info with non RT signals and tries to send
info with a bunch of kernel generated signals.
Also, I have removed non-rt signal syscalls from 64bit sparc userland to
remove cruft. Can you think of any reason why not to have all signals
SA_SIGINFO other than binary compatibility (which I still don't care about
for sparc64 userland)? When we are not copying the 96 byte pad, those few
bytes won't be noticable IMHO.

--- ./arch/alpha/kernel/signal.c.jj Wed Jul 28 12:58:32 1999
+++ ./arch/alpha/kernel/signal.c Wed Jul 28 13:19:02 1999
@@ -221,7 +221,10 @@ struct sigframe

struct rt_sigframe
{
- struct siginfo info;
+ union {
+ struct siginfo info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct ucontext uc;
unsigned int retcode[3];
};
@@ -487,7 +490,7 @@ setup_rt_frame(int sig, struct k_sigacti
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;

- err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));
+ err |= __copy_to_user(&frame->info.info, info, sizeof(siginfo_t));

/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
--- ./arch/arm/kernel/signal.c.jj Wed Jul 28 12:59:04 1999
+++ ./arch/arm/kernel/signal.c Wed Jul 28 13:23:11 1999
@@ -129,7 +129,10 @@ struct rt_sigframe
{
struct siginfo *pinfo;
void *puc;
- struct siginfo info;
+ union {
+ struct siginfo info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct ucontext uc;
unsigned long retcode;
};
@@ -365,9 +368,9 @@ static void setup_rt_frame(int sig, stru
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto segv_and_exit;

- err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->info.info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= __copy_to_user(&frame->info, info, sizeof(*info));
+ err |= __copy_to_user(&frame->info.info, info, sizeof(*info));

/* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
--- ./arch/i386/kernel/signal.c.jj Wed Jul 28 12:59:40 1999
+++ ./arch/i386/kernel/signal.c Wed Jul 28 13:24:19 1999
@@ -144,7 +144,10 @@ struct rt_sigframe
int sig;
struct siginfo *pinfo;
void *puc;
- struct siginfo info;
+ union {
+ struct siginfo info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct ucontext uc;
struct _fpstate fpstate;
char retcode[8];
@@ -483,9 +486,9 @@ static void setup_rt_frame(int sig, stru
? current->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
- err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->info.info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= __copy_to_user(&frame->info, info, sizeof(*info));
+ err |= __copy_to_user(&frame->info.info, info, sizeof(*info));

/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
--- ./arch/m68k/kernel/signal.c.jj Wed Jul 28 13:00:58 1999
+++ ./arch/m68k/kernel/signal.c Wed Jul 28 13:28:57 1999
@@ -175,7 +175,10 @@ struct rt_sigframe
int sig;
struct siginfo *pinfo;
void *puc;
- struct siginfo info;
+ union {
+ struct siginfo info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct ucontext uc;
char retcode[8];
};
@@ -864,9 +867,9 @@ static void setup_rt_frame (int sig, str
? current->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
- err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->info.info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
- err |= __copy_to_user(&frame->info, info, sizeof(*info));
+ err |= __copy_to_user(&frame->info.info, info, sizeof(*info));

/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
--- ./arch/sparc/ap1000/msc.c.jj Wed Jul 28 13:02:44 1999
+++ ./arch/sparc/ap1000/msc.c Wed Jul 28 15:33:55 1999
@@ -623,9 +623,13 @@ static void fail_write(int context,int i
if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
handle_signal(context,vaddr);
} else {
- task[tsk]->tss.sig_address = vaddr;
- task[tsk]->tss.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, task[tsk], 1);
+ siginfo_t info;
+
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = vaddr;
+ force_sig_info (SIGSEGV, &info, task[tsk]);
}
}
}
--- ./arch/sparc/kernel/signal.c.jj Wed Jul 28 13:02:57 1999
+++ ./arch/sparc/kernel/signal.c Wed Jul 28 15:28:00 1999
@@ -83,7 +83,10 @@ struct new_signal_frame {

struct rt_signal_frame {
struct sparc_stackf ss;
- siginfo_t info;
+ union {
+ siginfo_t info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct pt_regs regs;
sigset_t mask;
__siginfo_fpu_t *fpu_save;
@@ -424,11 +427,13 @@ static inline void *get_sigframe(struct

static inline void
setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
- struct pt_regs *regs, int signr, sigset_t *oldset)
+ struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
{
struct signal_sframe *sframep;
struct sigcontext *sc;
int window = 0, err;
+ void *sig_address;
+ int sig_code;

synchronize_user_stack();
sframep = (struct signal_sframe *)get_sigframe(sa, regs, SF_ALIGNEDSZ);
@@ -474,17 +479,55 @@ setup_frame(struct sigaction *sa, unsign

current->tss.w_saved = 0; /* So process is allowed to execute. */
err |= __put_user(signr, &sframep->sig_num);
- if(signr == SIGSEGV ||
- signr == SIGILL ||
- signr == SIGFPE ||
- signr == SIGBUS ||
- signr == SIGEMT) {
- err |= __put_user(current->tss.sig_desc, &sframep->sig_code);
- err |= __put_user(current->tss.sig_address, &sframep->sig_address);
- } else {
- err |= __put_user(0, &sframep->sig_code);
- err |= __put_user(0, &sframep->sig_address);
+ sig_address = NULL;
+ sig_code = 0;
+ if (SI_FROMKERNEL (info)) {
+ sig_address = info->si_addr;
+ switch (signr) {
+ case SIGSEGV:
+ switch (info->si_code) {
+ case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
+ default: sig_code = SUBSIG_PROTECTION; break;
+ }
+ break;
+ case SIGILL:
+ switch (info->si_code) {
+ case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
+ case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
+ case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP (info->si_trapno); break;
+ default: sig_code = SUBSIG_STACK; break;
+ }
+ break;
+ case SIGFPE:
+ switch (info->si_code) {
+ case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
+ case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
+ case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
+ case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
+ case FPE_FLFUND: sig_code = SUBSIG_FPUNFLOW; break;
+ case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
+ case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
+ default: sig_code = SUBSIG_FPERROR; break;
+ }
+ break;
+ case SIGBUS:
+ switch (info->si_code) {
+ case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
+ case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
+ default: sig_code = SUBSIG_BUSTIMEOUT; break;
+ }
+ break;
+ case SIGEMT:
+ switch (info->si_code) {
+ case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
+ }
+ break;
+ default:
+ sig_address = NULL;
+ }
}
+ err |= __put_user(sig_address, &sframep->sig_address);
+ err |= __put_user(sig_code, &sframep->sig_code);
err |= __put_user(sc, &sframep->sig_scptr);
if (err)
goto sigsegv;
@@ -659,12 +702,14 @@ new_setup_rt_frame(struct k_sigaction *k

err |= __copy_to_user(sf, (char *) regs->u_regs [UREG_FP],
sizeof (struct reg_window));
+ err |= __copy_to_user(&sf->info.info, info, sizeof(siginfo_t));
+
if (err)
goto sigsegv;

regs->u_regs[UREG_FP] = (unsigned long) sf;
regs->u_regs[UREG_I0] = signo;
- regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+ regs->u_regs[UREG_I1] = (unsigned long) &sf->info.info;

regs->pc = (unsigned long) ka->sa.sa_handler;
regs->npc = (regs->pc + 4);
@@ -973,7 +1018,7 @@ handle_signal(unsigned long signr, struc
else if (current->tss.new_signal)
new_setup_frame (ka, regs, signr, oldset);
else
- setup_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset);
+ setup_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset, info);
}
if(ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
--- ./arch/sparc/kernel/unaligned.c.jj Wed Jul 28 13:03:09 1999
+++ ./arch/sparc/kernel/unaligned.c Wed Jul 28 14:50:47 1999
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/signal.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -422,14 +423,19 @@ void user_mna_trap_fault(struct pt_regs

void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
{
- current->tss.sig_address = regs->pc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGBUS, current, 1);
+ siginfo_t info;
+
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = address;
+ send_sig_info (SIGBUS, &info, tsk);
}

asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
{
enum direction dir;
+ siginfo_t info;

lock_kernel();
if(!(current->tss.flags & SPARC_FLAG_UNALIGNED) ||
@@ -487,9 +493,11 @@ asmlinkage void user_unaligned_trap(stru
}

kill_user:
- current->tss.sig_address = regs->pc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGBUS, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = address;
+ send_sig_info (SIGBUS, &info, tsk);
out:
unlock_kernel();
}
--- ./arch/sparc/kernel/traps.c.jj Wed Jul 28 13:03:08 1999
+++ ./arch/sparc/kernel/traps.c Wed Jul 28 16:23:28 1999
@@ -128,6 +128,8 @@ void die_if_kernel(char *str, struct pt_

void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
{
+ siginfo_t info;
+
lock_kernel();
if(type < 0x80) {
/* Sun OS's puke from bad traps, Linux survives! */
@@ -141,9 +143,12 @@ void do_hw_interrupt(unsigned long type,
if(psr & PSR_PS)
die_if_kernel("Kernel bad trap", current->tss.kregs);

- current->tss.sig_desc = SUBSIG_BADTRAP(type - 0x80);
- current->tss.sig_address = pc;
- send_sig(SIGILL, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_ILLTRP;
+ info.si_addr = pc;
+ info.si_trapno = type - 0x80;
+ send_sig_info (SIGILL, &info, tsk);
}
unlock_kernel();
}
@@ -151,6 +156,8 @@ void do_hw_interrupt(unsigned long type,
void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(psr & PSR_PS)
die_if_kernel("Kernel illegal instruction", regs);
@@ -163,9 +170,11 @@ void do_illegal_instruction(struct pt_re
if (!do_user_muldiv (regs, pc))
goto out;
}
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_ILLINST;
- send_sig(SIGILL, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = pc;
+ send_sig_info (SIGILL, &info, tsk);
out:
unlock_kernel();
}
@@ -173,12 +182,16 @@ out:
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(psr & PSR_PS)
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_PRVOPC;
+ info.si_addr = pc;
+ send_sig_info (SIGILL, &info, tsk);
unlock_kernel();
}

@@ -187,6 +200,8 @@ void do_priv_instruction(struct pt_regs
void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(regs->psr & PSR_PS) {
printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
@@ -194,14 +209,16 @@ void do_memaccess_unaligned(struct pt_re
die_if_kernel("BOGUS", regs);
/* die_if_kernel("Kernel MNA access", regs); */
}
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
#if 0
show_regs (regs);
instruction_dump ((unsigned long *) regs->pc);
printk ("do_MNA!\n");
#endif
- send_sig(SIGBUS, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = pc;
+ send_sig_info (SIGBUS, &info, tsk);
unlock_kernel();
}

@@ -269,6 +286,7 @@ void do_fpe_trap(struct pt_regs *regs, u
unsigned long psr)
{
static int calls = 0;
+ siginfo_t info;
int ret = 0;
#ifndef __SMP__
struct task_struct *fpt = last_task_used_math;
@@ -326,8 +344,19 @@ void do_fpe_trap(struct pt_regs *regs, u
}
/* nope, better SIGFPE the offending process... */

- fpt->tss.sig_address = pc;
- fpt->tss.sig_desc = SUBSIG_FPERROR; /* as good as any */
+ memset (&info, 0, sizeof (info));
+ info.si_signo = SIGFPE;
+ if (fpt->tss.fsr & 0x10)
+ info.si_code = FPE_FLTINV;
+ else if (fpt->tss.fsr & 8)
+ info.si_code = FPE_FLTOVF;
+ else if (fpt->tss.fsr & 4)
+ info.si_code = FPE_FLTUND;
+ else if (fpt->tss.fsr & 2)
+ info.si_code = FPE_FLTDIV;
+ else
+ info.si_code = FPE_FLTRES;
+ info.si_addr = pc;
#ifdef __SMP__
fpt->flags &= ~PF_USEDFPU;
#endif
@@ -345,7 +374,7 @@ void do_fpe_trap(struct pt_regs *regs, u
regs);
goto out;
}
- send_sig(SIGFPE, fpt, 1);
+ send_sig_info (SIGFPE, &info, fpt);
#ifndef __SMP__
last_task_used_math = NULL;
#endif
@@ -359,12 +388,16 @@ out:
void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(psr & PSR_PS)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
- send_sig(SIGEMT, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGEMT;
+ info.si_code = EMT_TAGOVF;
+ info.si_addr = pc;
+ send_sig_info (SIGEMT, &info, tsk);
unlock_kernel();
}

--- ./arch/sparc/kernel/process.c.jj Wed Jul 28 13:02:53 1999
+++ ./arch/sparc/kernel/process.c Wed Jul 28 15:08:06 1999
@@ -305,7 +305,6 @@ void show_thread(struct thread_struct *t

printk("uwinmask: 0x%08lx kregs: 0x%08lx\n", tss->uwinmask, (unsigned long)tss->kregs);
show_regs(tss->kregs);
- printk("sig_address: 0x%08lx sig_desc: 0x%08lx\n", tss->sig_address, tss->sig_desc);
printk("ksp: 0x%08lx kpc: 0x%08lx\n", tss->ksp, tss->kpc);
printk("kpsr: 0x%08lx kwim: 0x%08lx\n", tss->kpsr, tss->kwim);
printk("fork_kpsr: 0x%08lx fork_kwim: 0x%08lx\n", tss->fork_kpsr, tss->fork_kwim);
--- ./arch/sparc/kernel/sys_sunos.c.jj Wed Jul 28 13:03:05 1999
+++ ./arch/sparc/kernel/sys_sunos.c Wed Jul 28 16:39:52 1999
@@ -595,15 +595,21 @@ asmlinkage int sunos_uname(struct sunos_
asmlinkage int sunos_nosys(void)
{
struct pt_regs *regs;
+ siginfo_t info;
+ static int cnt;

lock_kernel();
regs = current->tss.kregs;
- current->tss.sig_address = regs->pc;
- current->tss.sig_desc = regs->u_regs[UREG_G1];
- send_sig(SIGSYS, current, 1);
- printk("Process makes ni_syscall number %d, register dump:\n",
- (int) regs->u_regs[UREG_G1]);
- show_regs(regs);
+ memset (&info, 0, sizeof (info));
+ info.si_signo = SIGSYS;
+ info.si_addr = regs->pc;
+ info.si_code = regs->u_regs[UREG_G1] & 0x7fffffff;
+ send_sig_info(SIGSYS, &info, current);
+ if (cnt++ < 4) {
+ printk("Process makes ni_syscall number %d, register dump:\n",
+ (int) regs->u_regs[UREG_G1]);
+ show_regs(regs);
+ }
unlock_kernel();
return -ENOSYS;
}
--- ./arch/sparc/mm/fault.c.jj Wed Jul 28 13:03:26 1999
+++ ./arch/sparc/mm/fault.c Wed Jul 28 14:52:53 1999
@@ -197,6 +197,7 @@ asmlinkage void do_sparc_fault(struct pt
unsigned int fixup;
unsigned long g2;
int from_user = !(regs->psr & PSR_PS);
+ siginfo_t info;

if(text_fault)
address = regs->pc;
@@ -280,9 +281,11 @@ do_kernel_fault:
printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lx\n",
tsk->comm, tsk->pid, address, regs->pc);
#endif
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_NOMAPPING;
- force_sig(SIGSEGV, tsk);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = address;
+ force_sig_info (SIGSEGV, &info, tsk);
return;
}
unhandled_fault (address, tsk, regs);
@@ -290,9 +293,11 @@ do_kernel_fault:

do_sigbus:
up(&mm->mmap_sem);
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_MISCERROR;
- force_sig(SIGBUS, tsk);
+ memset (&info, 0, sizeof (info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = address;
+ force_sig_info (SIGBUS, &info, tsk);
if (! from_user)
goto do_kernel_fault;
}
@@ -366,6 +371,7 @@ inline void force_user_fault(unsigned lo
struct vm_area_struct *vma;
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
+ siginfo_t info;

#if 0
printk("wf<pid=%d,wr=%d,addr=%08lx>\n",
@@ -399,16 +405,20 @@ bad_area:
printk("Window whee %s [%d]: segfaults at %08lx\n",
tsk->comm, tsk->pid, address);
#endif
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, tsk, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = address;
+ send_sig_info (SIGSEGV, &info, tsk);
return;

do_sigbus:
up(&mm->mmap_sem);
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_MISCERROR;
- force_sig(SIGBUS, tsk);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = address;
+ force_sig_info (SIGBUS, &info, tsk);
}

void window_overflow_fault(void)
--- ./arch/sparc/mm/asyncd.c.jj Wed Jul 28 13:03:25 1999
+++ ./arch/sparc/mm/asyncd.c Wed Jul 28 14:52:16 1999
@@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/config.h>
#include <linux/interrupt.h>
+#include <linux/signal.h>

#include <asm/dma.h>
#include <asm/system.h> /* for cli()/sti() */
@@ -115,6 +116,7 @@ static int fault_in_page(int taskid,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
+ siginfo_t info;

if (!tsk || !tsk->mm)
return 1;
@@ -178,9 +180,11 @@ no_memory:

bad_area:
stats.failure++;
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, tsk, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = address;
+ send_sig_info (SIGSEGV, &info, tsk);
return 1;
}

--- ./arch/sparc64/kernel/signal32.c.jj Wed Jul 28 13:03:49 1999
+++ ./arch/sparc64/kernel/signal32.c Wed Jul 28 16:48:02 1999
@@ -84,7 +84,10 @@ struct new_signal_frame32 {

struct rt_signal_frame32 {
struct sparc_stackf32 ss;
- siginfo_t32 info;
+ union {
+ siginfo_t32 info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct pt_regs32 regs;
sigset_t32 mask;
/* __siginfo_fpu32_t * */ u32 fpu_save;
@@ -437,12 +440,14 @@ static inline void *get_sigframe(struct

static void
setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
- struct pt_regs *regs, int signr, sigset_t *oldset)
+ struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
{
struct signal_sframe32 *sframep;
struct sigcontext32 *sc;
unsigned seta[_NSIG_WORDS32];
int err = 0;
+ void *sig_address;
+ int sig_code;

#if 0
int window = 0;
@@ -513,17 +518,55 @@ setup_frame32(struct sigaction *sa, unsi

current->tss.w_saved = 0; /* So process is allowed to execute. */
err |= __put_user(signr, &sframep->sig_num);
- if(signr == SIGSEGV ||
- signr == SIGILL ||
- signr == SIGFPE ||
- signr == SIGBUS ||
- signr == SIGEMT) {
- err |= __put_user(current->tss.sig_desc, &sframep->sig_code);
- err |= __put_user(current->tss.sig_address, &sframep->sig_address);
- } else {
- err |= __put_user(0, &sframep->sig_code);
- err |= __put_user(0, &sframep->sig_address);
+ sig_address = NULL;
+ sig_code = 0;
+ if (SI_FROMKERNEL (info)) {
+ sig_address = info->si_addr;
+ switch (signr) {
+ case SIGSEGV:
+ switch (info->si_code) {
+ case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
+ default: sig_code = SUBSIG_PROTECTION; break;
+ }
+ break;
+ case SIGILL:
+ switch (info->si_code) {
+ case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
+ case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
+ case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP (info->si_trapno); break;
+ default: sig_code = SUBSIG_STACK; break;
+ }
+ break;
+ case SIGFPE:
+ switch (info->si_code) {
+ case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
+ case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
+ case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
+ case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
+ case FPE_FLFUND: sig_code = SUBSIG_FPUNFLOW; break;
+ case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
+ case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
+ default: sig_code = SUBSIG_FPERROR; break;
+ }
+ break;
+ case SIGBUS:
+ switch (info->si_code) {
+ case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
+ case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
+ default: sig_code = SUBSIG_BUSTIMEOUT; break;
+ }
+ break;
+ case SIGEMT:
+ switch (info->si_code) {
+ case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
+ }
+ break;
+ default:
+ sig_address = NULL;
+ }
}
+ err |= __put_user((long)sig_address, &sframep->sig_address);
+ err |= __put_user(sig_code, &sframep->sig_code);
err |= __put_user((u64)sc, &sframep->sig_scptr);
if (err)
goto sigsegv;
@@ -789,8 +832,7 @@ setup_svr4_frame32(struct sigaction *sa,

/* Setup the signal information. Solaris expects a bunch of
* information to be passed to the signal handler, we don't provide
- * that much currently, should use those that David already
- * is providing with tss.sig_desc
+ * that much currently, should use siginfo_t.
*/
err |= __put_user(signr, &si->siginfo.signo);
err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
@@ -1033,6 +1075,39 @@ static inline void setup_rt_frame32(stru
err |= __put_user(0, &sf->fpu_save);
}

+ /* Ugh. Now have to understand siginfo_t a little bit: */
+ err |= __put_user(info->si_signo, &sf->info.info.si_signo);
+ err |= __put_user(info->si_errno, &sf->info.info.si_errno);
+ err |= __put_user(info->si_code, &sf->info.info.si_code);
+ i = signr;
+ if (SI_FROMUSER (info))
+ i = SIGRTMIN;
+ switch (i) {
+ case SIGILL:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGEMT:
+ err |= __put_user((long)info->si_addr, &sf->info.info.si_addr);
+ err |= __put_user(info->si_trapno, &sf->info.info.si_trapno);
+ break;
+ case SIGCHLD:
+ err |= __put_user(info->si_pid, &sf->info.info.si_pid);
+ err |= __put_user(info->si_uid, &sf->info.info.si_uid);
+ err |= __put_user(info->si_status, &sf->info.info.si_status);
+ err |= __put_user(info->si_utime, &sf->info.info.si_utime);
+ err |= __put_user(info->si_stime, &sf->info.info.si_stime);
+ break;
+ default:
+ /* The rest of the union members can be handled by this code. */
+ err |= __put_user(info->si_pid, &sf->info.info.si_pid);
+ err |= __put_user(info->si_uid, &sf->info.info.si_uid);
+ /* This is uneasy, because we don't know whether we should copy
+ si_int or si_ptr. Choose arbitrarily. */
+ err |= __put_user(info->si_int, &sf->info.info.si_int);
+ break;
+ }
+
/* Setup sigaltstack */
err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
@@ -1059,7 +1134,7 @@ static inline void setup_rt_frame32(stru
/* 3. signal handler back-trampoline and parameters */
regs->u_regs[UREG_FP] = (unsigned long) sf;
regs->u_regs[UREG_I0] = signr;
- regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+ regs->u_regs[UREG_I1] = (unsigned long) &sf->info.info;

/* 4. signal handler */
regs->tpc = (unsigned long) ka->sa.sa_handler;
@@ -1116,7 +1191,7 @@ static inline void handle_signal32(unsig
else if (current->tss.new_signal)
new_setup_frame32(ka, regs, signr, oldset);
else
- setup_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset);
+ setup_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset, info);
}
if(ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
--- ./arch/sparc64/kernel/signal.c.jj Wed Jul 28 13:03:47 1999
+++ ./arch/sparc64/kernel/signal.c Wed Jul 28 17:25:36 1999
@@ -226,24 +226,12 @@ do_sigsegv:
do_exit(SIGSEGV);
}

-/*
- * The new signal frame, intended to be used for Linux applications only
- * (we have enough in there to work with clone).
- * All the interesting bits are in the info field.
- */
-
-struct new_signal_frame {
- struct sparc_stackf ss;
- __siginfo_t info;
- __siginfo_fpu_t * fpu_save;
- unsigned int insns [2];
- unsigned long extramask[_NSIG_WORDS-1];
- __siginfo_fpu_t fpu_state;
-};
-
struct rt_signal_frame {
struct sparc_stackf ss;
- siginfo_t info;
+ union {
+ siginfo_t info;
+ char pad [SI_MAX_SIZE];
+ } info;
struct pt_regs regs;
sigset_t mask;
__siginfo_fpu_t * fpu_save;
@@ -253,7 +241,6 @@ struct rt_signal_frame {
};

/* Align macros */
-#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))

/*
@@ -378,59 +365,6 @@ restore_fpu_state(struct pt_regs *regs,
return err;
}

-void do_sigreturn(struct pt_regs *regs)
-{
- struct new_signal_frame *sf;
- unsigned long tpc, tnpc, tstate;
- __siginfo_fpu_t *fpu_save;
- sigset_t set;
- int err;
-
- synchronize_user_stack ();
- sf = (struct new_signal_frame *)
- (regs->u_regs [UREG_FP] + STACK_BIAS);
-
- /* 1. Make sure we are not getting garbage from the user */
- if (((unsigned long) sf) & 3)
- goto segv;
-
- err = get_user(tpc, &sf->info.si_regs.tpc);
- err |= __get_user(tnpc, &sf->info.si_regs.tnpc);
- err |= ((tpc | tnpc) & 3);
-
- /* 2. Restore the state */
- err |= __get_user(regs->y, &sf->info.si_regs.y);
- err |= __get_user(tstate, &sf->info.si_regs.tstate);
- err |= copy_from_user(regs->u_regs, sf->info.si_regs.u_regs, sizeof(regs->u_regs));
-
- /* User can only change condition codes in %tstate. */
- regs->tstate &= ~(TSTATE_ICC);
- regs->tstate |= (tstate & TSTATE_ICC);
-
- err |= __get_user(fpu_save, &sf->fpu_save);
- if (fpu_save)
- err |= restore_fpu_state(regs, &sf->fpu_state);
-
- err |= __get_user(set.sig[0], &sf->info.si_mask);
- if (_NSIG_WORDS > 1)
- err |= __copy_from_user(&set.sig[1], &sf->extramask, sizeof(sf->extramask));
-
- if (err)
- goto segv;
-
- regs->tpc = tpc;
- regs->tnpc = tnpc;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
- current->blocked = set;
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
- return;
-segv:
- send_sig(SIGSEGV, current, 1);
-}
-
void do_rt_sigreturn(struct pt_regs *regs)
{
struct rt_signal_frame *sf;
@@ -533,77 +467,6 @@ static inline void *get_sigframe(struct
}

static inline void
-new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
- int signo, sigset_t *oldset)
-{
- struct new_signal_frame *sf;
- int sigframe_size, err;
-
- /* 1. Make sure everything is clean */
- synchronize_user_stack();
- save_and_clear_fpu();
-
- sigframe_size = NF_ALIGNEDSZ;
-
- if (!(current->tss.fpsaved[0] & FPRS_FEF))
- sigframe_size -= sizeof(__siginfo_fpu_t);
-
- sf = (struct new_signal_frame *)get_sigframe(ka, regs, sigframe_size);
-
- if (invalid_frame_pointer (sf, sigframe_size))
- goto sigill;
-
- if (current->tss.w_saved != 0) {
-#ifdef DEBUG_SIGNALS
- printk ("%s[%d]: Invalid user stack frame for "
- "signal delivery.\n", current->comm, current->pid);
-#endif
- goto sigill;
- }
-
- /* 2. Save the current process state */
- err = copy_to_user(&sf->info.si_regs, regs, sizeof (*regs));
-
- if (current->tss.fpsaved[0] & FPRS_FEF) {
- err |= save_fpu_state(regs, &sf->fpu_state);
- err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
- } else {
- err |= __put_user(0, &sf->fpu_save);
- }
-
- err |= __put_user(oldset->sig[0], &sf->info.si_mask);
- if (_NSIG_WORDS > 1)
- err |= __copy_to_user(sf->extramask, &oldset->sig[1],
- sizeof(sf->extramask));
-
- err |= copy_in_user((u64 *)sf,
- (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
- sizeof(struct reg_window));
- if (err)
- goto sigsegv;
-
- /* 3. signal handler back-trampoline and parameters */
- regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
- regs->u_regs[UREG_I0] = signo;
- regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
-
- /* 5. signal handler */
- regs->tpc = (unsigned long) ka->sa.sa_handler;
- regs->tnpc = (regs->tpc + 4);
-
- /* 4. return to kernel instructions */
- regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
- return;
-
-sigill:
- lock_kernel();
- do_exit(SIGILL);
-sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
-}
-
-static inline void
setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
int signo, sigset_t *oldset, siginfo_t *info)
{
@@ -652,7 +515,7 @@ setup_rt_frame(struct k_sigaction *ka, s
(u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
sizeof(struct reg_window));

- err |= copy_to_user(&sf->info, info, sizeof(siginfo_t));
+ err |= copy_to_user(&sf->info.info, info, sizeof(siginfo_t));
if (err)
goto sigsegv;

@@ -681,10 +544,7 @@ static inline void handle_signal(unsigne
siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
- if(ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(ka, regs, signr, oldset, info);
- else
- new_setup_frame(ka, regs, signr, oldset);
+ setup_rt_frame(ka, regs, signr, oldset, info);
if(ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if(!(ka->sa.sa_flags & SA_NOMASK)) {
--- ./arch/sparc64/kernel/systbls.S.jj Wed Jul 28 13:03:56 1999
+++ ./arch/sparc64/kernel/systbls.S Wed Jul 28 16:18:01 1999
@@ -112,15 +112,15 @@ sys_call_table:
.word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
+/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
.word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
/*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
-/*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall
+/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
.word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
- .word sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
-/*220*/ .word sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
+ .word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex
+/*220*/ .word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
/*230*/ .word sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
--- ./arch/sparc64/kernel/entry.S.jj Wed Jul 28 13:03:37 1999
+++ ./arch/sparc64/kernel/entry.S Wed Jul 28 16:21:03 1999
@@ -635,7 +635,7 @@ execve_merge:

.globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall
.globl sys_sigsuspend, sys_rt_sigsuspend, sys32_rt_sigsuspend
- .globl sys_sigreturn, sys_rt_sigreturn
+ .globl sys_rt_sigreturn
.globl sys32_sigreturn, sys32_rt_sigreturn
.globl sys32_execve, sys_ptrace
.globl sys_sigaltstack, sys32_sigaltstack
@@ -687,10 +687,6 @@ sys32_rt_sigsuspend: /* NOTE: %o0,%o1 ha
/* NOTE: %o0 has a correct value already */
sys_sigpause: add %sp, STACK_BIAS + REGWIN_SZ, %o1
call do_sigpause
- add %o7, 1f-.-4, %o7
- nop
-sys_sigreturn: add %sp, STACK_BIAS + REGWIN_SZ, %o0
- call do_sigreturn
add %o7, 1f-.-4, %o7
nop
sys32_sigreturn:
--- ./arch/sparc64/kernel/traps.c.jj Wed Jul 28 13:03:57 1999
+++ ./arch/sparc64/kernel/traps.c Wed Jul 28 16:36:53 1999
@@ -253,6 +253,8 @@ void rtrap_check(struct pt_regs *regs)

void bad_trap (struct pt_regs *regs, long lvl)
{
+ siginfo_t info;
+
lock_kernel ();
if (lvl < 0x100) {
char buffer[24];
@@ -262,9 +264,12 @@ void bad_trap (struct pt_regs *regs, lon
}
if (regs->tstate & TSTATE_PRIV)
die_if_kernel ("Kernel bad trap", regs);
- current->tss.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
- current->tss.sig_address = regs->tpc;
- force_sig(SIGILL, current);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_ILLTRP;
+ info.si_addr = pc;
+ info.si_trapno = type - 0x100;
+ send_sig_info (SIGILL, &info, tsk);
unlock_kernel ();
}

@@ -281,6 +286,8 @@ void bad_trap_tl1 (struct pt_regs *regs,
void instruction_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
+ siginfo_t info;
+
lock_kernel();
if (regs->tstate & TSTATE_PRIV) {
#if 1
@@ -289,9 +296,11 @@ void instruction_access_exception (struc
#endif
die_if_kernel("Iax", regs);
}
- current->tss.sig_desc = SUBSIG_ILLINST;
- current->tss.sig_address = regs->tpc;
- force_sig(SIGILL, current);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = pc;
+ send_sig_info (SIGSEGV, &info, tsk);
unlock_kernel();
}

@@ -402,9 +411,22 @@ void do_fpe_common(struct pt_regs *regs)
regs->tpc = regs->tnpc;
regs->tnpc += 4;
} else {
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_FPERROR;
- send_sig(SIGFPE, current, 1);
+ siginfo_t info;
+
+ memset (&info, 0, sizeof (info));
+ info.si_signo = SIGFPE;
+ if (current->tss.xfsr[0] & 0x10)
+ info.si_code = FPE_FLTINV;
+ else if (current->tss.xfsr[0] & 8)
+ info.si_code = FPE_FLTOVF;
+ else if (current->tss.xfsr[0] & 4)
+ info.si_code = FPE_FLTUND;
+ else if (current->tss.xfsr[0] & 2)
+ info.si_code = FPE_FLTDIV;
+ else
+ info.si_code = FPE_FLTRES;
+ info.si_addr = regs->tpc;
+ send_sig_info (SIGFPE, &info, current);
}
}

@@ -438,11 +460,16 @@ void do_fpother(struct pt_regs *regs)

void do_tof(struct pt_regs *regs)
{
+ siginfo_t info;
+
if(regs->tstate & TSTATE_PRIV)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
- send_sig(SIGEMT, current, 1);
+
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGEMT;
+ info.si_code = EMT_TAGOVF;
+ info.si_addr = regs->tpc;
+ send_sig_info (SIGEMT, &info, tsk);
}

void do_div0(struct pt_regs *regs)
@@ -537,6 +564,7 @@ void do_illegal_instruction(struct pt_re
unsigned long pc = regs->tpc;
unsigned long tstate = regs->tstate;
u32 insn;
+ siginfo_t info;

if(tstate & TSTATE_PRIV)
die_if_kernel("Kernel illegal instruction", regs);
@@ -551,9 +579,11 @@ void do_illegal_instruction(struct pt_re
return;
}
}
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_ILLINST;
- send_sig(SIGILL, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = pc;
+ send_sig_info (SIGILL, &info, tsk);
}

void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
@@ -565,34 +595,50 @@ void mem_address_unaligned(struct pt_reg

return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr);
} else {
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGBUS, current, 1);
+ siginfo_t info;
+
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = regs->tpc;
+ send_sig_info (SIGBUS, &info, tsk);
}
}

void do_privop(struct pt_regs *regs)
{
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
+ siginfo_t info;
+
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_PRVOPC;
+ info.si_addr = pc;
+ send_sig_info (SIGILL, &info, tsk);
}

void do_privact(struct pt_regs *regs)
{
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
+ siginfo_t info;
+
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_PRVOPC;
+ info.si_addr = pc;
+ send_sig_info (SIGILL, &info, tsk);
}

void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long tstate)
{
+ siginfo_t info;
+
if(tstate & TSTATE_PRIV)
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
- current->tss.sig_address = pc;
- current->tss.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGILL;
+ info.si_code = ILL_PRVOPC;
+ info.si_addr = pc;
+ send_sig_info (SIGILL, &info, tsk);
}

void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
--- ./arch/sparc64/kernel/process.c.jj Wed Jul 28 13:03:42 1999
+++ ./arch/sparc64/kernel/process.c Wed Jul 28 16:41:29 1999
@@ -377,8 +377,6 @@ void show_thread(struct thread_struct *t
printk("kregs: 0x%016lx\n", (unsigned long)tss->kregs);
show_regs(tss->kregs);
#endif
- printk("sig_address: 0x%016lx\n", tss->sig_address);
- printk("sig_desc: 0x%016lx\n", tss->sig_desc);
printk("ksp: 0x%016lx\n", tss->ksp);

if (tss->w_saved) {
@@ -706,7 +704,6 @@ void dump_thread(struct pt_regs * regs,
memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->tss.float_regs[0], (sizeof(unsigned long) * 32));
dump->fpu.fpstatus.fsr = current->tss.fsr;
dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
- dump->sigcode = current->tss.sig_desc;
#endif
}

--- ./arch/sparc64/kernel/sys_sunos32.c.jj Wed Jul 28 13:03:55 1999
+++ ./arch/sparc64/kernel/sys_sunos32.c Wed Jul 28 16:39:19 1999
@@ -555,15 +555,21 @@ asmlinkage int sunos_uname(struct sunos_
asmlinkage int sunos_nosys(void)
{
struct pt_regs *regs;
+ siginfo_t info;
+ static int cnt;

lock_kernel();
regs = current->tss.kregs;
- current->tss.sig_address = regs->tpc;
- current->tss.sig_desc = regs->u_regs[UREG_G1];
- send_sig(SIGSYS, current, 1);
- printk("Process makes ni_syscall number %d, register dump:\n",
- (int) regs->u_regs[UREG_G1]);
- show_regs(regs);
+ memset (&info, 0, sizeof (info));
+ info.si_signo = SIGSYS;
+ info.si_addr = regs->pc;
+ info.si_code = regs->u_regs[UREG_G1] & 0x7fffffff;
+ send_sig_info(SIGSYS, &info, current);
+ if (cnt++ < 4) {
+ printk("Process makes ni_syscall number %d, register dump:\n",
+ (int) regs->u_regs[UREG_G1]);
+ show_regs(regs);
+ }
unlock_kernel();
return -ENOSYS;
}
--- ./arch/sparc64/kernel/sys_sparc32.c.jj Wed Jul 28 13:03:54 1999
+++ ./arch/sparc64/kernel/sys_sparc32.c Wed Jul 28 17:09:45 1999
@@ -1666,19 +1666,17 @@ asmlinkage int sys32_rt_sigpending(sigse
siginfo_t32 *
siginfo64to32(siginfo_t32 *d, siginfo_t *s)
{
+ int i = s->si_signo;
memset (&d, 0, sizeof(siginfo_t32));
d->si_signo = s->si_signo;
d->si_errno = s->si_errno;
d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
+ if (SI_FROMUSER (s))
+ i = SIGRTMIN;
+ switch (i) {
case SIGCHLD:
d->si_pid = s->si_pid;
+ d->si_uid = s->si_uid;
d->si_status = s->si_status;
d->si_utime = s->si_utime;
d->si_stime = s->si_stime;
@@ -1687,17 +1685,15 @@ siginfo64to32(siginfo_t32 *d, siginfo_t
case SIGBUS:
case SIGFPE:
case SIGILL:
+ case SIGEMT:
d->si_addr = (long)(s->si_addr);
- /* XXX: Do we need to translate this from sparc64 to sparc32 traps? */
d->si_trapno = s->si_trapno;
break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
default:
d->si_pid = s->si_pid;
d->si_uid = s->si_uid;
+ /* XXX: Ouch, how to find this out??? */
+ d->si_int = s->si_int;
break;
}
return d;
@@ -1706,18 +1702,16 @@ siginfo64to32(siginfo_t32 *d, siginfo_t
siginfo_t *
siginfo32to64(siginfo_t *d, siginfo_t32 *s)
{
+ int i = s->si_signo;
d->si_signo = s->si_signo;
d->si_errno = s->si_errno;
d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
+ if (SI_FROMUSER (s))
+ i = SIGRTMIN;
+ switch (i) {
case SIGCHLD:
d->si_pid = s->si_pid;
+ d->si_uid = s->si_uid;
d->si_status = s->si_status;
d->si_utime = s->si_utime;
d->si_stime = s->si_stime;
@@ -1726,17 +1720,15 @@ siginfo32to64(siginfo_t *d, siginfo_t32
case SIGBUS:
case SIGFPE:
case SIGILL:
- d->si_addr = (void *)A(s->si_addr);
- /* XXX: Do we need to translate this from sparc32 to sparc64 traps? */
+ case SIGEMT:
+ d->si_addr = (long)(s->si_addr);
d->si_trapno = s->si_trapno;
break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
default:
d->si_pid = s->si_pid;
d->si_uid = s->si_uid;
+ /* XXX: Ouch, how to find this out??? */
+ d->si_int = s->si_int;
break;
}
return d;
--- ./arch/sparc64/mm/asyncd.c.jj Wed Jul 28 13:04:10 1999
+++ ./arch/sparc64/mm/asyncd.c Wed Jul 28 16:43:13 1999
@@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/config.h>
#include <linux/interrupt.h>
+#include <linux/signal.h>

#include <asm/dma.h>
#include <asm/system.h> /* for cli()/sti() */
@@ -115,6 +116,7 @@ static int fault_in_page(int taskid,
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
+ siginfo_t info;

if (!tsk || !tsk->mm)
return 1;
@@ -178,9 +180,11 @@ no_memory:

bad_area:
stats.failure++;
- tsk->tss.sig_address = address;
- tsk->tss.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, tsk, 1);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = address;
+ send_sig_info (SIGSEGV, &info, tsk);
return 1;
}

--- ./arch/sparc64/mm/fault.c.jj Wed Jul 28 13:04:11 1999
+++ ./arch/sparc64/mm/fault.c Wed Jul 28 16:46:53 1999
@@ -146,6 +146,7 @@ asmlinkage void do_sparc64_fault(struct
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned int insn = 0;
+ siginfo_t info;
#ifdef DEBUG_LOCKUPS
static unsigned long lastaddr, lastpc;
static int lastwrite, lockcnt;
@@ -282,9 +283,11 @@ do_kernel_fault:
return;
}
} else {
- current->tss.sig_address = address;
- current->tss.sig_desc = SUBSIG_NOMAPPING;
- force_sig(SIGSEGV, current);
+ memset (&info, 0, sizeof(info));
+ info.si_signo = SIGSEGV;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = address;
+ force_sig_info (SIGSEGV, &info, current);
return;
}
unhandled_fault (address, current, regs);
@@ -293,9 +296,11 @@ do_kernel_fault:

do_sigbus:
up(&mm->mmap_sem);
- current->tss.sig_address = address;
- current->tss.sig_desc = SUBSIG_MISCERROR;
- force_sig(SIGBUS, current);
+ memset (&info, 0, sizeof (info));
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = address;
+ force_sig_info (SIGBUS, &info, current);
if (regs->tstate & TSTATE_PRIV)
goto do_kernel_fault;
}
--- ./include/asm-alpha/siginfo.h.jj Wed Jul 28 13:30:53 1999
+++ ./include/asm-alpha/siginfo.h Wed Jul 28 15:38:05 1999
@@ -19,8 +19,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
-
+#endif
/* kill() */
struct {
pid_t _pid; /* sender's pid */
--- ./include/asm-arm/siginfo.h.jj Wed Jul 28 13:30:58 1999
+++ ./include/asm-arm/siginfo.h Wed Jul 28 15:37:47 1999
@@ -19,8 +19,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
-
+#endif
/* kill() */
struct {
pid_t _pid; /* sender's pid */
--- ./include/asm-i386/siginfo.h.jj Wed Jul 28 13:31:16 1999
+++ ./include/asm-i386/siginfo.h Wed Jul 28 15:37:31 1999
@@ -19,8 +19,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
-
+#endif
/* kill() */
struct {
pid_t _pid; /* sender's pid */
--- ./include/asm-m68k/siginfo.h.jj Wed Jul 28 13:31:27 1999
+++ ./include/asm-m68k/siginfo.h Wed Jul 28 15:37:08 1999
@@ -19,8 +19,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
-
+#endif
/* kill() */
struct {
pid_t _pid; /* sender's pid */
--- ./include/asm-mips/siginfo.h.jj Wed Jul 28 13:31:35 1999
+++ ./include/asm-mips/siginfo.h Wed Jul 28 15:36:46 1999
@@ -27,8 +27,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
-
+#endif
/* kill() */
struct {
pid_t _pid; /* sender's pid */
--- ./include/asm-ppc/siginfo.h.jj Wed Jul 28 13:31:49 1999
+++ ./include/asm-ppc/siginfo.h Wed Jul 28 15:36:20 1999
@@ -19,8 +19,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
-
+#endif
/* kill() */
struct {
pid_t _pid; /* sender's pid */
--- ./include/asm-sparc/siginfo.h.jj Wed Jul 28 13:31:58 1999
+++ ./include/asm-sparc/siginfo.h Wed Jul 28 15:04:35 1999
@@ -21,12 +21,14 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
+#endif

/* kill() */
struct {
pid_t _pid; /* sender's pid */
- uid_t _uid; /* sender's uid */
+ unsigned int _uid; /* sender's uid */
} _kill;

/* POSIX.1b timers */
@@ -38,20 +40,20 @@ typedef struct siginfo {
/* POSIX.1b signals */
struct {
pid_t _pid; /* sender's pid */
- uid_t _uid; /* sender's uid */
+ unsigned int _uid; /* sender's uid */
sigval_t _sigval;
} _rt;

/* SIGCHLD */
struct {
pid_t _pid; /* which child */
- uid_t _uid; /* sender's uid */
+ unsigned int _uid; /* sender's uid */
int _status; /* exit code */
clock_t _utime;
clock_t _stime;
} _sigchld;

- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
void *_addr; /* faulting insn/memory ref. */
int _trapno; /* TRAP # which caused the signal */
@@ -85,6 +87,7 @@ typedef struct siginfo {
* si_code values
* Digital reserves positive values for kernel-generated signals.
*/
+#define SI_NOINFO 32767 /* no information in siginfo_t */
#define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
#define SI_QUEUE -1 /* sent by sigqueue */
@@ -165,6 +168,12 @@ typedef struct siginfo {
#define POLL_PRI 5 /* high priority input available */
#define POLL_HUP 6 /* device disconnected */
#define NSIGPOLL 6
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF 1 /* tag overflow */
+#define NSIGEMT 1

/*
* sigevent definitions
--- ./include/asm-sparc/processor.h.jj Wed Jul 28 13:31:58 1999
+++ ./include/asm-sparc/processor.h Wed Jul 28 15:35:14 1999
@@ -57,10 +57,6 @@ struct thread_struct {
unsigned long uwinmask __attribute__ ((aligned (8)));
struct pt_regs *kregs;

- /* For signal handling */
- unsigned long sig_address __attribute__ ((aligned (8)));
- unsigned long sig_desc;
-
/* Context switch saved kernel state. */
unsigned long ksp __attribute__ ((aligned (8)));
unsigned long kpc;
@@ -97,8 +93,8 @@ struct thread_struct {
NULL, __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }

#define INIT_TSS { \
-/* uwinmask, kregs, sig_address, sig_desc, ksp, kpc, kpsr, kwim */ \
- 0, 0, 0, 0, 0, 0, 0, 0, \
+/* uwinmask, kregs, ksp, kpc, kpsr, kwim */ \
+ 0, 0, 0, 0, 0, 0, \
/* fork_kpsr, fork_kwim */ \
0, 0, \
/* reg_window */ \
--- ./include/asm-sparc64/siginfo.h.jj Wed Jul 28 13:32:18 1999
+++ ./include/asm-sparc64/siginfo.h Wed Jul 28 15:52:14 1999
@@ -27,7 +27,9 @@ typedef struct siginfo {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE];
+#endif

/* kill() */
struct {
@@ -57,7 +59,7 @@ typedef struct siginfo {
clock_t _stime;
} _sigchld;

- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
void *_addr; /* faulting insn/memory ref. */
int _trapno; /* TRAP # which caused the signal */
@@ -79,12 +81,14 @@ typedef struct siginfo32 {
int si_code;

union {
+#ifndef __KERNEL__
int _pad[SI_PAD_SIZE32];
+#endif

/* kill() */
struct {
__kernel_pid_t32 _pid; /* sender's pid */
- __kernel_uid_t32 _uid; /* sender's uid */
+ unsigned int _uid; /* sender's uid */
} _kill;

/* POSIX.1b timers */
@@ -96,19 +100,20 @@ typedef struct siginfo32 {
/* POSIX.1b signals */
struct {
__kernel_pid_t32 _pid; /* sender's pid */
- __kernel_uid_t32 _uid; /* sender's uid */
+ unsigned int _uid; /* sender's uid */
sigval_t32 _sigval;
} _rt;

/* SIGCHLD */
struct {
__kernel_pid_t32 _pid; /* which child */
- int _status; /* exit code */
+ unsigned int _uid; /* sender's uid */
+ int _status; /* exit code */
__kernel_clock_t32 _utime;
__kernel_clock_t32 _stime;
} _sigchld;

- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
u32 _addr; /* faulting insn/memory ref. */
int _trapno;
@@ -144,6 +149,7 @@ typedef struct siginfo32 {
* si_code values
* Digital reserves positive values for kernel-generated signals.
*/
+#define SI_NOINFO 32767 /* no information in siginfo_t */
#define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
#define SI_QUEUE -1 /* sent by sigqueue */
@@ -224,6 +230,12 @@ typedef struct siginfo32 {
#define POLL_PRI 5 /* high priority input available */
#define POLL_HUP 6 /* device disconnected */
#define NSIGPOLL 6
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF 1 /* tag overflow */
+#define NSIGEMT 1

/*
* sigevent definitions
--- ./include/asm-sparc64/processor.h.jj Wed Jul 28 13:32:14 1999
+++ ./include/asm-sparc64/processor.h Wed Jul 28 15:06:43 1999
@@ -68,9 +68,6 @@ struct thread_struct {
struct reg_window reg_window[NSWINS] __attribute__ ((aligned (16)));
unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));

- unsigned long sig_address __attribute__ ((aligned (8)));
- unsigned long sig_desc;
-
/* Performance counter state */
u64 *user_cntd0, *user_cntd1;
u64 kernel_cntd0, kernel_cntd1;
@@ -103,8 +100,6 @@ struct thread_struct {
{ { { 0, }, { 0, } }, }, \
/* rwbuf_stkptrs */ \
{ 0, 0, 0, 0, 0, 0, 0, }, \
-/* sig_address, sig_desc */ \
- 0, 0, \
/* user_cntd0, user_cndd1, kernel_cntd0, kernel_cntd0, pcr_reg */ \
0, 0, 0, 0, 0, \
}

Cheers,
Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux | http://ultra.linux.cz/ | http://ultra.penguin.cz/
Linux version 2.2.10 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/