Skip to content
Snippets Groups Projects
Commit bc22f1aa authored by wlott's avatar wlott
Browse files

Moved machine/arch specific stuff into machine/arch specific files.

parent ba332b46
No related branches found
No related tags found
No related merge requests found
/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/ldb/Attic/interrupt.c,v 1.27 1991/05/24 04:59:04 wlott Exp $ */ /* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/ldb/Attic/interrupt.c,v 1.28 1991/05/24 17:50:13 wlott Exp $ */
/* Interrupt handing magic. */ /* Interrupt handing magic. */
#include <stdio.h>
#include <signal.h> #include <signal.h>
#ifdef mips #ifdef mips
#include <mips/cpu.h> #include <mips/cpu.h>
#endif #endif
#ifdef sparc
#include <machine/trap.h>
#endif
#include "lisp.h"
#include "ldb.h" #include "ldb.h"
#include "os.h"
#include "arch.h"
#include "lisp.h"
#include "globals.h" #include "globals.h"
#include "lispregs.h" #include "lispregs.h"
#include "interrupt.h" #include "interrupt.h"
#include "validate.h" #include "validate.h"
#define crap_out(msg) do { write(2, msg, sizeof(msg)); exit(1); } while (0)
#define FIXNUM_VALUE(lispobj) (((int)lispobj)>>2) #define FIXNUM_VALUE(lispobj) (((int)lispobj)>>2)
boolean internal_errors_enabled = 0; boolean internal_errors_enabled = 0;
...@@ -26,7 +26,8 @@ boolean internal_errors_enabled = 0; ...@@ -26,7 +26,8 @@ boolean internal_errors_enabled = 0;
struct sigcontext *lisp_interrupt_contexts[MAX_INTERRUPTS]; struct sigcontext *lisp_interrupt_contexts[MAX_INTERRUPTS];
union interrupt_handler interrupt_handlers[NSIG]; union interrupt_handler interrupt_handlers[NSIG];
void (*interrupt_low_level_handlers[NSIG])() = {0};
static int pending_signal = 0, pending_code = 0, pending_mask = 0; static int pending_signal = 0, pending_code = 0, pending_mask = 0;
static boolean maybe_gc_pending = FALSE; static boolean maybe_gc_pending = FALSE;
...@@ -35,7 +36,7 @@ static boolean maybe_gc_pending = FALSE; ...@@ -35,7 +36,7 @@ static boolean maybe_gc_pending = FALSE;
* Utility routines used by various signal handlers. * * Utility routines used by various signal handlers. *
\****************************************************************/ \****************************************************************/
static void fake_foreign_function_call(context) void fake_foreign_function_call(context)
struct sigcontext *context; struct sigcontext *context;
{ {
int context_index; int context_index;
...@@ -106,7 +107,7 @@ static void fake_foreign_function_call(context) ...@@ -106,7 +107,7 @@ static void fake_foreign_function_call(context)
foreign_function_call_active = 1; foreign_function_call_active = 1;
} }
static void undo_fake_foreign_function_call(context) void undo_fake_foreign_function_call(context)
struct sigcontext *context; struct sigcontext *context;
{ {
/* Block all blockable signals */ /* Block all blockable signals */
...@@ -130,34 +131,7 @@ static void undo_fake_foreign_function_call(context) ...@@ -130,34 +131,7 @@ static void undo_fake_foreign_function_call(context)
call_into_lisp(MAYBE_GC, SymbolFunction(MAYBE_GC), \ call_into_lisp(MAYBE_GC, SymbolFunction(MAYBE_GC), \
current_control_stack_pointer, 0) current_control_stack_pointer, 0)
static void skip_instruction(context) void interrupt_internal_error(signal, code, context, continuable)
struct sigcontext *context;
{
#ifdef mips
/* Skip the offending instruction */
if (context->sc_cause & CAUSE_BD)
emulate_branch(context, *(unsigned long *)context->sc_pc);
else
context->sc_pc += 4;
#endif
#ifdef sparc
context->sc_pc = context->sc_npc;
context->sc_npc += 4;
#endif
#ifdef ibmrt
unsigned long pc = context->sc_iar;
unsigned long prev_inst = ((unsigned long *)pc)[-1];
if ((prev_inst >> 24) == 0x89) {
short offset = prev_inst & 0xffff;
context->sc_pc = pc - 4 + offset;
}
else
context->sc_pc = pc + 4;
#endif
}
static void internal_error(signal, code, context, continuable)
struct sigcontext *context; struct sigcontext *context;
boolean continuable; boolean continuable;
{ {
...@@ -177,13 +151,13 @@ static void internal_error(signal, code, context, continuable) ...@@ -177,13 +151,13 @@ static void internal_error(signal, code, context, continuable)
args, 2); args, 2);
undo_fake_foreign_function_call(context); undo_fake_foreign_function_call(context);
if (continuable) if (continuable)
skip_instruction(context); arch_skip_instruction(context);
} }
else else
handle_now(signal, code, context); interrupt_handle_now(signal, code, context);
} }
static void handle_pending_interrupt(context) void interrupt_handle_pending(context)
struct sigcontext *context; struct sigcontext *context;
{ {
if (foreign_function_call_active) if (foreign_function_call_active)
...@@ -208,20 +182,20 @@ static void handle_pending_interrupt(context) ...@@ -208,20 +182,20 @@ static void handle_pending_interrupt(context)
code = pending_code; code = pending_code;
pending_signal = 0; pending_signal = 0;
pending_code = 0; pending_code = 0;
handle_now(signal, code, context); interrupt_handle_now(signal, code, context);
} }
context->sc_mask = pending_mask; context->sc_mask = pending_mask;
pending_mask = 0; pending_mask = 0;
skip_instruction(context); arch_skip_instruction(context);
} }
/****************************************************************\ /****************************************************************\
* handle_now, maybe_now_maybe_later * * interrupt_handle_now, maybe_now_maybe_later *
* the two main signal handlers. * * the two main signal handlers. *
\****************************************************************/ \****************************************************************/
static handle_now(signal, code, context) void interrupt_handle_now(signal, code, context)
int signal, code; int signal, code;
struct sigcontext *context; struct sigcontext *context;
{ {
...@@ -231,20 +205,25 @@ struct sigcontext *context; ...@@ -231,20 +205,25 @@ struct sigcontext *context;
lispobj callname, function; lispobj callname, function;
handler = interrupt_handlers[signal]; handler = interrupt_handlers[signal];
were_in_lisp = !foreign_function_call_active;
if(handler.c==SIG_IGN)
if (handler.c == SIG_DFL || handler.c == SIG_IGN)
/* This can happen if someone tries to ignore or default on of the */
/* signals we need for runtime support. */
return; return;
were_in_lisp = !foreign_function_call_active;
if (were_in_lisp) if (were_in_lisp)
fake_foreign_function_call(context); fake_foreign_function_call(context);
/* Allow signals again. */ /* Allow signals again. */
sigsetmask(context->sc_mask); sigsetmask(context->sc_mask);
if (LowtagOf(handler.lisp) == type_EvenFixnum || if(handler.c==SIG_DFL){
/* This can happen if someone tries to ignore or default on of the */
/* signals we need for runtime support. */
fprintf(stderr,"interrupt_handle_now: No handler for signal %d?\n",signal);
printf("[exit debugger to continue]\n");
ldb_monitor();
}
else if (LowtagOf(handler.lisp) == type_EvenFixnum ||
LowtagOf(handler.lisp) == type_OddFixnum) LowtagOf(handler.lisp) == type_OddFixnum)
(*handler.c)(signal, code, context); (*handler.c)(signal, code, context);
else { else {
...@@ -265,7 +244,7 @@ struct sigcontext *context; ...@@ -265,7 +244,7 @@ struct sigcontext *context;
undo_fake_foreign_function_call(context); undo_fake_foreign_function_call(context);
} }
static maybe_now_maybe_later(signal, code, context) static void maybe_now_maybe_later(signal, code, context)
int signal, code; int signal, code;
struct sigcontext *context; struct sigcontext *context;
{ {
...@@ -292,249 +271,9 @@ struct sigcontext *context; ...@@ -292,249 +271,9 @@ struct sigcontext *context;
SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, T); SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, T);
#endif #endif
} else } else
handle_now(signal, code, context); interrupt_handle_now(signal, code, context);
} }
/****************************************************************\
* PMAX specific signal handlers. *
\****************************************************************/
#ifdef mips
static sigtrap_handler(signal, code, context)
int signal, code;
struct sigcontext *context;
{
switch (code) {
case trap_PendingInterrupt:
handle_pending_interrupt(context);
break;
case trap_Halt:
crap_out("%primitive halt called; the party is over.\n");
case trap_Error:
case trap_Cerror:
internal_error(signal, code, context, code==trap_Cerror);
break;
case trap_Breakpoint:
sigsetmask(context->sc_mask);
fake_foreign_function_call(context);
handle_breakpoint(signal, code, context);
undo_fake_foreign_function_call(context);
break;
default:
handle_now(signal, code, context);
break;
}
}
static sigfpe_handler(signal, code, context)
int signal, code;
struct sigcontext *context;
{
unsigned long bad_inst;
unsigned int op, rs, rt, rd, funct, dest;
int immed;
long result;
if (context->sc_cause & CAUSE_BD)
bad_inst = *(unsigned long *)(context->sc_pc + 4);
else
bad_inst = *(unsigned long *)(context->sc_pc);
op = (bad_inst >> 26) & 0x3f;
rs = (bad_inst >> 21) & 0x1f;
rt = (bad_inst >> 16) & 0x1f;
rd = (bad_inst >> 11) & 0x1f;
funct = bad_inst & 0x3f;
immed = (((int)(bad_inst & 0xffff)) << 16) >> 16;
switch (op) {
case 0x0: /* SPECIAL */
switch (funct) {
case 0x20: /* ADD */
result = FIXNUM_VALUE(context->sc_regs[rs]) + FIXNUM_VALUE(context->sc_regs[rt]);
dest = rd;
break;
case 0x22: /* SUB */
result = FIXNUM_VALUE(context->sc_regs[rs]) - FIXNUM_VALUE(context->sc_regs[rt]);
dest = rd;
break;
default:
dest = 32;
break;
}
break;
case 0x8: /* ADDI */
result = FIXNUM_VALUE(context->sc_regs[rs]) + (immed>>2);
dest = rt;
break;
default:
dest = 32;
break;
}
if (dest < 32) {
set_global_pointer(saved_global_pointer);
current_dynamic_space_free_pointer =
(lispobj *) context->sc_regs[ALLOC];
context->sc_regs[dest] = alloc_number(result);
context->sc_regs[ALLOC] =
(unsigned long) current_dynamic_space_free_pointer;
skip_instruction(context);
}
else
handle_now(signal, code, context);
}
#endif
/****************************************************************\
* SPARC specific signal handlers. *
\****************************************************************/
#ifdef sparc
static sigill_handler(signal, code, context)
int signal, code;
struct sigcontext *context;
{
int badinst;
if (code == T_UNIMP_INSTR) {
int trap;
trap = *(unsigned long *)(context->sc_pc) & 0x3fffff;
switch (trap) {
case trap_PendingInterrupt:
handle_pending_interrupt(context);
break;
case trap_Halt:
crap_out("%primitive halt called; the party is over.\n");
case trap_Error:
case trap_Cerror:
internal_error(signal, code, context, trap == trap_Cerror);
break;
default:
handle_now(signal, code, context);
break;
}
}
else if (code >= T_SOFTWARE_TRAP + 16 & code < T_SOFTWARE_TRAP + 32)
internal_error(signal, code, context, FALSE);
else
handle_now(signal, code, context);
}
static sigemt_handler(signal, code, context)
int signal, code;
struct sigcontext *context;
{
unsigned long badinst;
boolean subtract, immed;
int rd, rs1, op1, rs2, op2, result;
badinst = *(unsigned long *)context->sc_pc;
if ((badinst >> 30) != 2 || ((badinst >> 20) & 0x1f) != 0x11) {
/* It wasn't a tagged add. Pass the signal into lisp. */
handle_now(signal, code, context);
return;
}
/* Extract the parts of the inst. */
subtract = badinst & (1<<19);
rs1 = (badinst>>14) & 0x1f;
op1 = context->sc_regs[rs1];
if ((op1 & 3) != 0) {
/* The first arg wan't a fixnum. */
internal_error(signal, code, context, FALSE);
return;
}
if (immed = badinst & (1<<13)) {
op2 = badinst & 0x1fff;
if (op2 & (1<<12))
op2 |= -1<<13;
}
else {
rs2 = badinst & 0x1f;
op2 = context->sc_regs[rs2];
}
if ((op2 & 3) != 0) {
/* The second arg wan't a fixnum. */
internal_error(signal, code, context, FALSE);
return;
}
rd = (badinst>>25) & 0x1f;
if (rd != 0) {
/* Don't bother computing the result unless we are going to use it. */
if (subtract)
result = (op1>>2) - (op2>>2);
else
result = (op1>>2) + (op2>>2);
current_dynamic_space_free_pointer =
(lispobj *) context->sc_regs[ALLOC];
context->sc_regs[rd] = alloc_number(result);
context->sc_regs[ALLOC] =
(unsigned long) current_dynamic_space_free_pointer;
}
skip_instruction(context);
}
#endif
/****************************************************************\
* RT Specific Signal Handlers *
\****************************************************************/
#ifdef ibmrt
static sigtrap_handler(signal, code, context)
int signal, code;
struct sigcontext *context;
{
switch (*((unsigned short *)context->sc_iar+1)) {
case trap_PendingInterrupt:
handle_pending_interrupt(context);
break;
case trap_Halt:
crap_out("%primitive halt called; the party is over.\n");
case trap_Error:
case trap_Cerror:
internal_error(signal, code, context, code==trap_Cerror);
break;
case trap_Breakpoint:
sigsetmask(context->sc_mask);
fake_foreign_function_call(context);
handle_breakpoint(signal, code, context);
undo_fake_foreign_function_call(context);
break;
default:
handle_now(signal, code, context);
break;
}
}
#endif
/****************************************************************\ /****************************************************************\
* Stuff to detect and handle hitting the gc trigger. * * Stuff to detect and handle hitting the gc trigger. *
\****************************************************************/ \****************************************************************/
...@@ -542,78 +281,18 @@ static sigtrap_handler(signal, code, context) ...@@ -542,78 +281,18 @@ static sigtrap_handler(signal, code, context)
static boolean gc_trigger_hit(context) static boolean gc_trigger_hit(context)
struct sigcontext *context; struct sigcontext *context;
{ {
lispobj *badaddr;
#ifdef sparc
unsigned long badinst;
int rs1;
#endif
if (current_auto_gc_trigger == NULL) if (current_auto_gc_trigger == NULL)
return FALSE; return FALSE;
else{
lispobj *badaddr=(lispobj *)arch_get_bad_addr(context);
#ifdef mips return (badaddr >= current_auto_gc_trigger &&
/* Finding the bad address on the mips is easy. */ badaddr < current_dynamic_space + DYNAMIC_SPACE_SIZE);
badaddr = (lispobj *)context->sc_badvaddr;
#endif
#ifdef sparc
/* On the sparc, we have to decode the instruction. */
/* Make sure it's not the pc thats bogus, and that it was lisp code */
/* that caused the fault. */
if ((context->sc_pc & 3) != 0 ||
((context->sc_pc < READ_ONLY_SPACE_START ||
context->sc_pc >= READ_ONLY_SPACE_START+READ_ONLY_SPACE_SIZE) &&
((lispobj *)context->sc_pc < current_dynamic_space &&
(lispobj *)context->sc_pc >=
current_dynamic_space + DYNAMIC_SPACE_SIZE)))
return FALSE;
badinst = *(unsigned long *)context->sc_pc;
if ((badinst >> 30) != 3)
/* All load/store instructions have op = 11 (binary) */
return FALSE;
rs1 = (badinst>>14)&0x1f;
if (badinst & (1<<13)) {
/* r[rs1] + simm(13) */
int simm13 = badinst & 0x1fff;
if (simm13 & (1<<12))
simm13 |= -1<<13;
badaddr = (lispobj *)(context->sc_regs[rs1] + simm13);
} }
else {
/* r[rs1] + r[rs2] */
int rs2 = badinst & 0x1f;
badaddr = (lispobj *)(context->sc_regs[rs1] + context->sc_regs[rs2]);
}
#endif
#ifdef ibmrt
if (!SymbolValue(PSEUDO_ATOMIC_ATOMIC))
/* If we are not pseudo-atomic, then we could only have hit the */
/* trigger if the allocation pointer points beyond the trigger. */
badaddr = (lispobj *)SymbolValue(ALLOCATION_POINTER);
else
/* Otherwise, we might be inside an allocator. The best we can do */
/* is to try turning off the trigger and seeing if the problem goes */
/* away. If it does, then we guessed right. If it doesn't, we will */
/* end up back here, except current_auto_gc_trigger will be NULL, */
/* so we will take the sigbus at that time. */
return TRUE;
#endif
return (badaddr >= current_auto_gc_trigger &&
badaddr < current_dynamic_space + DYNAMIC_SPACE_SIZE);
} }
static sigbus_handler(signal, code, context) boolean interrupt_maybe_gc(context)
int signal, code;
struct sigcontext *context; struct sigcontext *context;
{ {
if (!foreign_function_call_active && gc_trigger_hit(context)) { if (!foreign_function_call_active && gc_trigger_hit(context)) {
...@@ -645,59 +324,57 @@ struct sigcontext *context; ...@@ -645,59 +324,57 @@ struct sigcontext *context;
call_maybe_gc(); call_maybe_gc();
undo_fake_foreign_function_call(context); undo_fake_foreign_function_call(context);
} }
}
else return TRUE;
handle_now(signal, code, context); }else
return FALSE;
} }
/****************************************************************\ /****************************************************************\
* Noise to install handlers. * * Noise to install handlers. *
\****************************************************************/ \****************************************************************/
void interrupt_install_low_level_handler(signal,handler)
int signal;
void (*handler)();
{
struct sigvec sv;
sv.sv_handler=handler;
sv.sv_mask=BLOCKABLE;
sv.sv_flags=0;
sigvec(signal,&sv,NULL);
interrupt_low_level_handlers[signal]=(handler==SIG_DFL ? 0 : handler);
}
unsigned long install_handler(signal, handler) unsigned long install_handler(signal, handler)
int signal; int signal;
int (*handler)(); void (*handler)();
{ {
struct sigvec sv; struct sigvec sv;
int oldmask; int oldmask;
union interrupt_handler oldhandler; union interrupt_handler oldhandler;
#ifdef mips
if (signal == SIGTRAP)
sv.sv_handler = sigtrap_handler;
else if (signal == SIGFPE)
sv.sv_handler = sigfpe_handler;
else if (signal == SIGBUS || signal == SIGSEGV)
sv.sv_handler = sigbus_handler;
#endif
#ifdef sparc
if (signal == SIGILL)
sv.sv_handler = sigill_handler;
else if (signal == SIGEMT)
sv.sv_handler = sigemt_handler;
else if (signal == SIGBUS)
sv.sv_handler = sigbus_handler;
#endif
#ifdef ibmrt
if (signal == SIGTRAP)
sv.sv_handler = sigtrap_handler;
else if (signal == SIGBUS)
sv.sv_handler = sigbus_handler;
#endif
else if (handler == SIG_DFL || handler == SIG_IGN)
sv.sv_handler = handler;
else if (sigmask(signal)&BLOCKABLE)
sv.sv_handler = maybe_now_maybe_later;
else
sv.sv_handler = handle_now;
sv.sv_mask = BLOCKABLE;
sv.sv_flags = 0;
oldmask = sigblock(sigmask(signal)); oldmask = sigblock(sigmask(signal));
if(interrupt_low_level_handlers[signal]==0){
if(handler==SIG_DFL || handler==SIG_IGN)
sv.sv_handler=handler;
else if (sigmask(signal)&BLOCKABLE)
sv.sv_handler = maybe_now_maybe_later;
else
sv.sv_handler = interrupt_handle_now;
sv.sv_mask = BLOCKABLE;
sv.sv_flags = 0;
sigvec(signal, &sv, NULL);
}
oldhandler = interrupt_handlers[signal]; oldhandler = interrupt_handlers[signal];
interrupt_handlers[signal].c = handler; interrupt_handlers[signal].c = handler;
sigvec(signal, &sv, NULL);
sigsetmask(oldmask); sigsetmask(oldmask);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment