* Copyright (c) 1988 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)trap.c 7.1 (Berkeley) 5/21/88
#include "../sys/syscalls.c"
#include "../tahoe/trap.h"
#define USER 040 /* user-mode flag added to type */
"Reserved addressing mode", /* T_RESADFLT */
"Privileged instruction", /* T_PRIVINFLT */
"Reserved operand", /* T_RESOPFLT */
"Breakpoint", /* T_BPTFLT */
"Kernel call", /* T_SYSCALL */
"Arithmetic trap", /* T_ARITHTRAP */
"System forced exception", /* T_ASTFLT */
"Segmentation fault", /* T_SEGFLT */
"Protection fault", /* T_PROTFLT */
"Trace trap", /* T_TRCTRAP */
"Page fault", /* T_PAGEFLT */
"Page table fault", /* T_TABLEFLT */
"Alignment fault", /* T_ALIGNFLT */
"Kernel stack not valid", /* T_KSPNOTVAL */
"Bus error", /* T_BUSERR */
"Kernel debugger trap", /* T_KDBTRAP */
int TRAP_TYPES
= sizeof (trap_type
) / sizeof (trap_type
[0]);
* Called from the trap handler when a processor trap occurs.
trap(sp
, type
, hfs
, accmst
, acclst
, dbl
, code
, pc
, psl
)
int r0
, r1
; /* must reserve space */
register int *locr0
= ((int *)&psl
)-PS
;
r0
= 0; r0
= r0
; r1
= 0; r1
= r1
;
if (USERMODE(locr0
[PS
])) {
printf("trap type %d, code = %x, pc = %x\n", type
, code
, pc
);
if (type
< TRAP_TYPES
&& trap_type
[type
])
case T_PROTFLT
+ USER
: /* protection fault */
case T_PRIVINFLT
+ USER
: /* privileged instruction fault */
case T_RESADFLT
+ USER
: /* reserved addressing fault */
case T_RESOPFLT
+ USER
: /* resereved operand fault */
case T_ALIGNFLT
+ USER
: /* unaligned data fault */
case T_ASTFLT
+ USER
: /* Allow process switch */
if ((u
.u_procp
->p_flag
& SOWEUPC
) && u
.u_prof
.pr_scale
) {
addupc(pc
, &u
.u_prof
, 1);
u
.u_procp
->p_flag
&= ~SOWEUPC
;
* If the user SP is above the stack segment,
* grow the stack automatically.
if (grow((unsigned)locr0
[SP
]) || grow(code
))
case T_TABLEFLT
: /* allow page table faults in kernel */
case T_TABLEFLT
+ USER
: /* page table fault */
case T_PAGEFLT
: /* allow page faults in kernel mode */
case T_PAGEFLT
+ USER
: /* page fault */
case T_BPTFLT
+ USER
: /* bpt instruction fault */
case T_TRCTRAP
+ USER
: /* trace trap */
* For T_KSPNOTVAL and T_BUSERR, can not allow spl to
* drop to 0 as clock could go off and we would end up
* doing an rei to the interrupt stack at ipl 0 (a
* reserved operand fault). Instead, we allow psignal
* to post an ast, then return to user mode where we
* will reenter the kernel on the kernel's stack and
* can then service the signal.
printf("pid %d: ksp not valid\n", u
.u_procp
->p_pid
);
/* must insure valid kernel stack pointer? */
psignal(u
.u_procp
, SIGKILL
);
psignal(u
.u_procp
, SIGBUS
);
if (p
->p_cursig
|| ISSIG(p
))
* Since we are u.u_procp, clock will normally just change
* our priority without moving us from one queue to another
* (since the running process is not on a queue.)
* If that happened after we setrq ourselves but before we
* swtch()'ed, we might not be on the queue indicated by
struct timeval
*tv
= &u
.u_ru
.ru_stime
;
ticks
= ((tv
->tv_sec
- syst
.tv_sec
) * 1000 +
(tv
->tv_usec
- syst
.tv_usec
) / 1000) / (tick
/ 1000);
addupc(locr0
[PC
], &u
.u_prof
, ticks
);
* Called from locore when a system call occurs
syscall(sp
, type
, hfs
, accmst
, acclst
, dbl
, code
, pc
, psl
)
int r0
, r1
; /* must reserve space */
register int *locr0
= ((int *)&psl
)-PS
;
register struct sysent
*callp
;
r0
= 0; r0
= r0
; r1
= 0; r1
= r1
;
if (!USERMODE(locr0
[PS
]))
if (code
== 139) { /* 4.2 COMPATIBILTY XXX */
osigcleanup(); /* 4.2 COMPATIBILTY XXX */
goto done
; /* 4.2 COMPATIBILTY XXX */
params
= (caddr_t
)locr0
[FP
] + NBPW
;
* Try to reconstruct pc, assuming code
* is an immediate constant
opc
= pc
- 2; /* short literal */
opc
--; /* byte immediate */
opc
--; /* word immediate */
opc
-= 2; /* long immediate */
callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
callp
= (code
>= nsysent
) ? &sysent
[63] : &sysent
[code
];
if ((i
= callp
->sy_narg
* sizeof (int)) &&
(u
.u_error
= copyin(params
, (caddr_t
)u
.u_arg
, (u_int
)i
)) != 0) {
locr0
[PS
] |= PSL_C
; /* carry bit */
u
.u_r
.r_val2
= locr0
[R1
];
if (setjmp(&u
.u_qsave
)) {
if (u
.u_error
== 0 && u
.u_eosys
!= RESTARTSYS
)
u
.u_eosys
= NORMALRETURN
;
printf("%s", syscallnames
[code
]);
for (a
= 0; a
< callp
->sy_narg
; a
++) {
printf("%s%x", cp
, u
.u_arg
[a
]);
if (u
.u_eosys
== NORMALRETURN
) {
locr0
[PS
] |= PSL_C
; /* carry bit */
locr0
[PS
] &= ~PSL_C
; /* clear carry bit */
locr0
[R0
] = u
.u_r
.r_val1
;
locr0
[R1
] = u
.u_r
.r_val2
;
} else if (u
.u_eosys
== RESTARTSYS
)
/* else if (u.u_eosys == JUSTRETURN) */
if (p
->p_cursig
|| ISSIG(p
))
* Since we are u.u_procp, clock will normally just change
* our priority without moving us from one queue to another
* (since the running process is not on a queue.)
* If that happened after we setrq ourselves but before we
* swtch()'ed, we might not be on the queue indicated by
struct timeval
*tv
= &u
.u_ru
.ru_stime
;
ticks
= ((tv
->tv_sec
- syst
.tv_sec
) * 1000 +
(tv
->tv_usec
- syst
.tv_usec
) / 1000) / (tick
/ 1000);
addupc(locr0
[PC
], &u
.u_prof
, ticks
);
* nonexistent system call-- signal process (may want to handle it)
* flag error if process won't see signal immediately
* Q: should we do that all the time ??
if (u
.u_signal
[SIGSYS
] == SIG_IGN
|| u
.u_signal
[SIGSYS
] == SIG_HOLD
)
psignal(u
.u_procp
, SIGSYS
);