* Copyright (c) 1988 University of Utah.
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* %sccs.include.redist.c%
* from: Utah $Hdr: trap.c 1.28 89/09/25$
* @(#)trap.c 7.8 (Berkeley) %G%
#include "../vm/vm_param.h"
#include "../vm/vm_map.h"
#include "../hpux/hpux.h"
#define USER 040 /* user-mode flag added to type */
#define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0])
* Called from the trap handler when a processor trap occurs.
trap(type
, code
, v
, frame
)
register struct proc
*p
= u
.u_procp
;
if (USERMODE(frame
.f_sr
)) {
if (!panicstr
&& kgdb_trap(type
, code
, v
, &frame
))
printf("trap type %d, code = %x, v = %x\n", type
, code
, v
);
regdump(frame
.f_regs
, 128);
if ((unsigned)type
< TRAP_TYPES
)
case T_BUSERR
: /* kernel bus error */
if (!u
.u_pcb
.pcb_onfault
)
* If we have arranged to catch this fault in any of the
* copy to/from user space routines, set PC to return to
* indicated location and set flag informing buserror code
* that it may need to clean up stack frame.
frame
.f_pc
= (int) u
.u_pcb
.pcb_onfault
;
case T_BUSERR
+USER
: /* bus error */
case T_ADDRERR
+USER
: /* address error */
case T_COPERR
: /* kernel coprocessor violation */
case T_FMTERR
: /* kernel format error */
* The user has most likely trashed the RTE or FP state info
* in the stack frame of a signal handler.
printf("pid %d: kernel %s exception\n", u
.u_procp
->p_pid
,
type
==T_COPERR
? "coprocessor" : "format");
u
.u_signal
[SIGILL
] = SIG_DFL
;
ucode
= frame
.f_format
; /* XXX was ILL_RESAD_FAULT */
case T_COPERR
+USER
: /* user coprocessor violation */
/* What is a proper response here? */
case T_FPERR
+USER
: /* 68881 exceptions */
* We pass along the 68881 status register which locore stashed
* in code for us. Note that there is a possibility that the
* bit pattern of this register will conflict with one of the
* FPE_* codes defined in signal.h. Fortunately for us, the
* only such codes we use are all in the range 1-7 and the low
* 3 bits of the status register are defined as 0 so there is
case T_ILLINST
+USER
: /* illegal instruction fault */
if (u
.u_procp
->p_flag
& SHPUX
) {
ucode
= HPUX_ILL_ILLINST_TRAP
;
case T_PRIVINST
+USER
: /* privileged instruction fault */
if (u
.u_procp
->p_flag
& SHPUX
)
ucode
= HPUX_ILL_PRIV_TRAP
;
ucode
= frame
.f_format
; /* XXX was ILL_PRIVIN_FAULT */
case T_ZERODIV
+USER
: /* Divide by zero */
if (u
.u_procp
->p_flag
& SHPUX
)
ucode
= HPUX_FPE_INTDIV_TRAP
;
ucode
= frame
.f_format
; /* XXX was FPE_INTDIV_TRAP */
case T_CHKINST
+USER
: /* CHK instruction trap */
if (u
.u_procp
->p_flag
& SHPUX
) {
/* handled differently under hp-ux */
ucode
= HPUX_ILL_CHK_TRAP
;
ucode
= frame
.f_format
; /* XXX was FPE_SUBRNG_TRAP */
case T_TRAPVINST
+USER
: /* TRAPV instruction trap */
if (u
.u_procp
->p_flag
& SHPUX
) {
/* handled differently under hp-ux */
ucode
= HPUX_ILL_TRAPV_TRAP
;
ucode
= frame
.f_format
; /* XXX was FPE_INTOVF_TRAP */
* XXX: Trace traps are a nightmare.
* HP-UX uses trap #1 for breakpoints,
* KGDB uses trap #15 (for kernel breakpoints).
* HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
* SUN 3.x traps get passed through as T_TRAP15 and are not really
* supported yet. KGDB traps are also passed through as T_TRAP15
case T_TRACE
: /* kernel trace trap */
case T_TRAP15
: /* SUN (or KGDB) kernel trace trap */
if (kgdb_trap(type
, code
, v
, &frame
))
case T_TRACE
+USER
: /* user trace trap */
case T_TRAP15
+USER
: /* SUN user trace trap */
case T_ASTFLT
: /* system async trap, cannot happen */
case T_ASTFLT
+USER
: /* user async trap */
* We check for software interrupts first. This is because
* they are at a higher level than ASTs, and on a VAX would
* interrupt the AST. We assume that if we are processing
* an AST that we must be at IPL0 so we don't bother to
* check. Note that we ensure that we are at least at SIR
* IPL while processing the SIR.
case T_SSIR
: /* software interrupt */
softclock((caddr_t
)frame
.f_pc
, (int)frame
.f_sr
);
* If this was not an AST trap, we are all done.
if (type
!= T_ASTFLT
+USER
) {
if ((u
.u_procp
->p_flag
&SOWEUPC
) && u
.u_prof
.pr_scale
) {
addupc(frame
.f_pc
, &u
.u_prof
, 1);
u
.u_procp
->p_flag
&= ~SOWEUPC
;
case T_MMUFLT
: /* kernel mode page fault */
case T_MMUFLT
+USER
: /* page fault */
extern vm_map_t kernel_map
;
* It is only a kernel address space fault iff:
* 1. (type & USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space data fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
(code
& (SSW_DF
|FC_SUPERD
)) == (SSW_DF
|FC_SUPERD
)))
if ((code
& (SSW_DF
|SSW_RW
)) == SSW_DF
) /* what about RMW? */
ftype
= VM_PROT_READ
| VM_PROT_WRITE
;
va
= trunc_page((vm_offset_t
)v
);
if (map
== kernel_map
&& va
== 0) {
printf("trap: bad kernel access at %x\n", v
);
* XXX: rude hack to make stack limits "work"
if ((caddr_t
)va
>= u
.u_maxsaddr
&& map
!= kernel_map
) {
nss
= clrnd(btoc(USRSTACK
-(unsigned)va
));
if (nss
> btoc(u
.u_rlimit
[RLIMIT_STACK
].rlim_cur
)) {
rv
= vm_fault(map
, va
, ftype
, FALSE
);
if (rv
== KERN_SUCCESS
) {
* XXX: continuation of rude stack hack
printf("vm_fault(%x, %x, %x, 0) -> %x\n",
printf(" type %x, code [mmu,,ssw]: %x\n",
i
= (rv
== KERN_PROTECTION_FAILURE
) ? SIGBUS
: SIGSEGV
;
* 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(frame
.f_pc
, &u
.u_prof
, ticks
* profscale
);
addupc(frame
.f_pc
, &u
.u_prof
, ticks
);
* Called from the trap handler when a system call occurs
register struct sysent
*callp
;
register struct proc
*p
= u
.u_procp
;
extern struct sysent hpuxsysent
[];
extern int hpuxnsysent
, notimp();
if (!USERMODE(frame
.f_sr
))
params
= (caddr_t
)frame
.f_regs
[SP
] + NBPW
;
if (code
== 0) { /* indir */
callp
= &systab
[0]; /* indir (illegal) */
if ((i
= callp
->sy_narg
* sizeof (int)) &&
(error
= copyin(params
, (caddr_t
)&args
, (u_int
)i
))) {
error
= bsdtohpuxerrno(error
);
frame
.f_regs
[D0
] = (u_char
) error
;
frame
.f_sr
|= PSL_C
; /* carry bit */
if (KTRPOINT(p
, KTR_SYSCALL
))
ktrsyscall(p
->p_tracep
, code
, callp
->sy_narg
, args
.i
);
if (KTRPOINT(p
, KTR_SYSCALL
))
ktrsyscall(p
->p_tracep
, code
, callp
->sy_narg
, args
.i
);
rval
[1] = frame
.f_regs
[D1
];
if (callp
->sy_call
== notimp
)
error
= notimp(u
.u_procp
, args
.i
, rval
, code
, callp
->sy_narg
);
error
= (*callp
->sy_call
)(u
.u_procp
, &args
, rval
);
else if (error
!= EJUSTRETURN
) {
error
= bsdtohpuxerrno(error
);
frame
.f_regs
[D0
] = (u_char
) error
;
frame
.f_sr
|= PSL_C
; /* carry bit */
frame
.f_regs
[D0
] = rval
[0];
frame
.f_regs
[D1
] = rval
[1];
/* else if (error == EJUSTRETURN) */
* Reinitialize proc pointer `p' as it may be different
* if this is a child returning from fork syscall.
* XXX the check for sigreturn ensures that we don't
* attempt to set up a call to a signal handler (sendsig) before
* we have cleaned up the stack from the last call (sigreturn).
* Allowing this seems to lock up the machine in certain scenarios.
* What should really be done is to clean up the signal handling
* so that this is not a problem.
if (code
!= SYS_sigreturn
&& (i
= CURSIG(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
if (code
!= SYS_sigreturn
&& (i
= CURSIG(p
)))
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(frame
.f_pc
, &u
.u_prof
, ticks
* profscale
);
addupc(frame
.f_pc
, &u
.u_prof
, ticks
);
if (KTRPOINT(p
, KTR_SYSRET
))
ktrsysret(p
->p_tracep
, code
, error
, rval
[0]);