1
0
Files
irix-657m-src/irix/kern/ml/addrprobe.s
2022-09-29 17:59:04 +03:00

622 lines
12 KiB
ArmAsm

/**************************************************************************
* *
* Copyright (C) 1989-1996, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#include "ml/ml.h"
#ifdef _MEM_PARITY_WAR
ABS(mem_parity_nofault,0xa00002F0)
#define set_mem_parity_nofault(x) \
sw x,mem_parity_nofault
#else
#define set_mem_parity_nofault(x) ;
#endif
BADADDRFRM= FRAMESZ((NARGSAVE+1)*SZREG) # 4 arg saves plus a ra
RAOFF= BADADDRFRM-(1*SZREG)
#if !EVEREST && !SN
/*
* badaddr(addr, len)
* check for bus error on read access to addr
* len is length of access (1=byte, 2=short, 4=long)
* On some machines this can generate a bus error interrupt - so we treat
* it just like a write
*/
NESTED(badaddr, BADADDRFRM, zero)
PTR_SUBU sp,BADADDRFRM
REG_S ra,RAOFF(sp)
.set noreorder
MFC0_NO_HAZ(t0,C0_SR)
NOP_0_4
NOINTS(t1,C0_SR)
NOP_0_4
.set reorder
clearbuserrm /* clear bus error */
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
li v0,NF_BADADDR
sh v0,K_NOFAULT(t2)
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(v0)
bne a1,1,1f
nop # BDSLOT
lb v0,0(a0)
b 5f
nop # BDSLOT
1: bne a1,2,2f
nop # BDSLOT
lh v0,0(a0)
b 5f
nop # BDSLOT
2: bne a1,4,3f
nop # BDSLOT
lw v0,0(a0)
b 5f
nop # BDSLOT
3: bne a1,8,4f
nop # BDSLOT
ld v0,0(a0)
b 5f
nop # BDSLOT
.set reorder
4: PANIC("baddaddr")
/* NOTREACHED */
5:
wbflushm /* wait for any bus errors */
.set noreorder
#if IP32
ld t1,CRM_HARDINT|K1BASE
#else
MFC0_NO_HAZ(t1,C0_CAUSE)
NOP_1_1
#endif
and t1,CAUSE_BERRINTR
bne t1,zero,baerror
nop # BDSLOT
.set reorder
checkbuserrm(t1,baerror)
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
sh zero,K_NOFAULT(t2)
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(zero)
MTC0_NO_HAZ(t0,C0_SR)
NOP_0_4
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM
j ra
move v0,zero
.set reorder
END(badaddr)
#endif /* !EVEREST && !SN */
/*
* badaddr_val(addr, len, pointer)
* Just like badaddr, but returns the value loaded in *value
*
* check for bus error on read access to addr
* len is length of access (1=byte, 2=short, 4=long)
* On some machines this can generate a bus error interrupt - so we treat
* it just like a write
*/
#if EVEREST || SN
NESTED(_badaddr_val, BADADDRFRM, zero)
#else
NESTED(badaddr_val, BADADDRFRM, zero)
#endif /* EVEREST || SN */
PTR_SUBU sp,BADADDRFRM
REG_S ra,RAOFF(sp)
.set noreorder
MFC0(t0,C0_SR)
NOP_0_4
NOINTS(t1,C0_SR)
NOP_0_4
.set reorder
clearbuserrm /* clear bus error */
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
beq t2, zero, 10f
li v0,NF_BADADDR #BDSLOT
sh v0,K_NOFAULT(t2)
b 11f
nop #BDSLOT
10: sw v0, VPDA_NOFAULT(zero)
11:
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(v0)
bne a1,1,1f
nop # BDSLOT
CACHE_BARRIER # protect store @ a2
lb v0,0(a0)
nop # LDSLOT
sb v0,0(a2)
b 5f
nop # BDSLOT
1: bne a1,2,2f
nop # BDSLOT
CACHE_BARRIER # protect store @ a2
lh v0,0(a0)
nop # LDSLOT
sh v0,0(a2)
b 5f
nop # BDSLOT
2: bne a1,4,3f
nop # BDSLOT
CACHE_BARRIER # protect store @ a2
lw v0,0(a0)
nop # LDSLOT
sw v0,0(a2)
b 5f
nop # BDSLOT
3: bne a1,8,4f
nop # BDSLOT
CACHE_BARRIER # protect store @ a2
ld v0,0(a0)
nop # LDSLOT
sd v0,0(a2)
b 5f
nop # BDSLOT
.set reorder
4: PANIC("baddaddr_val")
/* NOTREACHED */
5:
wbflushm /* wait for any bus errors */
.set noreorder
#if IP32
ld t1,CRM_HARDINT|K1BASE
#else
MFC0(t1,C0_CAUSE)
NOP_1_1
#endif
and t1,CAUSE_BERRINTR
bne t1,zero,baerror
nop # BDSLOT
.set reorder
checkbuserrm(t1,baerror)
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
beq t2, zero, 20f
nop #BDSLOT
sh zero,K_NOFAULT(t2)
b 21f
nop #BDSLOT
20: sw zero,VPDA_NOFAULT(zero)
21:
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(zero)
MTC0(t0,C0_SR)
NOP_0_4
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM
j ra
move v0,zero
.set reorder
#if EVEREST || SN
END(_badaddr_val)
#else
END(badaddr_val)
#endif
#if !EVEREST && !SN
/*
* wbadaddr(addr, len)
* check for bus error on write access to addr
* len is length of access (1=byte, 2=short, 4=long)
*/
NESTED(wbadaddr, BADADDRFRM, zero)
PTR_SUBU sp,BADADDRFRM
REG_S ra,RAOFF(sp)
.set noreorder
MFC0_NO_HAZ(t0,C0_SR)
NOP_0_4
NOINTS(t1,C0_SR)
NOP_0_4
.set reorder
clearbuserrm /* clear bus error */
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
li v0,NF_BADADDR
sh v0,K_NOFAULT(t2)
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(v0)
bne a1,1,1f
nop # BDSLOT
CACHE_BARRIER # protect store to a0
sb zero,0(a0)
b 5f
nop # BDSLOT
1: bne a1,2,2f
nop # BDSLOT
CACHE_BARRIER # protect store to a0
sh zero,0(a0)
b 5f
nop # BDSLOT
2: bne a1,4,3f
nop # BDSLOT
CACHE_BARRIER # protect store to a0
sw zero,0(a0)
b 5f
nop # BDSLOT
3: bne a1,8,4f
nop # BDSLOT
CACHE_BARRIER # protect store to a0
sd zero,0(a0)
b 5f
nop # BDSLOT
.set reorder
4: PANIC("wbaddaddr")
/* NOTREACHED */
5:
wbflushm /* wait for any bus errors */
wbflushm /* MC systems need more on write */
/* since we're doing a write, the VMEbus could time out after
* some LONG time. It appears that practically though, we need
* only wait for a few mem references (needed on IP4)
*/
lw t2, K1BASE
.set noreorder
nop # let previous load complete
#if IP32
ld t1,CRM_HARDINT|K1BASE
#else
MFC0_NO_HAZ(t1,C0_CAUSE)
NOP_1_1
#endif
and t1,CAUSE_BERRINTR
bne t1,zero,baerror
nop # BDSLOT
.set reorder
checkbuserrm(t1,baerror)
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
sh zero,K_NOFAULT(t2)
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(zero)
MTC0_NO_HAZ(t0,C0_SR)
NOP_0_4
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM # LDSLOT
j ra
move v0,zero
.set reorder
END(wbadaddr)
#endif /* !EVEREST && !SN */
/*
* wbadaddr_val(addr, len, value)
* check for bus error on write access to addr
* len is length of access (1=byte, 2=short, 4=long)
*/
#if EVEREST || SN
NESTED(_wbadaddr_val, BADADDRFRM, zero)
#else
NESTED(wbadaddr_val, BADADDRFRM, zero)
#endif /* EVEREST || SN */
PTR_SUBU sp,BADADDRFRM
REG_S ra,RAOFF(sp)
.set noreorder
MFC0(t0,C0_SR)
NOP_0_4
NOINTS(t1,C0_SR)
NOP_0_4
.set reorder
clearbuserrm /* clear bus error */
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
li v0,NF_BADADDR
#if SN
/*
* If we're not being called from a thread, we're being called
* from the error handling code and interrupts are disabled.
*/
bnez t2, 1f
nop
sw v0,VPDA_NOFAULT(zero)
b 2f
nop
1: sh v0,K_NOFAULT(t2)
2:
#else
sh v0,K_NOFAULT(t2)
#endif
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(v0)
bne a1,1,1f
nop # BDSLOT
CACHE_BARRIER # protect a0 store
lb v0,0(a2)
nop # LDSLOT
sb v0,0(a0)
b 5f
nop # BDSLOT
1: bne a1,2,2f
nop # BDSLOT
CACHE_BARRIER # protect a0 store
lh v0,0(a2)
nop # LDSLOT
sh v0,0(a0)
b 5f
nop # BDSLOT
2: bne a1,4,3f
nop # BDSLOT
CACHE_BARRIER # protect a0 store
lw v0,0(a2)
nop # LDSLOT
sw v0,0(a0)
b 5f
nop # BDSLOT
3: bne a1,8,4f
nop # BDSLOT
CACHE_BARRIER # protect a0 store
ld v0,0(a2)
nop # LDSLOT
sd v0,0(a0)
b 5f
nop # BDSLOT
.set reorder
4: PANIC("wbaddaddr_val")
/* NOTREACHED */
5:
wbflushm /* wait for any bus errors */
wbflushm /* MC systems need more on write */
/* since we're doing a write, the VMEbus could time out after
* some LONG time. It appears that practically though, we need
* only wait for a few mem references (needed on IP4)
*/
lw t2, K1BASE
.set noreorder
#if IP32
ld t1,CRM_HARDINT|K1BASE
#else
MFC0(t1,C0_CAUSE)
NOP_1_1
#endif
and t1,CAUSE_BERRINTR
bne t1,zero,baerror
nop # BDSLOT
.set reorder
checkbuserrm(t1,baerror)
.set noreorder
AUTO_CACHE_BARRIERS_DISABLE # t2 is dependent
PTR_L t2,VPDA_CURKTHREAD(zero)
#if SN
/*
* If we're not being called from a thread, we're being called
* from the error handling code and interrupts are disabled.
*/
bnez t2, 1f
nop
sw zero,VPDA_NOFAULT(zero)
b 2f
nop
1: sh zero,K_NOFAULT(t2)
2:
#else
sh zero,K_NOFAULT(t2)
#endif
AUTO_CACHE_BARRIERS_ENABLE
set_mem_parity_nofault(zero)
MTC0(t0,C0_SR)
NOP_0_4
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM # LDSLOT
j ra
move v0,zero
.set reorder
#if EVEREST || SN
END(_wbadaddr_val)
#else
END(wbadaddr_val)
#endif
#if !EVEREST
/*
* earlybadaddr(addr, len)
* check for bus error on read access to addr
* len is length of access (1=byte, 2=short, 4=long)
*
* This routine is exactly the same as badaddr, except it
* doesn't assume that the u area's been set up yet, so it
* can be called very early on.
*/
NESTED(earlybadaddr, BADADDRFRM, zero)
PTR_SUBU sp,BADADDRFRM
REG_S ra,RAOFF(sp)
.set noreorder
MFC0(t0,C0_SR)
NOP_0_4
NOINTS(t1,C0_SR)
NOP_0_4
.set reorder
clearbuserrm /* clear bus error */
.set noreorder
CACHE_BARRIER # protect nofault store
li v0,NF_EARLYBADADDR
sw v0,nofault
set_mem_parity_nofault(v0)
bne a1,1,1f
nop # BDSLOT
lb v0,0(a0)
b 4f
nop # BDSLOT
1: bne a1,2,2f
nop # BDSLOT
lh v0,0(a0)
b 4f
nop # BDSLOT
2: bne a1,4,3f
nop # BDSLOT
lw v0,0(a0)
b 4f
nop # BDSLOT
.set reorder
3: PANIC("earlybaddaddr")
/* NOTREACHED */
4:
wbflushm /* wait for any bus errors */
.set noreorder
#if IP32
ld t1,CRM_HARDINT|K1BASE
#else
MFC0(t1,C0_CAUSE)
NOP_1_1
#endif
and t1,CAUSE_BERRINTR
bne t1,zero,earlybaerror
nop # BDSLOT
.set reorder
checkbuserrm(t1,earlybaerror)
.set noreorder
CACHE_BARRIER # protect nofault store
sw zero,nofault
set_mem_parity_nofault(zero)
MTC0(t0,C0_SR)
NOP_0_4
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM
.set reorder
move v0,zero
j ra
END(earlybadaddr)
/*
* wbadmemaddr(addr)
* check for address error on word access to addr
* Assumes addr points to RAM since trap is generated by read-back
*
* ***NOTE***
* Because this is used during startup, before a user structure
* exists, we must use the global "nofault" instead of u+U_NOFAULT
*/
NESTED(wbadmemaddr, BADADDRFRM, zero)
.set noreorder
MFC0_NO_HAZ(t0,C0_SR)
NOP_0_4
NOINTS(t1,C0_SR)
NOP_0_4
.set reorder
PTR_SUBU sp,BADADDRFRM
REG_S ra,RAOFF(sp)
.set noreorder
CACHE_BARRIER # protect nofault store
li v0,NF_EARLYBADADDR
sw v0,nofault
set_mem_parity_nofault(v0)
sw zero,0(a0) # store first to generate ECC
lw v0,0(a0) # load can cause sync DBE
.set reorder
checkbuserrm(t1,baerror)
.set noreorder
CACHE_BARRIER # protect nofault store
sw zero,nofault
set_mem_parity_nofault(zero)
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM
MTC0_NO_HAZ(t0,C0_SR)
NOP_0_4
j ra
move v0,zero # BDSLOT
.set reorder
END(wbadmemaddr)
#endif /* !EVEREST */
/*
* trap() nofault code comes here on bus errors when nofault == NF_BADADDR
*/
NESTED(baerror, BADADDRFRM, zero)
clearbuserrm /* clear bus error */
.set noreorder
MTC0(t0,C0_SR)
NOP_0_4
.set noreorder
PTR_L t2,VPDA_CURKTHREAD(zero)
beq t2, zero, 1f
li v0,1 # BDSLOT
AUTO_CACHE_BARRIERS_DISABLE # t2 is either zero or a ptr (ok)
sh zero,K_NOFAULT(t2)
AUTO_CACHE_BARRIERS_ENABLE
b 2f
nop # BDSLOT
1:
sw zero,VPDA_NOFAULT(zero)
2:
.set reorder
set_mem_parity_nofault(zero)
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM
j ra
END(baerror)
/*
* trap() nofault code comes here on bus errors when nofault == NF_EARLYBADADDR
* used before u area is set up
*/
NESTED(earlybaerror, BADADDRFRM, zero)
clearbuserrm /* clear bus error */
.set noreorder
MTC0(t0,C0_SR)
NOP_0_4
.set reorder
li v0,1
sw zero,nofault
set_mem_parity_nofault(zero)
REG_L ra,RAOFF(sp)
PTR_ADDU sp,BADADDRFRM
j ra
END(earlybaerror)