* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992 OMRON Corporation.
* Copyright (c) 1980, 1990, 1993
* The Regents of the University of California. All rights reserved.
* 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: locore.s 1.62 92/01/20$
* from: hp300/hp300/locore.s 7.22 (Berkeley) 2/18/93
* @(#)locore.s 8.1 (Berkeley) %G%
* STACKCHECK enables two types of kernel stack checking:
* 1. stack "overflow". On every clock interrupt we ensure that
* the current kernel stack has not grown into the user struct
* page, i.e. size exceeded UPAGES-1 pages.
* 2. stack "underflow". Before every rte to user mode we ensure
* that we will be exactly at the base of the stack after the
* exception frame has been popped.
* Both checks are performed at splclock since they operate on the
* global temporary stack.
#include <luna68k/luna68k/vectors.s>
* Temporary stack for a variety of purposes.
* Try and make this the first thing is the data segment so it
* is page aligned. Note that if we overflow here, we run into
* This is where we wind up if the kernel jumps to location 0.
* (i.e. a bogus PC) This is known to immediately follow the vector
* table and is hence at 0x400 (see reset vector in vectors.s).
.asciz "kernel jump to zero"
* Called by auto-restart.
* Trap/interrupt vector routines
.globl _trap, _nofault, _longjmp
tstl _nofault | device probe?
jeq Lberr | no, handle as usual
movl _nofault,sp@- | yes,
jbsr _longjmp | longjmp(nofault)
cmpl #-2,_mmutype | 68040?
clrl sp@- | stack adjust count
moveml #0xFFFF,sp@- | save user registers
movl usp,a0 | save the user SP
movl a0,sp@(FR_SP) | in the savearea
lea sp@(FR_HW),a1 | grab base of HW berr frame
movw a1@(12),d0 | grab SSW
movl a1@(20),d1 | and fault VA
btst #11,d0 | check for mis-aligned access
addl #3,d1 | yes, get into next page
andl #PG_FRAME,d1 | and truncate
movl d1,sp@- | push fault VA
movl d0,sp@- | and padded SSW
btst #10,d0 | ATC bit set?
jeq Lisberr | no, must be a real bus error
movc dfc,d1 | yes, get MMU fault
movc d0,dfc | store faulting function code
movl sp@(4),a0 | get faulting address
.word 0xf568 | ptestr a0@
.long 0x4e7a0805 | movc mmusr,d0
movw d0,sp@ | save (ONLY LOW 16 BITS!)
clrl sp@- | stack adjust count
moveml #0xFFFF,sp@- | save user registers
movl usp,a0 | save the user SP
movl a0,sp@(FR_SP) | in the savearea
lea sp@(FR_HW),a1 | grab base of HW berr frame
cmpl #-2,_mmutype | 68040?
movl a1@(8),sp@- | yes, push fault address
clrl sp@- | no SSW for address fault
jra Lisaerr | go deal with it
movw a1@(10),d0 | grab SSW for fault processing
bset #14,d0 | yes, must set FB
movw d0,a1@(10) | for hardware too
bset #15,d0 | yes, must set FC
movw d0,a1@(10) | for hardware too
jeq Lbe0 | no, check for hard cases
movl a1@(16),d1 | fault address is as given in frame
btst #4,a1@(6) | long (type B) stack frame?
jne Lbe4 | yes, go handle
movl a1@(2),d1 | no, can use save PC
addql #4,d1 | yes, adjust address
addql #2,d1 | yes, adjust address
movl a1@(36),d1 | long format, use stage B address
subql #2,d1 | yes, adjust address
movl d1,sp@- | push fault VA
movl d0,sp@- | and padded SSW
movw a1@(6),d0 | get frame format/vector offset
andw #0x0FFF,d0 | clear out frame format
cmpw #12,d0 | address error vector?
jeq Lisaerr | yes, go to it
movl d1,a0 | fault address
ptestr #1,a0@,#7 | do a table search
pmove psr,sp@ | save result
btst #7,sp@ | bus error bit set?
jeq Lismerr | no, must be MMU fault
clrw sp@ | yes, re-clear pad word
jra Lisberr | and process as normal bus error
movl #T_MMUFLT,sp@- | show that we are an MMU fault
jra Ltrapnstkadj | and deal with it
movl #T_ADDRERR,sp@- | mark address error
jra Ltrapnstkadj | and deal with it
movl #T_BUSERR,sp@- | mark bus error
jbsr _trap | handle the error
lea sp@(12),sp | pop value args
movl sp@(FR_SP),a0 | restore user SP
movl a0,usp | from save area
movw sp@(FR_ADJ),d0 | need to adjust stack?
jne Lstkadj | yes, go to it
moveml sp@+,#0x7FFF | no, restore most user regs
addql #8,sp | toss SSP and stkadj
lea sp@(FR_HW),a1 | pointer to HW frame
addql #8,a1 | source pointer
addw d0,a0 | + hole size = dest pointer
movl a0,sp@(FR_SP) | new SSP
moveml sp@+,#0x7FFF | restore user registers
cmpw #0x202c,sp@(6) | format type 2?
jne _illinst | no, not an FP emulation
jmp fpsp_unimp | yes, go handle it
clrl sp@- | stack adjust count
moveml #0xFFFF,sp@- | save registers
moveq #T_FPEMULI,d0 | denote as FP emulation trap
cmpl #-2,_mmutype | 68040?
jne _illinst | no, treat as illinst
jmp fpsp_unsupp | yes, go handle it
clrl sp@- | stack adjust count
moveml #0xFFFF,sp@- | save registers
moveq #T_FPEMULD,d0 | denote as FP emulation trap
* Handles all other FP coprocessor exceptions.
* Note that since some FP exceptions generate mid-instruction frames
* and may cause signal delivery, we need to test for stack adjustment
clrl sp@- | stack adjust count
moveml #0xFFFF,sp@- | save user registers
movl a0,sp@(FR_SP) | the user stack pointer
movl _curpcb,a0 | current pcb
lea a0@(PCB_FPCTX),a0 | address of FP savearea
tstb a0@ | null state frame?
clrw d0 | no, need to tweak BIU
movb a0@(1),d0 | get frame size
bset #3,a0@(0,d0:w) | set exc_pend bit of BIU
fmovem fpsr,sp@- | push fpsr as code argument
frestore a0@ | restore state
movl #T_FPERR,sp@- | push type arg
jra Ltrapnstkadj | call trap and deal with stack cleanup
jra _badtrap | treat as an unexpected trap
* We wind up here from the 040 FP emulation library after
* the exception has been processed.
subql #4,sp | space for rts addr
movl d0,sp@- | scratch register
movw sp@(14),d0 | get vector offset
andl #0xFFF,d0 | mask out frame type and clear high word
cmpl #0x100,d0 | HP-UX style reschedule trap?
movl sp@+,d0 | restore scratch register
cmpl #0xC0,d0 | FP exception?
movl sp@+,d0 | yes, backoff
addql #4,sp | and prepare for normal trap frame
addl #Lvectab,d0 | convert to vector table offset
movl a0@,sp@(4) | get exception vector and save for rts
movl sp@+,d0 | scratch registers
rts | return to handler from vectab
* Coprocessor and format errors can generate mid-instruction stack
* frames and cause signal delivery hence we need to check for potential
clrl sp@- | stack adjust count
movl usp,a0 | get and save
movl a0,sp@(FR_SP) | the user stack pointer
movl #T_COPERR,sp@- | push trap type
jra Ltrapnstkadj | call trap and deal with stack adjustments
clrl sp@- | stack adjust count
movl usp,a0 | get and save
movl a0,sp@(FR_SP) | the user stack pointer
movl #T_FMTERR,sp@- | push trap type
jra Ltrapnstkadj | call trap and deal with stack adjustments
* Other exceptions only cause four and six word stack frame and require
* no post-trap stack adjustment.
movl usp,a0 | get and save
movl a0,sp@(FR_SP) | the user stack pointer
movl d0,sp@- | push trap type
lea sp@(12),sp | pop value args
movl sp@(FR_SP),a0 | restore
moveml sp@+,#0x7FFF | restore most user regs
addql #8,sp | pop SP and stack adjust
moveml #0xC0C0,sp@- | save scratch regs
movw sp@(22),sp@- | push exception vector info
movl sp@(22),sp@- | and PC
moveml sp@+,#0x0303 | restore regs
clrl sp@- | stack adjust count
moveml #0xFFFF,sp@- | save user registers
movl usp,a0 | save the user SP
movl a0,sp@(FR_SP) | in the savearea
movl d0,sp@- | push syscall number
jbsr _syscall | handle it
addql #4,sp | pop syscall arg
movl sp@(FR_SP),a0 | grab and restore
moveml sp@+,#0x7FFF | restore most registers
addql #8,sp | pop SP and stack adjust
* trap1 is sigreturn and trap2 is breakpoint.
jra sigreturn | trap1 is sigreturn
jra _trace | trap2 is breakpoint
* Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
* cachectl(command, addr, length)
* command in d0, addr in a1, length in d1
movl d1,sp@- | push length
movl d0,sp@- | push command
lea sp@(12),sp | pop args
* - trace traps for SUN binaries (not fully supported yet)
* We just pass it on and let trap() sort it all out
movw sp@(FR_HW),d1 | get PSW
andw #PSL_S,d1 | from user mode?
jeq fault | yes, just a regular fault
jbsr _kgdb_trap_glue | returns if no debugger
* Hit a breakpoint (trap 1 or 2) instruction.
* Push the code and treat as a normal fault.
movw sp@(FR_HW),d1 | get SSW
andw #PSL_S,d1 | from user mode?
jeq fault | no, regular fault
jbsr _kgdb_trap_glue | returns if no debugger
* The sigreturn() syscall comes here. It requires special handling
* because we must open a hole in the stack to fill in the (possibly much
* larger) original stack frame.
lea sp@(-84),sp | leave enough space for largest frame
movl sp@(84),sp@ | move up current 8 byte frame
movl #84,sp@- | default: adjust by 84 bytes
moveml #0xFFFF,sp@- | save user registers
movl usp,a0 | save the user SP
movl a0,sp@(FR_SP) | in the savearea
movl #SYS_sigreturn,sp@- | push syscall number
jbsr _syscall | handle it
addql #4,sp | pop syscall#
movl sp@(FR_SP),a0 | grab and restore
lea sp@(FR_HW),a1 | pointer to HW frame
movw sp@(FR_ADJ),d0 | do we need to adjust the stack?
jeq Lsigr1 | no, just continue
moveq #92,d1 | total size
subw d0,d1 | - hole size = frame size
lea a1@(92),a0 | destination
lsrw #1,d1 | convert to word count
subqw #1,d1 | minus 1 for dbf
movw a1@-,a0@- | copy a word
dbf d1,Lsigrlp | continue
movl a0,a1 | new HW frame base
movl a1,sp@(FR_SP) | new SP value
moveml sp@+,#0x7FFF | restore user registers
* All DIO device interrupts are auto-vectored. Most can be configured
* to interrupt in the range IPL2 to IPL5. Here are our assignments:
* Level 0: Spurious: ignored.
* Level 7: Non-maskable: parity errors, Abort SW
.globl _hardclock, _nmihand
jra rei | XP not surpported yet XXXX
jra rei | EX-PC not surpported yet XXXX
.globl _panicstr,_badkstack
cmpl #_kstack+NBPG,sp | are we still in stack page?
jcc Lstackok | yes, continue normally
tstl _curproc | if !curproc could have swtch_exit'ed,
jeq Lstackok | might be on tmpstk
tstl _panicstr | have we paniced?
jne Lstackok | yes, do not re-panic
movl sp@(4),tmpstk-4 | no, copy common
movl sp@,tmpstk-8 | frame info
movl sp,tmpstk-16 | no, save original SP
lea tmpstk-16,sp | switch to tmpstk
moveml #0xFFFE,sp@- | push remaining registers
movl #1,sp@- | is an overflow
jbsr _badkstack | badkstack(1, frame)
moveml sp@+,#0x7FFF | restore most registers
lea sp@(16),a1 | a1 = &clockframe
btst #CLK_INT,CLOCK_REG | system-clock intrrupt?
jeq Lnottimer | no, skip hardclock
movb #CLK_CLR,CLOCK_REG | clear system-clock interrupt
tstl _clock_on | system-clock started?
jeq Lnottimer | no, skip hardclock
addql #1,_intrcnt+28 | count hardclock interrupt
jbsr _hardclock | hardclock(&frame)
moveml sp@+,#0x0303 | restore scratch regs
addql #1,_cnt+V_INTR | chalk up another interrupt
clrl sp@- | pad SR to longword
moveml #0xFFFF,sp@- | save registers
movl a0,sp@(FR_SP) | the user stack pointer
jbsr _nmihand | call handler
movl sp@(FR_SP),a0 | restore
moveml sp@+,#0x7FFF | and remaining registers
addql #8,sp | pop SSP and align word
* Emulation of VAX REI instruction.
* This code deals with checking for and servicing ASTs
* (profiling, scheduling) and software interrupts (network, softclock).
* We check for ASTs first, just like the VAX. To avoid excess overhead
* the T_ASTFLT handling code will also check for software interrupts so we
* do not have to do it here. After identifing that we need an AST we
* drop the IPL to allow device interrupts.
* This code is complicated by the fact that sendsig may have been called
* necessitating a stack cleanup.
tstl _panicstr | have we paniced?
jne Ldorte1 | yes, do not make matters worse
tstl _astpending | AST pending?
jeq Lchksir | no, go check for SIR
btst #5,sp@ | yes, are we returning to user mode?
jne Lchksir | no, go check for SIR
movw #PSL_LOWIPL,sr | lower SPL
moveml #0xFFFF,sp@- | save all registers
movl a1,sp@(FR_SP) | the users SP
movl #T_ASTFLT,sp@- | type == async system trap
jbsr _trap | go handle it
lea sp@(12),sp | pop value args
movl sp@(FR_SP),a0 | restore user SP
movl a0,usp | from save area
movw sp@(FR_ADJ),d0 | need to adjust stack?
jne Laststkadj | yes, go to it
moveml sp@+,#0x7FFF | no, restore most user regs
addql #8,sp | toss SP and stack adjust
lea sp@(FR_HW),a1 | pointer to HW frame
addql #8,a1 | source pointer
addw d0,a0 | + hole size = dest pointer
movl a0,sp@(FR_SP) | new SSP
moveml sp@+,#0x7FFF | restore user registers
tstb _ssir | SIR pending?
jeq Ldorte | no, all done
movl d0,sp@- | need a scratch register
andw #PSL_IPL7,d0 | mask all but IPL
jne Lnosir | came from interrupt, no can do
movl sp@+,d0 | restore scratch register
movw #SPL1,sr | prevent others from servicing int
jeq Ldorte | yes, oh well...
moveml #0xFFFF,sp@- | save all registers
movl a1,sp@(FR_SP) | the users SP
movl #T_SSIR,sp@- | type == software interrupt
jbsr _trap | go handle it
lea sp@(12),sp | pop value args
movl sp@(FR_SP),a0 | restore
moveml sp@+,#0x7FFF | and all remaining registers
addql #8,sp | pop SP and stack adjust
movl sp@+,d0 | restore scratch register
movw #SPL6,sr | avoid trouble
btst #5,sp@ | are we returning to user mode?
jne Ldorte1 | no, skip it
movb sp@(6),d0 | get format/vector
lsrl #3,d0 | convert to index
lea _exframesize,a6 | into exframesize
addl d0,a6 | to get pointer to correct entry
movw a6@,d0 | get size for this frame
addql #8,d0 | adjust for unaccounted for bytes
lea _kstackatbase,a6 | desired stack base
subl d0,a6 | - frame size == our stack
cmpl a6,sp | are we where we think?
jeq Ldorte2 | yes, skip it
lea tmpstk,a6 | will be using tmpstk
movl sp@(4),a6@- | copy common
movl sp@,a6@- | frame info
subql #4,a6 | skip over already saved a6
moveml #0x7FFC,a6@- | push remaining regs (d0/a6/a7 done)
lea a6@(-4),sp | switch to tmpstk (skip saved d0)
clrl sp@- | is an underflow
jbsr _badkstack | badkstack(0, frame)
moveml sp@+,#0x7FFF | restore most registers
* Kernel access to the current processes kernel stack is via a fixed
* virtual address. It is at the same address as in the users VA space.
* Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack.
.set _kstack,KERNELSTACK | KERNELSTACK(0x3ff00000) != USRSTACK
* VBR contains zero from ROM. Exceptions will continue to vector
* through ROM until MMU is turned on at which time they will vector
* through our table (vectors.s).
movw #PSL_HIGHIPL,sr | no interrupts
lea tmpstk,sp | give ourselves a temporary stack
clrl d0 | XXXX if loader set vbr = 0
movc d0,vbr | XXXX please remove these 2 lines
* a5 contains parameters address from booter.
* First, we copy whole parameters to Kernel InterFace Field
movl #KIFF_SIZE,sp@- | KIFF size
pea _KernInter | KIFF address
pea a5@ | bootor's KIFF address
lea sp@(12),sp | pop value args
movl a5@(KI_MAXADDR),d0 | maxaddr
lsrl d1,d0 | convert to page (click) number
movl d0,_maxmem | argument saved in maxmem
movl d0,_physmem | physmem = maxmem
clrl _lowram | lowram = 0
movl #0,a5 | kernel is loaded at 0
movc d0,cacr | clear and disable on-chip cache(s)
/* determine our CPU/MMU combo - check for all regardless of kernel config */
movl #0x200,d0 | data freeze bit
movc d0,cacr | only exists on 68030
movc cacr,d0 | read it back
jeq Lnot68030 | yes, we have 68040(LUNA2)
movl #1,_machineid | no, must be a LUNA-I
movl #-1,_mmutype | set to reflect 68030 PMMU
movl #2,_machineid | must be a LUNA-II
movl #-2,_mmutype | set to reflect 68040 MMU
movl #3,_processor | HP-UX style processor id
/* set 60 to hz, when running LUNA-I */
.globl _modify_clock_param
/* initialize source/destination control registers for movs */
moveq #FC_USERD,d0 | user space
movc d0,dfc | and destination of transfers
* LUNA PIO initialization.
movw PIO0_A,d0 | dipsw-1,2 (from port A&B)
/* configure kernel and proc0 VA space so we can get going */
.globl _Sysseg, _pmap_bootstrap, _avail_start
movl #_end,d5 | end of static kernel text/data
andl #PG_FRAME,d5 | round to a page
jbsr _pmap_bootstrap | bootstrap(firstpa, nextpa)
movl _Sysseg,d1 | system segment table addr read value (a KVA)
cmpl #-2,_mmutype | 68040?
.long 0x4e7b1807 | movc d1,srp
/* we must set tt-registers here */
movl #0x403FA040,d0 | tt0 for LUNA2 0x40000000-0x7fffffff
.long 0x4e7b0004 | movc d0,itt0
.long 0x4e7b0006 | movc d0,dtt0
movl #0x807FA040,d0 | tt1 for LUNA2 0x80000000-0xffffffff
.long 0x4e7b0005 | movc d0,itt1
.long 0x4e7b0007 | movc d0,dtt1
.long 0x4e7b0003 | movc d0,tc
movc d0,cacr | turn on both caches
movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs
movl d1,a0@(4) | + segtable address
pmove a0@,srp | load the supervisor root pointer
movl #0x80000002,a0@ | reinit upper half for CRP loads
/* we must set tt-registers here */
lea _protott0,a0 | tt0 for LUNA1 0x40000000-0x7fffffff
.word 0xf010 | pmove a0@,mmutt0
lea _protott1,a0 | tt1 for LUNA1 0x80000000-0xffffffff
.word 0xf010 | pmove a0@,mmutt1
movl #0x82c0aa00,a2@ | value to load TC with
* Should be running mapped from this point on
jbsr _checkfpp | check fpp
frestore _fppnull | reset
/* select the software page size now */
lea tmpstk,sp | temporary stack
jbsr _vm_set_page_size | select software page size
/* set kernel stack, user SP, and initial pcb */
lea _kstack,a1 | proc0 kernel stack
lea a1@(UPAGES*NBPG-4),sp | set kernel stack to end of area
movl a2,usp | init user SP
movl _proc0paddr,a1 | get proc0 pcb addr
movl a1,_curpcb | proc0 is running
clrl a1@(PCB_FPCTX) | ensure null FP context
jbsr _m68881_restore | restore it (does not kill a1)
/* flush TLB and turn on caches */
jbsr _TBIA | invalidate TLB
cmpl #-2,_mmutype | 68040?
jeq Lnocache0 | yes, cache already on
movc d0,cacr | clear cache(s)
/* final setup for C code */
movw #PSL_LOWIPL,sr | lower SPL
movl d7,_boothowto | save reboot flags
movl d6,_bootdev | and boot device
/* proc[1] == init now running here;
* create a null exception frame and return to user mode in icode
cmpl #-2,_mmutype | 68040?
clrw sp@- | vector offset/frame type
clrl sp@- | return to icode location 0
movw #PSL_USER,sp@- | in user mode
* Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig().
* sp+4 signal specific code
* sp+8 pointer to signal context frame (scp)
* sp+12 address of handler
* sp+16 saved hardware state
* scp+0-> beginning of signal context frame
.globl _sigcode, _esigcode, _sigcodetrap
movl sp@(12),a0 | signal handler addr (4 bytes)
jsr a0@ | call signal handler (2 bytes)
addql #4,sp | pop signo (2 bytes)
trap #1 | special syscall entry (2 bytes)
movl d0,sp@(4) | save errno (4 bytes)
moveq #1,d0 | syscall == exit (2 bytes)
trap #0 | exit(errno) (2 bytes)
* Icode is copied out to process 1 to exec init.
* If the exec fails, process 1 exits.
.long init+6-_icode | argv[0] = "init" ("/sbin/init" + 6)
.long eicode-_icode | argv[1] follows icode after copyout
#define EXPORT(name) .globl _ ## name; _ ## name:
#define EXPORT(name) .globl _/**/name; _/**/name:
EXPORT(name) link a6,\#0; jbsr mcount; unlk a6
EXPORT(name) link a6,#0; jbsr mcount; unlk a6
#define ALTENTRY(name, rname) \
ENTRY(name); jra rname+12
#define ALTENTRY(name, rname) \
* copyinstr(fromaddr, toaddr, maxlength, &lencopied)
* Copy a null terminated string from the user address space into
* the kernel address space.
* NOTE: maxlength must be < 64K
movl _curpcb,a0 | current pcb
movl #Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults
movl sp@(4),a0 | a0 = fromaddr
movl sp@(8),a1 | a1 = toaddr
movw sp@(14),d0 | d0 = maxlength
jlt Lcisflt1 | negative count, error
jeq Lcisdone | zero count, all done
subql #1,d0 | set up for dbeq
movsb a0@+,d1 | grab a byte
dbeq d0,Lcisloop | if !null and more, continue
jne Lcisflt2 | ran out of room, error
moveq #0,d0 | got a null, all done
tstl sp@(16) | return length desired?
jeq Lcisret | no, just return
subl sp@(4),a0 | determine how much was copied
movl sp@(16),a1 | return location
movl _curpcb,a0 | current pcb
clrl a0@(PCB_ONFAULT) | clear fault addr
moveq #EFAULT,d0 | copy fault
moveq #ENAMETOOLONG,d0 | ran out of space
* copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
* Copy a null terminated string from the kernel
* address space to the user address space.
* NOTE: maxlength must be < 64K
movl _curpcb,a0 | current pcb
movl #Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults
movl sp@(4),a0 | a0 = fromaddr
movl sp@(8),a1 | a1 = toaddr
movw sp@(14),d0 | d0 = maxlength
jlt Lcosflt1 | negative count, error
jeq Lcosdone | zero count, all done
subql #1,d0 | set up for dbeq
movb a0@+,d1 | grab a byte
dbeq d0,Lcosloop | if !null and more, continue
jne Lcosflt2 | ran out of room, error
moveq #0,d0 | got a null, all done
tstl sp@(16) | return length desired?
jeq Lcosret | no, just return
subl sp@(4),a0 | determine how much was copied
movl sp@(16),a1 | return location
movl _curpcb,a0 | current pcb
clrl a0@(PCB_ONFAULT) | clear fault addr
moveq #EFAULT,d0 | copy fault
moveq #ENAMETOOLONG,d0 | ran out of space
* copystr(fromaddr, toaddr, maxlength, &lencopied)
* Copy a null terminated string from one point to another in
* the kernel address space.
* NOTE: maxlength must be < 64K
movl sp@(4),a0 | a0 = fromaddr
movl sp@(8),a1 | a1 = toaddr
movw sp@(14),d0 | d0 = maxlength
jlt Lcsflt1 | negative count, error
jeq Lcsdone | zero count, all done
subql #1,d0 | set up for dbeq
movb a0@+,a1@+ | copy a byte
dbeq d0,Lcsloop | if !null and more, continue
jne Lcsflt2 | ran out of room, error
moveq #0,d0 | got a null, all done
tstl sp@(16) | return length desired?
jeq Lcsret | no, just return
subl sp@(4),a0 | determine how much was copied
movl sp@(16),a1 | return location
moveq #EFAULT,d0 | copy fault
moveq #ENAMETOOLONG,d0 | ran out of space
* Copyin(from_user, to_kernel, len)
* Copyout(from_kernel, to_user, len)
* Copy specified amount of data between kernel and user space.
* XXX both use the DBcc instruction which has 16-bit limitation so only
* 64k units can be copied, where "unit" is either a byte or a longword
* depending on alignment. To be safe, assume it can copy at most
* 64k bytes. Don't make MAXBSIZE or MAXPHYS larger than 64k without
movl d2,sp@- | scratch register
movl _curpcb,a0 | current pcb
movl #Lciflt,a0@(PCB_ONFAULT) | set up to catch faults
movl sp@(16),d2 | check count
jlt Lciflt | negative, error
movl sp@(8),a0 | src address
movl sp@(12),a1 | dest address
btst #0,d0 | src address odd?
jeq Lcieven | no, go check dest
movsb a0@+,d1 | yes, get a byte
movb d1,a1@+ | put a byte
subql #1,d2 | adjust count
jeq Lcidone | exit if done
btst #0,d0 | dest address odd?
jne Lcibyte | yes, must copy by bytes
movl d2,d0 | no, get count
lsrl #2,d0 | convert to longwords
jeq Lcibyte | no longwords, copy bytes
subql #1,d0 | set up for dbf
movsl a0@+,d1 | get a long
movl d1,a1@+ | put a long
dbf d0,Lcilloop | til done
andl #3,d2 | what remains
subql #1,d2 | set up for dbf
movsb a0@+,d1 | get a byte
movb d1,a1@+ | put a byte
dbf d2,Lcibloop | til done
movl _curpcb,a0 | current pcb
clrl a0@(PCB_ONFAULT) | clear fault catcher
movl sp@+,d2 | restore scratch reg
moveq #EFAULT,d0 | got a fault
movl d2,sp@- | scratch register
movl _curpcb,a0 | current pcb
movl #Lcoflt,a0@(PCB_ONFAULT) | catch faults
movl sp@(16),d2 | check count
jlt Lcoflt | negative, error
movl sp@(8),a0 | src address
movl sp@(12),a1 | dest address
btst #0,d0 | src address odd?
jeq Lcoeven | no, go check dest
movb a0@+,d1 | yes, get a byte
movsb d1,a1@+ | put a byte
subql #1,d2 | adjust count
jeq Lcodone | exit if done
btst #0,d0 | dest address odd?
jne Lcobyte | yes, must copy by bytes
movl d2,d0 | no, get count
lsrl #2,d0 | convert to longwords
jeq Lcobyte | no longwords, copy bytes
subql #1,d0 | set up for dbf
movl a0@+,d1 | get a long
movsl d1,a1@+ | put a long
dbf d0,Lcolloop | til done
andl #3,d2 | what remains
subql #1,d2 | set up for dbf
movb a0@+,d1 | get a byte
movsb d1,a1@+ | put a byte
dbf d2,Lcobloop | til done
movl _curpcb,a0 | current pcb
clrl a0@(PCB_ONFAULT) | clear fault catcher
movl sp@+,d2 | restore scratch reg
moveq #EFAULT,d0 | got a fault
movl sp@(4),a0 | savearea pointer
moveml #0xFCFC,a0@ | save d2-d7/a2-a7
movl sp@,a0@(48) | and return address
* The following primitives manipulate the run queues.
* _whichqs tells which of the 32 queues _qs
* have processes in them. Setrq puts processes into queues, Remrq
* removes them from queues. The running process is on no queue,
* other processes are on a queue related to p->p_pri, divided by 4
* actually to shrink the 0-127 range of priorities into the 32 available
.globl _whichqs,_qs,_cnt,_panic
.globl _curproc,_want_resched
* Call should be made at spl6(), and p->p_stat should be SRUN
movl a1@(P_RLINK),a0@(P_RLINK)
* Call should be made at spl6().
movl a0@(P_RLINK),a1@(P_RLINK)
movl a0@(P_LINK),a1@(P_LINK)
.globl _masterpaddr | XXX compatibility (debuggers)
_masterpaddr: | XXX compatibility (debuggers)
.byte 0 | copy of proc md_flags low byte
* At exit of a process, do a swtch for the last time.
* The mapping of the pcb at p->p_addr has already been deleted,
* and the memory for the pcb+stack has been freed.
* The ipl is high enough to prevent the memory from being reallocated.
movl #nullpcb,_curpcb | save state into garbage pcb
lea tmpstk,sp | goto a tmp stack
* When no processes are on the runq, Swtch branches to idle
* to wait for something to come ready.
* NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
* entire ATC. The effort involved in selective flushing may not be
* worth it, maybe we should just flush the whole thing?
* NOTE 2: With the new VM layout we now no longer know if an inactive
* user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
* bit). For now, we just always flush the full ATC.
movl _curpcb,a0 | current pcb
movw sr,a0@(PCB_PS) | save sr before changing ipl
movl _curproc,sp@- | remember last proc running
* Find the highest-priority queue that isn't empty,
* then take the first proc from that queue.
movw #PSL_HIGHIPL,sr | lock out interrupts
movl a0@,d1 | and check again...
jeq Lsw1 | proc moved, rescan
movl d1,a0@ | update whichqs
moveq #1,d1 | double check for higher priority
lsll d0,d1 | process (which may have snuck in
subql #1,d1 | while we were finding this one)
jeq Lswok | no one got in, continue
bset d0,d1 | otherwise put this one back
lslb #3,d1 | convert queue number to index
addl #_qs,d1 | locate queue (q)
cmpl a1@(P_LINK),a1 | anyone on queue?
movl a1@(P_LINK),a0 | p = q->p_link
movl a0@(P_LINK),a1@(P_LINK) | q->p_link = p->p_link
movl a0@(P_LINK),a1 | q = p->p_link
movl a0@(P_RLINK),a1@(P_RLINK) | q->p_rlink = p->p_rlink
cmpl a0@(P_LINK),d1 | anyone left on queue?
bset d0,d1 | yes, reset bit
cmpl a0,a1 | switching to same proc?
jeq Lswdone | yes, skip save and restore
* Save state of previous process in its pcb.
moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
movl usp,a2 | grab USP (a2 has been saved)
movl a2,a1@(PCB_USP) | and save it
lea a1@(PCB_FPCTX),a2 | pointer to FP save area
fsave a2@ | save FP state
tstb a2@ | null state frame?
jeq Lswnofpsave | yes, all done
fmovem fp0-fp7,a2@(216) | save FP general registers
fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers
clrl a0@(P_RLINK) | clear back link
movb a0@(P_MDFLAG+3),mdpflag | low byte of p_md.md_flags
movl a0@(P_ADDR),a1 | get p_addr
/* see if pmap_activate needs to be called; should remove this */
movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace
tstl a0 | map == VM_MAP_NULL?
lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap
tstl a0@(PM_STCHG) | pmap->st_changed?
pea a1@ | push pcb (at p_addr)
jbsr _pmap_activate | pmap_activate(pmap, pcb)
movl _curpcb,a1 | restore p_addr
lsrl d1,d0 | convert p_addr to page number
lsll #2,d0 | and now to Sysmap offset
addl _Sysmap,d0 | add Sysmap base to get PTE addr
movw #PSL_HIGHIPL,sr | go crit while changing PTEs
lea tmpstk,sp | now goto a tmp stack for NMI
movl d0,a0 | address of new context
movl _Umap,a2 | address of PTEs for kstack
moveq #UPAGES-1,d0 | sizeof kstack
andl #~PG_PROT,d1 | mask out old protection
orl #PG_RW+PG_V,d1 | ensure valid and writable
movl d1,a2@+ | load it up
cmpl #-2,_mmutype | 68040?
.word 0xf518 | yes, pflusha
movl a1@(PCB_USTP),d0 | get USTP
lsll d1,d0 | convert to addr
.long 0x4e7b0806 | movc d0,urp
movc d0,cacr | invalidate cache(s)
pflusha | flush entire TLB
movl a1@(PCB_USTP),d0 | get USTP
lsll d1,d0 | convert to addr
lea _protorp,a0 | CRP prototype
movl d0,a0@(4) | stash USTP
pmove a0@,crp | load new user root pointer
moveml a1@(PCB_REGS),#0xFCFC | and registers
lea a1@(PCB_FPCTX),a0 | pointer to FP save area
tstb a0@ | null state frame?
jeq Lresfprest | yes, easy
cmpl #-2,_mmutype | 68040?
jne Lresnot040 | no, skip
frestore sp@+ | ...magic!
fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
fmovem a0@(216),fp0-fp7 | restore FP general registers
frestore a0@ | restore state
movw a1@(PCB_PS),sr | no, restore PS
moveq #1,d0 | return 1 (for alternate returns)
* savectx(pcb, altreturn)
* Update pcb, saving current processor state and arranging
* for alternate return ala longjmp in swtch if altreturn is true.
movl a0,a1@(PCB_USP) | and save it
moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
lea a1@(PCB_FPCTX),a0 | pointer to FP save area
fsave a0@ | save FP state
tstb a0@ | null state frame?
jeq Lsvnofpsave | yes, all done
fmovem fp0-fp7,a0@(216) | save FP general registers
fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
movl sp,d0 | relocate current sp relative to a1
subl #_kstack,d0 | (sp is relative to kstack):
addl d0,a1 | a1 += sp - kstack;
movl sp@,a1@ | write return pc at (relocated) sp@
* {fu,su},{byte,sword,word}
ALTENTRY(fuiword, _fuword)
movl sp@(4),a0 | address to read
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsl a0@,d0 | do read from user space
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsw a0@,d0 | do read from user space
/* Just like fusword, but tells trap code not to page in. */
movl #_fswintr,a1@(PCB_ONFAULT)
ALTENTRY(fuibyte, _fubyte)
movl sp@(4),a0 | address to read
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsb a0@,d0 | do read from user space
moveq #-1,d0 | error indicator
clrl a1@(PCB_ONFAULT) | clear fault address
/* Just like Lfserr, but the address is different (& exported). */
* Write a longword in user instruction space.
* Largely the same as suword but with a final i-cache purge on those
* machines with split caches.
movl sp@(4),a0 | address to write
movl sp@(8),d0 | value to put there
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsl d0,a0@ | do write to user space
moveq #0,d0 | indicate no fault
cmpl #-2,_mmutype | 68040?
jne Lsuicpurge | no, skip
.word 0xf498 | cinva ic (XXX overkill)
movc d1,cacr | invalidate i-cache
movl sp@(4),a0 | address to write
movl sp@(8),d0 | value to put there
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsl d0,a0@ | do write to user space
moveq #0,d0 | indicate no fault
movl sp@(4),a0 | address to write
movw sp@(10),d0 | value to put there
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsw d0,a0@ | do write to user space
moveq #0,d0 | indicate no fault
movl #_fswintr,a1@(PCB_ONFAULT)
ALTENTRY(suibyte, _subyte)
movl sp@(4),a0 | address to write
movb sp@(11),d0 | value to put there
movl _curpcb,a1 | current pcb
movl #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
movsb d0,a0@ | do write to user space
moveq #0,d0 | indicate no fault
movl sp@(4),a0 | address to write
movl _curpcb,a1 | current pcb
movl #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault
movl sp@(8),a1 | address of line
movsl d0,a0@+ | put lword
movsl d0,a0@+ | put lword
movsl d0,a0@+ | put lword
movsl d0,a0@+ | put lword
moveq #0,d0 | indicate no fault
movl _curpcb,a1 | current pcb
clrl a1@(PCB_ONFAULT) | clear fault address
cmpl #-2,_mmutype | 68040?
.word 0xf518 | yes, pflusha
pflusha | flush entire TLB
movc d0,cacr | invalidate on-chip d-cache
* Invalidate any TLB entry for given VA (TB Invalidate Single)
tstl fulltflush | being conservative?
jne __TBIA | yes, flush entire TLB
cmpl #-2,_mmutype | 68040?
.word 0xf508 | pflush a0@
moveq #5,d0 | super space
.word 0xf508 | pflush a0@
movl sp@(4),a0 | get addr to flush
pflush #0,#0,a0@ | flush address from both sides
movc d0,cacr | invalidate on-chip data cache
* Invalidate supervisor side of TLB
tstl fulltflush | being conservative?
jne __TBIA | yes, flush everything
cmpl #-2,_mmutype | 68040?
.word 0xf518 | yes, pflusha (for now) XXX
pflush #4,#4 | flush supervisor TLB entries
movc d0,cacr | invalidate on-chip d-cache
* Invalidate user side of TLB
tstl fulltflush | being conservative?
jne __TBIA | yes, flush everything
cmpl #-2,_mmutype | 68040?
.word 0xf518 | yes, pflusha (for now) XXX
pflush #0,#4 | flush user TLB entries
movc d0,cacr | invalidate on-chip d-cache
* Invalidate instruction cache
cmpl #-2,_mmutype | 68040
movc d0,cacr | invalidate i-cache
* NOTE: we do not flush 68030 on-chip cache as there are no aliasing
* problems with DC_WA. The only cases we have to worry about are context
* switch and TLB changes, both of which are handled "in-line" in resume
cmpl #-2,_mmutype | 68040
cmpl #-2,_mmutype | 68040
cmpl #-2,_mmutype | 68040
.word 0xf488 | cinvl ic,a0@
.word 0xf490 | cinvp ic,a0@
.word 0xf448 | cinvl dc,a0@
.word 0xf450 | cinvp dc,a0@
.word 0xf468 | cpushl dc,a0@
.word 0xf470 | cpushp dc,a0@
cmpl #-2,_mmutype | 68040
movc d0,cacr | invalidate on-chip d-cache
#if 0 /****************************************************************/
/* external cache control */
#endif /****************************************************************/
* Get callers current SP value.
* Note that simply taking the address of a local variable in a C function
* doesn't work because callee saved registers may be outside the stack frame
* defined by A6 (e.g. GCC generated code).
movl sp,d0 | get current SP
addql #4,d0 | compensate for return address
* Load a new user segment table pointer.
movl sp@(4),d0 | new USTP
lsll d1,d0 | convert to addr
cmpl #-2,_mmutype | 68040?
.long 0x4e7b0806 | movc d0,urp
lea _protorp,a0 | CRP prototype
movl d0,a0@(4) | stash USTP
pmove a0@,crp | load root pointer
movc d0,cacr | invalidate on-chip d-cache
movl sp@(4),a0 | address to load
ploadw #1,a0@ | pre-load translation
* Set processor priority level calls. Most are implemented with
* inline asm expansions. However, spl0 requires special handling
* as we need to check for our emulated software interrupts.
movw sr,d0 | get old SR for return
movw #PSL_LOWIPL,sr | restore new SR
tstb _ssir | software interrupt pending?
jeq Lspldone | no, all done
subql #4,sp | make room for RTE frame
movl sp@(4),sp@(2) | position return address
clrw sp@(6) | set frame type 0
movw #PSL_LOWIPL,sp@ | and new SR
jra Lgotsir | go handle it
movw #PSL_HIGHIPL,sr | atomic
movl sp@(8),a0 | where to insert (after)
movl sp@(4),a1 | element to insert (e)
movl a0@,a1@ | e->next = after->next
movl a0,a1@(4) | e->prev = after
movl a1,a0@ | after->next = e
movl a1,a0@(4) | e->next->prev = e
movw #PSL_HIGHIPL,sr | atomic
movl sp@(4),a0 | element to remove (e)
movl a0,a1@(4) | e->next->prev = e->prev
movl a1,a0@ | e->prev->next = e->next
jeq Lbzdone | if zero, nothing to do
btst #0,d1 | address odd?
jeq Lbzeven | no, can copy words
clrb a0@+ | yes, zero byte to get to even boundary
subql #1,d0 | decrement count
jeq Lbzdone | none left, all done
lsrl #5,d1 | convert count to 8*longword count
jeq Lbzbyte | no such blocks, zero byte at a time
clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+;
clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+;
subql #1,d1 | one more block zeroed
jne Lbzloop | more to go, do it
tstl d0 | partial block left?
jeq Lbzdone | no, all done
subql #1,d0 | one more byte cleared
jne Lbzbyte | more to go, do it
addql #1,d0 | increment count
jne Lslloop | no, keep going
* WARNING! This guy only works with counts up to 64K
movl sp@(4),a0 | string 1
movl sp@(8),a1 | string 2
jeq Lcmpdone | if zero, nothing to do
subqw #1,d0 | set up for DBcc loop
dbne d0,Lcmploop | yes, keep going
addqw #1,d0 | +1 gives zero on match
* {ov}bcopy(from, to, len)
* Works for counts up to 128K.
ALTENTRY(ovbcopy, _bcopy)
movl sp@(12),d0 | get count
jeq Lcpyexit | if zero, return
movl sp@(4),a0 | src address
movl sp@(8),a1 | dest address
cmpl a1,a0 | src before dest?
jlt Lcpyback | yes, copy backwards (avoids overlap)
btst #0,d1 | src address odd?
jeq Lcfeven | no, go check dest
movb a0@+,a1@+ | yes, copy a byte
subql #1,d0 | update count
jeq Lcpyexit | exit if done
btst #0,d1 | dest address odd?
jne Lcfbyte | yes, must copy by bytes
movl d0,d1 | no, get count
lsrl #2,d1 | convert to longwords
jeq Lcfbyte | no longwords, copy bytes
subql #1,d1 | set up for dbf
movl a0@+,a1@+ | copy longwords
dbf d1,Lcflloop | til done
andl #3,d0 | get remaining count
jeq Lcpyexit | done if none
subql #1,d0 | set up for dbf
movb a0@+,a1@+ | copy bytes
dbf d0,Lcfbloop | til done
addl d0,a0 | add count to src
addl d0,a1 | add count to dest
btst #0,d1 | src address odd?
jeq Lcbeven | no, go check dest
movb a0@-,a1@- | yes, copy a byte
subql #1,d0 | update count
jeq Lcpyexit | exit if done
btst #0,d1 | dest address odd?
jne Lcbbyte | yes, must copy by bytes
movl d0,d1 | no, get count
lsrl #2,d1 | convert to longwords
jeq Lcbbyte | no longwords, copy bytes
subql #1,d1 | set up for dbf
movl a0@-,a1@- | copy longwords
dbf d1,Lcblloop | til done
andl #3,d0 | get remaining count
jeq Lcpyexit | done if none
subql #1,d0 | set up for dbf
movb a0@-,a1@- | copy bytes
dbf d0,Lcbbloop | til done
* Emulate fancy VAX string operations:
* scanc(count, startc, table, mask)
* skpc(mask, count, startc)
* locc(mask, count, startc)
movl sp@(4),d0 | get length
jeq Lscdone | nothing to do, return
movl sp@(8),a0 | start of scan
movl sp@(12),a1 | table to compare with
movb sp@(19),d1 | and mask to use
movw d2,sp@- | need a scratch register
subqw #1,d0 | adjust for dbra
movb a0@+,d2 | get character
movb a1@(0,d2:w),d2 | get table entry
dbne d0,Lscloop | keep going til no more or non-zero
addqw #1,d0 | overshot by one
movw sp@+,d2 | restore scratch
movl sp@(8),d0 | get length
jeq Lskdone | nothing to do, return
movb sp@(7),d1 | mask to use
movl sp@(12),a0 | where to start
subqw #1,d0 | adjust for dbcc
cmpb a0@+,d1 | compate with mask
dbne d0,Lskloop | keep going til no more or zero
addqw #1,d0 | overshot by one
movl sp@(8),d0 | get length
jeq Llcdone | nothing to do, return
movb sp@(7),d1 | mask to use
movl sp@(12),a0 | where to start
subqw #1,d0 | adjust for dbcc
cmpb a0@+,d1 | compate with mask
dbeq d0,Llcloop | keep going til no more or non-zero
addqw #1,d0 | overshot by one
* Emulate VAX FFS (find first set) instruction.
* Save and restore 68881 state.
* Pretty awful looking since our assembler does not
* recognize FP mnemonics.
movl sp@(4),a0 | save area pointer
tstb a0@ | null state frame?
jeq Lm68881sdone | yes, all done
fmovem fp0-fp7,a0@(216) | save FP general registers
fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
movl sp@(4),a0 | save area pointer
tstb a0@ | null state frame?
jeq Lm68881rdone | yes, easy
fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
fmovem a0@(216),fp0-fp7 | restore FP general registers
frestore a0@ | restore state
frestore _fppnull | initialize fpp
lea _fpp_svarea,a0 | save area
movw sr,d1 | save status reg.
movw #0x2700,sr | mask intrrupt
fsave a0@ | save fpp context
movw d1,sr | restore status reg.
andl #0x00ff0000,d1 | check status field
cmpl #0x00180000,d1 | 68881(idle)?
cmpl #0x00b40000,d1 | 68881(busy)?
cmpl #0x00380000,d1 | 68882(idle)?
cmpl #0x00d40000,d1 | 68882(busy)?
bra _is82out | default 68881
movl a2@(FLINE_VEC),a0 | save vectors
movl #_fpvec,a2@(FLINE_VEC) | change vectors
movl #_fpvec,a2@(COPRO_VEC)
_fpvec: movl a0,a2@(FLINE_VEC) | restore vectors
* Handle the nitty-gritty of rebooting the machine.
* Basically we just turn off the MMU and jump to the appropriate ROM routine.
* Note that we must be running in an address range that is mapped one-to-one
* logical to physical so that the PC is still valid immediately after the MMU
* is turned off. We have conveniently mapped the last page of physical
movl a0@,a1 | get PROM restart entry address
cmpl #-2,_mmutype | 68040?
movw #PSL_HIGHIPL,sr | no interrupts
movc d0,cacr | caches off
.long 0x4e7b0004 | movc d0,itt0
.long 0x4e7b0005 | movc d0,itt1
.long 0x4e7b0006 | movc d0,dtt0
.long 0x4e7b0007 | movc d0,dtt1
.long 0x4e7b0003 | movc d0,tc
movc d0,cacr | disable on-chip cache(s)
movl #_tcroff,a0 | value for pmove to TC (turn off MMU)
pmove a0@,tc | disable MMU
.globl _machineid,_mmutype
.long 1 | default to LUNA-I
.long -1 | default to 68030 PMMU
.globl _protorp,_protott0,_protott1
.long 0,0 | prototype root pointer
.long 0x403f8543 | tt0 (for LUNA1 kernel 0x40000000-0x7fffffff)
.long 0x807F8543 | tt1 (for LUNA1 kernel 0x80000000-0xffffffff)
.long 1 | cold start flag
.long 0 | KVA of proc0 u-area
.long 0 | TC reg. reset flag
.long 0 | clock is enable ?
.word 0 | dipsw(front panel) value
_KernInter: | Kernel InterFace Field
.globl fulltflush, fullcflush
* Undefined symbols from hpux_float.o:
* kdb_printf: A kernel debugger print routine, we just use printf instead.
* processor: HP-UX equiv. of machineid, set to 3 if it is a 68040.
* u: Ye ole u-area. The code wants to grab the first longword
* indirect off of that and clear the 0x40000 bit there.
* Oddly enough this was incorrect even in HP-UX!
* runrun: Old name for want_resched.
.globl _kdb_printf,_processor,_u,_runrun
.set _runrun,_want_resched
.globl _intrcnt,_eintrcnt,_intrnames,_eintrnames