Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: l2subr.s | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
46 | * Use is subject to license terms. | |
47 | */ | |
48 | ||
49 | .ident "@(#)l2subr.s 1.11 07/05/03 SMI" | |
50 | ||
51 | #include <sys/asm_linkage.h> | |
52 | #include <sys/htypes.h> | |
53 | #include "offsets.h" | |
54 | #include "cpu_errs.h" | |
55 | #include "util.h" | |
56 | ||
57 | ||
58 | /* | |
59 | * L2_FLUSH_BASEADDR - get a 4MB-aligned DRAM address for l2$ flushing | |
60 | * The assumption is that %htba contains a valid dram address valid | |
61 | * for the current machine configuration. Round it down to a 4MB | |
62 | * boundary to use as a base address for l2$ flushing. | |
63 | */ | |
64 | #define L2_FLUSH_BASEADDR(addr, scr) \ | |
65 | rdhpr %htba, addr ;\ | |
66 | set (4 MB) - 1, scr ;\ | |
67 | andn addr, scr, addr | |
68 | ||
69 | ||
70 | /* | |
71 | * get_l2_vdbits_for_pa()() | |
72 | * Read VD (Valid Dirty) bits of l2$ set for a given PA | |
73 | * Arguments: | |
74 | * %g1 -> input - physical address (preserved) | |
75 | * %g2 -> output - VD bit array for 12 ways | |
76 | * --------------------------------------- | |
77 | * |VPARITY| DPARITY||V11|..|V0|D11|..|D0| | |
78 | * --------------------------------------- | |
79 | * Bits-> 25 24 23 12 11 0 | |
80 | * | |
81 | * %g3 -> scratch | |
82 | * %g4 - preserved | |
83 | * %g5, %g6 - preserved | |
84 | * %g7 -> input - return address | |
85 | */ | |
86 | ENTRY_NP(get_l2_vdbits_for_pa) | |
87 | set 0xa6004000, %g2 | |
88 | sllx %g2, 8, %g2 ! %g2 = L2_SELECT_A6 | L2_VDSEL | |
89 | and %g1, 0xC0, %g3 ! %g3 = paddr & L2_BANK_MASK | |
90 | or %g2, %g3, %g2 ! %g2 |= %g3 | |
91 | set 0x3FF00, %g3 ! %g3 = L2_SET_MASK | |
92 | and %g1, %g3, %g3 ! %g3 &= paddr | |
93 | or %g2, %g3, %g2 ! %g2 |= %g3 | |
94 | jmp %g7 + 4 ! return | |
95 | ldx [%g2], %g2 ! %g2 -> output | |
96 | SET_SIZE(get_l2_vdbits_for_pa) | |
97 | ||
98 | ||
99 | /* | |
100 | * get_l2_vdbits_for_set() | |
101 | * Read VD (Valid Dirty) bits of l2$ set specified by index and bank | |
102 | * Arguments: | |
103 | * %g1 -> input - set index (preserved) | |
104 | * %g2 -> input - L2 bank number (preserved) | |
105 | * %g3 -> output - VD bit array for 12 ways | |
106 | * --------------------------------------- | |
107 | * |VPARITY| DPARITY |V11 .. V0|D11 .. D0| | |
108 | * --------------------------------------- | |
109 | * Bits-> 25 24 23 12 11 0 | |
110 | * | |
111 | * %g4 -> scratch | |
112 | * %g5, %g6 - preserved | |
113 | * %g7 -> input - return address | |
114 | */ | |
115 | ENTRY_NP(get_l2_vdbits_for_set) | |
116 | set 0xa6004000, %g3 | |
117 | sllx %g3, 8, %g3 ! %g3 = L2_SELECT_A6 | L2_VDSEL | |
118 | sllx %g1, L2_SET_SHIFT, %g4 ! %g4 = set << L2_SET_SHIFT | |
119 | or %g3, %g4, %g3 ! %g3 |= %g4 | |
120 | sllx %g2, L2_BANK_SHIFT, %g4 ! %g4 = bank << L2_BANK_SHIFT | |
121 | or %g3, %g4, %g3 ! %g3 |= %g4 | |
122 | jmp %g7 + 4 ! return | |
123 | ldx [%g3], %g3 ! %g3 -> output | |
124 | SET_SIZE(get_l2_vdbits_for_set) | |
125 | ||
126 | /* | |
127 | * get_l2_uabits_for_pa()() | |
128 | * Read UA (Used Allocated) bits of l2$ set for a given PA | |
129 | * Arguments: | |
130 | * %g1 -> input - physical address (preserved) | |
131 | * %g2 -> output - UA bit array for 12 ways | |
132 | * ------------------------------- | |
133 | * | DPARITY |V11 .. V0|D11 .. D0| | |
134 | * ------------------------------- | |
135 | * Bits-> 24 23 12 11 0 | |
136 | * | |
137 | * %g3 -> scratch | |
138 | * %g4 - preserved | |
139 | * %g5, %g6 - preserved | |
140 | * %g7 -> input - return address | |
141 | */ | |
142 | ENTRY_NP(get_l2_uabits_for_pa) | |
143 | set 0xa6000000, %g2 | |
144 | sllx %g2, 8, %g2 ! %g2 = L2_SELECT_A6 | |
145 | and %g1, 0xC0, %g3 ! %g3 = paddr & L2_BANK_MASK | |
146 | or %g2, %g3, %g2 ! %g2 |= %g3 | |
147 | set 0x3FF00, %g3 ! %g3 = L2_SET_MASK | |
148 | and %g1, %g3, %g3 ! %g3 &= paddr | |
149 | or %g2, %g3, %g2 ! %g2 |= %g3 | |
150 | jmp %g7 + 4 ! return | |
151 | ldx [%g2], %g2 ! %g2 -> output | |
152 | SET_SIZE(get_l2_uabits_for_pa) | |
153 | ||
154 | /* | |
155 | * get_l2_tag_for_line(int way, int set, int bank) | |
156 | * Read L2$ tag for a given way, set, and bank. | |
157 | * Arguments: | |
158 | * %g1 -> input - cache way | |
159 | * %g2 -> input - set index | |
160 | * %g3 -> input - bank number | |
161 | * %g4 -> output - L2$ tag | |
162 | * -------------------------- | |
163 | * | TAG => PA<39:18> | ECC | | |
164 | * -------------------------- | |
165 | * 27...............6 5...0 | |
166 | * %g5, %g6 - preserved | |
167 | * %g7 -> return address | |
168 | */ | |
169 | ENTRY_NP(get_l2_tag_for_line) | |
170 | set 0xa4000000, %g4 ! %g4 = L2_SELECT_A4 >> 8 | |
171 | or %g4, %g2, %g4 ! %g4 += set index | |
172 | sllx %g4, L2_SET_SHIFT, %g4 ! %g4 << L2_SET_SHIFT (8) | |
173 | sllx %g1, L2_WAY_SHIFT, %g1 ! %g1 = %g1 << L2_WAY_SHIFT | |
174 | or %g4, %g1, %g4 ! %g4 |= %g1 | |
175 | srlx %g1, L2_WAY_SHIFT, %g1 ! %g1 = %g1 >> L2_WAY_SHIFT | |
176 | sllx %g3, L2_BANK_SHIFT, %g3 ! %g3 = %g3 << L2_BANK_SHIFT | |
177 | or %g4, %g3, %g4 ! %g4 |= %g3 | |
178 | srlx %g3, L2_BANK_SHIFT, %g3 ! %g3 = %g3 >> L2_BANK_SHIFT | |
179 | jmp %g7 + 4 ! return | |
180 | ldx [%g4], %g4 ! %g4 -> output | |
181 | SET_SIZE(get_l2_tag_for_line) | |
182 | ||
183 | /* | |
184 | * get_l2_tag_by_way(uint64_t pa, int way) | |
185 | * Read L2$ tag for a given way and physical address | |
186 | * Arguments: | |
187 | * %g1 -> input - physical address | |
188 | * %g2 -> input - way | |
189 | * %g3 -> output - L2$ tag | |
190 | * -------------------------- | |
191 | * | TAG => PA<39:18> | ECC | | |
192 | * -------------------------- | |
193 | * 27...............6 5...0 | |
194 | * %g4 -> scratch | |
195 | * %g5, %g6 - preserved | |
196 | * %g7 -> return address | |
197 | */ | |
198 | ENTRY_NP(get_l2_tag_by_way) | |
199 | set 0x3FFC0, %g4 ! %g4 = L2 SET|BANK MASK <17:6> | |
200 | and %g4, %g1, %g4 ! %g4 &= %g1 (pa) | |
201 | sllx %g2, L2_WAY_SHIFT, %g3 ! %g3 = %g2 << L2_WAY_SHIFT | |
202 | or %g4, %g3, %g4 ! %g4 |= %g3 | |
203 | set 0xA4, %g3 | |
204 | sllx %g3, 32, %g3 ! %g3 = L2_SELECT_A4 | |
205 | or %g3, %g4, %g3 ! %g3 |= %g4 | |
206 | jmp %g7 + 4 ! return | |
207 | ldx [%g3], %g3 ! %g3 -> output | |
208 | SET_SIZE(get_l2_tag_by_way) | |
209 | ||
210 | /* | |
211 | * set_l2_bank_dmmode(int bank) | |
212 | * Set the L2 bank in direct-mapped displacement mode | |
213 | * Arguments: | |
214 | * %g1 - input -> L2 bank number (preserved) | |
215 | * %g2 - scratch | |
216 | * %g3 - scratch | |
217 | * %g4, %g5, %g6 - preserved | |
218 | * %g7 - input -> return address | |
219 | */ | |
220 | ENTRY_NP(set_l2_bank_dmmode) | |
221 | setx L2_CONTROL_REG, %g3, %g2 | |
222 | sllx %g1, L2_BANK_SHIFT, %g3 | |
223 | or %g2, %g3, %g2 ! or in L2 bank | |
224 | ldx [%g2], %g3 ! read L2_CONTROL[bank] | |
225 | or %g3, L2_DMMODE, %g3 ! %g3 |= L2_DMMODE | |
226 | jmp %g7 + 4 ! return | |
227 | stx %g3, [%g2] ! L2_CONTROL[bank] = %g3 | |
228 | SET_SIZE(set_l2_bank_dmmode) | |
229 | ||
230 | ||
231 | /* | |
232 | * reset_l2_bank_dmmode(int bank) | |
233 | * Reset the L2 bank to normal mode | |
234 | * Arguments: | |
235 | * %g1 - input -> L2 bank number (preserved) | |
236 | * %g2 - scratch | |
237 | * %g3 - scratch | |
238 | * %g4, %g5, %g6 - preserved | |
239 | * %g7 - input -> return address | |
240 | */ | |
241 | ENTRY_NP(reset_l2_bank_dmmode) | |
242 | setx L2_CONTROL_REG, %g3, %g2 | |
243 | sllx %g1, L2_BANK_SHIFT, %g3 | |
244 | or %g2, %g3, %g2 ! or in L2 bank | |
245 | ldx [%g2], %g3 ! read L2_CONTROL[bank] | |
246 | bclr L2_DMMODE, %g3 ! %g3 &= ~L2_DMMODE | |
247 | jmp %g7 + 4 ! return | |
248 | stx %g3, [%g2] ! L2_CONTROL[bank] = %g3 | |
249 | SET_SIZE(reset_l2_bank_dmmode) | |
250 | ||
251 | ||
252 | /* | |
253 | * set_all_banks_dmmode - set all l2 banks to direct-mapped mode | |
254 | * | |
255 | * NON-LEAF | |
256 | * %g7 - return address | |
257 | * clobbers %g6 along with the lowered-numbered registers | |
258 | * clobbered by set_l2_bank_dmmode | |
259 | */ | |
260 | ENTRY_NP(set_all_banks_dmmode) | |
261 | mov %g7, %g6 ! save return | |
262 | ||
263 | mov 0, %g1 ! bank 0 | |
264 | HVCALL(set_l2_bank_dmmode) | |
265 | ||
266 | mov 1, %g1 ! bank 1 | |
267 | HVCALL(set_l2_bank_dmmode) | |
268 | ||
269 | mov 2, %g1 ! bank 2 | |
270 | HVCALL(set_l2_bank_dmmode) | |
271 | ||
272 | mov 3, %g1 ! bank 3 | |
273 | HVCALL(set_l2_bank_dmmode) | |
274 | ||
275 | mov %g6, %g7 ! restore return | |
276 | HVRET | |
277 | SET_SIZE(set_all_banks_dmmode) | |
278 | ||
279 | /* | |
280 | * reset_all_banks_dmmode - set all l2 banks to normal mode | |
281 | * | |
282 | * NON-LEAF | |
283 | * %g7 - return address | |
284 | * clobbers %g6 along with the lowered-numbered registers | |
285 | * clobbered by reset_set_l2_bank_dmmode | |
286 | */ | |
287 | ENTRY_NP(reset_all_banks_dmmode) | |
288 | mov %g7, %g6 ! save return | |
289 | ||
290 | mov 0, %g1 | |
291 | HVCALL(reset_l2_bank_dmmode) | |
292 | ||
293 | mov 1, %g1 ! bank 1 | |
294 | HVCALL(reset_l2_bank_dmmode) | |
295 | ||
296 | mov 2, %g1 ! bank 2 | |
297 | HVCALL(reset_l2_bank_dmmode) | |
298 | ||
299 | mov 3, %g1 ! bank 3 | |
300 | HVCALL(reset_l2_bank_dmmode) | |
301 | ||
302 | mov %g6, %g7 ! restore return | |
303 | HVRET | |
304 | SET_SIZE(reset_all_banks_dmmode) | |
305 | ||
306 | /* | |
307 | * l2_flush_cache(void) | |
308 | * Flush the entire l2 cache | |
309 | * clobbers %g1-%g6 | |
310 | * %g7 - return address | |
311 | */ | |
312 | ENTRY_NP(l2_flush_cache) | |
313 | mov %g7, %g5 ! set_all_banks_dmmode clobbers %g6 | |
314 | ||
315 | HVCALL(set_all_banks_dmmode) | |
316 | ||
317 | /* | |
318 | * read in from 0 to 3MB * 2. Experiments have shown that reading | |
319 | * in 3 times the size of L2$ from 3 different 4MB-aligned addresses | |
320 | * flushes the cache reliably. | |
321 | */ | |
322 | L2_FLUSH_BASEADDR(%g2, %g4) | |
323 | set 0x900000, %g1 ! end | |
324 | add %g2, %g1, %g1 | |
325 | ||
326 | 1: | |
327 | ldx [%g2], %g0 | |
328 | inc L2_LINE_SIZE, %g2 ! next cache line | |
329 | cmp %g2, %g1 | |
330 | blu,pt %xcc, 1b ! not done, go to 1 | |
331 | nop | |
332 | ||
333 | HVCALL(reset_all_banks_dmmode) | |
334 | ||
335 | mov %g5, %g7 | |
336 | HVRET | |
337 | SET_SIZE(l2_flush_cache) | |
338 | ||
339 | ||
340 | /* | |
341 | * l2_flush_line(uint64_t pa) [Non-leaf function] | |
342 | * Flush the L2$ line corresponding to the physical address, pa | |
343 | * Arguments: | |
344 | * %g1 - input - physical address | |
345 | * %g2-%g6 - scratch | |
346 | * %g7 - input - return address | |
347 | */ | |
348 | ENTRY_NP(l2_flush_line) | |
349 | mov %g1, %g6 ! save phys addr | |
350 | mov %g7, %g5 ! save return address | |
351 | and %g1, 0xC0, %g1 ! %g1 &= L2_BANK_MASK | |
352 | srlx %g1, L2_BANK_SHIFT, %g1 ! %g1 = L2 bank | |
353 | ba set_l2_bank_dmmode ! set L2[bank] = DMMODE | |
354 | rd %pc, %g7 | |
355 | ||
356 | ! do displacement flush | |
357 | set 0x3FFC0, %g1 ! %g1 = L2 SET|BANK MASK <17:6> | |
358 | and %g1, %g6, %g1 ! %g1 = pa & L2_SET|BANK MASK | |
359 | ||
360 | L2_FLUSH_BASEADDR(%g3, %g4) | |
361 | ||
362 | add %g3, %g1, %g3 ! %g3 = flush addr for set, bank | |
363 | set 0x40000, %g2 ! way increment | |
364 | set 0x2C0000, %g4 | |
365 | mov 0, %g1 ! current way | |
366 | ! loop 12-way | |
367 | 1: | |
368 | ldx [%g3 + %g1], %g0 ! displacement flush read | |
369 | add %g1, %g2, %g1 ! way += 0x40000 (next way) | |
370 | cmp %g1, %g4 ! done? | |
371 | bleu %xcc, 1b | |
372 | nop | |
373 | ||
374 | ! reset dmmode bit | |
375 | and %g6, 0xC0, %g1 ! %g1 &= L2_BANK_MASK | |
376 | srlx %g1, L2_BANK_SHIFT, %g1 ! %g1 = L2 bank | |
377 | ba reset_l2_bank_dmmode | |
378 | rd %pc, %g7 | |
379 | ||
380 | ! return | |
381 | mov %g6, %g1 ! restore input args | |
382 | mov %g5, %g7 ! restore input args | |
383 | HVRET | |
384 | SET_SIZE(l2_flush_line) | |
385 | ||
386 | /* | |
387 | * dump_l2_set_tag_data_ecc(uint64_t pa, void *dump_area) [Non-leaf] | |
388 | * Dump the L2$ tag and data and ECC for the set corresponding to the | |
389 | * given physical address, pa. | |
390 | * | |
391 | * The dump format is: | |
392 | * 0x0 [VPARITY | DPARITY | VALID bits | DIRTY bits] | |
393 | * 0x8 [APARITY | USED bits | ALLOC bits] | |
394 | * 0x10 [way 0 tag + ECC] | |
395 | * 0x18 [way 0 32-bit word 0 + ECC] | |
396 | * 0x20 [way 0 32-bit word 1 + ECC] | |
397 | * 0x28 [way 0 32-bit word 2 + ECC] | |
398 | * ... | |
399 | * 0x90 [way 0 32-bit word 15 + ECC] | |
400 | * 0x98 [way 1 tag + ECC] | |
401 | * 0xa0 way 1 data | |
402 | * ... | |
403 | * | |
404 | * This function does not change L2$ enabled/disabled status. | |
405 | * | |
406 | * Arguments: | |
407 | * %g1 - input - physical address | |
408 | * %g2 - input - pointer to dump area | |
409 | * %g3-%g6 - scratch | |
410 | * %g7 - input - return address | |
411 | */ | |
412 | ENTRY_NP(dump_l2_set_tag_data_ecc) | |
413 | mov %g2, %g5 | |
414 | mov %g7, %g6 | |
415 | ba get_l2_vdbits_for_pa | |
416 | rd %pc, %g7 | |
417 | ||
418 | stx %g2, [%g5] ! store VD bits and parity | |
419 | add %g5, 8, %g5 | |
420 | ||
421 | ba get_l2_uabits_for_pa | |
422 | rd %pc, %g7 | |
423 | ||
424 | stx %g2, [%g5] ! save UA bits and parity | |
425 | add %g5, 8, %g5 | |
426 | ||
427 | mov %g0, %g2 ! set way = 0 | |
428 | ba get_l2_tag_by_way | |
429 | rd %pc, %g7 | |
430 | ||
431 | stx %g3, [%g5] ! save tag_ECC[0] | |
432 | add %g5, 8, %g5 | |
433 | ||
434 | mov %g6, %g7 ! restore original return | |
435 | ||
436 | mov %g0, %g2 ! way number | |
437 | 1: | |
438 | set 0x3FFC0, %g4 ! %g4 = L2 SET|BANK MASK <17:6> | |
439 | and %g4, %g1, %g4 ! %g4 &= %g1 (pa) | |
440 | or %g4, %g2, %g4 ! %g4 |= (way_num << L2_WAY_SHIFT) | |
441 | ! way 0, word 0 | |
442 | set 0xA1, %g3 | |
443 | sllx %g3, 32, %g3 ! %g3 = L2_SELECT_A1 | EVEN | |
444 | or %g4, %g3, %g4 ! %g4 |= L2_SELECT_A1 | |
445 | ldx [%g4], %g6 ! read even 32-bit | |
446 | stx %g6, [%g5] ! store even 32-bit data | |
447 | add %g5, 8, %g5 ! increment pointer | |
448 | set (1 << 22), %g3 ! ODDEVEN = 1 | |
449 | or %g4, %g3, %g4 ! select ODD | |
450 | ldx [%g4], %g6 ! read odd 32-bit | |
451 | stx %g6, [%g5] ! store odd 32-bit data | |
452 | add %g5, 8, %g5 ! increment pointer | |
453 | ! way 0, word 1 | |
454 | add %g4, 8, %g4 ! next word | |
455 | andn %g4, %g3, %g4 ! EVEN | |
456 | ldx [%g4], %g6 ! read even 32-bit | |
457 | stx %g6, [%g5] ! store even 32-bit data | |
458 | add %g5, 8, %g5 ! increment pointer | |
459 | set (1 << 22), %g3 ! ODDEVEN = 1 | |
460 | or %g4, %g3, %g4 ! select ODD | |
461 | ldx [%g4], %g6 ! read odd 32-bit | |
462 | stx %g6, [%g5] ! store odd 32-bit data | |
463 | add %g5, 8, %g5 ! increment pointer | |
464 | ! way 0, word 2 | |
465 | add %g4, 8, %g4 ! next word | |
466 | andn %g4, %g3, %g4 ! EVEN | |
467 | ldx [%g4], %g6 ! read even 32-bit | |
468 | stx %g6, [%g5] ! store even 32-bit data | |
469 | add %g5, 8, %g5 ! increment pointer | |
470 | or %g4, %g3, %g4 ! select ODD | |
471 | ldx [%g4], %g6 ! read odd 32-bit | |
472 | stx %g6, [%g5] ! store odd 32-bit data | |
473 | add %g5, 8, %g5 ! increment pointer | |
474 | ! way 0, word 3 | |
475 | add %g4, 8, %g4 ! next word | |
476 | andn %g4, %g3, %g4 ! EVEN | |
477 | ldx [%g4], %g6 ! read even 32-bit | |
478 | stx %g6, [%g5] ! store even 32-bit data | |
479 | add %g5, 8, %g5 ! increment pointer | |
480 | or %g4, %g3, %g4 ! select ODD | |
481 | ldx [%g4], %g6 ! read odd 32-bit | |
482 | stx %g6, [%g5] ! store odd 32-bit data | |
483 | add %g5, 8, %g5 ! increment pointer | |
484 | ! way 0, word 4 | |
485 | add %g4, 8, %g4 ! next word | |
486 | andn %g4, %g3, %g4 ! EVEN | |
487 | ldx [%g4], %g6 ! read even 32-bit | |
488 | stx %g6, [%g5] ! store even 32-bit data | |
489 | add %g5, 8, %g5 ! increment pointer | |
490 | or %g4, %g3, %g4 ! select ODD | |
491 | ldx [%g4], %g6 ! read odd 32-bit | |
492 | stx %g6, [%g5] ! store odd 32-bit data | |
493 | add %g5, 8, %g5 ! increment pointer | |
494 | ! way 0, word 5 | |
495 | add %g4, 8, %g4 ! next word | |
496 | andn %g4, %g3, %g4 ! EVEN | |
497 | ldx [%g4], %g6 ! read even 32-bit | |
498 | stx %g6, [%g5] ! store even 32-bit data | |
499 | add %g5, 8, %g5 ! increment pointer | |
500 | or %g4, %g3, %g4 ! select ODD | |
501 | ldx [%g4], %g6 ! read odd 32-bit | |
502 | stx %g6, [%g5] ! store odd 32-bit data | |
503 | add %g5, 8, %g5 ! increment pointer | |
504 | ! way 0, word 6 | |
505 | add %g4, 8, %g4 ! next word | |
506 | andn %g4, %g3, %g4 ! EVEN | |
507 | ldx [%g4], %g6 ! read even 32-bit | |
508 | stx %g6, [%g5] ! store even 32-bit data | |
509 | add %g5, 8, %g5 ! increment pointer | |
510 | or %g4, %g3, %g4 ! select ODD | |
511 | ldx [%g4], %g6 ! read odd 32-bit | |
512 | stx %g6, [%g5] ! store odd 32-bit data | |
513 | add %g5, 8, %g5 ! increment pointer | |
514 | ! way 0, word 7 | |
515 | add %g4, 8, %g4 ! next word | |
516 | andn %g4, %g3, %g4 ! EVEN | |
517 | ldx [%g4], %g6 ! read even 32-bit | |
518 | stx %g6, [%g5] ! store even 32-bit data | |
519 | add %g5, 8, %g5 ! increment pointer | |
520 | or %g4, %g3, %g4 ! select ODD | |
521 | ldx [%g4], %g6 ! read odd 32-bit | |
522 | stx %g6, [%g5] ! store odd 32-bit data | |
523 | add %g5, 8, %g5 ! increment pointer | |
524 | ! next way | |
525 | srlx %g2, L2_WAY_SHIFT, %g2 ! current way | |
526 | add %g2, 1, %g2 ! next way | |
527 | cmp %g2, L2_NUM_WAYS | |
528 | bz 2f ! read tag and loop back if not done | |
529 | nop | |
530 | ||
531 | ! read tag | |
532 | mov %g7, %g6 ! save original return | |
533 | ba get_l2_tag_by_way | |
534 | rd %pc, %g7 | |
535 | mov %g6, %g7 ! restore original return | |
536 | stx %g3, [%g5] ! save tag_ECC[next] | |
537 | add %g5, 8, %g5 ! increment | |
538 | ba 1b | |
539 | sllx %g2, L2_WAY_SHIFT, %g2 ! shift to way field | |
540 | ||
541 | 2: | |
542 | ! set %g2 back to original value based on %g5 | |
543 | sub %g5, 0x618, %g2 ! restore %g2 | |
544 | HVRET | |
545 | SET_SIZE(dump_l2_set_tag_data_ecc) | |
546 | ||
547 | /* | |
548 | * check_l2_state(uint64_t pa) | |
549 | * Checks L2$ line state for the given physical address | |
550 | * and returns 0 for clean, 1 for dirty, 2 for invalid, 3 = not found | |
551 | * Arguments: | |
552 | * %g1 - input - physical address | |
553 | * %g4 - output - clean, dirty or invalid state | |
554 | * %g7 - input - return address | |
555 | */ | |
556 | ENTRY_NP(check_l2_state) | |
557 | mov %g7, %g6 | |
558 | ||
559 | ! get PA<39:18> from pa | |
560 | setx L2_PA_TAG_MASK, %g2, %g5 | |
561 | and %g1, %g5, %g5 ! %g5 has PA<39:18> | |
562 | srlx %g5, L2_PA_TAG_SHIFT, %g5 | |
563 | ||
564 | ! read L2 tag | |
565 | set 0, %g2 | |
566 | 2: | |
567 | ba get_l2_tag_by_way ! returns tag in %g3 | |
568 | rd %pc, %g7 | |
569 | setx L2_TAG_MASK, %g7, %g4 | |
570 | and %g3, %g4, %g3 | |
571 | srlx %g3, L2_TAG_SHIFT, %g3 ! %g3 has L2 TAG<27:6> | |
572 | cmp %g3, %g5 ! %g5 has the PA tag | |
573 | bz 1f | |
574 | add %g2, 1, %g2 | |
575 | cmp %g2, 12 ! 12th way? | |
576 | bnz 2b ! no, do next way | |
577 | mov %g6, %g7 | |
578 | ! done, return not found | |
579 | jmp %g7 + 4 | |
580 | set L2_LINE_NOT_FOUND, %g4 ! return not found | |
581 | ||
582 | ! tag match found | |
583 | 1: | |
584 | mov %g2, %g5 ! %g5 = %g2 | |
585 | sub %g5, 1, %g5 ! %g5 has the way number | |
586 | ba get_l2_vdbits_for_pa ! returns vdbits in %g2 | |
587 | rd %pc, %g7 | |
588 | add %g5, 12, %g5 | |
589 | set 1, %g3 | |
590 | sllx %g3, %g5, %g3 ! set valid[way] | |
591 | btst %g3, %g2 ! is valid? | |
592 | bz 0f | |
593 | mov %g6, %g7 | |
594 | ||
595 | ! check dirty or clean | |
596 | srlx %g3, 12, %g3 ! set dirty[way] | |
597 | btst %g3, %g2 ! is dirty? | |
598 | bnz 2f ! yes, return dirty | |
599 | mov %g6, %g7 | |
600 | ! return clean | |
601 | jmp %g7 + 4 | |
602 | set L2_LINE_CLEAN, %g4 ! return clean | |
603 | ||
604 | ! return dirty | |
605 | 2: | |
606 | jmp %g7 + 4 | |
607 | set L2_LINE_DIRTY, %g4 ! return dirty | |
608 | ||
609 | ! return invalid | |
610 | 0: | |
611 | jmp %g7 + 4 | |
612 | set L2_LINE_INVALID, %g4 ! return invalid | |
613 | SET_SIZE(check_l2_state) |