Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/powermac/cache.S
10818 views
1
/*
2
* This file contains low-level cache management functions
3
* used for sleep and CPU speed changes on Apple machines.
4
* (In fact the only thing that is Apple-specific is that we assume
5
* that we can read from ROM at physical address 0xfff00000.)
6
*
7
* Copyright (C) 2004 Paul Mackerras ([email protected]) and
8
* Benjamin Herrenschmidt ([email protected])
9
*
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License
12
* as published by the Free Software Foundation; either version
13
* 2 of the License, or (at your option) any later version.
14
*
15
*/
16
17
#include <asm/processor.h>
18
#include <asm/ppc_asm.h>
19
#include <asm/cputable.h>
20
21
/*
22
* Flush and disable all data caches (dL1, L2, L3). This is used
23
* when going to sleep, when doing a PMU based cpufreq transition,
24
* or when "offlining" a CPU on SMP machines. This code is over
25
* paranoid, but I've had enough issues with various CPU revs and
26
* bugs that I decided it was worth beeing over cautious
27
*/
28
29
_GLOBAL(flush_disable_caches)
30
#ifndef CONFIG_6xx
31
blr
32
#else
33
BEGIN_FTR_SECTION
34
b flush_disable_745x
35
END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
36
BEGIN_FTR_SECTION
37
b flush_disable_75x
38
END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
39
b __flush_disable_L1
40
41
/* This is the code for G3 and 74[01]0 */
42
flush_disable_75x:
43
mflr r10
44
45
/* Turn off EE and DR in MSR */
46
mfmsr r11
47
rlwinm r0,r11,0,~MSR_EE
48
rlwinm r0,r0,0,~MSR_DR
49
sync
50
mtmsr r0
51
isync
52
53
/* Stop DST streams */
54
BEGIN_FTR_SECTION
55
DSSALL
56
sync
57
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
58
59
/* Stop DPM */
60
mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */
61
rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
62
sync
63
mtspr SPRN_HID0,r4 /* Disable DPM */
64
sync
65
66
/* Disp-flush L1. We have a weird problem here that I never
67
* totally figured out. On 750FX, using the ROM for the flush
68
* results in a non-working flush. We use that workaround for
69
* now until I finally understand what's going on. --BenH
70
*/
71
72
/* ROM base by default */
73
lis r4,0xfff0
74
mfpvr r3
75
srwi r3,r3,16
76
cmplwi cr0,r3,0x7000
77
bne+ 1f
78
/* RAM base on 750FX */
79
li r4,0
80
1: li r4,0x4000
81
mtctr r4
82
1: lwz r0,0(r4)
83
addi r4,r4,32
84
bdnz 1b
85
sync
86
isync
87
88
/* Disable / invalidate / enable L1 data */
89
mfspr r3,SPRN_HID0
90
rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE)
91
mtspr SPRN_HID0,r3
92
sync
93
isync
94
ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)
95
sync
96
isync
97
mtspr SPRN_HID0,r3
98
xori r3,r3,(HID0_DCI|HID0_ICFI)
99
mtspr SPRN_HID0,r3
100
sync
101
102
/* Get the current enable bit of the L2CR into r4 */
103
mfspr r5,SPRN_L2CR
104
/* Set to data-only (pre-745x bit) */
105
oris r3,r5,L2CR_L2DO@h
106
b 2f
107
/* When disabling L2, code must be in L1 */
108
.balign 32
109
1: mtspr SPRN_L2CR,r3
110
3: sync
111
isync
112
b 1f
113
2: b 3f
114
3: sync
115
isync
116
b 1b
117
1: /* disp-flush L2. The interesting thing here is that the L2 can be
118
* up to 2Mb ... so using the ROM, we'll end up wrapping back to memory
119
* but that is probbaly fine. We disp-flush over 4Mb to be safe
120
*/
121
lis r4,2
122
mtctr r4
123
lis r4,0xfff0
124
1: lwz r0,0(r4)
125
addi r4,r4,32
126
bdnz 1b
127
sync
128
isync
129
lis r4,2
130
mtctr r4
131
lis r4,0xfff0
132
1: dcbf 0,r4
133
addi r4,r4,32
134
bdnz 1b
135
sync
136
isync
137
138
/* now disable L2 */
139
rlwinm r5,r5,0,~L2CR_L2E
140
b 2f
141
/* When disabling L2, code must be in L1 */
142
.balign 32
143
1: mtspr SPRN_L2CR,r5
144
3: sync
145
isync
146
b 1f
147
2: b 3f
148
3: sync
149
isync
150
b 1b
151
1: sync
152
isync
153
/* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
154
oris r4,r5,L2CR_L2I@h
155
mtspr SPRN_L2CR,r4
156
sync
157
isync
158
159
/* Wait for the invalidation to complete */
160
1: mfspr r3,SPRN_L2CR
161
rlwinm. r0,r3,0,31,31
162
bne 1b
163
164
/* Clear L2I */
165
xoris r4,r4,L2CR_L2I@h
166
sync
167
mtspr SPRN_L2CR,r4
168
sync
169
170
/* now disable the L1 data cache */
171
mfspr r0,SPRN_HID0
172
rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE)
173
mtspr SPRN_HID0,r0
174
sync
175
isync
176
177
/* Restore HID0[DPM] to whatever it was before */
178
sync
179
mfspr r0,SPRN_HID0
180
rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */
181
mtspr SPRN_HID0,r0
182
sync
183
184
/* restore DR and EE */
185
sync
186
mtmsr r11
187
isync
188
189
mtlr r10
190
blr
191
192
/* This code is for 745x processors */
193
flush_disable_745x:
194
/* Turn off EE and DR in MSR */
195
mfmsr r11
196
rlwinm r0,r11,0,~MSR_EE
197
rlwinm r0,r0,0,~MSR_DR
198
sync
199
mtmsr r0
200
isync
201
202
/* Stop prefetch streams */
203
DSSALL
204
sync
205
206
/* Disable L2 prefetching */
207
mfspr r0,SPRN_MSSCR0
208
rlwinm r0,r0,0,0,29
209
mtspr SPRN_MSSCR0,r0
210
sync
211
isync
212
lis r4,0
213
dcbf 0,r4
214
dcbf 0,r4
215
dcbf 0,r4
216
dcbf 0,r4
217
dcbf 0,r4
218
dcbf 0,r4
219
dcbf 0,r4
220
dcbf 0,r4
221
222
/* Due to a bug with the HW flush on some CPU revs, we occasionally
223
* experience data corruption. I'm adding a displacement flush along
224
* with a dcbf loop over a few Mb to "help". The problem isn't totally
225
* fixed by this in theory, but at least, in practice, I couldn't reproduce
226
* it even with a big hammer...
227
*/
228
229
lis r4,0x0002
230
mtctr r4
231
li r4,0
232
1:
233
lwz r0,0(r4)
234
addi r4,r4,32 /* Go to start of next cache line */
235
bdnz 1b
236
isync
237
238
/* Now, flush the first 4MB of memory */
239
lis r4,0x0002
240
mtctr r4
241
li r4,0
242
sync
243
1:
244
dcbf 0,r4
245
addi r4,r4,32 /* Go to start of next cache line */
246
bdnz 1b
247
248
/* Flush and disable the L1 data cache */
249
mfspr r6,SPRN_LDSTCR
250
lis r3,0xfff0 /* read from ROM for displacement flush */
251
li r4,0xfe /* start with only way 0 unlocked */
252
li r5,128 /* 128 lines in each way */
253
1: mtctr r5
254
rlwimi r6,r4,0,24,31
255
mtspr SPRN_LDSTCR,r6
256
sync
257
isync
258
2: lwz r0,0(r3) /* touch each cache line */
259
addi r3,r3,32
260
bdnz 2b
261
rlwinm r4,r4,1,24,30 /* move on to the next way */
262
ori r4,r4,1
263
cmpwi r4,0xff /* all done? */
264
bne 1b
265
/* now unlock the L1 data cache */
266
li r4,0
267
rlwimi r6,r4,0,24,31
268
sync
269
mtspr SPRN_LDSTCR,r6
270
sync
271
isync
272
273
/* Flush the L2 cache using the hardware assist */
274
mfspr r3,SPRN_L2CR
275
cmpwi r3,0 /* check if it is enabled first */
276
bge 4f
277
oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h
278
b 2f
279
/* When disabling/locking L2, code must be in L1 */
280
.balign 32
281
1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */
282
3: sync
283
isync
284
b 1f
285
2: b 3f
286
3: sync
287
isync
288
b 1b
289
1: sync
290
isync
291
ori r0,r3,L2CR_L2HWF_745x
292
sync
293
mtspr SPRN_L2CR,r0 /* set the hardware flush bit */
294
3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */
295
andi. r0,r0,L2CR_L2HWF_745x
296
bne 3b
297
sync
298
rlwinm r3,r3,0,~L2CR_L2E
299
b 2f
300
/* When disabling L2, code must be in L1 */
301
.balign 32
302
1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */
303
3: sync
304
isync
305
b 1f
306
2: b 3f
307
3: sync
308
isync
309
b 1b
310
1: sync
311
isync
312
oris r4,r3,L2CR_L2I@h
313
mtspr SPRN_L2CR,r4
314
sync
315
isync
316
1: mfspr r4,SPRN_L2CR
317
andis. r0,r4,L2CR_L2I@h
318
bne 1b
319
sync
320
321
BEGIN_FTR_SECTION
322
/* Flush the L3 cache using the hardware assist */
323
4: mfspr r3,SPRN_L3CR
324
cmpwi r3,0 /* check if it is enabled */
325
bge 6f
326
oris r0,r3,L3CR_L3IO@h
327
ori r0,r0,L3CR_L3DO
328
sync
329
mtspr SPRN_L3CR,r0 /* lock the L3 cache */
330
sync
331
isync
332
ori r0,r0,L3CR_L3HWF
333
sync
334
mtspr SPRN_L3CR,r0 /* set the hardware flush bit */
335
5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */
336
andi. r0,r0,L3CR_L3HWF
337
bne 5b
338
rlwinm r3,r3,0,~L3CR_L3E
339
sync
340
mtspr SPRN_L3CR,r3 /* disable the L3 cache */
341
sync
342
ori r4,r3,L3CR_L3I
343
mtspr SPRN_L3CR,r4
344
1: mfspr r4,SPRN_L3CR
345
andi. r0,r4,L3CR_L3I
346
bne 1b
347
sync
348
END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
349
350
6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */
351
rlwinm r0,r0,0,~HID0_DCE
352
mtspr SPRN_HID0,r0
353
sync
354
isync
355
mtmsr r11 /* restore DR and EE */
356
isync
357
blr
358
#endif /* CONFIG_6xx */
359
360