hc
2023-08-30 862c27fc9920c83318c784bfdadf43a65df1ec8f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#include <config.h>
#include <linux/linkage.h>
#include <linux/sizes.h>
#include <asm/system.h>
 
#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
#define ARM(x...)
#define THUMB(x...)    x
#else
#define ARM(x...)    x
#define THUMB(x...)
#endif
 
/*
 *    v7_flush_dcache_all()
 *
 *    Flush the whole D-cache.
 *
 *    Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
 *
 *    Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
 */
ENTRY(__v7_flush_dcache_all)
   dmb                    @ ensure ordering with previous memory accesses
   mrc    p15, 1, r0, c0, c0, 1        @ read clidr
   mov    r3, r0, lsr #23            @ move LoC into position
   ands    r3, r3, #7 << 1            @ extract LoC*2 from clidr
   beq    finished            @ if loc is 0, then no need to clean
start_flush_levels:
   mov    r10, #0                @ start clean at cache level 0
flush_levels:
   add    r2, r10, r10, lsr #1        @ work out 3x current cache level
   mov    r1, r0, lsr r2            @ extract cache type bits from clidr
   and    r1, r1, #7            @ mask of the bits for current cache only
   cmp    r1, #2                @ see what cache we have at this level
   blt    skip                @ skip if no cache, or just i-cache
   mcr    p15, 2, r10, c0, c0, 0        @ select current cache level in cssr
   isb                    @ isb to sych the new cssr&csidr
   mrc    p15, 1, r1, c0, c0, 0        @ read the new csidr
   and    r2, r1, #7            @ extract the length of the cache lines
   add    r2, r2, #4            @ add 4 (line length offset)
   movw    r4, #0x3ff
   ands    r4, r4, r1, lsr #3        @ find maximum number on the way size
   clz    r5, r4                @ find bit position of way size increment
   movw    r7, #0x7fff
   ands    r7, r7, r1, lsr #13        @ extract max number of the index size
loop1:
   mov    r9, r7                @ create working copy of max index
loop2:
 ARM(    orr    r11, r10, r4, lsl r5    )    @ factor way and cache number into r11
 THUMB(    lsl    r6, r4, r5        )
 THUMB(    orr    r11, r10, r6        )    @ factor way and cache number into r11
 ARM(    orr    r11, r11, r9, lsl r2    )    @ factor index number into r11
 THUMB(    lsl    r6, r9, r2        )
 THUMB(    orr    r11, r11, r6        )    @ factor index number into r11
   mcr    p15, 0, r11, c7, c14, 2        @ clean & invalidate by set/way
   subs    r9, r9, #1            @ decrement the index
   bge    loop2
   subs    r4, r4, #1            @ decrement the way
   bge    loop1
skip:
   add    r10, r10, #2            @ increment cache number
   cmp    r3, r10
   bgt    flush_levels
finished:
   mov    r10, #0                @ swith back to cache level 0
   mcr    p15, 2, r10, c0, c0, 0        @ select current cache level in cssr
   dsb    st
   isb
   bx    lr
ENDPROC(__v7_flush_dcache_all)
 
ENTRY(v7_flush_dcache_all)
 ARM(    stmfd    sp!, {r4-r5, r7, r9-r11, lr}    )
 THUMB(    stmfd    sp!, {r4-r7, r9-r11, lr}    )
   bl    __v7_flush_dcache_all
 ARM(    ldmfd    sp!, {r4-r5, r7, r9-r11, lr}    )
 THUMB(    ldmfd    sp!, {r4-r7, r9-r11, lr}    )
   bx    lr
ENDPROC(v7_flush_dcache_all)
 
/*
 *    v7_invalidate_dcache_all()
 *
 *    Invalidate the whole D-cache.
 *
 *    Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
 *
 *    Note: copied from __v7_flush_dcache_all above with
 *    mcr     p15, 0, r11, c7, c14, 2
 *    Replaced with:
 *    mcr     p15, 0, r11, c7, c6, 2
 */
ENTRY(__v7_invalidate_dcache_all)
   dmb                    @ ensure ordering with previous memory accesses
   mrc    p15, 1, r0, c0, c0, 1        @ read clidr
   mov    r3, r0, lsr #23            @ move LoC into position
   ands    r3, r3, #7 << 1            @ extract LoC*2 from clidr
   beq    inval_finished            @ if loc is 0, then no need to clean
   mov    r10, #0                @ start clean at cache level 0
inval_levels:
   add    r2, r10, r10, lsr #1        @ work out 3x current cache level
   mov    r1, r0, lsr r2            @ extract cache type bits from clidr
   and    r1, r1, #7            @ mask of the bits for current cache only
   cmp    r1, #2                @ see what cache we have at this level
   blt    inval_skip            @ skip if no cache, or just i-cache
   mcr    p15, 2, r10, c0, c0, 0        @ select current cache level in cssr
   isb                    @ isb to sych the new cssr&csidr
   mrc    p15, 1, r1, c0, c0, 0        @ read the new csidr
   and    r2, r1, #7            @ extract the length of the cache lines
   add    r2, r2, #4            @ add 4 (line length offset)
   movw    r4, #0x3ff
   ands    r4, r4, r1, lsr #3        @ find maximum number on the way size
   clz    r5, r4                @ find bit position of way size increment
   movw    r7, #0x7fff
   ands    r7, r7, r1, lsr #13        @ extract max number of the index size
inval_loop1:
   mov    r9, r7                @ create working copy of max index
inval_loop2:
 ARM(    orr    r11, r10, r4, lsl r5    )    @ factor way and cache number into r11
 THUMB(    lsl    r6, r4, r5        )
 THUMB(    orr    r11, r10, r6        )    @ factor way and cache number into r11
 ARM(    orr    r11, r11, r9, lsl r2    )    @ factor index number into r11
 THUMB(    lsl    r6, r9, r2        )
 THUMB(    orr    r11, r11, r6        )    @ factor index number into r11
   mcr    p15, 0, r11, c7, c6, 2        @ invalidate by set/way
   subs    r9, r9, #1            @ decrement the index
   bge    inval_loop2
   subs    r4, r4, #1            @ decrement the way
   bge    inval_loop1
inval_skip:
   add    r10, r10, #2            @ increment cache number
   cmp    r3, r10
   bgt    inval_levels
inval_finished:
   mov    r10, #0                @ swith back to cache level 0
   mcr    p15, 2, r10, c0, c0, 0        @ select current cache level in cssr
   dsb    st
   isb
   bx    lr
ENDPROC(__v7_invalidate_dcache_all)
 
ENTRY(v7_invalidate_dcache_all)
 ARM(    stmfd    sp!, {r4-r5, r7, r9-r11, lr}    )
 THUMB(    stmfd    sp!, {r4-r7, r9-r11, lr}    )
   bl    __v7_invalidate_dcache_all
 ARM(    ldmfd    sp!, {r4-r5, r7, r9-r11, lr}    )
 THUMB(    ldmfd    sp!, {r4-r7, r9-r11, lr}    )
   bx    lr
ENDPROC(v7_invalidate_dcache_all)