5a667d2381546a38524a16f4b4311f4666998e11
* 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: machdep.c 1.51 89/11/28$
* @(#)machdep.c 7.10 (Berkeley) %G%
#include "../hpux/hpux.h"
#include "../include/cpu.h"
#include "../include/reg.h"
#include "../include/psl.h"
#define MAXMEM 64*1024*CLSIZE /* XXX - from cmap.h */
#include "vm/vm_object.h"
extern vm_offset_t avail_end
;
* Declare these as initialized data so we can patch them.
int msgbufmapped
; /* set when safe to use msgbuf */
int physmem
= MAXMEM
; /* max supported memory, changes to actual */
* safepri is a safe priority for sleep to set for a spin-wait
* during autoconfiguration or after a panic.
int safepri
= PSL_LOWIPL
;
* Machine-dependent startup code
extern struct map
*useriomap
;
int opmapdebug
= pmapdebug
;
vm_offset_t minaddr
, maxaddr
;
* Set cpuspeed immediately since cninit() called routines
* Find what hardware is attached to this machine.
* Initialize the console before we print anything out.
* Initialize error message buffer (at end of core).
/* avail_end was pre-decremented in pmap_bootstrap to compensate */
for (i
= 0; i
< btoc(sizeof (struct msgbuf
)); i
++)
pmap_enter(pmap_kernel(), msgbufp
, avail_end
+ i
* NBPG
,
* Good {morning,afternoon,evening,night}.
printf("real mem = %d\n", ctob(physmem
));
* Allocate space for system data structures.
* The first available real memory address is in "firstaddr".
* The first available kernel virtual address is in "v".
* As pages of kernel virtual memory are allocated, "v" is incremented.
* As pages of memory are allocated and cleared,
* "firstaddr" is incremented.
* An index into the kernel page table corresponding to the
* virtual memory address maintained in "v" is kept in "mapaddr".
* Make two passes. The first pass calculates how much memory is
* needed and allocates it. The second pass assigns virtual
* addresses to the various data structures.
#define valloc(name, type, num) \
(name) = (type *)v; v = (caddr_t)((name)+(num))
#define valloclim(name, type, num, lim) \
(name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
valloclim(file
, struct file
, nfile
, fileNFILE
);
valloclim(proc
, struct proc
, nproc
, procNPROC
);
valloc(cfree
, struct cblock
, nclist
);
valloc(callout
, struct callout
, ncallout
);
valloc(swapmap
, struct map
, nswapmap
= nproc
* 2);
valloc(shmsegs
, struct shmid_ds
, shminfo
.shmmni
);
* Determine how many buffers to allocate.
* Since HPs tend to be long on memory and short on disk speed,
* we allocate more buffer space than the BSD standard of
* use 10% of memory for the first 2 Meg, 5% of remaining.
* We just allocate a flat 10%. Insure a minimum of 16 buffers.
* We allocate 1/2 as many swap buffer headers as file i/o buffers.
bufpages
= physmem
/ 10 / CLSIZE
;
nswbuf
= (nbuf
/ 2) &~ 1; /* force even */
nswbuf
= 256; /* sanity */
valloc(swbuf
, struct buf
, nswbuf
);
valloc(buf
, struct buf
, nbuf
);
* End of first pass, size has been calculated so allocate memory
size
= (vm_size_t
)(v
- firstaddr
);
firstaddr
= (int)kmem_alloc(kernel_map
, round_page(size
));
panic("startup: no room for tables");
* End of second pass, addresses have been assigned
if ((vm_size_t
)(v
- firstaddr
) != size
)
panic("startup: table size inconsistency");
* Now allocate buffers proper. They are different than the above
* in that they usually occupy more virtual memory than physical.
buffer_map
= kmem_suballoc(kernel_map
, (vm_offset_t
)&buffers
,
minaddr
= (vm_offset_t
)buffers
;
if (vm_map_find(buffer_map
, vm_object_allocate(size
), (vm_offset_t
)0,
&minaddr
, size
, FALSE
) != KERN_SUCCESS
)
panic("startup: cannot allocate buffers");
residual
= bufpages
% nbuf
;
for (i
= 0; i
< nbuf
; i
++) {
* First <residual> buffers get (base+1) physical pages
* allocated for them. The rest get (base) physical pages.
* The rest of each buffer occupies virtual space,
* but has no physical memory allocated for it.
curbuf
= (vm_offset_t
)buffers
+ i
* MAXBSIZE
;
curbufsize
= CLBYTES
* (i
< residual
? base
+1 : base
);
vm_map_pageable(buffer_map
, curbuf
, curbuf
+curbufsize
, FALSE
);
vm_map_simplify(buffer_map
, curbuf
);
* Allocate a submap for exec arguments. This map effectively
* limits the number of processes exec'ing at any time.
exec_map
= kmem_suballoc(kernel_map
, &minaddr
, &maxaddr
,
* Allocate a submap for physio
phys_map
= kmem_suballoc(kernel_map
, &minaddr
, &maxaddr
,
* Finally, allocate mbuf pool. Since mclrefcnt is an off-size
* we use the more space efficient malloc in place of kmem_alloc.
mclrefcnt
= (char *)malloc(NMBCLUSTERS
+CLBYTES
/MCLBYTES
,
bzero(mclrefcnt
, NMBCLUSTERS
+CLBYTES
/MCLBYTES
);
mb_map
= kmem_suballoc(kernel_map
, (vm_offset_t
)&mbutl
, &maxaddr
,
for (i
= 1; i
< ncallout
; i
++)
callout
[i
-1].c_next
= &callout
[i
];
printf("avail mem = %d\n", ptoa(vm_page_free_count
));
printf("using %d buffers containing %d bytes of memory\n",
nbuf
, bufpages
* CLBYTES
);
* Set up CPU-specific registers, cache, etc.
* Set up buffers, so they can be used to read disk labels.
* Return the difference (in microseconds)
* between the current time and a previous
* time as represented by the arguments.
vmtime(otime
, olbolt
, oicr
)
register int otime
, olbolt
, oicr
;
return (((time
.tv_sec
-otime
)*100 + lbolt
-olbolt
)*10000);
* Clear registers on exec
u
.u_ar0
[PC
] = entry
& ~1;
/* restore a null state frame */
u
.u_pcb
.pcb_fpregs
.fpf_null
= 0;
m68881_restore(&u
.u_pcb
.pcb_fpregs
);
if (u
.u_procp
->p_flag
& SHPUX
) {
u
.u_ar0
[A0
] = 0; /* not 68010 (bit 31), no FPA (30) */
retval
[0] = 0; /* no float card */
retval
[1] = 1; /* yes 68881 */
retval
[1] = 0; /* no 68881 */
* Ensure we perform the right action on traps type 1 and 2:
* If our parent is an HPUX process and we are being traced, turn
* on HPUX style interpretation. Else if we were using the HPUX
* style interpretation, revert to the BSD interpretation.
* XXX This doesn't have much to do with setting registers but
* I didn't want to muck up kern_exec.c with this code, so I
if ((u
.u_procp
->p_pptr
->p_flag
& SHPUX
) &&
(u
.u_procp
->p_flag
& STRC
)) {
u
.u_pcb
.pcb_flags
|= PCB_HPUXTRACE
;
} else if (u
.u_pcb
.pcb_flags
& PCB_HPUXTRACE
) {
u
.u_pcb
.pcb_flags
&= ~PCB_HPUXTRACE
;
printf("318/319/330 (16.67Mhz");
printf("345/375 (50Mhz");
printf("\nunknown machine type %d\n", machineid
);
printf(" MC680%s CPU", mmutype
== MMU_68030
? "30" : "20");
printf("\nunknown MMU type %d\n", mmutype
);
if (mmutype
== MMU_68030
)
printf(", %sMhz MC68882 FPU",
machineid
== HP_340
? "16.67" :
(machineid
== HP_360
? "25" :
(machineid
== HP_370
? "33.33" : "50")));
printf(", %sMhz MC68881 FPU",
machineid
== HP_350
? "20" : "16.67");
printf(", %dK virtual-address cache",
machineid
== HP_320
? 16 : 32);
printf(", %dK physical-address cache",
machineid
== HP_370
? 64 : 32);
* Now that we have told the user what they have,
* let them know if that machine type isn't configured.
case -1: /* keep compilers happy */
#if !defined(HP320) && !defined(HP350)
#if !defined(HP360) && !defined(HP370)
panic("CPU type not configured");
static short *sigtrap
= NULL
;
/* locate trap instruction in pcb_sigc */
register struct pcb
*pcp
= &u
.u_pcb
;
sigtrap
= &pcp
->pcb_sigc
[sizeof(pcp
->pcb_sigc
)/sizeof(short)];
while (--sigtrap
>= pcp
->pcb_sigc
)
if ((*sigtrap
& 0xFFF0) == 0x4E40)
if (sigtrap
< pcp
->pcb_sigc
)
panic("bogus sigcode\n");
*sigtrap
= ishpux
? 0x4E42 : 0x4E41;
int ss_flags
; /* which of the following are valid */
struct frame ss_frame
; /* original exception frame */
struct fpframe ss_fpstate
; /* 68881/68882 state info */
* WARNING: code in locore.s assumes the layout shown for sf_signum
* thru sf_handler so... don't screw with them!
int sf_signum
; /* signo for handler */
int sf_code
; /* additional info for handler */
struct sigcontext
*sf_scp
; /* context ptr for handler */
sig_t sf_handler
; /* handler addr for u_sigc */
struct sigstate sf_state
; /* state of the hardware */
struct sigcontext sf_sc
; /* actual context */
/* the rest aren't part of the context but are included for our convenience */
u_int hsc_magic
; /* XXX sigreturn: cookie */
struct sigcontext
*hsc_realsc
; /* XXX sigreturn: ptr to BSD context */
* For an HP-UX process, a partial hpuxsigframe follows the normal sigframe.
* Tremendous waste of space, but some HP-UX applications (e.g. LCL) need it.
struct sigcontext
*hsf_scp
;
struct hpuxsigcontext hsf_sc
;
* Send an interrupt to process.
sendsig(catcher
, sig
, mask
, code
)
register struct proc
*p
= u
.u_procp
;
register struct sigframe
*fp
, *kfp
;
register struct frame
*frame
;
frame
= (struct frame
*)u
.u_ar0
;
* Allocate and validate space for the signal handler
* context. Note that if the stack is in P0 space, the
* call to grow() is a nop, and the useracc() check
* will fail if the process has not already allocated
* the space with a `brk'.
fsize
= sizeof(struct sigframe
) + sizeof(struct hpuxsigframe
);
fsize
= sizeof(struct sigframe
);
if (!u
.u_onstack
&& (u
.u_sigonstack
& sigmask(sig
))) {
fp
= (struct sigframe
*)(u
.u_sigsp
- fsize
);
fp
= (struct sigframe
*)(frame
->f_regs
[SP
] - fsize
);
if ((unsigned)fp
<= USRSTACK
- ctob(u
.u_ssize
))
(void)grow((unsigned)fp
);
if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
printf("sendsig(%d): sig %d ssp %x usp %x scp %x ft %d\n",
p
->p_pid
, sig
, &oonstack
, fp
, &fp
->sf_sc
, ft
);
if (useracc((caddr_t
)fp
, fsize
, B_WRITE
) == 0) {
if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
printf("sendsig(%d): useracc failed on sig %d\n",
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
SIGACTION(p
, SIGILL
) = SIG_DFL
;
kfp
= (struct sigframe
*)malloc((u_long
)fsize
, M_TEMP
, M_WAITOK
);
* Build the argument list for the signal handler.
kfp
->sf_scp
= &fp
->sf_sc
;
kfp
->sf_handler
= catcher
;
* Save necessary hardware state. Currently this includes:
* - original exception frame (if not a "normal" frame)
kfp
->sf_state
.ss_flags
= SS_USERREGS
;
bcopy((caddr_t
)frame
->f_regs
,
(caddr_t
)kfp
->sf_state
.ss_frame
.f_regs
, sizeof frame
->f_regs
);
if (ft
!= FMT9
&& ft
!= FMTA
&& ft
!= FMTB
)
panic("sendsig: bogus frame type");
kfp
->sf_state
.ss_flags
|= SS_RTEFRAME
;
kfp
->sf_state
.ss_frame
.f_format
= frame
->f_format
;
kfp
->sf_state
.ss_frame
.f_vector
= frame
->f_vector
;
bcopy((caddr_t
)&frame
->F_u
,
(caddr_t
)&kfp
->sf_state
.ss_frame
.F_u
,
(ft
== FMT9
) ? FMT9SIZE
:
(ft
== FMTA
) ? FMTASIZE
: FMTBSIZE
);
* Gag! Leave an indicator that we need to clean up the
* kernel stack. We do this by setting the "pad word"
* above the hardware stack frame. "bexit" in locore
* will then know that it must compress the kernel stack
* and create a normal four word stack frame.
if (sigdebug
& SDB_FOLLOW
)
printf("sendsig(%d): copy out %d of frame %d\n",
(ft
== FMT9
) ? FMT9SIZE
:
(ft
== FMTA
) ? FMTASIZE
: FMTBSIZE
, ft
);
kfp
->sf_state
.ss_flags
|= SS_FPSTATE
;
m68881_save(&kfp
->sf_state
.ss_fpstate
);
if ((sigdebug
& SDB_FPSTATE
) && *(char *)&kfp
->sf_state
.ss_fpstate
)
printf("sendsig(%d): copy out FP state (%x) to %x\n",
p
->p_pid
, *(u_int
*)&kfp
->sf_state
.ss_fpstate
,
&kfp
->sf_state
.ss_fpstate
);
* Build the signal context to be used by sigreturn.
kfp
->sf_sc
.sc_onstack
= oonstack
;
kfp
->sf_sc
.sc_mask
= mask
;
kfp
->sf_sc
.sc_sp
= frame
->f_regs
[SP
];
kfp
->sf_sc
.sc_fp
= frame
->f_regs
[A6
];
kfp
->sf_sc
.sc_ap
= (int)&fp
->sf_state
;
kfp
->sf_sc
.sc_pc
= frame
->f_pc
;
kfp
->sf_sc
.sc_ps
= frame
->f_sr
;
* Create an HP-UX style sigcontext structure and associated goo
register struct hpuxsigframe
*hkfp
;
hkfp
= (struct hpuxsigframe
*)&kfp
[1];
hkfp
->hsf_signum
= bsdtohpuxsig(kfp
->sf_signum
);
hkfp
->hsf_code
= kfp
->sf_code
;
hkfp
->hsf_scp
= (struct sigcontext
*)
&((struct hpuxsigframe
*)(&fp
[1]))->hsf_sc
;
hkfp
->hsf_sc
.hsc_syscall
= 0; /* XXX */
hkfp
->hsf_sc
.hsc_action
= 0; /* XXX */
hkfp
->hsf_sc
.hsc_pad1
= hkfp
->hsf_sc
.hsc_pad2
= 0;
hkfp
->hsf_sc
.hsc_onstack
= kfp
->sf_sc
.sc_onstack
;
hkfp
->hsf_sc
.hsc_mask
= kfp
->sf_sc
.sc_mask
;
hkfp
->hsf_sc
.hsc_sp
= kfp
->sf_sc
.sc_sp
;
hkfp
->hsf_sc
.hsc_ps
= kfp
->sf_sc
.sc_ps
;
hkfp
->hsf_sc
.hsc_pc
= kfp
->sf_sc
.sc_pc
;
hkfp
->hsf_sc
.hsc_pad
= 0;
hkfp
->hsf_sc
.hsc_magic
= 0xdeadbeef;
hkfp
->hsf_sc
.hsc_realsc
= kfp
->sf_scp
;
bcopy((caddr_t
)frame
->f_regs
, (caddr_t
)hkfp
->hsf_regs
,
sizeof (hkfp
->hsf_regs
));
kfp
->sf_signum
= hkfp
->hsf_signum
;
kfp
->sf_scp
= hkfp
->hsf_scp
;
(void) copyout((caddr_t
)kfp
, (caddr_t
)fp
, fsize
);
frame
->f_regs
[SP
] = (int)fp
;
if (sigdebug
& SDB_FOLLOW
)
printf("sendsig(%d): sig %d scp %x fp %x sc_sp %x sc_ap %x\n",
p
->p_pid
, sig
, kfp
->sf_scp
, fp
,
kfp
->sf_sc
.sc_sp
, kfp
->sf_sc
.sc_ap
);
* Signal trampoline code is at base of user stack.
frame
->f_pc
= USRSTACK
- sizeof(u
.u_pcb
.pcb_sigc
);
if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
printf("sendsig(%d): sig %d returns\n",
free((caddr_t
)kfp
, M_TEMP
);
* System call to cleanup state after a signal
* has been taken. Reset signal mask and
* stack state from context left by sendsig (above).
* Return to previous pc and psl as specified by
* context left by sendsig. Check carefully to
* make sure that the user has not modified the
* psl to gain improper priviledges or to cause
sigreturn(p
, uap
, retval
)
struct sigcontext
*sigcntxp
;
register struct sigcontext
*scp
;
register struct frame
*frame
;
if (sigdebug
& SDB_FOLLOW
)
printf("sigreturn: pid %d, scp %x\n", p
->p_pid
, scp
);
* Grab context as an HP-UX style context and determine if it
* was one that we contructed in sendsig.
struct hpuxsigcontext
*hscp
= (struct hpuxsigcontext
*)scp
;
struct hpuxsigcontext htsigc
;
if (useracc((caddr_t
)hscp
, sizeof (*hscp
), B_WRITE
) == 0 ||
copyin((caddr_t
)hscp
, (caddr_t
)&htsigc
, sizeof htsigc
))
* If not generated by sendsig or we cannot restore the
* BSD-style sigcontext, just restore what we can -- state
* will be lost, but them's the breaks.
if (hscp
->hsc_magic
!= 0xdeadbeef ||
(scp
= hscp
->hsc_realsc
) == 0 ||
useracc((caddr_t
)scp
, sizeof (*scp
), B_WRITE
) == 0 ||
copyin((caddr_t
)scp
, (caddr_t
)&tsigc
, sizeof tsigc
)) {
u
.u_onstack
= hscp
->hsc_onstack
& 01;
p
->p_sigmask
= hscp
->hsc_mask
&~ sigcantmask
;
frame
= (struct frame
*) u
.u_ar0
;
frame
->f_regs
[SP
] = hscp
->hsc_sp
;
frame
->f_pc
= hscp
->hsc_pc
;
frame
->f_sr
= hscp
->hsc_ps
&~ PSL_USERCLR
;
* Otherwise, overlay BSD context with possibly modified
tsigc
.sc_onstack
= hscp
->hsc_onstack
;
tsigc
.sc_mask
= hscp
->hsc_mask
;
tsigc
.sc_sp
= hscp
->hsc_sp
;
tsigc
.sc_ps
= hscp
->hsc_ps
;
tsigc
.sc_pc
= hscp
->hsc_pc
;
* Test and fetch the context structure.
* We grab it all at once for speed.
if (useracc((caddr_t
)scp
, sizeof (*scp
), B_WRITE
) == 0 ||
copyin((caddr_t
)scp
, (caddr_t
)&tsigc
, sizeof tsigc
))
if ((scp
->sc_ps
& (PSL_MBZ
|PSL_IPL
|PSL_S
)) != 0)
* Restore the user supplied information
u
.u_onstack
= scp
->sc_onstack
& 01;
p
->p_sigmask
= scp
->sc_mask
&~ sigcantmask
;
frame
= (struct frame
*) u
.u_ar0
;
frame
->f_regs
[SP
] = scp
->sc_sp
;
frame
->f_regs
[A6
] = scp
->sc_fp
;
frame
->f_pc
= scp
->sc_pc
;
frame
->f_sr
= scp
->sc_ps
;
* Grab pointer to hardware state information.
* If zero, the user is probably doing a longjmp.
if ((rf
= scp
->sc_ap
) == 0)
* See if there is anything to do before we go to the
* expense of copying in close to 1/2K of data
flags
= fuword((caddr_t
)rf
);
if (sigdebug
& SDB_FOLLOW
)
printf("sigreturn(%d): sc_ap %x flags %x\n",
if (flags
== 0 || copyin((caddr_t
)rf
, (caddr_t
)&tstate
, sizeof tstate
))
if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
printf("sigreturn(%d): ssp %x usp %x scp %x ft %d\n",
p
->p_pid
, &flags
, scp
->sc_sp
, uap
->sigcntxp
,
(flags
&SS_RTEFRAME
) ? tstate
.ss_frame
.f_format
: -1);
* Restore most of the users registers except for A6 and SP
* which were handled above.
bcopy((caddr_t
)tstate
.ss_frame
.f_regs
,
(caddr_t
)frame
->f_regs
, sizeof(frame
->f_regs
)-2*NBPW
);
* Restore long stack frames. Note that we do not copy
* back the saved SR or PC, they were picked up above from
* the sigcontext structure.
if (flags
& SS_RTEFRAME
) {
/* grab frame type and validate */
sz
= tstate
.ss_frame
.f_format
;
/* no k-stack adjustment necessary */
frame
->f_format
= tstate
.ss_frame
.f_format
;
frame
->f_vector
= tstate
.ss_frame
.f_vector
;
bcopy((caddr_t
)&tstate
.ss_frame
.F_u
, (caddr_t
)&frame
->F_u
, sz
);
if (sigdebug
& SDB_FOLLOW
)
printf("sigreturn(%d): copy in %d of frame type %d\n",
p
->p_pid
, sz
, tstate
.ss_frame
.f_format
);
* Finally we restore the original FP context
m68881_restore(&tstate
.ss_fpstate
);
if ((sigdebug
& SDB_FPSTATE
) && *(char *)&tstate
.ss_fpstate
)
printf("sigreturn(%d): copied in FP state (%x) at %x\n",
p
->p_pid
, *(u_int
*)&tstate
.ss_fpstate
,
if ((sigdebug
& SDB_FOLLOW
) ||
((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
))
printf("sigreturn(%d): returns\n", p
->p_pid
);
/* take a snap shot before clobbering any registers */
resume((u_int
)pcbb(u
.u_procp
));
if ((howto
&RB_NOSYNC
) == 0 && waittime
< 0 && bfreelist
[0].b_forw
) {
printf("syncing disks... ");
* Release vnodes held by texts before sync.
vnode_pager_umount(NULL
);
sync((struct sigcontext
*)0);
for (iter
= 0; iter
< 20; iter
++) {
for (bp
= &buf
[nbuf
]; --bp
>= buf
; )
if ((bp
->b_flags
& (B_BUSY
|B_INVAL
)) == B_BUSY
)
* If we've been adjusting the clock, the todr
* will be out of synch; adjust it now.
splhigh(); /* extreme priority */
int dumpmag
= 0x8fca0101; /* magic number for savecore */
int dumpsize
= 0; /* also for savecore */
if (dumpdev
!= NODEV
&& bdevsw
[major(dumpdev
)].d_psize
) {
nblks
= (*bdevsw
[major(dumpdev
)].d_psize
)(dumpdev
);
if (dumpsize
> btoc(dbtob(nblks
- dumplo
)))
dumpsize
= btoc(dbtob(nblks
- dumplo
));
dumplo
= nblks
- btodb(ctob(physmem
));
* Don't dump on the first CLBYTES (why CLBYTES?)
* in case the dump device includes a disk label.
if (dumplo
< btodb(CLBYTES
))
* Doadump comes here after turning off memory management and
* getting on the dump stack, either when called above, or by
* For dumps during autoconfiguration,
* if dump device has already configured...
printf("\ndumping to dev %x, offset %d\n", dumpdev
, dumplo
);
switch ((*bdevsw
[major(dumpdev
)].d_dump
)(dumpdev
)) {
printf("device not ready\n");
printf("area improper\n");
* Return the best possible estimate of the time in the timeval
* to which tvp points. We do this by returning the current time
* plus the amount of time since the last clock interrupt (clock.c:clkread).
* Check that this time is no less than any previously-reported time,
* which could happen around the time of a clock adjustment. Just for fun,
* we guarantee that the time will be greater than the value obtained by a
register struct timeval
*tvp
;
static struct timeval lasttime
;
tvp
->tv_usec
+= clkread();
while (tvp
->tv_usec
> 1000000) {
if (tvp
->tv_sec
== lasttime
.tv_sec
&&
tvp
->tv_usec
<= lasttime
.tv_usec
&&
(tvp
->tv_usec
= lasttime
.tv_usec
+ 1) > 1000000) {
printf("stray trap, addr 0x%x\n", addr
);
i
= *addr
; if (i
) return(0);
nofault
= (int *) &faultbuf
;
if (setjmp((label_t
*)nofault
)) {
i
= *(volatile short *)addr
;
i
= *addr
; if (i
) return(0);
nofault
= (int *) &faultbuf
;
if (setjmp((label_t
*)nofault
)) {
i
= *(volatile char *)addr
;
if (netisr
& (1 << NETISR_IP
)) {
netisr
&= ~(1 << NETISR_IP
);
if (netisr
& (1 << NETISR_NS
)) {
netisr
&= ~(1 << NETISR_NS
);
if (netisr
& (1 << NETISR_ISO
)) {
netisr
&= ~(1 << NETISR_ISO
);
register struct isr
*isr
;
extern struct isr isrqueue
[];
isr
= isrqueue
[ipl
].isr_forw
;
for (; isr
!= &isrqueue
[ipl
]; isr
= isr
->isr_forw
) {
if ((isr
->isr_intr
)(isr
->isr_arg
)) {
printf("stray interrupt, sr 0x%x\n", sr
);
printf("intrhand: unexpected sr 0x%x\n", sr
);
#if defined(DEBUG) && !defined(PANICBUTTON)
int panicbutton
= 1; /* non-zero if panic buttons are enabled */
int candbdelay
= 50; /* give em half a second */
* Level 7 interrupts can be caused by the keyboard or parity errors.
printf("Got a keyboard NMI\n");
"forced crash, nosync" : "forced crash");
timeout(candbtimer
, (caddr_t
)0, candbdelay
);
printf("unexpected level 7 interrupt ignored\n");
* Parity error section. Contains magic.
#define PARREG ((volatile short *)IOV(0x5B0000))
static int gotparmem
= 0;
int ignorekperr
= 0; /* ignore kernel parity errors */
* Enable parity detection
nofault
= (int *) &faultbuf
;
if (setjmp((label_t
*)nofault
)) {
printf("No parity memory\n");
printf("Parity detection enabled\n");
* Determine if level 7 interrupt was caused by a parity error
* and deal with it if it was. Returns 1 if it was a parity error.
printf("parity error after panic ignored\n");
printf("WARNING: transient parity error ignored\n");
else if (USERMODE(fp
->f_sr
)) {
printf("pid %d: parity error\n", u
.u_procp
->p_pid
);
uprintf("sorry, pid %d killed due to memory parity error\n",
psignal(u
.u_procp
, SIGKILL
);
} else if (ignorekperr
) {
printf("WARNING: kernel parity error ignored\n");
regdump(fp
->f_regs
, 128);
panic("kernel parity error");
* Yuk! There has got to be a better way to do this!
* Searching all of memory with interrupts blocked can lead to disaster.
volatile struct pte opte
;
register volatile int *ip
;
i
= o
= pg
= 0; if (i
) return(0);
* If looking is true we are searching for a known parity error
* and it has just occured. All we do is return to the higher
* If setjmp returns true, the parity error we were searching
* for has just occured (longjmp above) at the current pg+o
printf("Parity error at 0x%x\n", ctob(pg
)|o
);
* If we get here, a parity error has occured for the first time
* and we need to find it. We turn off any external caches and
* loop thru memory, testing every longword til a fault occurs and
* we regain control at setjmp above. Note that because of the
* setjmp, pg and o need to be volatile or their values will be lost.
for (pg
= btoc(lowram
); pg
< btoc(lowram
)+physmem
; pg
++) {
pmap_enter(pmap_kernel(), vmmap
, ctob(pg
), VM_PROT_READ
, TRUE
);
for (o
= 0; o
< NBPG
; o
+= sizeof(int))
* Getting here implies no fault was found. Should never happen.
printf("Couldn't locate parity error\n");
pmap_remove(pmap_kernel(), vmmap
, &vmmap
[NBPG
]);
int *rp
; /* must not be register */
static int doingdump
= 0;
printf("pid = %d, pc = %s, ", u
.u_procp
->p_pid
, hexstr(rp
[PC
], 8));
printf("ps = %s, ", hexstr(rp
[PS
], 4));
printf("sfc = %s, ", hexstr(getsfc(), 4));
printf("dfc = %s\n", hexstr(getdfc(), 4));
printf(" %s", hexstr(rp
[i
], 8));
printf(" %s", hexstr(rp
[i
+8], 8));
printf("\n\nKernel stack (%s):",
hexstr((int)(((int *)&rp
)-1), 8));
dumpmem(((int *)&rp
)-1, sbytes
, 0);
printf("\n\nUser stack (%s):", hexstr(rp
[SP
], 8));
dumpmem((int *)rp
[SP
], sbytes
, 1);
#define KSADDR ((int *)&(((char *)&u)[(UPAGES-1)*NBPG]))
for (i
= 0; i
< sz
; i
++) {
printf("\n%s: ", hexstr((int)ptr
, 6));
if ((val
= fuword(ptr
++)) == -1)
if (ustack
== 0 && (ptr
< KSADDR
|| ptr
> KSADDR
+(NBPG
/4-1)))
printf("%s", hexstr(val
, 8));
for (i
= len
-1; i
>= 0; --i
) {