]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/teg2/cache.v7.s
add tegra2 soc kernel (from sources)
[plan9front.git] / sys / src / 9 / teg2 / cache.v7.s
1 /*
2  * cortex arm arch v7 cache flushing and invalidation
3  * included by l.s and rebootcode.s
4  */
5
6 TEXT cacheiinv(SB), $-4                         /* I invalidate */
7         MOVW    $0, R0
8         MTCP    CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall /* ok on cortex */
9         ISB
10         RET
11
12 /*
13  * set/way operators, passed a suitable set/way value in R0.
14  */
15 TEXT cachedwb_sw(SB), $-4
16         MTCP    CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEsi
17         RET
18
19 TEXT cachedwbinv_sw(SB), $-4
20         MTCP    CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEsi
21         RET
22
23 TEXT cachedinv_sw(SB), $-4
24         MTCP    CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEsi
25         RET
26
27         /* set cache size select */
28 TEXT setcachelvl(SB), $-4
29         MTCP    CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0
30         ISB
31         RET
32
33         /* return cache sizes */
34 TEXT getwayssets(SB), $-4
35         MFCP    CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0
36         RET
37
38 /*
39  * l1 cache operations.
40  * l1 and l2 ops are intended to be called from C, thus need save no
41  * caller's regs, only those we need to preserve across calls.
42  */
43
44 TEXT cachedwb(SB), $-4
45         MOVW.W  R14, -8(R13)
46         MOVW    $cachedwb_sw(SB), R0
47         MOVW    $1, R8
48         BL      wholecache(SB)
49         MOVW.P  8(R13), R15
50
51 TEXT cachedwbinv(SB), $-4
52         MOVW.W  R14, -8(R13)
53         MOVW    $cachedwbinv_sw(SB), R0
54         MOVW    $1, R8
55         BL      wholecache(SB)
56         MOVW.P  8(R13), R15
57
58 TEXT cachedinv(SB), $-4
59         MOVW.W  R14, -8(R13)
60         MOVW    $cachedinv_sw(SB), R0
61         MOVW    $1, R8
62         BL      wholecache(SB)
63         MOVW.P  8(R13), R15
64
65 TEXT cacheuwbinv(SB), $-4
66         MOVM.DB.W [R14], (R13)  /* save lr on stack */
67         MOVW    CPSR, R1
68         CPSID                   /* splhi */
69
70         MOVM.DB.W [R1], (R13)   /* save R1 on stack */
71
72         BL      cachedwbinv(SB)
73         BL      cacheiinv(SB)
74
75         MOVM.IA.W (R13), [R1]   /* restore R1 (saved CPSR) */
76         MOVW    R1, CPSR
77         MOVM.IA.W (R13), [R14]  /* restore lr */
78         RET
79
80 /*
81  * architectural l2 cache operations
82  */
83
84 TEXT _l2cacheuwb(SB), $-4
85         MOVW.W  R14, -8(R13)
86         MOVW    $cachedwb_sw(SB), R0
87         MOVW    $2, R8
88         BL      wholecache(SB)
89         MOVW.P  8(R13), R15     /* return */
90
91 TEXT _l2cacheuwbinv(SB), $-4
92         MOVW.W  R14, -8(R13)
93         MOVW    CPSR, R1
94         CPSID                   /* splhi */
95
96         MOVM.DB.W [R1], (R13)   /* save R1 on stack */
97
98         MOVW    $cachedwbinv_sw(SB), R0
99         MOVW    $2, R8
100         BL      wholecache(SB)
101
102         BL      _l2cacheuinv(SB)
103
104         MOVM.IA.W (R13), [R1]   /* restore R1 (saved CPSR) */
105         MOVW    R1, CPSR
106         MOVW.P  8(R13), R15     /* return */
107
108 TEXT _l2cacheuinv(SB), $-4
109         MOVW.W  R14, -8(R13)
110         MOVW    $cachedinv_sw(SB), R0
111         MOVW    $2, R8
112         BL      wholecache(SB)
113         MOVW.P  8(R13), R15     /* return */
114
115 /*
116  * callers are assumed to be the above l1 and l2 ops.
117  * R0 is the function to call in the innermost loop.
118  * R8 is the cache level (1-origin: 1 or 2).
119  *
120  * R0   func to call at entry
121  * R1   func to call after entry
122  * R2   nsets
123  * R3   way shift (computed from R8)
124  * R4   set shift (computed from R8)
125  * R5   nways
126  * R6   set scratch
127  * R7   way scratch
128  * R8   cache level, 0-origin
129  * R9   extern reg up
130  * R10  extern reg m
131  *
132  * initial translation by 5c, then massaged by hand.
133  */
134 TEXT wholecache+0(SB), $-4
135         MOVW    CPSR, R2
136         MOVM.DB.W [R2,R14], (SP) /* save regs on stack */
137
138         MOVW    R0, R1          /* save argument for inner loop in R1 */
139         SUB     $1, R8          /* convert cache level to zero origin */
140
141         /* we might not have the MMU on yet, so map R1 (func) to R14's space */
142         MOVW    R14, R0         /* get R14's segment ... */
143         AND     $KSEGM, R0
144         BIC     $KSEGM, R1      /* strip segment from func address */
145         ORR     R0, R1          /* combine them */
146
147         /* get cache sizes */
148         SLL     $1, R8, R0      /* R0 = (cache - 1) << 1 */
149         MTCP    CpSC, CpIDcssel, R0, C(CpID), C(CpIDidct), 0 /* set cache select */
150         ISB
151         MFCP    CpSC, CpIDcsize, R0, C(CpID), C(CpIDidct), 0 /* get cache sizes */
152
153         /* compute # of ways and sets for this cache level */
154         SRA     $3, R0, R5      /* R5 (ways) = R0 >> 3 */
155         AND     $((1<<10)-1), R5 /* R5 = (R0 >> 3) & MASK(10) */
156         ADD     $1, R5          /* R5 (ways) = ((R0 >> 3) & MASK(10)) + 1 */
157
158         SRA     $13, R0, R2     /* R2 = R0 >> 13 */
159         AND     $((1<<15)-1), R2 /* R2 = (R0 >> 13) & MASK(15) */
160         ADD     $1, R2          /* R2 (sets) = ((R0 >> 13) & MASK(15)) + 1 */
161
162         /* precompute set/way shifts for inner loop */
163         MOVW    $(CACHECONF+0), R3      /* +0 = l1waysh */
164         MOVW    $(CACHECONF+4), R4      /* +4 = l1setsh */
165         CMP     $0, R8          /* cache == 1? */
166         ADD.NE  $(4*2), R3      /* no, assume l2: +8 = l2waysh */
167         ADD.NE  $(4*2), R3      /* +12 = l2setsh */
168
169         MOVW    R14, R0         /* get R14's segment ... */
170         AND     $KSEGM, R0
171
172         BIC     $KSEGM, R3      /* strip segment from address */
173         ORR     R0, R3          /* combine them */
174         BIC     $KSEGM, R4      /* strip segment from address */
175         ORR     R0, R4          /* combine them */
176         MOVW    (R3), R3
177         MOVW    (R4), R4
178
179         CMP     $0, R3          /* sanity checks */
180         BEQ     wbuggery
181         CMP     $0, R4
182         BEQ     sbuggery
183
184         CPSID                   /* splhi to make entire op atomic */
185         BARRIERS
186
187         /* iterate over ways */
188         MOVW    $0, R7          /* R7: way */
189 outer:
190         /* iterate over sets */
191         MOVW    $0, R6          /* R6: set */
192 inner:
193         /* compute set/way register contents */
194         SLL     R3, R7, R0      /* R0 = way << R3 (L?WAYSH) */
195         ORR     R8<<1, R0       /* R0 = way << L?WAYSH | (cache - 1) << 1 */
196         ORR     R6<<R4, R0      /* R0 = way<<L?WAYSH | (cache-1)<<1 |set<<R4 */
197
198         BL      (R1)            /* call set/way operation with R0 arg. */
199
200         ADD     $1, R6          /* set++ */
201         CMP     R2, R6          /* set >= sets? */
202         BLT     inner           /* no, do next set */
203
204         ADD     $1, R7          /* way++ */
205         CMP     R5, R7          /* way >= ways? */
206         BLT     outer           /* no, do next way */
207
208         MOVM.IA.W (SP), [R2,R14] /* restore regs */
209         BARRIERS
210         MOVW    R2, CPSR        /* splx */
211
212         RET
213
214 wbuggery:
215         PUTC('?')
216         PUTC('c')
217         PUTC('w')
218         B       topanic
219 sbuggery:
220         PUTC('?')
221         PUTC('c')
222         PUTC('s')
223 topanic:
224         MOVW    $.string<>+0(SB), R0
225         BIC     $KSEGM, R0      /* strip segment from address */
226         MOVW    R14, R1         /* get R14's segment ... */
227         AND     $KSEGM, R1
228         ORR     R1, R0          /* combine them */
229         SUB     $12, R13        /* not that it matters, since we're panicing */
230         MOVW    R14, 8(R13)
231         BL      panic(SB)       /* panic("msg %#p", LR) */
232 bugloop:
233         WFI
234         B       bugloop
235
236         DATA    .string<>+0(SB)/8,$"bad cach"
237         DATA    .string<>+8(SB)/8,$"e params"
238         DATA    .string<>+16(SB)/8,$"\073 pc %\043p"
239         DATA    .string<>+24(SB)/1,$"\z"
240         GLOBL   .string<>+0(SB),$25