]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm/armv7.s
kernel: get rid of KSTKSIZE alias for KSTACK
[plan9front.git] / sys / src / 9 / bcm / armv7.s
1 /*
2  * Broadcom bcm2836 SoC, as used in Raspberry Pi 2
3  * 4 x Cortex-A7 processor (armv7)
4  */
5
6 #include "arm.s"
7
8 #define CACHELINESZ     64
9 #define ICACHELINESZ    32
10
11 #undef DSB
12 #undef DMB
13 #undef ISB
14 #define DSB     WORD    $0xf57ff04f     /* data synch. barrier; last f = SY */
15 #define DMB     WORD    $0xf57ff05f     /* data mem. barrier; last f = SY */
16 #define ISB     WORD    $0xf57ff06f     /* instr. sync. barrier; last f = SY */
17 #define WFI     WORD    $0xe320f003     /* wait for interrupt */
18 #define WFI_EQ  WORD    $0x0320f003     /* wait for interrupt if eq */
19 #define ERET    WORD    $0xe160006e     /* exception return from HYP */
20 #define SEV     WORD    $0xe320f004     /* send event */
21
22 /* tas/cas strex debugging limits; started at 10000 */
23 #define MAXSC 1000000
24
25 TEXT armstart(SB), 1, $-4
26
27         /*
28          * if not cpu0, go to secondary startup
29          */
30         CPUID(R1)
31         BNE     reset
32
33         /*
34          * go to SVC mode, interrupts disabled
35          */
36         BL      svcmode(SB)
37
38         /*
39          * disable the mmu and caches
40          */
41         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
42         BIC     $(CpCdcache|CpCicache|CpCmmu), R1
43         ORR     $(CpCsbo|CpCsw), R1
44         BIC     $CpCsbz, R1
45         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
46         BARRIERS
47
48         /*
49          * turn SMP off
50          */
51         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
52         BIC     $CpACsmp, R1
53         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
54         BARRIERS
55
56         /*
57          * clear mach and page tables
58          */
59         MOVW    $PADDR(MACHADDR), R1
60         MOVW    $PADDR(KTZERO), R2
61         MOVW    $0, R0
62 _ramZ:
63         MOVW    R0, (R1)
64         ADD     $4, R1
65         CMP     R1, R2
66         BNE     _ramZ   
67
68         /*
69          * start stack at top of mach (physical addr)
70          * set up page tables for kernel
71          */
72         MOVW    $PADDR(MACHADDR+MACHSIZE-4), R13
73
74         MOVW    $PADDR(L1), R0
75         BL      mmuinit(SB)
76         BL      mmuinvalidate(SB)
77
78         /*
79          * set up domain access control and page table base
80          */
81         MOVW    $Client, R1
82         MCR     CpSC, 0, R1, C(CpDAC), C(0)
83         MOVW    $PADDR(L1), R1
84         ORR     $(CpTTBs|CpTTBowba|CpTTBiwba), R1
85         MCR     CpSC, 0, R1, C(CpTTB), C(0)
86         MCR     CpSC, 0, R1, C(CpTTB), C(0), CpTTB1     /* cortex has two */
87
88         /*
89          * invalidate my caches before enabling
90          */
91         BL      cachedinv(SB)
92         BL      cacheiinv(SB)
93         BL      l2cacheuinv(SB)
94         BARRIERS
95
96         /*
97          * turn SMP on
98          */
99         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
100         ORR     $CpACsmp, R1
101         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
102         BARRIERS
103
104         /*
105          * enable caches, mmu, and high vectors
106          */
107         MRC     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
108         ORR     $(CpChv|CpCdcache|CpCicache|CpCmmu), R0
109         MCR     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
110         BARRIERS
111
112         /*
113          * switch SB, SP, and PC into KZERO space
114          */
115         MOVW    $setR12(SB), R12
116         MOVW    $(MACHADDR+MACHSIZE-4), R13
117         MOVW    $_startpg(SB), R15
118
119 TEXT _startpg(SB), 1, $-4
120
121         /*
122          * enable cycle counter
123          */
124         MOVW    $(1<<31), R1
125         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc
126         MOVW    $1, R1
127         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc
128
129         /*
130          * call main and loop forever if it returns
131          */
132         BL      ,main(SB)
133         B       ,0(PC)
134
135         BL      _div(SB)                /* hack to load _div, etc. */
136
137 /*
138  * startup entry for cpu(s) other than 0
139  */
140 TEXT cpureset(SB), 1, $-4
141 reset:
142         /*
143          * load physical base for SB addressing while mmu is off
144          */
145         MOVW    $setR12(SB), R12
146         SUB     $KZERO, R12
147         ADD     $PHYSDRAM, R12
148
149         /*
150          * SVC mode, interrupts disabled
151          */
152         BL      svcmode(SB)
153
154         /*
155          * disable the mmu and caches
156          */
157         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
158         BIC     $(CpCdcache|CpCicache|CpCmmu), R1
159         ORR     $(CpCsbo|CpCsw), R1
160         BIC     $CpCsbz, R1
161         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
162         BARRIERS
163
164         /*
165          * turn SMP off
166          */
167         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
168         BIC     $CpACsmp, R1
169         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
170         BARRIERS
171
172         /*
173          * find Mach for this cpu
174          */
175         MRC     CpSC, 0, R2, C(CpID), C(CpIDidct), CpIDmpid
176         AND     $(MAXMACH-1), R2        /* mask out non-cpu-id bits */
177         SLL     $2, R2                  /* convert to word index */
178         MOVW    $machaddr(SB), R0
179         BIC     $KSEGM, R0
180         ORR     $PHYSDRAM, R0
181         ADD     R2, R0                  /* R0 = &machaddr[cpuid] */
182         MOVW    (R0), R0                /* R0 = machaddr[cpuid] */
183         CMP     $0, R0
184         BEQ     0(PC)                   /* must not be zero */
185         SUB     $KZERO, R0, R(MACH)     /* m = PADDR(machaddr[cpuid]) */
186
187         /*
188          * start stack at top of local Mach
189          */
190         ADD     $(MACHSIZE-4), R(MACH), R13
191
192         BL      mmuinvalidate(SB)
193
194         /*
195          * set up domain access control and page table base
196          */
197         MOVW    $Client, R1
198         MCR     CpSC, 0, R1, C(CpDAC), C(0)
199         MOVW    12(R(MACH)), R1 /* m->mmul1 */
200         SUB     $KZERO, R1              /* phys addr */
201         ORR     $(CpTTBs|CpTTBowba|CpTTBiwba), R1
202         MCR     CpSC, 0, R1, C(CpTTB), C(0)
203         MCR     CpSC, 0, R1, C(CpTTB), C(0), CpTTB1     /* cortex has two */
204
205         /*
206          * invalidate my caches before enabling
207          */
208         BL      cachedinv(SB)
209         BL      cacheiinv(SB)
210         BARRIERS
211
212         /*
213          * turn SMP on
214          */
215         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
216         ORR     $CpACsmp, R1
217         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
218         BARRIERS
219
220         /*
221          * enable caches, mmu, and high vectors
222          */
223         MRC     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
224         ORR     $(CpChv|CpCdcache|CpCicache|CpCmmu), R0
225         MCR     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
226         BARRIERS
227
228         /*
229          * switch MACH, SB, SP, and PC into KZERO space
230          */
231         ADD     $KZERO, R(MACH)
232         MOVW    $setR12(SB), R12
233         ADD     $KZERO, R13
234         MOVW    $_startpg2(SB), R15
235
236 TEXT _startpg2(SB), 1, $-4
237
238         /*
239          * enable cycle counter
240          */
241         MOVW    $(1<<31), R1
242         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc
243         MOVW    $1, R1
244         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc
245
246         /*
247          * call cpustart and loop forever if it returns
248          */
249         MRC     CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDmpid
250         AND     $(MAXMACH-1), R0                /* mask out non-cpu-id bits */
251         BL      ,cpustart(SB)
252         B       ,0(PC)
253
254 /*
255  * get into SVC mode with interrupts disabled
256  * raspberry pi firmware since 29 Sept 2015 starts in HYP mode
257  */
258 TEXT svcmode(SB), 1, $-4
259         MOVW    CPSR, R1
260         AND     $PsrMask, R1
261         MOVW    $PsrMhyp, R2
262         CMP     R2, R1
263         MOVW    $(PsrDirq|PsrDfiq|PsrMsvc), R1
264         BNE     nothyp
265         MSR(1, 1, 1, 0xe)       /* MOVW R1, SPSR_HYP */
266         MSR(0, 14, 1, 0xe)      /* MOVW R14, ELR_HYP */
267         ERET
268 nothyp:
269         MOVW    R1, CPSR
270         RET
271
272 TEXT cpidget(SB), 1, $-4                        /* main ID */
273         MRC     CpSC, 0, R0, C(CpID), C(0), CpIDid
274         RET
275
276 TEXT fsrget(SB), 1, $-4                         /* data fault status */
277         MRC     CpSC, 0, R0, C(CpFSR), C(0), CpFSRdata
278         RET
279
280 TEXT ifsrget(SB), 1, $-4                        /* instruction fault status */
281         MRC     CpSC, 0, R0, C(CpFSR), C(0), CpFSRinst
282         RET
283
284 TEXT farget(SB), 1, $-4                         /* fault address */
285         MRC     CpSC, 0, R0, C(CpFAR), C(0x0)
286         RET
287
288 TEXT cpctget(SB), 1, $-4                        /* cache type */
289         MRC     CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDct
290         RET
291
292 TEXT lcycles(SB), 1, $-4
293         MRC     CpSC, 0, R0, C(CpCLD), C(CpCLDcyc), 0
294         RET
295
296 TEXT splhi(SB), 1, $-4
297         MOVW    R14, 4(R(MACH))         /* save caller pc in m->splpc */
298
299         MOVW    CPSR, R0                        /* turn off irqs (but not fiqs) */
300         ORR     $(PsrDirq), R0, R1
301         MOVW    R1, CPSR
302         RET
303
304 TEXT splfhi(SB), 1, $-4
305         MOVW    R14, 4(R(MACH))         /* save caller pc in m->splpc */
306
307         MOVW    CPSR, R0                        /* turn off irqs and fiqs */
308         ORR     $(PsrDirq|PsrDfiq), R0, R1
309         MOVW    R1, CPSR
310         RET
311
312 TEXT splflo(SB), 1, $-4
313         MOVW    CPSR, R0                        /* turn on fiqs */
314         BIC     $(PsrDfiq), R0, R1
315         MOVW    R1, CPSR
316         RET
317
318 TEXT spllo(SB), 1, $-4
319         MOVW    CPSR, R0                        /* turn on irqs and fiqs */
320         MOVW    $0, R1
321         CMP.S   R1, R(MACH)
322         MOVW.NE R1, 4(R(MACH))                  /* clear m->splpc */
323         BIC     $(PsrDirq|PsrDfiq), R0, R1
324         MOVW    R1, CPSR
325         RET
326
327 TEXT splx(SB), 1, $-4
328         MOVW    R14, 4(R(MACH))         /* save caller pc in m->splpc */
329
330         MOVW    R0, R1                          /* reset interrupt level */
331         MOVW    CPSR, R0
332         MOVW    R1, CPSR
333         RET
334
335 TEXT spldone(SB), 1, $0                         /* end marker for devkprof.c */
336         RET
337
338 TEXT islo(SB), 1, $-4
339         MOVW    CPSR, R0
340         AND     $(PsrDirq), R0
341         EOR     $(PsrDirq), R0
342         RET
343
344 TEXT cas(SB), $0
345 TEXT cmpswap(SB), $0
346         MOVW    ov+4(FP), R1
347         MOVW    nv+8(FP), R2
348 spincas:
349         LDREX   (R0), R3
350         CMP.S   R3, R1
351         BNE     fail
352         STREX   R2, (R0), R4
353         CMP.S   $0, R4
354         BNE     spincas
355         MOVW    $1, R0
356         DMB
357         RET
358 fail:
359         CLREX
360         MOVW    $0, R0
361         RET
362
363 TEXT    tas(SB), $-4
364 TEXT    _tas(SB), $-4                   /* _tas(ulong *) */
365         /* returns old (R0) after modifying (R0) */
366         MOVW    R0,R5
367         DMB
368
369         MOVW    $1,R2           /* new value of (R0) */
370         MOVW    $MAXSC, R8
371 tas1:
372         LDREX (R5), R7
373         CMP.S   $0, R7          /* old value non-zero (lock taken)? */
374         BNE     lockbusy        /* we lose */
375         SUB.S   $1, R8
376         BEQ     lockloop2
377         STREX R2,(R5),R4
378         CMP.S   $0, R4
379         BNE     tas1            /* strex failed? try again */
380         DMB
381         B       tas0
382 lockloop2:
383         BL      abort(SB)
384 lockbusy:
385         CLREX
386 tas0:
387         MOVW    R7, R0          /* return old value */
388         RET
389
390 TEXT setlabel(SB), 1, $-4
391         MOVW    R13, 0(R0)              /* sp */
392         MOVW    R14, 4(R0)              /* pc */
393         MOVW    $0, R0
394         RET
395
396 TEXT gotolabel(SB), 1, $-4
397         MOVW    0(R0), R13              /* sp */
398         MOVW    4(R0), R14              /* pc */
399         MOVW    $1, R0
400         RET
401
402 TEXT getcallerpc(SB), 1, $-4
403         MOVW    0(R13), R0
404         RET
405
406 TEXT idlehands(SB), $-4
407         MOVW    CPSR, R3
408         ORR     $(PsrDirq|PsrDfiq), R3, R1              /* splfhi */
409         MOVW    R1, CPSR
410
411         DSB
412         MOVW    nrdy(SB), R0
413         CMP     $0, R0
414         WFI_EQ
415         DSB
416
417         MOVW    R3, CPSR                        /* splx */
418         RET
419
420
421 TEXT coherence(SB), $-4
422         BARRIERS
423         RET
424
425 TEXT sev(SB), $-4
426         SEV
427         RET
428
429 /*
430  * invalidate tlb
431  */
432 TEXT mmuinvalidate(SB), 1, $-4
433         DSB
434         MOVW    $0, R0
435         MCR     CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
436         BARRIERS
437         RET
438
439 /*
440  * mmuinvalidateaddr(va)
441  *   invalidate tlb entry for virtual page address va, ASID 0
442  */
443 TEXT mmuinvalidateaddr(SB), 1, $-4
444         DSB
445         MCR     CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
446         BARRIERS
447         RET
448
449 /*
450  * `single-element' cache operations.
451  * in arm arch v7, if effective to PoC, they operate on all cache levels, so separate
452  * l2 functions are unnecessary.
453  */
454
455 TEXT cachedwbse(SB), $-4                        /* D writeback SE */
456         MOVW    R0, R2
457
458         MOVW    CPSR, R3
459         CPSID                                   /* splhi */
460
461         BARRIERS                        /* force outstanding stores to cache */
462         MOVW    R2, R0
463         MOVW    4(FP), R1
464         ADD     R0, R1                          /* R1 is end address */
465         BIC     $(CACHELINESZ-1), R0            /* cache line start */
466 _dwbse:
467         MCR     CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
468         /* can't have a BARRIER here since it zeroes R0 */
469         ADD     $CACHELINESZ, R0
470         CMP.S   R0, R1
471         BGT     _dwbse
472         B       _wait
473
474 /*
475  * TLB on armv7 loads from cache, so no need for writeback
476  */
477 TEXT cachedwbtlb(SB), $-4
478         DSB
479         ISB
480         RET
481
482 TEXT cachedwbinvse(SB), $-4                     /* D writeback+invalidate SE */
483         MOVW    R0, R2
484
485         MOVW    CPSR, R3
486         CPSID                                   /* splhi */
487
488         BARRIERS                        /* force outstanding stores to cache */
489         MOVW    R2, R0
490         MOVW    4(FP), R1
491         ADD     R0, R1                          /* R1 is end address */
492         BIC     $(CACHELINESZ-1), R0            /* cache line start */
493 _dwbinvse:
494         MCR     CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
495         /* can't have a BARRIER here since it zeroes R0 */
496         ADD     $CACHELINESZ, R0
497         CMP.S   R0, R1
498         BGT     _dwbinvse
499 _wait:                                          /* drain write buffer */
500         BARRIERS
501
502         MOVW    R3, CPSR                        /* splx */
503         RET
504
505 TEXT cachedinvse(SB), $-4                       /* D invalidate SE */
506         MOVW    R0, R2
507
508         MOVW    CPSR, R3
509         CPSID                                   /* splhi */
510
511         BARRIERS                        /* force outstanding stores to cache */
512         MOVW    R2, R0
513         MOVW    4(FP), R1
514         ADD     R0, R1                          /* R1 is end address */
515         BIC     $(CACHELINESZ-1), R0            /* cache line start */
516 _dinvse:
517         MCR     CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
518         /* can't have a BARRIER here since it zeroes R0 */
519         ADD     $CACHELINESZ, R0
520         CMP.S   R0, R1
521         BGT     _dinvse
522         B       _wait
523
524 #include "cache.v7.s"