Interdata_v6/usr/sys/trap.c
#
#include "param.h"
#include "systm.h"
#include "user.h"
#include "proc.h"
#include "reg.h"
#include "seg.h"
#define EBIT 010 /*** user err bit in psw: C-bit ***/
#define UMODE 01<<8 /*** user-mode bit in tsw (prot bit) ***/
#define SYS 0341 /*** svc (trap) instruction ***/
#define USER 020 /* user-mode flag added to dev */
/*
* structure of the system entry table (sysent.c)
*/
extern struct sysent {
int count; /* argument count */
int (*call)(); /* name of handler */
} sysent[64];
/*
* Offsets of the user's registers relative to
* the saved r0. See reg.h
*/
int regloc[18]
{
R0, R1, R2, R3, R4, R5, R6, R7, /***/
R8, R9, R10, R11, R12, R13, R14, R15, /***/
RPS, RPC
};
/*
* Called from low.s when a processor trap occurs.
* The arguments are the words saved on the system stack
* by the software during the trap processing.
* Their order is dictated by the details
* of C's calling sequence. They are peculiar in that
* this call is not 'by value' and changed user registers
* get copied back on return.
* dev is the kind of trap that occurred.
*/
trap(dev, stat, r0, r1, r2, r3, r4, r5, r6, asp, rf, ps, pc, nps) /***/
{
register i, a;
register struct sysent *callp;
trace(02, "trap", dev);
trace(02, "psw", pc);
#ifdef FPREGS
savfp();
#endif
if ((ps&UMODE) == UMODE)
dev =| USER;
u.u_ar0 = &r0;
switch(dev) {
/*
* Trap not expected.
* Usually a kernel mode address error.
*/
default:
printf("Useg = %x\n", *ka6);
printf("PSW = %x %x\n", ps, pc);
printf("SP = %x\n", asp);
printf("trap type %d\n", dev);
panic("trap");
case 0+USER: /* address error */
i = SIGBUS;
break;
case 1+USER: /* illegal instruction */
#ifdef FPTRAP
/**** if illegal instruction assume it to be a floating
point one and call fptrap.
passing fptrap a pointer to the user's saved r0
( see reg.h ) and a pointer to his fp regs in the ppda ****/
if ( i=fptrap(&r0,u.u_fsav))
break; /*** error returned by fptrap ***/
goto out;
#else
i = SIGINS;
break;
#endif
case 2+USER: /* bpt or trace */
i = SIGTRC;
break;
case 3+USER: /* iot */
i = SIGIOT;
break;
case 5+USER: /* emt */
i = SIGEMT;
break;
case 6+USER: /* sys call */
u.u_error = 0;
ps =& ~EBIT;
callp = &sysent[stat&077]; /*** stat is svc no. ***/
if (callp == sysent) { /* indirect */
a = fuiword(pc);
pc =+ 4; /***/
i = fuword(a);
if ((i >> 24) != SYS)
i = 077; /* illegal */
callp = &sysent[i&077];
for(i=0; i<callp->count; i++)
u.u_arg[i] = fuword(a =+ 4); /***/
} else {
for(i=0; i<callp->count; i++) {
u.u_arg[i] = fuiword(pc);
pc =+ 4; /***/
}
}
trace(04, "svc", callp-sysent);
u.u_dirp = u.u_arg[0];
trap1(callp->call);
if(u.u_intflg)
u.u_error = EINTR;
if(u.u_error < 100) {
if(u.u_error) {
ps =| EBIT;
r0 = u.u_error;
}
goto out;
}
i = SIGSYS;
break;
/*
* Since the floating exception is an
* imprecise trap, a user generated
* trap may actually come from kernel
* mode. In this case, a signal is sent
* to the current process to be picked
* up later.
*/
case 8: /* floating exception */
psignal(u.u_procp, SIGFPT);
return;
case 8+USER:
i = SIGFPT;
break;
/*
* If the user SP is below the stack segment,
* grow the stack automatically.
* This relies on the ability of the hardware
* to restart a half executed instruction.
* At the moment this is unimplemented (and possibly
* unimplementable) on the Interdata.
*/
case 9+USER: /* segmentation exception */
/***
a = asp;
if(backup(u.u_ar0) == 0)
if(grow(a))
goto out;
***/
i = SIGSEG;
break;
case 10+USER: /* illegal svc number */
i = SIGSYS;
break;
}
psignal(u.u_procp, i);
out:
if(issig())
psig();
setpri(u.u_procp);
}
/*
* Call the system-entry routine f (out of the
* sysent table). This is a subroutine for trap, and
* not in-line, because if a signal occurs
* during processing, an (abnormal) return is simulated from
* the last caller to savu(qsav); if this took place
* inside of trap, it wouldn't have a chance to clean up.
*
* If this occurs, the return takes place without
* clearing u_intflg; if it's still set, trap
* marks an error which means that a system
* call (like read on a typewriter) got interrupted
* by a signal.
*/
trap1(f)
int (*f)();
{
u.u_intflg = 1;
savu(u.u_qsav);
(*f)();
u.u_intflg = 0;
}
/*
* nonexistent system call-- set fatal error code.
*/
nosys()
{
u.u_error = 100;
}
/*
* Ignored system call
*/
nullsys()
{
}