774 lines
17 KiB
ArmAsm
774 lines
17 KiB
ArmAsm
/*
|
|
* sheevaplug machine assist
|
|
* arm926ej-s processor at 1.2GHz
|
|
*
|
|
* loader uses R11 as scratch.
|
|
* R9 and R10 are used for `extern register' variables.
|
|
*
|
|
* ARM v7 arch. ref. man. (I know, this is v5) §B1.3.3 that
|
|
* we don't need barriers around moves to CPSR. The ARM v6 manual
|
|
* seems to be silent on the subject.
|
|
*/
|
|
#include "arm.s"
|
|
|
|
/*
|
|
* MCR and MRC are counter-intuitively named.
|
|
* MCR coproc, opcode1, Rd, CRn, CRm[, opcode2] # arm -> coproc
|
|
* MRC coproc, opcode1, Rd, CRn, CRm[, opcode2] # coproc -> arm
|
|
*/
|
|
|
|
/*
|
|
* Entered here from Das U-Boot with MMU disabled.
|
|
* Until the MMU is enabled it is OK to call functions provided
|
|
* they are within ±32MiB relative and do not require any
|
|
* local variables or more than one argument (i.e. there is
|
|
* no stack).
|
|
*/
|
|
TEXT _start(SB), 1, $-4
|
|
MOVW $setR12(SB), R12 /* load the SB */
|
|
_main:
|
|
/* SVC mode, interrupts disabled */
|
|
MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
|
|
MOVW R1, CPSR
|
|
BARRIERS
|
|
|
|
/*
|
|
* disable the MMU & caches,
|
|
* switch to system permission & 32-bit addresses.
|
|
*/
|
|
MOVW $(CpCsystem|CpCd32|CpCi32), R1
|
|
MCR CpSC, 0, R1, C(CpCONTROL), C(0)
|
|
ISB
|
|
|
|
/*
|
|
* disable the Sheevaplug's L2 cache, invalidate all caches
|
|
*/
|
|
|
|
/* flush caches. 926ejs manual says we have to do it iteratively. */
|
|
_dwbinv0:
|
|
MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
|
|
BNE _dwbinv0
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
/* make the l2 cache pay attention */
|
|
MOVW $(PHYSIO+0x20100), R1 /* CPUCSREG */
|
|
MOVW (4*10)(R1), R2
|
|
ORR $(1<<3), R2 /* cpu->l2cfg |= L2exists */
|
|
MOVW R2, (4*10)(R1)
|
|
ISB
|
|
|
|
/* invalidate l2 cache */
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
|
|
ISB
|
|
|
|
/* disable l2 cache. do this while l1 caches are off */
|
|
MRC CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
|
|
/* disabling write allocation is probably for cortex-a8 errata 460075 */
|
|
/* l2 off, no wr alloc, no streaming */
|
|
BIC $(CpTCl2ena | CpTCl2wralloc | CpTCldcstream), R1
|
|
MCR CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
|
|
BARRIERS
|
|
|
|
/* flush caches. 926ejs manual says we have to do it iteratively. */
|
|
_dwbinv1:
|
|
MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
|
|
BNE _dwbinv1
|
|
BARRIERS
|
|
|
|
WAVE('\r')
|
|
/* clear Mach */
|
|
MOVW $PADDR(MACHADDR), R4 /* address of Mach */
|
|
_machZ:
|
|
MOVW R0, (R4)
|
|
ADD $4, R4 /* bump PTE address */
|
|
CMP.S $PADDR(L1+L1X(0)), R4
|
|
BNE _machZ
|
|
|
|
/*
|
|
* set up the MMU page table
|
|
*/
|
|
|
|
/* clear all PTEs first, to provide a default */
|
|
WAVE('\n')
|
|
MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
|
|
_ptenv0:
|
|
ZEROPTE()
|
|
CMP.S $PADDR(L1+16*KiB), R4
|
|
BNE _ptenv0
|
|
|
|
/* double map of PHYSDRAM, KZERO to PHYSDRAM for first few MBs */
|
|
MOVW $PTEDRAM, R2 /* PTE bits */
|
|
MOVW $PHYSDRAM, R3 /* pa */
|
|
MOVW $PADDR(L1+L1X(PHYSDRAM)), R4 /* address of PTE for PHYSDRAM */
|
|
MOVW $16, R5
|
|
_ptdbl:
|
|
FILLPTE()
|
|
SUB.S $1, R5
|
|
BNE _ptdbl
|
|
|
|
/*
|
|
* back up and fill in PTEs for memory at KZERO
|
|
* there is 1 bank of 512MB of SDRAM at PHYSDRAM
|
|
*/
|
|
MOVW $PTEDRAM, R2 /* PTE bits */
|
|
MOVW $PHYSDRAM, R3
|
|
MOVW $PADDR(L1+L1X(KZERO)), R4 /* start with PTE for KZERO */
|
|
MOVW $512, R5 /* inner loop count */
|
|
_ptekrw: /* set PTEs for 512MiB */
|
|
FILLPTE()
|
|
SUB.S $1, R5
|
|
BNE _ptekrw
|
|
|
|
/*
|
|
* back up and fill in PTE for MMIO
|
|
*/
|
|
MOVW $PTEIO, R2 /* PTE bits */
|
|
MOVW $PHYSIO, R3
|
|
MOVW $PADDR(L1+L1X(VIRTIO)), R4 /* start with PTE for VIRTIO */
|
|
FILLPTE()
|
|
|
|
/* mmu.c sets up the vectors later */
|
|
|
|
/*
|
|
* set up a temporary stack; avoid data & bss segments
|
|
*/
|
|
MOVW $(PHYSDRAM | (128*1024*1024)), R13
|
|
|
|
WAVE('P')
|
|
/* set the domain access control */
|
|
MOVW $Client, R0
|
|
BL dacput(SB)
|
|
|
|
/* set the translation table base */
|
|
MOVW $PADDR(L1), R0
|
|
BL ttbput(SB)
|
|
|
|
MOVW $0, R0
|
|
BL pidput(SB) /* paranoia */
|
|
|
|
/* the little dance to turn the MMU & caches on */
|
|
WAVE('l')
|
|
BL cacheuwbinv(SB)
|
|
BL mmuinvalidate(SB)
|
|
BL mmuenable(SB)
|
|
|
|
WAVE('a')
|
|
/* warp the PC into the virtual map */
|
|
MOVW $KZERO, R0
|
|
BL _r15warp(SB)
|
|
|
|
/*
|
|
* now running at KZERO+something!
|
|
*/
|
|
|
|
MOVW $setR12(SB), R12 /* reload the SB */
|
|
|
|
/*
|
|
* set up temporary stack again, in case we've just switched
|
|
* to a new register set.
|
|
*/
|
|
MOVW $(KZERO|(128*1024*1024)), R13
|
|
|
|
/* can now execute arbitrary C code */
|
|
|
|
BL cacheuwbinv(SB)
|
|
|
|
WAVE('n')
|
|
/* undo double map of 0, KZERO */
|
|
MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
|
|
MOVW $0, R0
|
|
MOVW $16, R5
|
|
_ptudbl:
|
|
MOVW R0, (R4)
|
|
ADD $4, R4 /* bump PTE address */
|
|
ADD $MiB, R0 /* bump pa */
|
|
SUB.S $1, R5
|
|
BNE _ptudbl
|
|
BARRIERS
|
|
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvd), CpTLBinvse
|
|
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
|
|
BARRIERS
|
|
|
|
WAVE(' ')
|
|
/* pass Mach to main and set up the stack */
|
|
MOVW $(MACHADDR), R0 /* Mach */
|
|
MOVW R0, R13
|
|
ADD $(MACHSIZE), R13 /* stack pointer */
|
|
SUB $4, R13 /* space for link register */
|
|
|
|
BL main(SB) /* void main(Mach*) */
|
|
/* fall through */
|
|
|
|
|
|
/* not used */
|
|
TEXT _reset(SB), 1, $-4
|
|
/* turn the caches off */
|
|
MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R0
|
|
MOVW R0, CPSR
|
|
BARRIERS
|
|
BL cacheuwbinv(SB)
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BIC $(CpCwb|CpCicache|CpCdcache|CpCalign), R0
|
|
MCR CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BARRIERS
|
|
WAVE('R')
|
|
|
|
/* redo double map of 0, KZERO */
|
|
MOVW $(L1+L1X(0)), R4 /* address of PTE for 0 */
|
|
MOVW $PTEDRAM, R2 /* PTE bits */
|
|
MOVW $0, R3
|
|
MOVW $16, R5
|
|
_ptrdbl:
|
|
ORR R3, R2, R1 /* first identity-map 0 to 0, etc. */
|
|
MOVW R1, (R4)
|
|
ADD $4, R4 /* bump PTE address */
|
|
ADD $MiB, R3 /* bump pa */
|
|
SUB.S $1, R5
|
|
BNE _ptrdbl
|
|
|
|
BARRIERS
|
|
WAVE('e')
|
|
MOVW $0, R0
|
|
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvd), CpTLBinv
|
|
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
|
|
BARRIERS
|
|
|
|
/* back to 29- or 26-bit addressing, mainly for SB */
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BIC $(CpCd32|CpCi32), R0
|
|
MCR CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BARRIERS
|
|
|
|
/* turn the MMU off */
|
|
MOVW $PHYSDRAM, R0
|
|
BL _r15warp(SB)
|
|
BL mmuinvalidate(SB)
|
|
BL mmudisable(SB)
|
|
|
|
WAVE('s')
|
|
/* set new reset vector */
|
|
MOVW $0, R2
|
|
MOVW $0xe59ff018, R3 /* MOVW 0x18(R15), R15 */
|
|
MOVW R3, (R2)
|
|
WAVE('e')
|
|
|
|
MOVW $PHYSBOOTROM, R3
|
|
MOVW R3, 0x20(R2) /* where $0xe59ff018 jumps to */
|
|
BARRIERS
|
|
WAVE('t')
|
|
WAVE('\r')
|
|
WAVE('\n')
|
|
|
|
/* ...and jump to it */
|
|
MOVW R2, R15 /* software reboot */
|
|
_limbo: /* should not get here... */
|
|
B _limbo /* ... and can't get out */
|
|
BL _div(SB) /* hack to load _div, etc. */
|
|
|
|
TEXT _r15warp(SB), 1, $-4
|
|
BIC $KSEGM, R14
|
|
ORR R0, R14
|
|
BIC $KSEGM, R13
|
|
ORR R0, R13
|
|
RET
|
|
|
|
/* clobbers R1, R6 */
|
|
TEXT myputc(SB), 1, $-4
|
|
MOVW $PHYSCONS, R6
|
|
_busy:
|
|
MOVW 20(R6), R1
|
|
BIC.S $~(1<<5), R1 /* (x->lsr & LSRthre) == 0? */
|
|
BEQ _busy
|
|
MOVW R3, (R6) /* print */
|
|
ISB
|
|
RET
|
|
|
|
/*
|
|
* l1 caches
|
|
*/
|
|
|
|
TEXT l1cacheson(SB), 1, $-4
|
|
MOVW CPSR, R5
|
|
ORR $(PsrDirq|PsrDfiq), R5, R4
|
|
MOVW R4, CPSR /* splhi */
|
|
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
ORR $(CpCdcache|CpCicache|CpCwb), R0
|
|
MCR CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BARRIERS
|
|
|
|
MOVW R5, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT l1cachesoff(SB), 1, $-4
|
|
MOVM.DB.W [R14], (SP) /* save lr on stack */
|
|
|
|
MOVW CPSR, R5
|
|
ORR $(PsrDirq|PsrDfiq), R5, R4
|
|
MOVW R4, CPSR /* splhi */
|
|
|
|
BL cacheuwbinv(SB)
|
|
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BIC $(CpCdcache|CpCicache|CpCwb), R0
|
|
MCR CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BARRIERS
|
|
|
|
MOVW R5, CPSR /* splx */
|
|
MOVM.IA.W (SP), [R14] /* restore lr */
|
|
RET
|
|
|
|
/*
|
|
* cache* functions affect only the L1 caches, which are VIVT.
|
|
*/
|
|
|
|
TEXT cachedwb(SB), 1, $-4 /* D writeback */
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
BARRIERS /* force outstanding stores to cache */
|
|
/* keep writing back dirty cache lines until no more exist */
|
|
_dwb:
|
|
MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwb), CpCACHEtest
|
|
BNE _dwb
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT cachedwbse(SB), 1, $-4 /* D writeback SE */
|
|
MOVW R0, R2 /* first arg: address */
|
|
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
BARRIERS /* force outstanding stores to cache */
|
|
MOVW 4(FP), R1 /* second arg: size */
|
|
|
|
// CMP.S $(4*1024), R1
|
|
// BGT _dwb
|
|
ADD R2, R1
|
|
BIC $(CACHELINESZ-1), R2
|
|
_dwbse:
|
|
MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEwb), CpCACHEse
|
|
ADD $CACHELINESZ, R2
|
|
CMP.S R2, R1
|
|
BGT _dwbse
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT cachedwbinv(SB), 1, $-4 /* D writeback+invalidate */
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
BARRIERS /* force outstanding stores to cache */
|
|
/* keep writing back dirty cache lines until no more exist */
|
|
_dwbinv:
|
|
MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
|
|
BNE _dwbinv
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT cachedwbinvse(SB), 1, $-4 /* D writeback+invalidate SE */
|
|
MOVW R0, R2 /* first arg: address */
|
|
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
BARRIERS /* force outstanding stores to cache */
|
|
MOVW 4(FP), R1 /* second arg: size */
|
|
|
|
DSB
|
|
// CMP.S $(4*1024), R1
|
|
// BGT _dwbinv
|
|
ADD R2, R1
|
|
BIC $(CACHELINESZ-1), R2
|
|
_dwbinvse:
|
|
MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
|
|
ADD $CACHELINESZ, R2
|
|
CMP.S R2, R1
|
|
BGT _dwbinvse
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT cachedinvse(SB), 1, $-4 /* D invalidate SE */
|
|
MOVW R0, R2 /* first arg: address */
|
|
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
MOVW 4(FP), R1 /* second arg: size */
|
|
|
|
DSB
|
|
// CMP.S $(4*1024), R1
|
|
// BGT _dinv
|
|
ADD R2, R1
|
|
BIC $(CACHELINESZ-1), R2
|
|
_dinvse:
|
|
MCR CpSC, 0, R2, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
|
|
ADD $CACHELINESZ, R2
|
|
CMP.S R2, R1
|
|
BGT _dinvse
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT cacheuwbinv(SB), 1, $-4 /* D+I writeback+invalidate */
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
BARRIERS /* force outstanding stores to cache */
|
|
/* keep writing back dirty cache lines until no more exist */
|
|
_uwbinv: /* D writeback+invalidate */
|
|
MRC CpSC, 0, PC, C(CpCACHE), C(CpCACHEwbi), CpCACHEtest
|
|
BNE _uwbinv
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW $0, R0 /* I invalidate */
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT cacheiinv(SB), 1, $-4 /* I invalidate */
|
|
BARRIERS
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
RET
|
|
|
|
TEXT cachedinv(SB), 1, $-4 /* D invalidate */
|
|
_dinv:
|
|
BARRIERS
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEall
|
|
/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
|
|
BARRIERS
|
|
RET
|
|
|
|
/*
|
|
* l2 cache
|
|
*
|
|
* these functions assume that the necessary l1 cache operations have been
|
|
* or will be done explicitly by the caller.
|
|
*/
|
|
|
|
/* enable l2 cache in config coproc. reg. do this while l1 caches are off. */
|
|
TEXT l2cachecfgon(SB), 1, $-4
|
|
BARRIERS
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
|
|
BARRIERS
|
|
|
|
MRC CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
|
|
ORR $(CpTCl2ena | CpTCl2prefdis), R1 /* l2 on, prefetch off */
|
|
MCR CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
|
|
BARRIERS
|
|
RET
|
|
|
|
/* disable l2 cache in config coproc. reg. do this while l1 caches are off. */
|
|
TEXT l2cachecfgoff(SB), 1, $-4
|
|
BARRIERS
|
|
MRC CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
|
|
BIC $CpTCl2ena, R1
|
|
MCR CpSC, CpL2, R1, C(CpTESTCFG), C(CpTCl2cfg), CpTCl2conf
|
|
BARRIERS
|
|
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
|
|
BARRIERS
|
|
RET
|
|
|
|
TEXT l2cacheuwb(SB), 1, $-4 /* L2 unified writeback */
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2flush), CpTCl2all
|
|
ISB
|
|
RET
|
|
|
|
TEXT l2cacheuwbse(SB), 1, $-4 /* L2 unified writeback SE */
|
|
MOVW R0, R2 /* first arg: address */
|
|
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
MOVW 4(FP), R1 /* second arg: size */
|
|
|
|
ADD R2, R1
|
|
BIC $(CACHELINESZ-1), R2
|
|
_l2wbse:
|
|
MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2flush), CpTCl2seva
|
|
ADD $CACHELINESZ, R2
|
|
CMP.S R2, R1
|
|
BGT _l2wbse
|
|
ISB
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT l2cacheuwbinv(SB), 1, $-4 /* L2 unified writeback+invalidate */
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2flush), CpTCl2all
|
|
ISB
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
|
|
ISB
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT l2cacheuwbinvse(SB), 1, $-4 /* L2 unified writeback+invalidate SE */
|
|
MOVW R0, R2 /* first arg: address */
|
|
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
MOVW 4(FP), R1 /* second arg: size */
|
|
|
|
ADD R2, R1
|
|
BIC $(CACHELINESZ-1), R2
|
|
_l2wbinvse:
|
|
MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2flush), CpTCl2seva
|
|
ISB
|
|
MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2inv), CpTCl2seva
|
|
ADD $CACHELINESZ, R2
|
|
CMP.S R2, R1
|
|
BGT _l2wbinvse
|
|
ISB
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT l2cacheuinv(SB), 1, $-4 /* L2 unified invalidate */
|
|
MCR CpSC, CpL2, R0, C(CpTESTCFG), C(CpTCl2inv), CpTCl2all
|
|
ISB
|
|
RET
|
|
|
|
TEXT l2cacheuinvse(SB), 1, $-4 /* L2 unified invalidate SE */
|
|
MOVW R0, R2 /* first arg: address */
|
|
|
|
MOVW CPSR, R3 /* splhi */
|
|
ORR $(PsrDirq), R3, R1
|
|
MOVW R1, CPSR
|
|
|
|
MOVW 4(FP), R1 /* second arg: size */
|
|
|
|
ADD R2, R1
|
|
BIC $(CACHELINESZ-1), R2
|
|
_l2invse:
|
|
MCR CpSC, CpL2, R2, C(CpTESTCFG), C(CpTCl2inv), CpTCl2seva
|
|
ADD $CACHELINESZ, R2
|
|
CMP.S R2, R1
|
|
BGT _l2invse
|
|
ISB
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
/*
|
|
* enable mmu, i and d caches, and high vector
|
|
*/
|
|
TEXT mmuenable(SB), 1, $-4
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
ORR $(CpChv|CpCmmu|CpCdcache|CpCicache|CpCwb|CpCsystem), R0
|
|
BIC $(CpCrom), R0
|
|
MCR CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BARRIERS
|
|
RET
|
|
|
|
TEXT mmudisable(SB), 1, $-4
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BIC $(CpChv|CpCmmu|CpCdcache|CpCicache|CpCwb), R0
|
|
MCR CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
BARRIERS
|
|
RET
|
|
|
|
TEXT mmuinvalidate(SB), 1, $-4 /* invalidate all */
|
|
MOVW $0, R0
|
|
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
|
|
BARRIERS
|
|
RET
|
|
|
|
TEXT mmuinvalidateaddr(SB), 1, $-4 /* invalidate single entry */
|
|
MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
|
|
BARRIERS
|
|
RET
|
|
|
|
TEXT cpidget(SB), 1, $-4 /* main ID */
|
|
MRC CpSC, 0, R0, C(CpID), C(0), CpIDid
|
|
RET
|
|
|
|
TEXT cpctget(SB), 1, $-4 /* cache type */
|
|
MRC CpSC, 0, R0, C(CpID), C(0), CpIDct
|
|
RET
|
|
|
|
TEXT controlget(SB), 1, $-4 /* control */
|
|
MRC CpSC, 0, R0, C(CpCONTROL), C(0)
|
|
RET
|
|
|
|
TEXT ttbget(SB), 1, $-4 /* translation table base */
|
|
MRC CpSC, 0, R0, C(CpTTB), C(0)
|
|
RET
|
|
|
|
TEXT ttbput(SB), 1, $-4 /* translation table base */
|
|
MCR CpSC, 0, R0, C(CpTTB), C(0)
|
|
ISB
|
|
RET
|
|
|
|
TEXT dacget(SB), 1, $-4 /* domain access control */
|
|
MRC CpSC, 0, R0, C(CpDAC), C(0)
|
|
RET
|
|
|
|
TEXT dacput(SB), 1, $-4 /* domain access control */
|
|
MCR CpSC, 0, R0, C(CpDAC), C(0)
|
|
ISB
|
|
RET
|
|
|
|
TEXT fsrget(SB), 1, $-4 /* fault status */
|
|
MRC CpSC, 0, R0, C(CpFSR), C(0)
|
|
RET
|
|
|
|
TEXT farget(SB), 1, $-4 /* fault address */
|
|
MRC CpSC, 0, R0, C(CpFAR), C(0x0)
|
|
RET
|
|
|
|
TEXT pidget(SB), 1, $-4 /* address translation pid */
|
|
MRC CpSC, 0, R0, C(CpPID), C(0x0)
|
|
RET
|
|
|
|
TEXT pidput(SB), 1, $-4 /* address translation pid */
|
|
MCR CpSC, 0, R0, C(CpPID), C(0x0)
|
|
ISB
|
|
RET
|
|
|
|
TEXT splhi(SB), 1, $-4
|
|
MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */
|
|
MOVW R14, 0(R2)
|
|
|
|
MOVW CPSR, R0 /* turn off interrupts */
|
|
ORR $(PsrDirq), R0, R1
|
|
MOVW R1, CPSR
|
|
RET
|
|
|
|
TEXT spllo(SB), 1, $-4
|
|
MOVW CPSR, R0
|
|
BIC $(PsrDirq), R0, R1
|
|
MOVW R1, CPSR
|
|
RET
|
|
|
|
TEXT splx(SB), 1, $-4
|
|
MOVW $(MACHADDR+0x04), R2 /* save caller pc in Mach */
|
|
MOVW R14, 0(R2)
|
|
|
|
MOVW R0, R1 /* reset interrupt level */
|
|
MOVW CPSR, R0
|
|
MOVW R1, CPSR
|
|
RET
|
|
|
|
TEXT splxpc(SB), 1, $-4 /* for iunlock */
|
|
MOVW R0, R1
|
|
MOVW CPSR, R0
|
|
MOVW R1, CPSR
|
|
RET
|
|
|
|
TEXT spldone(SB), 1, $0
|
|
RET
|
|
|
|
TEXT islo(SB), 1, $-4
|
|
MOVW CPSR, R0
|
|
AND $(PsrDirq), R0
|
|
EOR $(PsrDirq), R0
|
|
RET
|
|
|
|
TEXT splfhi(SB), $-4
|
|
MOVW CPSR, R0
|
|
ORR $(PsrDfiq|PsrDirq), R0, R1
|
|
MOVW R1, CPSR
|
|
RET
|
|
|
|
//TEXT splflo(SB), $-4
|
|
// MOVW CPSR, R0
|
|
// BIC $(PsrDfiq), R0, R1
|
|
// MOVW R1, CPSR
|
|
// RET
|
|
|
|
TEXT tas(SB), $-4
|
|
TEXT _tas(SB), $-4
|
|
MOVW R0,R1
|
|
MOVW $1,R0
|
|
SWPW R0,(R1) /* fix: deprecated in armv7 */
|
|
RET
|
|
|
|
//TEXT tas32(SB), 1, $-4
|
|
// MOVW R0, R1
|
|
// MOVW $0xDEADDEAD, R0
|
|
// MOVW R0, R3
|
|
// SWPW R0, (R1)
|
|
// CMP.S R0, R3
|
|
// BEQ _tasout
|
|
// EOR R3, R3 /* R3 = 0 */
|
|
// CMP.S R0, R3
|
|
// BEQ _tasout
|
|
// MOVW $1, R15 /* abort: lock != 0 && lock != $0xDEADDEAD */
|
|
//_tasout:
|
|
// RET
|
|
|
|
TEXT clz(SB), 1, $-4
|
|
CLZ(0, 0) /* 0 is R0 */
|
|
RET
|
|
|
|
TEXT setlabel(SB), 1, $-4
|
|
MOVW R13, 0(R0) /* sp */
|
|
MOVW R14, 4(R0) /* pc */
|
|
BARRIERS
|
|
MOVW $0, R0
|
|
RET
|
|
|
|
TEXT gotolabel(SB), 1, $-4
|
|
MOVW 0(R0), R13 /* sp */
|
|
MOVW 4(R0), R14 /* pc */
|
|
BARRIERS
|
|
MOVW $1, R0
|
|
RET
|
|
|
|
TEXT getcallerpc(SB), 1, $-4
|
|
MOVW 0(R13), R0
|
|
RET
|
|
|
|
TEXT _idlehands(SB), 1, $-4
|
|
MOVW CPSR, R3
|
|
// ORR $PsrDirq, R3, R1 /* splhi */
|
|
BIC $PsrDirq, R3, R1 /* spllo */
|
|
MOVW R1, CPSR
|
|
|
|
MOVW $0, R0 /* wait for interrupt */
|
|
MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEintr), CpCACHEwait
|
|
ISB
|
|
|
|
MOVW R3, CPSR /* splx */
|
|
RET
|
|
|
|
TEXT barriers(SB), 1, $-4
|
|
BARRIERS
|
|
RET
|