New bus error/address error trap handlers, code lifted from mac68k
port, which is lifted from amiga port, plus some changes from me: - Add support for the HP MMU to the 020/030 bus/address error handler (mostly lifted wholesale from the old code). - Rename addrerr and buserr to busaddrerr2030. The new name reflects that these functions are specific to the 68020 and 68030, and that the same handler function is used for both vectors. The vector table is patched once we know our CPU type, before the MMU is enabled. In the event that we're running on a CPU that we're not configured for, simply invoke the PROM's "reboot request"; we have no hope of running in the event of a config botch, since we need working a working bus error handler for console initialization. These new functions optimze for common-case page faults, eliminate many run-time checks, and are sharable.
This commit is contained in:
parent
89c8d10a08
commit
e296b3b344
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: locore.s,v 1.74 1997/05/13 18:01:03 gwr Exp $ */
|
||||
/* $NetBSD: locore.s,v 1.75 1997/07/14 19:18:31 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Gordon W. Ross
|
||||
@ -89,6 +89,17 @@ ASLOCAL(tmpstk)
|
||||
#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar)
|
||||
#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar)
|
||||
|
||||
/*
|
||||
* Final bits of grunt work required to reboot the system. The MMU
|
||||
* must be disabled when this is invoked.
|
||||
*/
|
||||
#define DOREBOOT \
|
||||
/* Reset Vector Base Register to what PROM expects. */ \
|
||||
movl #0,d0; \
|
||||
movc d0,vbr; \
|
||||
/* Jump to REQ_REBOOT */ \
|
||||
jmp 0x1A4;
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*
|
||||
@ -279,6 +290,41 @@ Lis320:
|
||||
*/
|
||||
|
||||
Lstart1:
|
||||
/*
|
||||
* Now that we know what CPU we have, initialize the address error
|
||||
* and bus error handlers in the vector table:
|
||||
*
|
||||
* vectab+8 bus error
|
||||
* vectab+12 address error
|
||||
*/
|
||||
RELOC(cputype, a0)
|
||||
#if 0
|
||||
/* XXX assembler/linker feature/bug */
|
||||
RELOC(vectab, a2)
|
||||
#else
|
||||
movl #_C_LABEL(vectab),a2
|
||||
addl a5,a2
|
||||
#endif
|
||||
#if defined(M68040)
|
||||
cmpl #CPU_68040,a0@ | 68040?
|
||||
jne 1f | no, skip
|
||||
movl #_C_LABEL(buserr40),a2@(8)
|
||||
movl #_C_LABEL(addrerr4060),a2@(12)
|
||||
jra Lstart2
|
||||
1:
|
||||
#endif
|
||||
#if defined(M68020) || defined(M68030)
|
||||
cmpl #CPU_68040,a0@ | 68040?
|
||||
jeq 1f | yes, skip
|
||||
movl #_C_LABEL(busaddrerr2030),a2@(8)
|
||||
movl #_C_LABEL(busaddrerr2030),a2@(12)
|
||||
jra Lstart2
|
||||
1:
|
||||
#endif
|
||||
/* Config botch; no hope. */
|
||||
DOREBOOT
|
||||
|
||||
Lstart2:
|
||||
movl #0,a1@(MMUCMD) | clear out MMU again
|
||||
/* initialize source/destination control registers for movs */
|
||||
moveq #FC_USERD,d0 | user space
|
||||
@ -300,10 +346,10 @@ Lstart1:
|
||||
#ifdef DDB
|
||||
RELOC(esym,a0) | end of static kernel test/data/syms
|
||||
movl a0@,d5
|
||||
jne Lstart2
|
||||
jne Lstart3
|
||||
#endif
|
||||
movl #_C_LABEL(end),d5 | end of static kernel text/data
|
||||
Lstart2:
|
||||
Lstart3:
|
||||
addl #NBPG-1,d5
|
||||
andl #PG_FRAME,d5 | round to a page
|
||||
movl d5,a4
|
||||
@ -477,85 +523,117 @@ GLOBAL(proc_trampoline)
|
||||
*/
|
||||
#include <m68k/m68k/trap_subr.s>
|
||||
|
||||
ENTRY_NOPROFILE(buserr)
|
||||
/*
|
||||
* XXX TODO: look at the mac68k _buserr and generalize
|
||||
* XXX the saving of the fault address so this routine
|
||||
* XXX can be shared.
|
||||
*/
|
||||
tstl _C_LABEL(nofault) | device probe?
|
||||
jeq Lberr | no, handle as usual
|
||||
movl _C_LABEL(nofault),sp@- | yes,
|
||||
jbsr _C_LABEL(longjmp) | longjmp(nofault)
|
||||
Lberr:
|
||||
#if defined(M68040)
|
||||
#if defined(M68020) || defined(M68030)
|
||||
cmpl #MMU_68040,_C_LABEL(mmutype) | 68040?
|
||||
jne _C_LABEL(addrerr) | no, skip
|
||||
#endif
|
||||
.data
|
||||
GLOBAL(m68k_fault_addr)
|
||||
.long 0
|
||||
|
||||
#if defined(M68040) || defined(M68060)
|
||||
ENTRY_NOPROFILE(addrerr4060)
|
||||
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
|
||||
moveq #0,d0
|
||||
movw a1@(12),d0 | grab SSW
|
||||
movl a1@(20),d1 | and fault VA
|
||||
btst #11,d0 | check for mis-aligned access
|
||||
jeq Lberr2 | no, skip
|
||||
addl #3,d1 | yes, get into next page
|
||||
andl #PG_FRAME,d1 | and truncate
|
||||
Lberr2:
|
||||
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@
|
||||
movc d1,dfc
|
||||
.long 0x4e7a0805 | movc mmusr,d0
|
||||
movw d0,sp@ | save (ONLY LOW 16 BITS!)
|
||||
jra Lismerr
|
||||
movl sp@(FR_HW+8),sp@-
|
||||
clrl sp@- | dummy code
|
||||
movl #T_ADDRERR,sp@- | mark address error
|
||||
jra _ASM_LABEL(faultstkadj) | and deal with it
|
||||
#endif
|
||||
|
||||
ENTRY_NOPROFILE(addrerr)
|
||||
#if defined(M68060)
|
||||
ENTRY_NOPROFILE(buserr60)
|
||||
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
|
||||
movel sp@(FR_HW+12),d0 | FSLW
|
||||
btst #2,d0 | branch prediction error?
|
||||
jeq Lnobpe
|
||||
movc cacr,d2
|
||||
orl #IC60_CABC,d2 | clear all branch cache entries
|
||||
movc d2,cacr
|
||||
movl d0,d1
|
||||
addql #1,L60bpe
|
||||
andl #0x7ffd,d1
|
||||
jeq _ASM_LABEL(faultstkadjnotrap2)
|
||||
Lnobpe:
|
||||
| we need to adjust for misaligned addresses
|
||||
movl sp@(FR_HW+8),d1 | grab VA
|
||||
btst #27,d0 | check for mis-aligned access
|
||||
jeq Lberr3 | no, skip
|
||||
addl #28,d1 | yes, get into next page
|
||||
| operand case: 3,
|
||||
| instruction case: 4+12+12
|
||||
andl #PG_FRAME,d1 | and truncate
|
||||
Lberr3:
|
||||
movl d1,sp@-
|
||||
movl d0,sp@- | code is FSLW now.
|
||||
andw #0x1f80,d0
|
||||
jeq Lberr60 | it is a bus error
|
||||
movl #T_MMUFLT,sp@- | show that we are an MMU fault
|
||||
jra _ASM_LABEL(faultstkadj) | and deal with it
|
||||
Lberr60:
|
||||
tstl _C_LABEL(nofault) | catch bus error?
|
||||
jeq Lisberr | no, handle as usual
|
||||
movl sp@(FR_HW+8+8),_C_LABEL(m68k_fault_addr) | save fault addr
|
||||
movl _C_LABEL(nofault),sp@- | yes,
|
||||
jbsr _C_LABEL(longjmp) | longjmp(nofault)
|
||||
/* NOTREACHED */
|
||||
#endif
|
||||
#if defined(M68040)
|
||||
#if defined(M68020) || defined(M68030)
|
||||
cmpl #MMU_68040,_C_LABEL(mmutype) | 68040?
|
||||
jne Lbenot040 | no, skip
|
||||
#endif
|
||||
movl a1@(8),sp@- | yes, push fault address
|
||||
clrl sp@- | no SSW for address fault
|
||||
jra Lisaerr | go deal with it
|
||||
Lbenot040:
|
||||
#endif
|
||||
ENTRY_NOPROFILE(buserr40)
|
||||
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 sp@(FR_HW+20),d1 | get fault address
|
||||
moveq #0,d0
|
||||
movw a1@(10),d0 | grab SSW for fault processing
|
||||
movw sp@(FR_HW+12),d0 | get SSW
|
||||
btst #11,d0 | check for mis-aligned
|
||||
jeq Lbe1stpg | no skip
|
||||
addl #3,d1 | get into next page
|
||||
andl #PG_FRAME,d1 | and truncate
|
||||
Lbe1stpg:
|
||||
movl d1,sp@- | pass fault address.
|
||||
movl d0,sp@- | pass SSW as code
|
||||
btst #10,d0 | test ATC
|
||||
jeq Lberr40 | it is a bus error
|
||||
movl #T_MMUFLT,sp@- | show that we are an MMU fault
|
||||
jra _ASM_LABEL(faultstkadj) | and deal with it
|
||||
Lberr40:
|
||||
tstl _C_LABEL(nofault) | catch bus error?
|
||||
jeq Lisberr | no, handle as usual
|
||||
movl sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr
|
||||
movl _C_LABEL(nofault),sp@- | yes,
|
||||
jbsr _C_LABEL(longjmp) | longjmp(nofault)
|
||||
/* NOTREACHED */
|
||||
#endif
|
||||
|
||||
#if defined(M68020) || defined(M68030)
|
||||
ENTRY_NOPROFILE(busaddrerr2030)
|
||||
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
|
||||
moveq #0,d0
|
||||
movw sp@(FR_HW+10),d0 | grab SSW for fault processing
|
||||
btst #12,d0 | RB set?
|
||||
jeq LbeX0 | no, test RC
|
||||
bset #14,d0 | yes, must set FB
|
||||
movw d0,a1@(10) | for hardware too
|
||||
movw d0,sp@(FR_HW+10) | for hardware too
|
||||
LbeX0:
|
||||
btst #13,d0 | RC set?
|
||||
jeq LbeX1 | no, skip
|
||||
bset #15,d0 | yes, must set FC
|
||||
movw d0,a1@(10) | for hardware too
|
||||
movw d0,sp@(FR_HW+10) | for hardware too
|
||||
LbeX1:
|
||||
btst #8,d0 | data fault?
|
||||
jeq Lbe0 | no, check for hard cases
|
||||
movl a1@(16),d1 | fault address is as given in frame
|
||||
movl sp@(FR_HW+16),d1 | fault address is as given in frame
|
||||
jra Lbe10 | thats it
|
||||
Lbe0:
|
||||
btst #4,a1@(6) | long (type B) stack frame?
|
||||
btst #4,sp@(FR_HW+6) | long (type B) stack frame?
|
||||
jne Lbe4 | yes, go handle
|
||||
movl a1@(2),d1 | no, can use save PC
|
||||
movl sp@(FR_HW+2),d1 | no, can use save PC
|
||||
btst #14,d0 | FB set?
|
||||
jeq Lbe3 | no, try FC
|
||||
addql #4,d1 | yes, adjust address
|
||||
@ -566,67 +644,75 @@ Lbe3:
|
||||
addql #2,d1 | yes, adjust address
|
||||
jra Lbe10 | done
|
||||
Lbe4:
|
||||
movl a1@(36),d1 | long format, use stage B address
|
||||
movl sp@(FR_HW+36),d1 | long format, use stage B address
|
||||
btst #15,d0 | FC set?
|
||||
jeq Lbe10 | no, all done
|
||||
subql #2,d1 | yes, adjust address
|
||||
Lbe10:
|
||||
movl d1,sp@- | push fault VA
|
||||
movl d0,sp@- | and padded SSW
|
||||
movw a1@(6),d0 | get frame format/vector offset
|
||||
movw sp@(FR_HW+8+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
|
||||
#if defined(M68K_MMU_MOTOROLA)
|
||||
#if defined(M68K_MMU_HP)
|
||||
tstl _C_LABEL(mmutype) | HP MMU?
|
||||
jeq Lbehpmmu | yes, skip
|
||||
jeq Lbehpmmu | yes, different MMU fault handler
|
||||
#endif
|
||||
movl d1,a0 | fault address
|
||||
movl sp@,d0 | function code from ssw
|
||||
btst #8,d0 | data fault?
|
||||
jne Lbe10a
|
||||
movql #1,d0 | user program access FC
|
||||
| (we dont separate data/program)
|
||||
btst #5,a1@ | supervisor mode?
|
||||
| (we dont seperate data/program)
|
||||
btst #5,sp@(FR_HW+8) | supervisor mode?
|
||||
jeq Lbe10a | if no, done
|
||||
movql #5,d0 | else supervisor program access
|
||||
Lbe10a:
|
||||
ptestr d0,a0@,#7 | do a table search
|
||||
pmove psr,sp@ | save result
|
||||
movb sp@,d1
|
||||
btst #2,d1 | invalid? (incl. limit viol and berr)
|
||||
btst #2,d1 | invalid (incl. limit viol. and berr)?
|
||||
jeq Lmightnotbemerr | no -> wp check
|
||||
btst #7,d1 | is it MMU table berr?
|
||||
jeq Lismerr | no, must be fast
|
||||
jra Lisberr1 | real bus err needs not be fast
|
||||
Lmightnotbemerr:
|
||||
btst #3,d1 | write protect bit set?
|
||||
jeq Lisberr1 | no, must be bus error
|
||||
movl sp@,d0 | ssw into low word of d0
|
||||
andw #0xc0,d0 | write protect is set on page:
|
||||
cmpw #0x40,d0 | was it read cycle?
|
||||
jeq Lisberr1 | yes, was not WPE, must be bus err
|
||||
jra Lismerr | no, must be mem err
|
||||
Lbehpmmu:
|
||||
#endif
|
||||
#if defined(M68K_MMU_HP)
|
||||
MMUADDR(a0)
|
||||
movl a0@(MMUSTAT),d0 | read status
|
||||
btst #3,d0 | MMU fault?
|
||||
jeq Lisberr | no, just a non-MMU bus error so skip
|
||||
andl #~MMU_FAULT,a0@(MMUSTAT)| yes, clear fault bits
|
||||
movw d0,sp@ | pass MMU stat in upper half of code
|
||||
#endif
|
||||
jne Lisberr1 | yes, needs not be fast.
|
||||
Lismerr:
|
||||
movl #T_MMUFLT,sp@- | show that we are an MMU fault
|
||||
jra _ASM_LABEL(faultstkadj) | and deal with it
|
||||
Lmightnotbemerr:
|
||||
btst #3,d1 | write protect bit set?
|
||||
jeq Lisberr1 | no: must be bus error
|
||||
movl sp@,d0 | ssw into low word of d0
|
||||
andw #0xc0,d0 | Write protect is set on page:
|
||||
cmpw #0x40,d0 | was it read cycle?
|
||||
jne Lismerr | no, was not WPE, must be MMU fault
|
||||
jra Lisberr1 | real bus err needs not be fast.
|
||||
#endif /* M68K_MMU_MOTOROLA */
|
||||
#if defined(M68K_MMU_HP)
|
||||
Lbehpmmu:
|
||||
MMUADDR(a0)
|
||||
movl a0@(MMUSTAT),d0 | read MMU status
|
||||
btst #3,d0 | MMU fault?
|
||||
jeq Lisberr1 | no, just a non-MMU bus error
|
||||
andl #~MMU_FAULT,a0@(MMUSTAT)| yes, clear fault bits
|
||||
movw d0,sp@ | pass MMU stat in upper half of code
|
||||
jra Lismerr | and handle it
|
||||
#endif
|
||||
Lisaerr:
|
||||
movl #T_ADDRERR,sp@- | mark address error
|
||||
jra _ASM_LABEL(faultstkadj) | and deal with it
|
||||
Lisberr1:
|
||||
clrw sp@ | re-clear pad word
|
||||
Lisberr:
|
||||
tstl _C_LABEL(nofault) | catch bus error?
|
||||
jeq Lisberr | no, handle as usual
|
||||
movl sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr
|
||||
movl _C_LABEL(nofault),sp@- | yes,
|
||||
jbsr _C_LABEL(longjmp) | longjmp(nofault)
|
||||
/* NOTREACHED */
|
||||
#endif /* M68020 || M68030 */
|
||||
|
||||
Lisberr: | also used by M68040/60
|
||||
movl #T_BUSERR,sp@- | mark bus error
|
||||
jra _ASM_LABEL(faultstkadj) | and deal with it
|
||||
|
||||
@ -1810,13 +1896,6 @@ LmotommuE:
|
||||
#endif
|
||||
jmp MAXADDR+8 | jump to last page
|
||||
|
||||
#define DOREBOOT \
|
||||
/* Reset Vector Base Register to what PROM expects. */ \
|
||||
movl #0,d0; \
|
||||
movc d0,vbr; \
|
||||
/* Jump to REQ_REBOOT */ \
|
||||
jmp 0x1A4;
|
||||
|
||||
Lbootcode:
|
||||
lea MAXADDR+0x800,sp | physical SP in case of NMI
|
||||
#if defined(M68040)
|
||||
@ -1845,8 +1924,6 @@ LhpmmuB:
|
||||
#endif
|
||||
Lebootcode:
|
||||
|
||||
#undef DOREBOOT
|
||||
|
||||
/*
|
||||
* Misc. global variables.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
| $NetBSD: vectors.s,v 1.11 1997/04/25 02:16:38 thorpej Exp $
|
||||
| $NetBSD: vectors.s,v 1.12 1997/07/14 19:18:32 thorpej Exp $
|
||||
|
||||
| Copyright (c) 1997 Jason R. Thorpe. All rights reserved.
|
||||
| Copyright (c) 1988 University of Utah
|
||||
@ -46,12 +46,17 @@
|
||||
VECTOR(badtrap) ; VECTOR(badtrap) ; \
|
||||
VECTOR(badtrap) ; VECTOR(badtrap)
|
||||
|
||||
/*
|
||||
* bus error and address error vectors are initialized
|
||||
* in locore.s once we know our CPU type.
|
||||
*/
|
||||
|
||||
.text
|
||||
GLOBAL(vectab)
|
||||
VECTOR_UNUSED /* 0: NOT USED (reset SSP) */
|
||||
VECTOR_UNUSED /* 1: NOT USED (reset PC) */
|
||||
VECTOR(buserr) /* 2: bus error */
|
||||
VECTOR(addrerr) /* 3: address error */
|
||||
VECTOR_UNUSED /* 2: bus error */
|
||||
VECTOR_UNUSED /* 3: address error */
|
||||
VECTOR(illinst) /* 4: illegal instruction */
|
||||
VECTOR(zerodiv) /* 5: zero divide */
|
||||
VECTOR(chkinst) /* 6: CHK instruction */
|
||||
|
Loading…
Reference in New Issue
Block a user