1// ------------------------------------------------------------
2// v7-A Cache and Branch Prediction Maintenance Operations
3//
4// Copyright (c) 2011-2018 Arm Limited (or its affiliates). All rights reserved.
5// Use, modification and redistribution of this file is subject to your possession of a
6// valid End User License Agreement for the Arm Product of which these examples are part of
7// and your compliance with all applicable terms and conditions of such licence agreement.
8// ------------------------------------------------------------
9
10    .arm
11// ------------------------------------------------------------
12// Interrupt enable/disable
13// ------------------------------------------------------------
14
15  // Could use intrinsic instead of these
16
17    .global enableInterrupts
18    .type   enableInterrupts,function
19  // void enableInterrupts(void)//
20enableInterrupts:
21    CPSIE   i
22    BX      lr
23
24
25    .global disableInterrupts
26    .type   disableInterrupts,function
27  // void disableInterrupts(void)//
28disableInterrupts:
29    CPSID   i
30    BX      lr
31
32
33// ------------------------------------------------------------
34// Cache Maintenance
35// ------------------------------------------------------------
36
37    .global enableCaches
38    .type   enableCaches,function
39  // void enableCaches(void)//
40enableCaches:
41    MRC     p15, 0, r0, c1, c0, 0   // Read System Control Register
42    ORR     r0, r0, #(1 << 2)       // Set C bit
43    ORR     r0, r0, #(1 << 12)      // Set I bit
44    MCR     p15, 0, r0, c1, c0, 0   // Write System Control Register
45    ISB
46    BX      lr
47
48
49
50    .global disableCaches
51    .type   disableCaches,function
52  // void disableCaches(void)
53disableCaches:
54    MRC     p15, 0, r0, c1, c0, 0   // Read System Control Register
55    BIC     r0, r0, #(1 << 2)       // Clear C bit
56    BIC     r0, r0, #(1 << 12)      // Clear I bit
57    MCR     p15, 0, r0, c1, c0, 0   // Write System Control Register
58    ISB
59    BX      lr
60
61
62
63    .global cleanDCache
64    .type   cleanDCache,function
65  // void cleanDCache(void)//
66cleanDCache:
67    PUSH    {r4-r12}
68
69    //
70    // Based on code example given in section 11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B)
71    //
72
73    MRC     p15, 1, r0, c0, c0, 1     // Read CLIDR
74    ANDS    r3, r0, #0x7000000
75    MOV     r3, r3, LSR #23           // Cache level value (naturally aligned)
76    BEQ     clean_dcache_finished
77    MOV     r10, #0
78
79clean_dcache_loop1:
80    ADD     r2, r10, r10, LSR #1      // Work out 3xcachelevel
81    MOV     r1, r0, LSR r2            // bottom 3 bits are the Cache type for this level
82    AND     r1, r1, #7                // get those 3 bits alone
83    CMP     r1, #2
84    BLT     clean_dcache_skip         // no cache or only instruction cache at this level
85    MCR     p15, 2, r10, c0, c0, 0    // write the Cache Size selection register
86    ISB                               // ISB to sync the change to the CacheSizeID reg
87    MRC     p15, 1, r1, c0, c0, 0     // reads current Cache Size ID register
88    AND     r2, r1, #7                // extract the line length field
89    ADD     r2, r2, #4                // add 4 for the line length offset (log2 16 bytes)
90    LDR     r4, =0x3FF
91    ANDS    r4, r4, r1, LSR #3        // R4 is the max number on the way size (right aligned)
92    CLZ     r5, r4                    // R5 is the bit position of the way size increment
93    LDR     r7, =0x00007FFF
94    ANDS    r7, r7, r1, LSR #13       // R7 is the max number of the index size (right aligned)
95
96clean_dcache_loop2:
97    MOV     r9, R4                    // R9 working copy of the max way size (right aligned)
98
99clean_dcache_loop3:
100    ORR     r11, r10, r9, LSL r5      // factor in the way number and cache number into R11
101    ORR     r11, r11, r7, LSL r2      // factor in the index number
102    MCR     p15, 0, r11, c7, c10, 2   // DCCSW - clean by set/way
103    SUBS    r9, r9, #1                // decrement the way number
104    BGE     clean_dcache_loop3
105    SUBS    r7, r7, #1                // decrement the index
106    BGE     clean_dcache_loop2
107
108clean_dcache_skip:
109    ADD     r10, r10, #2              // increment the cache number
110    CMP     r3, r10
111    BGT     clean_dcache_loop1
112
113clean_dcache_finished:
114    POP     {r4-r12}
115
116    BX      lr
117
118
119    .global cleanInvalidateDCache
120    .type   cleanInvalidateDCache,function
121  // void cleanInvalidateDCache(void)//
122cleanInvalidateDCache:
123    PUSH    {r4-r12}
124
125    //
126    // Based on code example given in section 11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B)
127    //
128
129    MRC     p15, 1, r0, c0, c0, 1     // Read CLIDR
130    ANDS    r3, r0, #0x7000000
131    MOV     r3, r3, LSR #23           // Cache level value (naturally aligned)
132    BEQ     clean_invalidate_dcache_finished
133    MOV     r10, #0
134
135clean_invalidate_dcache_loop1:
136    ADD     r2, r10, r10, LSR #1      // Work out 3xcachelevel
137    MOV     r1, r0, LSR r2            // bottom 3 bits are the Cache type for this level
138    AND     r1, r1, #7                // get those 3 bits alone
139    CMP     r1, #2
140    BLT     clean_invalidate_dcache_skip // no cache or only instruction cache at this level
141    MCR     p15, 2, r10, c0, c0, 0    // write the Cache Size selection register
142    ISB                               // ISB to sync the change to the CacheSizeID reg
143    MRC     p15, 1, r1, c0, c0, 0     // reads current Cache Size ID register
144    AND     r2, r1, #7                // extract the line length field
145    ADD     r2, r2, #4                // add 4 for the line length offset (log2 16 bytes)
146    LDR     r4, =0x3FF
147    ANDS    r4, r4, r1, LSR #3        // R4 is the max number on the way size (right aligned)
148    CLZ     r5, r4                    // R5 is the bit position of the way size increment
149    LDR     r7, =0x00007FFF
150    ANDS    r7, r7, r1, LSR #13       // R7 is the max number of the index size (right aligned)
151
152clean_invalidate_dcache_loop2:
153    MOV     r9, R4                    // R9 working copy of the max way size (right aligned)
154
155clean_invalidate_dcache_loop3:
156    ORR     r11, r10, r9, LSL r5      // factor in the way number and cache number into R11
157    ORR     r11, r11, r7, LSL r2      // factor in the index number
158    MCR     p15, 0, r11, c7, c14, 2   // DCCISW - clean and invalidate by set/way
159    SUBS    r9, r9, #1                // decrement the way number
160    BGE     clean_invalidate_dcache_loop3
161    SUBS    r7, r7, #1                // decrement the index
162    BGE     clean_invalidate_dcache_loop2
163
164clean_invalidate_dcache_skip:
165    ADD     r10, r10, #2              // increment the cache number
166    CMP     r3, r10
167    BGT     clean_invalidate_dcache_loop1
168
169clean_invalidate_dcache_finished:
170    POP     {r4-r12}
171
172    BX      lr
173
174
175
176    .global invalidateCaches
177    .type   invalidateCaches,function
178  // void invalidateCaches(void)//
179invalidateCaches:
180    PUSH    {r4-r12}
181
182    //
183    // Based on code example given in section B2.2.4/11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B)
184    //
185
186    MOV     r0, #0
187    MCR     p15, 0, r0, c7, c5, 0     // ICIALLU - Invalidate entire I Cache, and flushes branch target cache
188
189    MRC     p15, 1, r0, c0, c0, 1     // Read CLIDR
190    ANDS    r3, r0, #0x7000000
191    MOV     r3, r3, LSR #23           // Cache level value (naturally aligned)
192    BEQ     invalidate_caches_finished
193    MOV     r10, #0
194
195invalidate_caches_loop1:
196    ADD     r2, r10, r10, LSR #1      // Work out 3xcachelevel
197    MOV     r1, r0, LSR r2            // bottom 3 bits are the Cache type for this level
198    AND     r1, r1, #7                // get those 3 bits alone
199    CMP     r1, #2
200    BLT     invalidate_caches_skip    // no cache or only instruction cache at this level
201    MCR     p15, 2, r10, c0, c0, 0    // write the Cache Size selection register
202    ISB                               // ISB to sync the change to the CacheSizeID reg
203    MRC     p15, 1, r1, c0, c0, 0     // reads current Cache Size ID register
204    AND     r2, r1, #7                // extract the line length field
205    ADD     r2, r2, #4                // add 4 for the line length offset (log2 16 bytes)
206    LDR     r4, =0x3FF
207    ANDS    r4, r4, r1, LSR #3        // R4 is the max number on the way size (right aligned)
208    CLZ     r5, r4                    // R5 is the bit position of the way size increment
209    LDR     r7, =0x00007FFF
210    ANDS    r7, r7, r1, LSR #13       // R7 is the max number of the index size (right aligned)
211
212invalidate_caches_loop2:
213    MOV     r9, R4                    // R9 working copy of the max way size (right aligned)
214
215invalidate_caches_loop3:
216    ORR     r11, r10, r9, LSL r5      // factor in the way number and cache number into R11
217    ORR     r11, r11, r7, LSL r2      // factor in the index number
218    MCR     p15, 0, r11, c7, c6, 2    // DCISW - invalidate by set/way
219    SUBS    r9, r9, #1                // decrement the way number
220    BGE     invalidate_caches_loop3
221    SUBS    r7, r7, #1                // decrement the index
222    BGE     invalidate_caches_loop2
223
224invalidate_caches_skip:
225    ADD     r10, r10, #2              // increment the cache number
226    CMP     r3, r10
227    BGT     invalidate_caches_loop1
228
229invalidate_caches_finished:
230    POP     {r4-r12}
231    BX      lr
232
233
234
235    .global invalidateCaches_IS
236    .type   invalidateCaches_IS,function
237  // void invalidateCaches_IS(void)//
238invalidateCaches_IS:
239    PUSH    {r4-r12}
240
241    MOV     r0, #0
242    MCR     p15, 0, r0, c7, c1, 0     // ICIALLUIS - Invalidate entire I Cache inner shareable
243
244    MRC     p15, 1, r0, c0, c0, 1     // Read CLIDR
245    ANDS    r3, r0, #0x7000000
246    MOV     r3, r3, LSR #23           // Cache level value (naturally aligned)
247    BEQ     invalidate_caches_is_finished
248    MOV     r10, #0
249
250invalidate_caches_is_loop1:
251    ADD     r2, r10, r10, LSR #1      // Work out 3xcachelevel
252    MOV     r1, r0, LSR r2            // bottom 3 bits are the Cache type for this level
253    AND     r1, r1, #7                // get those 3 bits alone
254    CMP     r1, #2
255    BLT     invalidate_caches_is_skip // no cache or only instruction cache at this level
256    MCR     p15, 2, r10, c0, c0, 0    // write the Cache Size selection register
257    ISB                               // ISB to sync the change to the CacheSizeID reg
258    MRC     p15, 1, r1, c0, c0, 0     // reads current Cache Size ID register
259    AND     r2, r1, #7                // extract the line length field
260    ADD     r2, r2, #4                // add 4 for the line length offset (log2 16 bytes)
261    LDR     r4, =0x3FF
262    ANDS    r4, r4, r1, LSR #3        // R4 is the max number on the way size (right aligned)
263    CLZ     r5, r4                    // R5 is the bit position of the way size increment
264    LDR     r7, =0x00007FFF
265    ANDS    r7, r7, r1, LSR #13       // R7 is the max number of the index size (right aligned)
266
267invalidate_caches_is_loop2:
268    MOV     r9, R4                    // R9 working copy of the max way size (right aligned)
269
270invalidate_caches_is_loop3:
271    ORR     r11, r10, r9, LSL r5      // factor in the way number and cache number into R11
272    ORR     r11, r11, r7, LSL r2      // factor in the index number
273    MCR     p15, 0, r11, c7, c6, 2    // DCISW - clean by set/way
274    SUBS    r9, r9, #1                // decrement the way number
275    BGE     invalidate_caches_is_loop3
276    SUBS    r7, r7, #1                // decrement the index
277    BGE     invalidate_caches_is_loop2
278
279invalidate_caches_is_skip:
280    ADD     r10, r10, #2              // increment the cache number
281    CMP     r3, r10
282    BGT     invalidate_caches_is_loop1
283
284invalidate_caches_is_finished:
285    POP     {r4-r12}
286    BX      lr
287
288
289// ------------------------------------------------------------
290// TLB
291// ------------------------------------------------------------
292
293    .global invalidateUnifiedTLB
294    .type   invalidateUnifiedTLB,function
295  // void invalidateUnifiedTLB(void)//
296invalidateUnifiedTLB:
297    MOV     r0, #0
298    MCR     p15, 0, r0, c8, c7, 0                 // TLBIALL - Invalidate entire unified TLB
299    BX      lr
300
301
302    .global invalidateUnifiedTLB_IS
303    .type   invalidateUnifiedTLB_IS,function
304  // void invalidateUnifiedTLB_IS(void)//
305invalidateUnifiedTLB_IS:
306    MOV     r0, #1
307    MCR     p15, 0, r0, c8, c3, 0                 // TLBIALLIS - Invalidate entire unified TLB Inner Shareable
308    BX      lr
309
310
311// ------------------------------------------------------------
312// Branch Prediction
313// ------------------------------------------------------------
314
315    .global flushBranchTargetCache
316    .type   flushBranchTargetCache,function
317  // void flushBranchTargetCache(void)
318flushBranchTargetCache:
319  MOV     r0, #0
320  MCR     p15, 0, r0, c7, c5, 6                 // BPIALL - Invalidate entire branch predictor array
321  BX      lr
322
323
324    .global flushBranchTargetCache_IS
325    .type   flushBranchTargetCache_IS,function
326  // void flushBranchTargetCache_IS(void)
327flushBranchTargetCache_IS:
328  MOV     r0, #0
329  MCR     p15, 0, r0, c7, c1, 6                 // BPIALLIS - Invalidate entire branch predictor array Inner Shareable
330  BX      lr
331
332
333// ------------------------------------------------------------
334// High Vecs
335// ------------------------------------------------------------
336
337    .global enableHighVecs
338    .type   enableHighVecs,function
339  // void enableHighVecs(void)//
340enableHighVecs:
341  MRC     p15, 0, r0, c1, c0, 0 // Read Control Register
342  ORR     r0, r0, #(1 << 13)    // Set the V bit (bit 13)
343  MCR     p15, 0, r0, c1, c0, 0 // Write Control Register
344  ISB
345  BX      lr
346
347
348    .global disableHighVecs
349    .type   disableHighVecs,function
350  // void disable_highvecs(void)//
351disableHighVecs:
352  MRC     p15, 0, r0, c1, c0, 0 // Read Control Register
353  BIC     r0, r0, #(1 << 13)    // Clear the V bit (bit 13)
354  MCR     p15, 0, r0, c1, c0, 0 // Write Control Register
355  ISB
356  BX      lr
357
358
359// ------------------------------------------------------------
360// Context ID
361// ------------------------------------------------------------
362
363    .global getContextID
364    .type   getContextID,function
365  // uint32_t getContextIDd(void)//
366getContextID:
367  MRC     p15, 0, r0, c13, c0, 1 // Read Context ID Register
368  BX      lr
369
370
371    .global setContextID
372    .type   setContextID,function
373  // void setContextID(uint32_t)//
374setContextID:
375  MCR     p15, 0, r0, c13, c0, 1 // Write Context ID Register
376  BX      lr
377
378
379// ------------------------------------------------------------
380// ID registers
381// ------------------------------------------------------------
382
383    .global getMIDR
384    .type   getMIDR,function
385  // uint32_t getMIDR(void)//
386getMIDR:
387  MRC     p15, 0, r0, c0, c0, 0 // Read Main ID Register (MIDR)
388  BX      lr
389
390
391    .global getMPIDR
392    .type   getMPIDR,function
393  // uint32_t getMPIDR(void)//
394getMPIDR:
395  MRC     p15, 0, r0, c0 ,c0, 5// Read Multiprocessor ID register (MPIDR)
396  BX      lr
397
398
399// ------------------------------------------------------------
400// CP15 SMP related
401// ------------------------------------------------------------
402
403    .global getBaseAddr
404    .type   getBaseAddr,function
405  // uint32_t getBaseAddr(void)
406  // Returns the value CBAR (base address of the private peripheral memory space)
407getBaseAddr:
408  MRC     p15, 4, r0, c15, c0, 0  // Read peripheral base address
409  BX      lr
410
411
412// ------------------------------------------------------------
413
414    .global getCPUID
415    .type   getCPUID,function
416  // uint32_t getCPUID(void)
417  // Returns the CPU ID (0 to 3) of the CPU executed on
418getCPUID:
419  MRC     p15, 0, r0, c0, c0, 5   // Read CPU ID register
420  AND     r0, r0, #0x03           // Mask off, leaving the CPU ID field
421  BX      lr
422
423
424// ------------------------------------------------------------
425
426    .global goToSleep
427    .type   goToSleep,function
428  // void goToSleep(void)
429goToSleep:
430  DSB                             // Clear all pending data accesses
431  WFI                             // Go into standby
432  B       goToSleep               // Catch in case of rogue events
433  BX      lr
434
435
436// ------------------------------------------------------------
437
438    .global joinSMP
439    .type   joinSMP,function
440    // void joinSMP(void)
441    // Sets the ACTRL.SMP bit
442joinSMP:
443
444    // SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
445
446    MRC     p15, 0, r0, c1, c0, 1   // Read ACTLR
447    MOV     r1, r0
448    ORR     r0, r0, #0x040          // Set bit 6
449    CMP     r0, r1
450    MCRNE   p15, 0, r0, c1, c0, 1   // Write ACTLR
451    ISB
452
453    BX      lr
454
455
456// ------------------------------------------------------------
457
458    .global leaveSMP
459    .type   leaveSMP,function
460    // void leaveSMP(void)
461    // Clear the ACTRL.SMP bit
462leaveSMP:
463
464    // SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
465
466    MRC     p15, 0, r0, c1, c0, 1   // Read ACTLR
467    BIC     r0, r0, #0x040          // Clear bit 6
468    MCR     p15, 0, r0, c1, c0, 1   // Write ACTLR
469    ISB
470
471    BX      lr
472
473
474// ------------------------------------------------------------
475// End of v7.s
476// ------------------------------------------------------------
477