plan9fox/sys/src/9/bcm64/l.s

675 lines
13 KiB
ArmAsm

#include "mem.h"
#include "sysreg.h"
#undef SYSREG
#define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5))
TEXT _start(SB), 1, $-4
MOV R0, R26 /* save */
MOV $setSB-KZERO(SB), R28
BL svcmode<>(SB)
/* use dedicated stack pointer per exception level */
MOVWU $1, R1
MSR R1, SPSel
BL mmudisable<>(SB)
/* invalidate local caches */
BL cachedinv(SB)
BL cacheiinv(SB)
MOV $(MACHADDR(0)-KZERO), R27
MRS MPIDR_EL1, R1
ANDW $(MAXMACH-1), R1
MOVWU $MACHSIZE, R2
MULW R1, R2, R2
SUB R2, R27
ADD $(MACHSIZE-16), R27, R2
MOV R2, SP
CBNZ R1, _startup
/* clear page table and machs */
MOV $(L1-KZERO), R1
MOV $(MACHADDR(-1)-KZERO), R2
_zerol1:
MOV ZR, (R1)8!
CMP R1, R2
BNE _zerol1
/* clear BSS */
MOV $edata-KZERO(SB), R1
MOV $end-KZERO(SB), R2
_zerobss:
MOV ZR, (R1)8!
CMP R1, R2
BNE _zerobss
/* setup page tables */
MOV $(L1-KZERO), R0
BL mmu0init(SB)
SEVL
_startup:
WFE
BL mmuenable<>(SB)
MOV R26, R0
MOV $0, R26
ORR $KZERO, R27
MSR R27, TPIDR_EL1
MOV $setSB(SB), R28
BL main(SB)
TEXT stop<>(SB), 1, $-4
_stop:
WFE
B _stop
TEXT sev(SB), 1, $-4
SEV
WFE
RETURN
TEXT svcmode<>(SB), 1, $-4
MSR $0xF, DAIFSet
MRS CurrentEL, R0
ANDW $(3<<2), R0
CMPW $(1<<2), R0
BEQ el1
CMPW $(2<<2), R0
BEQ el2
B stop<>(SB)
el2:
MOV $0, R0
MSR R0, MDCR_EL2
ISB $SY
/* HCR = RW, HCD, SWIO, BSU, FB */
MOVWU $(1<<31 | 1<<29 | 1<<2 | 0<<10 | 0<<9), R0
MSR R0, HCR_EL2
ISB $SY
/* SCTLR = RES1 */
MOVWU $(3<<4 | 1<<11 | 1<<16 | 1<<18 | 3<<22 | 3<<28), R0
ISB $SY
MSR R0, SCTLR_EL2
ISB $SY
/* set VMID to zero */
MOV $0, R0
MSR R0, VTTBR_EL2
ISB $SY
MOVWU $(0xF<<6 | 4), R0
MSR R0, SPSR_EL2
MSR LR, ELR_EL2
ERET
el1:
RETURN
TEXT mmudisable<>(SB), 1, $-4
#define SCTLRCLR \
/* RES0 */ ( 3<<30 \
/* RES0 */ | 1<<27 \
/* UCI */ | 1<<26 \
/* EE */ | 1<<25 \
/* RES0 */ | 1<<21 \
/* E0E */ | 1<<24 \
/* WXN */ | 1<<19 \
/* nTWE */ | 1<<18 \
/* RES0 */ | 1<<17 \
/* nTWI */ | 1<<16 \
/* UCT */ | 1<<15 \
/* DZE */ | 1<<14 \
/* RES0 */ | 1<<13 \
/* RES0 */ | 1<<10 \
/* UMA */ | 1<<9 \
/* SA0 */ | 1<<4 \
/* SA */ | 1<<3 \
/* A */ | 1<<1 )
#define SCTLRSET \
/* RES1 */ ( 3<<28 \
/* RES1 */ | 3<<22 \
/* RES1 */ | 1<<20 \
/* RES1 */ | 1<<11 )
#define SCTLRMMU \
/* I */ ( 1<<12 \
/* C */ | 1<<2 \
/* M */ | 1<<0 )
/* initialise SCTLR, MMU and caches off */
ISB $SY
MRS SCTLR_EL1, R0
BIC $(SCTLRCLR | SCTLRMMU), R0
ORR $SCTLRSET, R0
ISB $SY
MSR R0, SCTLR_EL1
ISB $SY
B flushlocaltlb(SB)
TEXT mmuenable<>(SB), 1, $-4
/* return to virtual */
ORR $KZERO, LR
MOV LR, -16(RSP)!
BL flushlocaltlb(SB)
/* memory attributes */
#define MAIRINIT \
( 0xFF << MA_MEM_WB*8 \
| 0x33 << MA_MEM_WT*8 \
| 0x44 << MA_MEM_UC*8 \
| 0x00 << MA_DEV_nGnRnE*8 \
| 0x04 << MA_DEV_nGnRE*8 \
| 0x08 << MA_DEV_nGRE*8 \
| 0x0C << MA_DEV_GRE*8 )
MOV $MAIRINIT, R1
MSR R1, MAIR_EL1
ISB $SY
/* translation control */
#define TCRINIT \
/* TBI1 */ ( 0<<38 \
/* TBI0 */ | 0<<37 \
/* AS */ | 0<<36 \
/* TG1 */ | (((3<<16|1<<14|2<<12)>>PGSHIFT)&3)<<30 \
/* SH1 */ | SHARE_INNER<<28 \
/* ORGN1 */ | CACHE_WB<<26 \
/* IRGN1 */ | CACHE_WB<<24 \
/* EPD1 */ | 0<<23 \
/* A1 */ | 0<<22 \
/* T1SZ */ | (64-EVASHIFT)<<16 \
/* TG0 */ | (((1<<16|2<<14|0<<12)>>PGSHIFT)&3)<<14 \
/* SH0 */ | SHARE_INNER<<12 \
/* ORGN0 */ | CACHE_WB<<10 \
/* IRGN0 */ | CACHE_WB<<8 \
/* EPD0 */ | 0<<7 \
/* T0SZ */ | (64-EVASHIFT)<<0 )
MOV $TCRINIT, R1
MRS ID_AA64MMFR0_EL1, R2
ANDW $0x7, R2 // PARange
ADD R2<<32, R1 // IPS
MSR R1, TCR_EL1
ISB $SY
/* load the page tables */
MOV $(L1TOP-KZERO), R0
ISB $SY
MSR R0, TTBR0_EL1
MSR R0, TTBR1_EL1
ISB $SY
/* enable MMU and caches */
MRS SCTLR_EL1, R1
ORR $SCTLRMMU, R1
ISB $SY
MSR R1, SCTLR_EL1
ISB $SY
MOV RSP, R1
ORR $KZERO, R1
MOV R1, RSP
MOV (RSP)16!, LR
B cacheiinv(SB)
TEXT touser(SB), 1, $-4
MSR $0x3, DAIFSet // interrupts off
MOVWU $0x10028, R1 // entry
MOVWU $0, R2 // psr
MSR R0, SP_EL0 // sp
MSR R1, ELR_EL1
MSR R2, SPSR_EL1
ERET
TEXT cas(SB), 1, $-4
TEXT cmpswap(SB), 1, $-4
MOVWU ov+8(FP), R1
MOVWU nv+16(FP), R2
_cas1:
LDXRW (R0), R3
CMP R3, R1
BNE _cas0
STXRW R2, (R0), R4
CBNZ R4, _cas1
MOVW $1, R0
DMB $ISH
RETURN
_cas0:
CLREX
MOVW $0, R0
RETURN
TEXT tas(SB), 1, $-4
TEXT _tas(SB), 1, $-4
MOVW $0xdeaddead, R2
_tas1:
LDXRW (R0), R1
STXRW R2, (R0), R3
CBNZ R3, _tas1
MOVW R1, R0
TEXT coherence(SB), 1, $-4
DMB $ISH
RETURN
TEXT islo(SB), 1, $-4
MRS DAIF, R0
AND $(0x2<<6), R0
EOR $(0x2<<6), R0
RETURN
TEXT splhi(SB), 1, $-4
MRS DAIF, R0
MSR $0x2, DAIFSet
RETURN
TEXT splfhi(SB), 1, $-4
MRS DAIF, R0
MSR $0x3, DAIFSet
RETURN
TEXT spllo(SB), 1, $-4
MSR $0x3, DAIFClr
RETURN
TEXT splflo(SB), 1, $-4
MSR $0x1, DAIFClr
RETURN
TEXT splx(SB), 1, $-4
MSR R0, DAIF
RETURN
TEXT idlehands(SB), 1, $-4
DMB $ISH
MOV $nrdy(SB), R1
LDXRW (R1), R0
CBZ R0, _goodnight
CLREX
SEVL
_goodnight:
WFE
RETURN
TEXT vcycles(SB), 1, $-4
MRS CNTVCT_EL0, R0
RETURN
TEXT lcycles(SB), 1, $-4
MRS PMCCNTR_EL0, R0
RETURN
TEXT setlabel(SB), 1, $-4
MOV LR, 8(R0)
MOV SP, R1
MOV R1, 0(R0)
MOVW $0, R0
RETURN
TEXT gotolabel(SB), 1, $-4
MOV 8(R0), LR /* link */
MOV 0(R0), R1 /* sp */
MOV R1, SP
MOVW $1, R0
RETURN
TEXT returnto(SB), 1, $-4
MOV R0, 0(SP)
RETURN
TEXT getfar(SB), 1, $-4
MRS FAR_EL1, R0
RETURN
TEXT setttbr(SB), 1, $-4
DSB $ISHST
MSR R0, TTBR0_EL1
DSB $ISH
ISB $SY
RETURN
/*
* TLB maintenance operations.
* these broadcast to all cpu's in the cluser
* (inner sharable domain).
*/
TEXT flushasidva(SB), 1, $-4
TEXT tlbivae1is(SB), 1, $-4
DSB $ISHST
TLBI R0, 0,8,3,1 /* VAE1IS */
DSB $ISH
ISB $SY
RETURN
TEXT flushasidvall(SB), 1, $-4
TEXT tlbivale1is(SB), 1, $-4
DSB $ISHST
TLBI R0, 0,8,3,5 /* VALE1IS */
DSB $ISH
ISB $SY
RETURN
TEXT flushasid(SB), 1, $-4
TEXT tlbiaside1is(SB), 1, $-4
DSB $ISHST
TLBI R0, 0,8,3,2 /* ASIDE1IS */
DSB $ISH
ISB $SY
RETURN
TEXT flushtlb(SB), 1, $-4
TEXT tlbivmalle1is(SB), 1, $-4
DSB $ISHST
TLBI R0, 0,8,3,0 /* VMALLE1IS */
DSB $ISH
ISB $SY
RETURN
/*
* flush the tlb of this cpu. no broadcast.
*/
TEXT flushlocaltlb(SB), 1, $-4
TEXT tlbivmalle1(SB), 1, $-4
DSB $NSHST
TLBI R0, 0,8,7,0 /* VMALLE1 */
DSB $NSH
ISB $SY
RETURN
TEXT fpsaveregs(SB), 1, $-4
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 0) /* MOV { V0, V1, V2, V3 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 4) /* MOV { V4, V5, V6, V7 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 8) /* MOV { V8, V9, V10,V11 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 12) /* MOV { V12,V13,V14,V15 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 16) /* MOV { V16,V17,V18,V19 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 20) /* MOV { V20,V21,V22,V23 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 24) /* MOV { V24,V25,V26,V27 }, (R0)64! */
WORD $(1<<30 | 3 << 26 | 2<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 28) /* MOV { V28,V29,V30,V31 }, (R0)64! */
RETURN
TEXT fploadregs(SB), 1, $-4
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 0) /* MOV (R0)64!, { V0, V1, V2, V3 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 4) /* MOV (R0)64!, { V4, V5, V6, V7 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 8) /* MOV (R0)64!, { V8, V9, V10,V11 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 12) /* MOV (R0)64!, { V12,V13,V14,V15 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 16) /* MOV (R0)64!, { V16,V17,V18,V19 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 20) /* MOV (R0)64!, { V20,V21,V22,V23 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 24) /* MOV (R0)64!, { V24,V25,V26,V27 } */
WORD $(1<<30 | 3 << 26 | 3<<22 | 0x1F<<16 | 3<<10 | 0<<5 | 28) /* MOV (R0)64!, { V28,V29,V30,V31 } */
RETURN
// syscall or trap from EL0
TEXT vsys0(SB), 1, $-4
LSRW $26, R0, R17 // ec
CMPW $0x15, R17 // SVC trap?
BNE _itsatrap // nope.
MOVP R26, R27, 224(RSP)
MOVP R28, R29, 240(RSP)
MRS SP_EL0, R1
MRS ELR_EL1, R2
MRS SPSR_EL1, R3
MOV R0, 288(RSP) // type
MOV R1, 264(RSP) // sp
MOV R2, 272(RSP) // pc
MOV R3, 280(RSP) // psr
MOV $setSB(SB), R28
MRS TPIDR_EL1, R27
MOV 16(R27), R26
ADD $16, RSP, R0 // ureg
BL syscall(SB)
TEXT forkret(SB), 1, $-4
MSR $0x3, DAIFSet // interrupts off
ADD $16, RSP, R0 // ureg
MOV 16(RSP), R0 // ret
MOV 264(RSP), R1 // sp
MOV 272(RSP), R2 // pc
MOV 280(RSP), R3 // psr
MSR R1, SP_EL0
MSR R2, ELR_EL1
MSR R3, SPSR_EL1
MOVP 224(RSP), R26, R27
MOVP 240(RSP), R28, R29
MOV 256(RSP), R30 // link
ADD $TRAPFRAMESIZE, RSP
ERET
TEXT itsatrap<>(SB), 1, $-4
_itsatrap:
MOVP R1, R2, 24(RSP)
MOVP R3, R4, 40(RSP)
MOVP R5, R6, 56(RSP)
MOVP R7, R8, 72(RSP)
MOVP R9, R10, 88(RSP)
MOVP R11, R12, 104(RSP)
MOVP R13, R14, 120(RSP)
MOVP R15, R16, 136(RSP)
MOVP R18, R19, 160(RSP)
MOVP R20, R21, 176(RSP)
MOVP R22, R23, 192(RSP)
MOVP R24, R25, 208(RSP)
// trap/irq/fiq/serr from EL0
TEXT vtrap0(SB), 1, $-4
MOVP R26, R27, 224(RSP)
MOVP R28, R29, 240(RSP)
MRS SP_EL0, R1
MRS ELR_EL1, R2
MRS SPSR_EL1, R3
MOV R0, 288(RSP) // type
MOV R1, 264(RSP) // sp
MOV R2, 272(RSP) // pc
MOV R3, 280(RSP) // psr
MOV $setSB(SB), R28
MRS TPIDR_EL1, R27
MOV 16(R27), R26
ADD $16, RSP, R0 // ureg
BL trap(SB)
TEXT noteret(SB), 1, $-4
MSR $0x3, DAIFSet // interrupts off
ADD $16, RSP, R0 // ureg
MOV 264(RSP), R1 // sp
MOV 272(RSP), R2 // pc
MOV 280(RSP), R3 // psr
MSR R1, SP_EL0
MSR R2, ELR_EL1
MSR R3, SPSR_EL1
MOVP 224(RSP), R26, R27
MOVP 240(RSP), R28, R29
_intrreturn:
MOVP 16(RSP), R0, R1
MOVP 32(RSP), R2, R3
MOVP 48(RSP), R4, R5
MOVP 64(RSP), R6, R7
MOVP 80(RSP), R8, R9
MOVP 96(RSP), R10, R11
MOVP 112(RSP), R12, R13
MOVP 128(RSP), R14, R15
MOVP 144(RSP), R16, R17
MOVP 160(RSP), R18, R19
MOVP 176(RSP), R20, R21
MOVP 192(RSP), R22, R23
MOVP 208(RSP), R24, R25
MOV 256(RSP), R30 // link
ADD $TRAPFRAMESIZE, RSP
ERET
// irq/fiq/trap/serr from EL1
TEXT vtrap1(SB), 1, $-4
MOV R29, 248(RSP) // special
ADD $TRAPFRAMESIZE, RSP, R1
MRS ELR_EL1, R2
MRS SPSR_EL1, R3
MOV R0, 288(RSP) // type
MOV R1, 264(RSP) // sp
MOV R2, 272(RSP) // pc
MOV R3, 280(RSP) // psr
ADD $16, RSP, R0 // ureg
BL trap(SB)
MSR $0x3, DAIFSet // interrupts off
MOV 272(RSP), R2 // pc
MOV 280(RSP), R3 // psr
MSR R2, ELR_EL1
MSR R3, SPSR_EL1
MOV 248(RSP), R29 // special
B _intrreturn
// vector tables
TEXT vsys(SB), 1, $-4
SUB $TRAPFRAMESIZE, RSP
MOV R0, 16(RSP)
MOV R30, 256(RSP) // link
MOV R17, 152(RSP) // temp
MRS ESR_EL1, R0 // type
_vsyspatch:
B _vsyspatch // branch to vsys0() patched in
TEXT vtrap(SB), 1, $-4
SUB $TRAPFRAMESIZE, RSP
MOVP R0, R1, 16(RSP)
MOVP R2, R3, 32(RSP)
MOVP R4, R5, 48(RSP)
MOVP R6, R7, 64(RSP)
MOVP R8, R9, 80(RSP)
MOVP R10, R11, 96(RSP)
MOVP R12, R13, 112(RSP)
MOVP R14, R15, 128(RSP)
MOVP R16, R17, 144(RSP)
MOVP R18, R19, 160(RSP)
MOVP R20, R21, 176(RSP)
MOVP R22, R23, 192(RSP)
MOVP R24, R25, 208(RSP)
MOV R30, 256(RSP) // link
MRS ESR_EL1, R0 // type
_vtrappatch:
B _vtrappatch // branch to vtrapX() patched in
TEXT virq(SB), 1, $-4
SUB $TRAPFRAMESIZE, RSP
MOVP R0, R1, 16(RSP)
MOVP R2, R3, 32(RSP)
MOVP R4, R5, 48(RSP)
MOVP R6, R7, 64(RSP)
MOVP R8, R9, 80(RSP)
MOVP R10, R11, 96(RSP)
MOVP R12, R13, 112(RSP)
MOVP R14, R15, 128(RSP)
MOVP R16, R17, 144(RSP)
MOVP R18, R19, 160(RSP)
MOVP R20, R21, 176(RSP)
MOVP R22, R23, 192(RSP)
MOVP R24, R25, 208(RSP)
MOV R30, 256(RSP) // link
MOV $(1<<32), R0 // type irq
_virqpatch:
B _virqpatch // branch to vtrapX() patched in
TEXT vfiq(SB), 1, $-4
SUB $TRAPFRAMESIZE, RSP
MOVP R0, R1, 16(RSP)
MOVP R2, R3, 32(RSP)
MOVP R4, R5, 48(RSP)
MOVP R6, R7, 64(RSP)
MOVP R8, R9, 80(RSP)
MOVP R10, R11, 96(RSP)
MOVP R12, R13, 112(RSP)
MOVP R14, R15, 128(RSP)
MOVP R16, R17, 144(RSP)
MOVP R18, R19, 160(RSP)
MOVP R20, R21, 176(RSP)
MOVP R22, R23, 192(RSP)
MOVP R24, R25, 208(RSP)
MOV R30, 256(RSP) // link
MOV $(2<<32), R0 // type fiq
_vfiqpatch:
B _vfiqpatch // branch to vtrapX() patched in
TEXT vserr(SB), 1, $-4
SUB $TRAPFRAMESIZE, RSP
MOVP R0, R1, 16(RSP)
MOVP R2, R3, 32(RSP)
MOVP R4, R5, 48(RSP)
MOVP R6, R7, 64(RSP)
MOVP R8, R9, 80(RSP)
MOVP R10, R11, 96(RSP)
MOVP R12, R13, 112(RSP)
MOVP R14, R15, 128(RSP)
MOVP R16, R17, 144(RSP)
MOVP R18, R19, 160(RSP)
MOVP R20, R21, 176(RSP)
MOVP R22, R23, 192(RSP)
MOVP R24, R25, 208(RSP)
MOV R30, 256(RSP) // link
MRS ESR_EL1, R0
ORR $(3<<32), R0 // type
_vserrpatch:
B _vserrpatch // branch to vtrapX() patched in
/* fault-proof memcpy */
TEXT peek(SB), 1, $-4
MOV R0, R1
MOV dst+8(FP), R2
MOVWU len+16(FP), R0
TEXT _peekinst(SB), 1, $-4
_peekloop:
MOVBU (R1)1!, R3
MOVBU R3, (R2)1!
SUBS $1, R0
BNE _peekloop
RETURN