123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873 |
- /*
- * tegra 2 SoC machine assist
- * dual arm cortex-a9 processors
- *
- * ARM v7 arch. ref. man. §B1.3.3 says that we don't need barriers
- * around writes to CPSR.
- *
- * LDREX/STREX use an exclusive monitor, which is part of the data cache unit
- * for the L1 cache, so they won't work right if the L1 cache is disabled.
- */
- #include "arm.s"
- #define LDREX(fp,t) WORD $(0xe<<28|0x01900f9f | (fp)<<16 | (t)<<12)
- /* `The order of operands is from left to right in dataflow order' - asm man */
- #define STREX(f,tp,r) WORD $(0xe<<28|0x01800f90 | (tp)<<16 | (r)<<12 | (f)<<0)
- #define MAXMB (KiB-1) /* last MB has vectors */
- #define TMPSTACK (DRAMSIZE - 64*MiB) /* used only during cpu startup */
- /* tas/cas strex debugging limits; started at 10000 */
- #define MAXSC 100000
- GLOBL testmem(SB), $4
- /*
- * Entered here from Das U-Boot or another Plan 9 kernel 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
- CPSMODE(PsrMsvc)
- CPSID /* interrupts off */
- CPSAE
- SETEND(0) /* little-endian */
- BARRIERS
- CLREX
- SETZSB
- MOVW CPSR, R0
- ORR $PsrDfiq, R0
- MOVW R0, CPSR
- /* invalidate i-cache and branch-target cache */
- MTCP CpSC, 0, PC, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
- BARRIERS
- /* put cpus other than 0 to sleep until cpu 0 is ready */
- CPUID(R1)
- BEQ cpuinit
- /* not cpu 0 */
- PUTC('Z')
- PUTC('Z')
- BARRIERS
- dowfi:
- WFI
- MOVW cpus_proceed(SB), R1
- CMP $0, R1
- BEQ dowfi
- BL cpureset(SB)
- B dowfi
- cpuinit:
- DELAY(printloopret, 1)
- PUTC('\r')
- DELAY(printloopnl, 1)
- PUTC('\n')
- DELAY(printloops, 1)
- PUTC('P')
- /* disable the PL310 L2 cache on cpu0 */
- MOVW $(PHYSL2BAG+0x100), R1
- MOVW $0, R2
- MOVW R2, (R1)
- BARRIERS
- /* invalidate it */
- MOVW $((1<<16)-1), R2
- MOVW R2, 0x77c(R1)
- BARRIERS
- /*
- * disable my MMU & caches
- */
- MFCP CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- ORR $CpCsbo, R1
- BIC $(CpCsbz|CpCmmu|CpCdcache|CpCicache|CpCpredict), R1
- MTCP CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- /* cortex-a9 model-specific initial configuration */
- MOVW $0, R1
- MTCP CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- BARRIERS
- PUTC('l')
- DELAY(printloop3, 1)
- MOVW $testmem-KZERO(SB), R0
- BL memdiag(SB)
- PUTC('a')
- /* clear Mach for cpu 0 */
- MOVW $PADDR(MACHADDR), R4 /* address of Mach for cpu 0 */
- MOVW $0, R0
- _machZ:
- MOVW R0, (R4)
- ADD $4, R4
- CMP.S $PADDR(L1+L1X(0)), R4 /* end at top-level page table */
- BNE _machZ
- /*
- * set up the MMU page table for cpu 0
- */
- PUTC('n')
- /* clear all PTEs first, to provide a default */
- // MOVW $PADDR(L1+L1X(0)), R4 /* address of PTE for 0 */
- _ptenv0:
- ZEROPTE()
- CMP.S $PADDR(L1+16*KiB), R4
- BNE _ptenv0
- DELAY(printloop4, 2)
- PUTC(' ')
- /*
- * set up double map of PHYSDRAM, KZERO to PHYSDRAM for first few MBs,
- * but only if KZERO and PHYSDRAM differ.
- */
- MOVW $PTEDRAM, R2 /* PTE bits */
- MOVW $PHYSDRAM, R3 /* pa */
- CMP $KZERO, R3
- BEQ no2map
- MOVW $PADDR(L1+L1X(PHYSDRAM)), R4 /* address of PTE for PHYSDRAM */
- MOVW $DOUBLEMAPMBS, R5
- _ptdbl:
- FILLPTE()
- SUB.S $1, R5
- BNE _ptdbl
- no2map:
- /*
- * back up and fill in PTEs for memory at KZERO.
- * trimslice has 1 bank of 1GB at PHYSDRAM.
- * Map the maximum.
- */
- PUTC('9')
- MOVW $PTEDRAM, R2 /* PTE bits */
- MOVW $PHYSDRAM, R3
- MOVW $PADDR(L1+L1X(KZERO)), R4 /* start with PTE for KZERO */
- MOVW $MAXMB, R5 /* inner loop count (MBs) */
- _ptekrw: /* set PTEs */
- FILLPTE()
- SUB.S $1, R5 /* decrement inner loop count */
- BNE _ptekrw
- /*
- * back up and fill in PTEs for MMIO
- */
- PUTC(' ')
- MOVW $PTEIO, R2 /* PTE bits */
- MOVW $PHYSIO, R3
- MOVW $PADDR(L1+L1X(VIRTIO)), R4 /* start with PTE for VIRTIO */
- _ptenv2:
- FILLPTE()
- CMP.S $PADDR(L1+L1X(PHYSIOEND)), R4
- BNE _ptenv2
- /* mmu.c sets up the trap vectors later */
- MOVW $(PHYSDRAM | TMPSTACK), SP
- /*
- * learn l1 cache characteristics (on cpu 0 only).
- */
- MOVW $(1-1), R0 /* l1 */
- SLL $1, R0 /* R0 = (cache - 1) << 1 */
- MTCP CpSC, CpIDcssel, R0, C(CpID), C(CpIDid), 0 /* select l1 cache */
- BARRIERS
- MFCP CpSC, CpIDcsize, R0, C(CpID), C(CpIDid), 0 /* get sets & ways */
- MOVW $CACHECONF, R8
- /* get log2linelen into l1setsh */
- MOVW R0, R1
- AND $3, R1
- ADD $4, R1
- /* l1 & l2 must have same cache line size, thus same set shift */
- MOVW R1, 4(R8) /* +4 = l1setsh */
- MOVW R1, 12(R8) /* +12 = l2setsh */
- /* get nways in R1 */
- SRA $3, R0, R1
- AND $((1<<10)-1), R1
- ADD $1, R1
- /* get log2(nways) in R2 (assume nways is 2^n) */
- MOVW $(BI2BY*BY2WD - 1), R2
- CLZ(1, 1)
- SUB.S R1, R2 /* R2 = 31 - clz(nways) */
- ADD.EQ $1, R2
- // MOVW R2, R3 /* print log2(nways): 2 */
- MOVW $32, R1
- SUB R2, R1 /* R1 = 32 - log2(nways) */
- MOVW R1, 0(R8) /* +0 = l1waysh */
- BARRIERS
- MOVW $testmem-KZERO(SB), R0
- BL memdiag(SB)
- /*
- * the mpcore manual says invalidate d-cache, scu, pl310 in that order,
- * but says nothing about when to disable them.
- *
- * invalidate my caches before enabling
- */
- BL cachedinv(SB)
- MTCP CpSC, 0, PC, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
- BARRIERS
- PUTC('f')
- /*
- * the mpcore manual says enable scu, d-cache, pl310, smp mode
- * in that order. we have to reverse the last two; see main().
- */
- BL scuon(SB)
- /*
- * turn my L1 cache on; need it for tas below.
- */
- MFCP CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- ORR $(CpCdcache|CpCicache|CpCalign|CpCpredict), R1
- MTCP CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- /* cortex-a9 model-specific configuration */
- MOVW $CpACl1pref, R1
- MTCP CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- BARRIERS
- /* we're supposed to wait until l1 & l2 are on before calling smpon */
- PUTC('r')
- /* set the domain access control */
- MOVW $Client, R0
- BL dacput(SB)
- DELAY(printloop5, 2)
- PUTC('o')
- BL mmuinvalidate(SB)
- MOVW $0, R0
- BL pidput(SB)
- /* set the translation table base */
- MOVW $PADDR(L1), R0
- BL ttbput(SB)
- PUTC('m')
- /*
- * the little dance to turn the MMU on
- */
- BL cacheuwbinv(SB)
- BL mmuinvalidate(SB)
- BL mmuenable(SB)
- PUTC(' ')
- /* warp the PC into the virtual map */
- MOVW $KZERO, R0
- BL _r15warp(SB)
- /*
- * cpu 0 is now running at KZERO+something!
- */
- BARRIERS
- MOVW $setR12(SB), R12 /* reload kernel SB */
- MOVW $(KZERO | TMPSTACK), SP
- BL cacheuwbinv(SB)
- PUTC('B')
- MOVW $PHYSDRAM, R3 /* pa */
- CMP $KZERO, R3
- BEQ no2unmap
- /* undo double map of PHYSDRAM, KZERO & first few MBs */
- MOVW $(L1+L1X(PHYSDRAM)), R4 /* addr. of PTE for PHYSDRAM */
- MOVW $0, R0
- MOVW $DOUBLEMAPMBS, R5
- _ptudbl:
- ZEROPTE()
- SUB.S $1, R5
- BNE _ptudbl
- no2unmap:
- BL cachedwb(SB)
- BL mmuinvalidate(SB)
- /*
- * call main in C
- * pass Mach to main and set up the stack in it
- */
- MOVW $MACHADDR, R0 /* cpu 0 Mach */
- MOVW R0, R(MACH) /* m = MACHADDR */
- ADD $(MACHSIZE-4), R0, SP /* leave space for link register */
- PUTC('e')
- BL main(SB) /* main(m) */
- limbo:
- BL idlehands(SB)
- B limbo
- BL _div(SB) /* hack to load _div, etc. */
- /*
- * called on cpu(s) other than 0, to start them, from _vrst
- * (reset vector) in lexception.s, with interrupts disabled
- * and in SVC mode, running in the zero segment (pc is in lower 256MB).
- * SB is set for the zero segment.
- */
- TEXT cpureset(SB), 1, $-4
- CLREX
- MOVW CPSR, R0
- ORR $PsrDfiq, R0
- MOVW R0, CPSR
- MOVW $(PHYSDRAM | TMPSTACK), SP /* stack for cache ops */
- /* paranoia: turn my mmu and caches off. */
- MFCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- ORR $CpCsbo, R0
- BIC $(CpCsbz|CpCmmu|CpCdcache|CpCicache|CpCpredict), R0
- MTCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- /* cortex-a9 model-specific initial configuration */
- MOVW $0, R1
- MTCP CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
- ISB
- /* invalidate my caches before enabling */
- BL cachedinv(SB)
- MTCP CpSC, 0, PC, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
- BARRIERS
- /*
- * turn my L1 cache on; need it (and mmu) for tas below.
- * need branch prediction to make delay() timing right.
- */
- MFCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- ORR $(CpCdcache|CpCicache|CpCalign|CpCpredict), R0
- MTCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- /* enable l1 caches coherency, at minimum for ldrex/strex. */
- BL smpon(SB)
- BARRIERS
- /*
- * we used to write to PHYSEVP here; now we do it in C, which offers
- * more assurance that we're up and won't go off the rails.
- */
- /* set the domain access control */
- MOVW $Client, R0
- BL dacput(SB)
- BL setmach(SB)
- /*
- * redo double map of PHYSDRAM, KZERO in this cpu's ptes.
- * mmuinit will undo this later.
- */
- MOVW $PHYSDRAM, R3
- CMP $KZERO, R3
- BEQ noun2map
- /* launchinit set m->mmul1 to a copy of cpu0's l1 page table */
- MOVW 12(R(MACH)), R0 /* m->mmul1 (virtual addr) */
- BL k2paddr(SB) /* R0 = PADDR(m->mmul1) */
- ADD $L1X(PHYSDRAM), R0, R4 /* R4 = address of PHYSDRAM's PTE */
- MOVW $PTEDRAM, R2 /* PTE bits */
- MOVW $DOUBLEMAPMBS, 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
- noun2map:
- MOVW $0, R0
- BL pidput(SB)
- /* set the translation table base to PADDR(m->mmul1) */
- MOVW 12(R(MACH)), R0 /* m->mmul1 */
- BL k2paddr(SB) /* R0 = PADDR(m->mmul1) */
- BL ttbput(SB)
- /*
- * the little dance to turn the MMU on
- */
- BL cacheuwbinv(SB)
- BL mmuinvalidate(SB)
- BL mmuenable(SB)
- /*
- * mmu is now on, with l1 pt at m->mmul1.
- */
- /* warp the PC into the virtual map */
- MOVW $KZERO, R0
- BL _r15warp(SB)
- /*
- * now running at KZERO+something!
- */
- BARRIERS
- MOVW $setR12(SB), R12 /* reload kernel's SB */
- MOVW $(KZERO | TMPSTACK), SP /* stack for cache ops*/
- BL setmach(SB)
- ADD $(MACHSIZE-4), R(MACH), SP /* leave space for link register */
- BL cpustart(SB)
- /*
- * converts virtual address in R0 to a physical address.
- */
- TEXT k2paddr(SB), 1, $-4
- BIC $KSEGM, R0
- ADD $PHYSDRAM, R0
- RET
- /*
- * converts physical address in R0 to a virtual address.
- */
- TEXT p2kaddr(SB), 1, $-4
- BIC $KSEGM, R0
- ORR $KZERO, R0
- RET
- /*
- * converts address in R0 to the current segment, as defined by the PC.
- * clobbers R1.
- */
- TEXT addr2pcseg(SB), 1, $-4
- BIC $KSEGM, R0
- MOVW PC, R1
- AND $KSEGM, R1 /* segment PC is in */
- ORR R1, R0
- RET
- /* sets R(MACH), preserves other registers */
- TEXT setmach(SB), 1, $-4
- MOVM.DB.W [R14], (R13)
- MOVM.DB.W [R0-R2], (R13)
- CPUID(R2)
- SLL $2, R2 /* convert to word index */
- MOVW $machaddr(SB), R0
- BL addr2pcseg(SB)
- ADD R2, R0 /* R0 = &machaddr[cpuid] */
- MOVW (R0), R0 /* R0 = machaddr[cpuid] */
- CMP $0, R0
- MOVW.EQ $MACHADDR, R0 /* paranoia: use MACHADDR if 0 */
- BL addr2pcseg(SB)
- MOVW R0, R(MACH) /* m = machaddr[cpuid] */
- MOVM.IA.W (R13), [R0-R2]
- MOVM.IA.W (R13), [R14]
- RET
- /*
- * memory diagnostic
- * tests word at (R0); modifies R7 and R8
- */
- TEXT memdiag(SB), 1, $-4
- MOVW $0xabcdef89, R7
- MOVW R7, (R0)
- MOVW (R0), R8
- CMP R7, R8
- BNE mbuggery /* broken memory */
- BARRIERS
- MOVW (R0), R8
- CMP R7, R8
- BNE mbuggery /* broken memory */
- MOVW $0, R7
- MOVW R7, (R0)
- BARRIERS
- RET
- /* modifies R0, R3—R6 */
- TEXT printhex(SB), 1, $-4
- MOVW R0, R3
- PUTC('0')
- PUTC('x')
- MOVW $(32-4), R5 /* bits to shift right */
- nextdig:
- SRA R5, R3, R4
- AND $0xf, R4
- ADD $'0', R4
- CMP.S $'9', R4
- BLE nothex /* if R4 <= 9, jump */
- ADD $('a'-('9'+1)), R4
- nothex:
- PUTC(R4)
- SUB.S $4, R5
- BGE nextdig
- PUTC('\r')
- PUTC('\n')
- DELAY(proct, 50)
- RET
- mbuggery:
- PUTC('?')
- PUTC('m')
- mtopanic:
- MOVW $membmsg(SB), R0
- MOVW R14, R1 /* get R14's segment ... */
- AND $KSEGM, R1
- BIC $KSEGM, R0 /* strip segment from address */
- ORR R1, R0 /* combine them */
- BL panic(SB)
- mbugloop:
- WFI
- B mbugloop
- DATA membmsg+0(SB)/8,$"memory b"
- DATA membmsg+8(SB)/6,$"roken\z"
- GLOBL membmsg(SB), $14
- TEXT _r15warp(SB), 1, $-4
- BIC $KSEGM, R14 /* link reg, will become PC */
- ORR R0, R14
- BIC $KSEGM, SP
- ORR R0, SP
- RET
- /*
- * `single-element' cache operations.
- * in arm arch v7, they operate on all architected cache levels, so separate
- * l2 functions are usually unnecessary.
- */
- TEXT cachedwbse(SB), $-4 /* D writeback SE */
- MOVW R0, R2
- MOVW CPSR, R3
- CPSID /* splhi */
- BARRIERS /* force outstanding stores to cache */
- MOVW R2, R0
- MOVW 4(FP), R1
- ADD R0, R1 /* R1 is end address */
- BIC $(CACHELINESZ-1), R0 /* cache line start */
- _dwbse:
- MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
- ADD $CACHELINESZ, R0
- CMP.S R0, R1
- BGT _dwbse
- B _wait
- TEXT cachedwbinvse(SB), $-4 /* D writeback+invalidate SE */
- MOVW R0, R2
- MOVW CPSR, R3
- CPSID /* splhi */
- BARRIERS /* force outstanding stores to cache */
- MOVW R2, R0
- MOVW 4(FP), R1
- ADD R0, R1 /* R1 is end address */
- BIC $(CACHELINESZ-1), R0 /* cache line start */
- _dwbinvse:
- MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
- ADD $CACHELINESZ, R0
- CMP.S R0, R1
- BGT _dwbinvse
- _wait: /* drain write buffer */
- BARRIERS
- MOVW R3, CPSR /* splx */
- RET
- TEXT cachedinvse(SB), $-4 /* D invalidate SE */
- MOVW R0, R2
- MOVW CPSR, R3
- CPSID /* splhi */
- BARRIERS /* force outstanding stores to cache */
- MOVW R2, R0
- MOVW 4(FP), R1
- ADD R0, R1 /* R1 is end address */
- /*
- * if start & end addresses are not on cache-line boundaries,
- * flush first & last cache lines before invalidating.
- */
- AND.S $(CACHELINESZ-1), R0, R4
- BEQ stok
- BIC $(CACHELINESZ-1), R0, R4 /* cache line start */
- MTCP CpSC, 0, R4, C(CpCACHE), C(CpCACHEwb), CpCACHEse
- stok:
- AND.S $(CACHELINESZ-1), R1, R4
- BEQ endok
- BIC $(CACHELINESZ-1), R1, R4 /* cache line start */
- MTCP CpSC, 0, R4, C(CpCACHE), C(CpCACHEwb), CpCACHEse
- endok:
- BIC $(CACHELINESZ-1), R0 /* cache line start */
- _dinvse:
- MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
- ADD $CACHELINESZ, R0
- CMP.S R0, R1
- BGT _dinvse
- B _wait
- /*
- * enable mmu and high vectors
- */
- TEXT mmuenable(SB), 1, $-4
- MFCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- ORR $CpCmmu, R0
- MTCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- RET
- TEXT mmudisable(SB), 1, $-4
- MFCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BIC $CpCmmu, R0
- MTCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- BARRIERS
- RET
- /*
- * If one of these MCR instructions crashes or hangs the machine,
- * check your Level 1 page table (at TTB) closely.
- */
- TEXT mmuinvalidate(SB), $-4 /* invalidate all */
- MOVW CPSR, R2
- CPSID /* interrupts off */
- BARRIERS
- MTCP CpSC, 0, PC, C(CpTLB), C(CpTLBinvu), CpTLBinv
- BARRIERS
- MOVW R2, CPSR /* interrupts restored */
- RET
- TEXT mmuinvalidateaddr(SB), $-4 /* invalidate single entry */
- MTCP CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
- BARRIERS
- RET
- TEXT cpidget(SB), 1, $-4 /* main ID */
- MFCP CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDid
- RET
- TEXT cpctget(SB), 1, $-4 /* cache type */
- MFCP CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDct
- RET
- TEXT controlget(SB), 1, $-4 /* system control (sctlr) */
- MFCP CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
- RET
- TEXT ttbget(SB), 1, $-4 /* translation table base */
- MFCP CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
- RET
- TEXT ttbput(SB), 1, $-4 /* translation table base */
- MOVW CPSR, R2
- CPSID
- MOVW R0, R1
- BARRIERS /* finish prior accesses before changing ttb */
- MTCP CpSC, 0, R1, C(CpTTB), C(0), CpTTB0
- MTCP CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* non-secure too */
- MOVW $0, R0
- MTCP CpSC, 0, R0, C(CpTTB), C(0), CpTTBctl
- BARRIERS
- MOVW R2, CPSR
- RET
- TEXT dacget(SB), 1, $-4 /* domain access control */
- MFCP CpSC, 0, R0, C(CpDAC), C(0)
- RET
- TEXT dacput(SB), 1, $-4 /* domain access control */
- MOVW R0, R1
- BARRIERS
- MTCP CpSC, 0, R1, C(CpDAC), C(0)
- ISB
- RET
- TEXT fsrget(SB), 1, $-4 /* fault status */
- MFCP CpSC, 0, R0, C(CpFSR), C(0), CpDFSR
- RET
- TEXT farget(SB), 1, $-4 /* fault address */
- MFCP CpSC, 0, R0, C(CpFAR), C(0), CpDFAR
- RET
- TEXT getpsr(SB), 1, $-4
- MOVW CPSR, R0
- RET
- TEXT getscr(SB), 1, $-4 /* secure configuration */
- MFCP CpSC, 0, R0, C(CpCONTROL), C(CpCONTROLscr), CpSCRscr
- RET
- TEXT pidget(SB), 1, $-4 /* address translation pid */
- MFCP CpSC, 0, R0, C(CpPID), C(0x0)
- RET
- TEXT pidput(SB), 1, $-4 /* address translation pid */
- MTCP CpSC, 0, R0, C(CpPID), C(0), 0 /* pid, v7a deprecated */
- MTCP CpSC, 0, R0, C(CpPID), C(0), 1 /* context id, errata 754322 */
- ISB
- RET
- /*
- * access to yet more coprocessor registers
- */
- TEXT getauxctl(SB), 1, $-4 /* get cortex-a9 aux. ctl. */
- MFCP CpSC, 0, R0, C(CpCONTROL), C(0), CpAuxctl
- RET
- TEXT putauxctl(SB), 1, $-4 /* put cortex-a9 aux. ctl. */
- BARRIERS
- MTCP CpSC, 0, R0, C(CpCONTROL), C(0), CpAuxctl
- BARRIERS
- RET
- TEXT getclvlid(SB), 1, $-4
- MFCP CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), CpIDclvlid
- RET
- TEXT getcyc(SB), 1, $-4
- MFCP CpSC, 0, R0, C(CpCLD), C(CpCLDcyc), 0
- RET
- TEXT getdebug(SB), 1, $-4 /* get cortex-a9 debug enable register */
- MFCP CpSC, 0, R0, C(1), C(1), 1
- RET
- TEXT getpc(SB), 1, $-4
- MOVW PC, R0
- RET
- TEXT getsb(SB), 1, $-4
- MOVW R12, R0
- RET
- TEXT setsp(SB), 1, $-4
- MOVW R0, SP
- RET
- TEXT splhi(SB), 1, $-4
- MOVW CPSR, R0 /* return old CPSR */
- CPSID /* turn off interrupts */
- CMP.S $0, R(MACH)
- MOVW.NE R14, 4(R(MACH)) /* save caller pc in m->splpc */
- RET
- TEXT spllo(SB), 1, $-4 /* start marker for devkprof.c */
- MOVW CPSR, R0 /* return old CPSR */
- MOVW $0, R1
- CMP.S R1, R(MACH)
- MOVW.NE R1, 4(R(MACH)) /* clear m->splpc */
- CPSIE
- RET
- TEXT splx(SB), 1, $-4
- MOVW CPSR, R3 /* must return old CPSR */
- CPSID
- CMP.S $0, R(MACH)
- MOVW.NE R14, 4(R(MACH)) /* save caller pc in m->splpc */
- MOVW R0, CPSR /* reset interrupt level */
- MOVW R3, R0 /* must return old CPSR */
- RET
- TEXT spldone(SB), 1, $0 /* end marker for devkprof.c */
- RET
- TEXT islo(SB), 1, $-4
- MOVW CPSR, R0
- AND $(PsrDirq), R0
- EOR $(PsrDirq), R0
- RET
- TEXT clz(SB), $-4
- CLZ(0, 0) /* 0 is R0 */
- RET
- TEXT setlabel(SB), 1, $-4
- MOVW SP, 0(R0)
- MOVW R14, 4(R0) /* pc */
- MOVW $0, R0
- RET
- TEXT gotolabel(SB), 1, $-4
- MOVW 0(R0), SP
- MOVW 4(R0), R14 /* pc */
- MOVW $1, R0
- RET
- TEXT getcallerpc(SB), 1, $-4
- MOVW 0(SP), R0
- RET
- TEXT wfi(SB), $-4
- MOVW CPSR, R1
- /*
- * an interrupt should break us out of wfi. masking interrupts
- * slows interrupt response slightly but prevents recursion.
- */
- // CPSIE
- CPSID
- BARRIERS
- WFI
- MOVW R1, CPSR
- RET
- TEXT coherence(SB), $-4
- BARRIERS
- RET
- GLOBL cpus_proceed+0(SB), $4
- #include "cache.v7.s"
- TEXT tas(SB), $-4 /* _tas(ulong *) */
- /* returns old (R0) after modifying (R0) */
- MOVW R0,R5
- DMB
- MOVW $1,R2 /* new value of (R0) */
- MOVW $MAXSC, R8
- tas1:
- LDREX(5,7) /* LDREX 0(R5),R7 */
- CMP.S $0, R7 /* old value non-zero (lock taken)? */
- BNE lockbusy /* we lose */
- SUB.S $1, R8
- BEQ lockloop2
- STREX(2,5,4) /* STREX R2,(R5),R4 */
- CMP.S $0, R4
- BNE tas1 /* strex failed? try again */
- DMB
- B tas0
- lockloop2:
- PUTC('?')
- PUTC('l')
- PUTC('t')
- BL abort(SB)
- lockbusy:
- CLREX
- tas0:
- MOVW R7, R0 /* return old value */
- RET
|