Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / ontario / src / l2subr.s
CommitLineData
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
3261:
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
3671:
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
4371:
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
5412:
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
5662:
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
5831:
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
6052:
606 jmp %g7 + 4
607 set L2_LINE_DIRTY, %g4 ! return dirty
608
609 ! return invalid
6100:
611 jmp %g7 + 4
612 set L2_LINE_INVALID, %g4 ! return invalid
613 SET_SIZE(check_l2_state)