[parisc-linux] RFC - Changes to traps.c (Handlers for 13, changes to 16/17)
Carlos O'Donell
carlos@baldric.uwo.ca
Sat, 7 Sep 2002 21:50:59 -0400
--61jdw2sOBCFtR2d/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
parisc,
After some banter on IRC about how one should set the stride
for a cache flush using the 'fic' instruction, I noted the
following possible problems our trap handler:
a. Non-access instruction TLB miss fault (16)
- No implemented case statement in traps.c
- No problem, falls through to do_page_fault.
- Suggest forcing a sigsegv on the process.
b. Non-access data TLB miss fault (17)
- Calls parisc_terminate and gutters the cpu.
- This should not happen.
- Suggest forcing a sigsegv on the process.
c. Conditional Trap (13)
- No implemented case statment in traps.c
- Suggest forcing SIGFPE and setting si_code to zero,
and allowing the userspace app the decode the
situation from the signal andler (HPUX seems to
this?) via si_addr.
c. All paths must either return or set the fault_address
and fault_space values? One place does not, I put a
FIXME there. Needs review. Those two values are needed
by the check after the switch statement in handle_interruption.
Is setting them to zero, as is done now, good enough?
Patch attached :)
c.
--61jdw2sOBCFtR2d/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="traps.c.diff"
--- traps.c.orig 2002-09-07 21:30:15.000000000 -0400
+++ traps.c.new 2002-09-07 21:30:05.000000000 -0400
@@ -425,11 +425,11 @@
/*
- * This routine handles page faults. It determines the address,
+ * This routine handles various exception codes. It determines the address,
* and the problem, and then passes it off to one of the appropriate
* routines.
*/
-void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
+void parisc_handle_code(char *msg, struct pt_regs *regs, int code, unsigned long offset)
{
static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED;
@@ -444,8 +444,17 @@
if (!console_drivers)
pdc_console_restart();
- if (code == 1)
- transfer_pim_to_trap_frame(regs);
+
+ /* Not all switch paths will gutter the processor... */
+ switch(code){
+
+ case 1:
+ transfer_pim_to_trap_frame(regs);
+ break;
+
+ default:
+ /* Fall through */
+ }
show_stack(regs);
@@ -461,6 +470,7 @@
* system will shut down immediately right here. */
pdc_soft_power_button(0);
+ /* Gutter the processor... */
for(;;)
;
}
@@ -487,7 +497,7 @@
case 1:
/* High-priority machine check (HPMC) */
- parisc_terminate("High Priority Machine Check (HPMC)",
+ parisc_handle_code("High Priority Machine Check (HPMC)",
regs, code, 0);
/* NOT REACHED */
@@ -554,6 +564,7 @@
die_if_kernel("Privileged register usage", regs, code);
si.si_code = ILL_PRVREG;
+ /* Fall thru */
give_sigill:
si.si_signo = SIGILL;
si.si_errno = 0;
@@ -568,6 +579,20 @@
si.si_addr = (void *) regs->iaoq[0];
force_sig_info(SIGFPE, &si, current);
return;
+
+ case 13:
+ /* Conditional Trap */
+ /* The condition succees in an instruction which traps
+ * on condition
+ */
+ si.si_signo = SIGFPE;
+ /* Set to zero, and let the userspace app figure it out from
+ * the insn pointed to by si_addr
+ */
+ si.si_code = 0;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGFPE, &si, current);
+ return;
case 14:
/* Assist Exception Trap, i.e. floating point exception. */
@@ -575,11 +600,24 @@
handle_fpe(regs);
return;
+ case 15:
+ /* Data TLB miss fault/Data page fault */
+ /* Fall thru */
+ case 16:
+ /* Non-access instruction TLB miss fault */
+ /* The instruction TLB entry needed for the target address of the FIC
+ * is absent, and hardware can't find it, so we get to cleanup
+ */
+ /* Fall thru */
case 17:
/* Non-access data TLB miss fault/Non-access data page fault */
/* TODO: Still need to add slow path emulation code here */
+ /* TODO: Understand what is meant by the TODO listed
+ * above this one. (Carlos - Sep 7, 2002) */
+
fault_address = regs->ior;
- parisc_terminate("Non access data tlb fault!",regs,code,fault_address);
+ fault_space = regs->isr;
+ break;
case 18:
/* PCXS only -- later cpu's split this into types 26,27 & 28 */
@@ -589,9 +627,8 @@
return;
}
/* Fall Through */
-
- case 15: /* Data TLB miss fault/Data page fault */
- case 26: /* PCXL: Data memory access rights trap */
+ case 26:
+ /* PCXL: Data memory access rights trap */
fault_address = regs->ior;
fault_space = regs->isr;
break;
@@ -621,6 +658,11 @@
pt_regs_to_ssp(regs, &ssp);
kgdb_trap(I_TAKEN_BR, &ssp, 1);
ssp_to_pt_regs(&ssp, regs);
+
+ /* FIXME: Should this break without setting fault_address
+ * and fault_space? They are required for the dump later on.
+ * (Carlos - Sep 7, 2002) */
+
break;
#endif /* CONFIG_KWDB */
@@ -656,7 +698,6 @@
up_read(¤t->mm->mmap_sem);
}
/* Fall Through */
-
case 27:
/* Data memory protection ID trap */
die_if_kernel("Protection id trap", regs, code);
@@ -690,7 +731,7 @@
force_sig_info(SIGBUS, &si, current);
return;
}
- parisc_terminate("Unexpected interruption", regs, code, 0);
+ parisc_handle_code("Unexpected interruption", regs, code, 0);
/* NOT REACHED */
}
@@ -719,7 +760,8 @@
*/
if (fault_space == 0)
- parisc_terminate("Kernel Fault", regs, code, fault_address);
+ parisc_handle_code("Kernel Fault", regs, code, fault_address);
+ /* NOT REACHED */
}
#ifdef CONFIG_KWDB
--61jdw2sOBCFtR2d/--