restore pi2 to compiling. i don't have one, so testing will have to wait. Reference: /n/atom/patch/applied/pi2compile Date: Sun Jan 3 20:00:15 CET 2016 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/bcm/main.c Sun Jan 3 20:00:01 2016 +++ /sys/src/9/bcm/main.c Sun Jan 3 20:00:02 2016 @@ -194,6 +194,36 @@ } } +/* enable scheduling of this cpu */ +void +machon(uint cpu) +{ + ulong cpubit; + + cpubit = 1 << cpu; + lock(&active); + if ((active.machs & cpubit) == 0) { /* currently off? */ + conf.nmach++; + active.machs |= cpubit; + } + unlock(&active); +} + +/* disable scheduling of this cpu */ +void +machoff(uint cpu) +{ + ulong cpubit; + + cpubit = 1 << cpu; + lock(&active); + if (active.machs & cpubit) { /* currently on? */ + conf.nmach--; + active.machs &= ~cpubit; + } + unlock(&active); +} + void machinit(void) { --- /sys/src/9/bcm/armv7.s Sun Jan 3 20:00:04 2016 +++ /sys/src/9/bcm/armv7.s Sun Jan 3 20:00:05 2016 @@ -4,11 +4,25 @@ */ #include "arm.s" + #define CACHELINESZ 64 +#define DMB WORD $0xf57ff05f /* data mem. barrier; last f = SY */ +#define WFI WORD $0xe320f003 /* wait for interrupt */ +#define WFI_EQ WORD $0x0320f003 /* wait for interrupt if eq */ + +/* tas/cas strex debugging limits; started at 10000 */ +#define MAXSC 100000 + TEXT armstart(SB), 1, $-4 /* + * if not cpu0, go to secondary startup + */ + CPUID(R1) + BNE reset + + /* * disable the mmu and caches * invalidate tlb */ @@ -36,6 +50,7 @@ * set up page tables for kernel */ MOVW $PADDR(MACHADDR+MACHSIZE-4), R13 + MOVW $PADDR(L1), R0 BL ,mmuinit(SB) /* @@ -44,8 +59,17 @@ MOVW $Client, R1 MCR CpSC, 0, R1, C(CpDAC), C(0) MOVW $PADDR(L1), R1 + ORR $(CpTTBs/*|CpTTBowba|CpTTBiwba*/), R1 MCR CpSC, 0, R1, C(CpTTB), C(0) - MCR CpSC, 0, R0, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + + /* + * invalidate my caches before enabling + */ + BL cachedinv(SB) + BL cacheiinv(SB) + BL l2cacheuinv(SB) + BARRIERS /* * enable caches, mmu, and high vectors @@ -85,6 +109,122 @@ BL _div(SB) /* hack to load _div, etc. */ +/* + * startup entry for cpu(s) other than 0 + */ +TEXT cpureset(SB), 1, $-4 +reset: + /* + * load physical base for SB addressing while mmu is off + * keep a handy zero in R0 until first function call + */ + MOVW $setR12(SB), R12 + SUB $KZERO, R12 + ADD $PHYSDRAM, R12 + MOVW $0, R0 + + /* + * SVC mode, interrupts disabled + */ + MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 + MOVW R1, CPSR + + /* + * disable the mmu and caches + * invalidate tlb + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + BIC $(CpCdcache|CpCicache|CpCmmu), R1 + ORR $(CpCsbo|CpCsw), R1 + BIC $CpCsbz, R1 + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl + MCR CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv + ISB + + /* + * find Mach for this cpu + */ + MRC CpSC, 0, R2, C(CpID), C(CpIDidct), CpIDmpid + AND $(MAXMACH-1), R2 /* mask out non-cpu-id bits */ + SLL $2, R2 /* convert to word index */ + MOVW $machaddr(SB), R0 + ADD R2, R0 /* R0 = &machaddr[cpuid] */ + MOVW (R0), R0 /* R0 = machaddr[cpuid] */ + CMP $0, R0 + MOVW.EQ $MACHADDR, R0 /* paranoia: use MACHADDR if 0 */ + SUB $KZERO, R0 /* phys addr */ + MOVW R0, R(MACH) /* m = PADDR(machaddr[cpuid]) */ + + /* + * start stack at top of local Mach + */ + MOVW R(MACH), R13 + ADD $(MACHSIZE-4), R13 + + /* + * set up page tables for kernel + */ + MOVW 12(R(MACH)), R0 /* m->mmul1 */ + SUB $KZERO, R0 /* phys addr */ + BL ,mmuinit(SB) + + /* + * set up domain access control and page table base + */ + MOVW $Client, R1 + MCR CpSC, 0, R1, C(CpDAC), C(0) + MOVW 12(R(MACH)), R1 /* m->mmul1 */ + SUB $KZERO, R1 /* phys addr */ + ORR $(CpTTBs/*|CpTTBowba|CpTTBiwba*/), R1 + MCR CpSC, 0, R1, C(CpTTB), C(0) + MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1 /* cortex has two */ + + /* + * invalidate my caches before enabling + */ + BL cachedinv(SB) + BL cacheiinv(SB) + BARRIERS + + /* + * enable caches, mmu, and high vectors + */ + MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + ORR $CpACsmp, R1 /* turn SMP on */ + MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl + BARRIERS + + MRC CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + ORR $(CpChv|CpCdcache|CpCicache|CpCmmu), R0 + MCR CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl + BARRIERS + + /* + * switch MACH, SB, SP, and PC into KZERO space + */ + ADD $KZERO, R(MACH) + MOVW $setR12(SB), R12 + ADD $KZERO, R13 + MOVW $_startpg2(SB), R15 + +TEXT _startpg2(SB), 1, $-4 + + /* + * enable cycle counter + */ + MOVW $(1<<31), R1 + MCR CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc + MOVW $1, R1 + MCR CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc + + /* + * call cpustart and loop forever if it returns + */ + MRC CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDmpid + AND $(MAXMACH-1), R0 /* mask out non-cpu-id bits */ + BL ,cpustart(SB) + B ,0(PC) + TEXT cpidget(SB), 1, $-4 /* main ID */ MRC CpSC, 0, R0, C(CpID), C(0), CpIDid RET @@ -101,10 +241,19 @@ MRC CpSC, 0, R0, C(CpFAR), C(0x0) RET +TEXT cpctget(SB), 1, $-4 /* cache type */ + MRC CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDct + RET + TEXT lcycles(SB), 1, $-4 MRC CpSC, 0, R0, C(CpCLD), C(CpCLDcyc), 0 RET +TEXT tmrget(SB), 1, $-4 /* local generic timer physical counter value */ + MRRC(CpSC, 0, 1, 2, CpTIMER) + MOVM.IA [R1-R2], (R0) + RET + TEXT splhi(SB), 1, $-4 MOVW $(MACHADDR+4), R2 /* save caller pc in Mach */ MOVW R14, 0(R2) @@ -154,10 +303,30 @@ RET TEXT tas(SB), $-4 -TEXT _tas(SB), $-4 - MOVW R0,R1 - MOVW $1,R0 - SWPW R0,(R1) /* fix: deprecated in armv6 */ +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: + BL abort(SB) +lockbusy: + CLREX +tas0: + MOVW R7, R0 /* return old value */ RET TEXT setlabel(SB), 1, $-4 @@ -177,14 +346,17 @@ RET TEXT idlehands(SB), $-4 - BARRIERS MOVW CPSR, R3 - BIC $(PsrDirq|PsrDfiq), R3, R1 /* spllo */ + ORR $(PsrDirq|PsrDfiq), R3, R1 /* splfhi */ MOVW R1, CPSR - MOVW $0, R0 /* wait for interrupt */ - MCR CpSC, 0, R0, C(CpCACHE), C(CpCACHEintr), CpCACHEwait - ISB + DSB + MOVW nrdy(SB), R0 + CMP $0, R0 +/*** with WFI, local timer interrupts can be lost and dispatching stops + WFI_EQ +***/ + DSB MOVW R3, CPSR /* splx */ RET