Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / cpu / src / N2_TrieTlb.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2_TrieTlb.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21
22#include "N2_Tlb.h"
23#include "N2_TrieTlb.h"
24#include <new>
25
26N2_TrieTlb::N2_TrieTlb( N2_Tlb* _tlb )/*{{{*/
27 :
28 tlb(_tlb),
29 fail_node1(0),
30 fail_node2(0),
31 fail_node3(0),
32 fail_page5(0),
33 fail_page3(0),
34 fail_page1(0),
35 free_node1(0),
36 free_node2(0),
37 free_node3(0),
38 free_page5(0),
39 free_page3(0),
40 free_page1(0)
41{
42 fail_page1 = new Page1(0);
43 fail_page3 = new Page3(fail_page1);
44 fail_page5 = new Page5(fail_page3);
45 fail_node3 = new Node3(fail_page5);
46 fail_node2 = new Node2(fail_node3);
47 fail_node1 = new Node1(fail_node2);
48
49 fail_node1->fail_node();
50 fail_node2->fail_node();
51 fail_node3->fail_node();
52 fail_page5->fail_node();
53 fail_page3->fail_node();
54 fail_page1->fail_node();
55
56 for (uint_t p=0; p < PID_SIZE; p++)
57 {
58 real[p] = fail_node1;
59 for (uint_t c=0; c < CTX_SIZE; c++)
60 virt[p][c] = fail_node1;
61 }
62}
63/*}}}*/
64N2_TrieTlb::N2_TrieTlb( N2_TrieTlb& trie, N2_Tlb* _tlb )/*{{{*/
65 :
66 tlb(_tlb),
67 fail_node1(trie.fail_node1),
68 fail_node2(trie.fail_node2),
69 fail_node3(trie.fail_node3),
70 fail_page5(trie.fail_page5),
71 fail_page3(trie.fail_page3),
72 fail_page1(trie.fail_page1),
73 free_node1(trie.free_node1),
74 free_node2(trie.free_node2),
75 free_node3(trie.free_node3),
76 free_page5(trie.free_page5),
77 free_page3(trie.free_page3),
78 free_page1(trie.free_page1)
79{
80 trie.free_node1 = 0;
81 trie.free_node2 = 0;
82 trie.free_node3 = 0;
83 trie.free_page5 = 0;
84 trie.free_page3 = 0;
85 trie.free_page1 = 0;
86
87 for (uint_t p=0; p < PID_SIZE; p++)
88 {
89 real[p] = trie.copy(trie.real[p]);
90 for (uint_t c=0; c < CTX_SIZE; c++)
91 virt[p][c] = trie.copy(trie.virt[p][c]);
92 }
93}
94/*}}}*/
95N2_TrieTlb::~N2_TrieTlb()/*{{{*/
96{
97 for (uint_t p=0; p < PID_SIZE; p++)
98 demap_all(0,p);
99
100 while (free_node1)
101 {
102 Node1* help = free_node1;
103 free_node1 = free_node1->next;
104 delete help;
105 }
106
107 while (free_node2)
108 {
109 Node2* help = free_node2;
110 free_node2 = free_node2->next;
111 delete help;
112 }
113
114 while (free_node3)
115 {
116 Node3* help = free_node3;
117 free_node3 = free_node3->next;
118 delete help;
119 }
120
121 while (free_page5)
122 {
123 Page5* help = free_page5;
124 free_page5 = free_page5->next;
125 delete help;
126 }
127
128 while (free_page3)
129 {
130 Page3* help = free_page3;
131 free_page3 = free_page3->next;
132 delete help;
133 }
134
135 while (free_page1)
136 {
137 Page1* help = free_page1;
138 free_page1 = free_page1->next;
139 delete help;
140 }
141}
142/*}}}*/
143
144N2_TrieTlb::Node1* N2_TrieTlb::copy( Node1* r_n1 )/*{{{*/
145{
146 if (r_n1 == fail_node1)
147 return r_n1;
148 Node1* l_n1 = new_node1();
149
150 for (uint_t i0=0; i0 < Node1::SIZE; i0++)
151 {
152 Node2* r_n2 = r_n1->idx(i0);
153
154 if (r_n2 == fail_node2)
155 continue;
156 Node2* l_n2 = new_node2();
157
158 l_n1->insert(i0,l_n2);
159
160 for (uint_t i1=0; i1 < Node2::SIZE; i1++)
161 {
162 Node3* r_n3 = r_n2->idx(i1);
163
164 if (r_n3 == fail_node3)
165 continue;
166 Node3* l_n3 = new_node3();
167
168 l_n2->insert(i1,l_n3);
169
170 for (uint_t i2=0; i2 < Node3::SIZE; i2++)
171 {
172 Page5* r_p5 = r_n3->idx(i2);
173
174 if (r_p5 == fail_page5)
175 continue;
176 Page5* l_p5 = new_page5();
177
178 l_p5->tte = r_p5->tte;
179 l_n3->insert(i2,l_p5);
180
181 for (uint_t i3=0; i3 < Page5::SIZE; i3++)
182 {
183 Page3* r_p3 = r_p5->idx(i3);
184
185 if (r_p3 == fail_page3)
186 continue;
187 Page3* l_p3 = new_page3();
188
189 l_p3->tte = r_p3->tte;
190 l_p5->insert(i3,l_p3);
191
192 for (uint_t i4=0; i4 < Page3::SIZE; i4++)
193 {
194 Page1* r_p1 = r_p3->idx(i4);
195
196 if (r_p1 == fail_page1)
197 continue;
198 Page1* l_p1 = new_page1();
199
200 l_p1->tte = r_p1->tte;
201 l_p3->insert(i4,l_p1);
202
203 for (uint_t i5=0; i5 < Page1::SIZE; i5++)
204 {
205 SS_Tte* tte = r_p1->idx(i5);
206
207 if (tte)
208 l_p1->insert(i5,tte);
209 }
210 }
211 }
212 }
213 }
214 }
215 return l_n1;
216}
217/*}}}*/
218
219void N2_TrieTlb::insert( SS_Strand* strand, SS_Tte* tte, SS_Tte* rem_tte )/*{{{*/
220{
221 Node1* n1;
222
223 if (tte->is_virt())
224 {
225 n1 = virt[tte->pid()][tte->context()];
226 if (n1 == fail_node1)
227 {
228 n1 = new_node1();
229 virt[tte->pid()][tte->context()] = n1;
230 }
231 }
232 else if (tte->is_real())
233 {
234 n1 = real[tte->pid()];
235 if (n1 == fail_node1)
236 {
237 n1 = new_node1();
238 real[tte->pid()] = n1;
239 }
240 }
241 else
242 {
243 remove(rem_tte);
244 return;
245 }
246
247 // For the va we use the non aligned tag value, e.g we don't
248 // use tte->virt_page. We do this so we auto demap the
249 // correct smaller page(s).
250
251 SS_Vaddr va = tte->tag();
252 uint_t ps = tte->page_size();
253
254 Node2* n2 = n1->at(va);
255 Node3* n3 = n2->at(va);
256 Page5* p5 = n3->at(va);
257 Page3* p3 = p5->at(va);
258 Page1* p1 = p3->at(va);
259
260 Page5* p5_new = 0;
261 Page3* p3_new = 0;
262 Page1* p1_new = 0;
263
264 SS_Tte* p5_tte = p5->tte;
265 SS_Tte* p3_tte = p3->tte;
266 SS_Tte* p1_tte = p1->tte;
267 SS_Tte* p0_tte = p1->at(va);
268
269 // Inserts the TTE and auto demap the overlapping TTEs. E.g. demap
270 // p0_tte, p1_tte, p3_tte, and p5_tte is they are valid TTEs (!= 0).
271 // This insert and demap has to be (like in hardware) an atomic operation.
272 // We do this by creating a new path with the TTEs that are to be
273 // demapped removed and the new TTE inserted.
274
275 if (p0_tte)
276 {
277 // We have a full path: p5, p3, p1 and the have to demap a p0 TTE.
278 // Optimise for a simple case: replace p0_tte, as Solaris often
279 // changes readonly TTEs into readwrite TTEs: a result from fork().
280 // The unoptimised case creates a new path and updates the TTEs and
281 // inserts the path in the trie as the last operation.
282
283 if ((ps == 0) && (p1_tte == 0) && (p3_tte == 0) && (p5_tte == 0))
284 {
285 p1->at(va) = tte;
286
287 if (p0_tte != rem_tte)
288 {
289 tlb->clr_used(p0_tte->index);
290 tlb->invalidate_tte(strand,p0_tte);
291 remove(rem_tte);
292 }
293 return;
294 }
295 else
296 {
297 p5_new = new_page5(p5);
298 p3_new = new_page3(p3);
299 p1_new = new_page1(p1);
300
301 p5_new->at(va) = p3_new;
302 p3_new->at(va) = p1_new;
303
304 p5_new->tte = (ps == 5) ? tte : 0;
305 p3_new->tte = (ps == 3) ? tte : 0;
306 p1_new->tte = (ps == 1) ? tte : 0;
307
308 if (ps == 0)
309 p1_new->at(va) = tte;
310 else
311 p1_new->remove(va,0);
312
313 if (p1_new->is_empty())
314 {
315 p3_new->remove(va,fail_page1);
316 if (p3_new->is_empty())
317 {
318 p5_new->remove(va,fail_page3);
319 del_page3(p3_new);
320 p3_new = 0;
321 }
322 del_page1(p1_new);
323 p1_new = 0;
324 }
325
326 n3->at(va) = p5_new;
327 }
328 }
329 else if (p1_tte)
330 {
331 // Again we have a full path: p5, p3, p1 and the smallest TTE we have
332 // to demap is p1 TTE. Optimise for a trivial case. Otherwise create
333 // a new path with the TTEs updated and insert in the trie at the end.
334
335 if ((ps == 1) && (p3_tte == 0) && (p5_tte == 0))
336 {
337 p1->tte = tte;
338
339 if (p1_tte != rem_tte)
340 {
341 tlb->clr_used(p1_tte->index);
342 tlb->invalidate_tte(strand,p1_tte);
343 remove(rem_tte);
344 }
345 return;
346 }
347 else
348 {
349 p5_new = new_page5(p5);
350 p3_new = new_page3(p3);
351 p1_new = new_page1(p1);
352
353 p5_new->at(va) = p3_new;
354 p3_new->at(va) = p1_new;
355
356 p5_new->tte = (ps == 5) ? tte : 0;
357 p3_new->tte = (ps == 3) ? tte : 0;
358 p1_new->tte = (ps == 1) ? tte : 0;
359
360 if (ps == 0)
361 p1_new->insert(va,tte);
362
363 if (p1_new->is_empty())
364 {
365 p3_new->remove(va,fail_page1);
366 if (p3_new->is_empty())
367 {
368 p5_new->remove(va,fail_page3);
369 del_page3(p3_new);
370 p3_new = 0;
371 }
372 del_page1(p1_new);
373 p1_new = 0;
374 }
375
376 n3->at(va) = p5_new;
377 }
378 }
379 else if (p3_tte)
380 {
381 // We have at least a p5 and p3 node. Select the trivial case for
382 // optimisation. Else switch between possibly shrinking the path
383 // (ps >= 3) or extending the path.
384
385 if ((ps == 3) && (p5_tte == 0))
386 {
387 p3->tte = tte;
388
389 if (p3_tte != rem_tte)
390 {
391 tlb->clr_used(p3_tte->index);
392 tlb->invalidate_tte(strand,p3_tte);
393 remove(rem_tte);
394 }
395 return;
396 }
397 else if (ps >= 3)
398 {
399 p5_new = new_page5(p5);
400 p3_new = new_page3(p3);
401
402 p5_new->at(va) = p3_new;
403
404 p5_new->tte = (ps == 5) ? tte : 0;
405 p3_new->tte = (ps == 3) ? tte : 0;
406
407 if (p3_new->is_empty())
408 {
409 p5_new->remove(va,fail_page3);
410 del_page3(p3_new);
411 p3_new = 0;
412 }
413
414 n3->at(va) = p5_new;
415 }
416 else
417 {
418 Page1* p1_tmp;
419
420 p5_new = new_page5(p5);
421 p3_new = new_page3(p3);
422 p5_new->at(va) = p3_new;
423
424 if (p1 == fail_page1)
425 {
426 p1 = new_page1();
427 p3_new->insert(va,p1);
428 p1_tmp = p1;
429 }
430 else
431 {
432 p1_new = new_page1(p1);
433 p3_new->at(va) = p1_new;
434 p1_tmp = p1_new;
435 }
436
437 p5_new->tte = 0;
438 p3_new->tte = 0;
439 p1_tmp->tte = (ps == 1) ? tte : 0;
440
441 if (ps == 0)
442 p1_tmp->insert(va,tte);
443
444 n3->at(va) = p5_new;
445 }
446 }
447 else if (p5_tte)
448 {
449 // We have a p5 node. Optimise the simple case. Otherwise
450 // insert and create missing path.
451
452 if (ps == 5)
453 {
454 p5->tte = tte;
455
456 if (p5_tte != rem_tte)
457 {
458 tlb->clr_used(p5_tte->index);
459 tlb->invalidate_tte(strand,p5_tte);
460 remove(rem_tte);
461 }
462 return;
463 }
464 else
465 {
466 Page1* p1_tmp;
467 Page3* p3_tmp;
468
469 p5_new = new_page5(p5);
470 p5_new->tte = 0;
471
472 if (p3 == fail_page3)
473 {
474 p3 = new_page3();
475 p5_new->insert(va,p3);
476 p3_tmp = p3;
477 }
478 else
479 {
480 p3_new = new_page3(p3);
481 p5_new->at(va) = p3_new;
482 p3_tmp = p3_new;
483 }
484
485 if (ps == 3)
486 {
487 p3_tmp->tte = tte;
488 }
489 else
490 {
491 p3_tmp->tte = 0;
492
493 if (p1 == fail_page1)
494 {
495 p1 = new_page1();
496 p3_tmp->insert(va,p1);
497 p1_tmp = p1;
498 }
499 else
500 {
501 p1_new = new_page1(p1);
502 p3_new->at(va) = p1_new;
503 p1_tmp = p1_new;
504 }
505
506 if (ps == 1)
507 {
508 p1_tmp->tte = tte;
509 }
510 else
511 {
512 p1_tmp->tte = 0;
513 p1_tmp->insert(va,tte);
514 }
515 }
516
517 n3->at(va) = p5_new;
518 }
519 }
520 else if (p1 != fail_page1)
521 {
522 // We have no overlapping TTEs and the path p5, p3, p1 is there.
523 // This is a simple case, likely to happen often. We can just set
524 // the new TTE, remove the replaced TTE and return.
525
526 if (ps == 0)
527 p1->insert(va,tte);
528 else if (ps == 1)
529 p1->tte = tte;
530 else if (ps == 3)
531 p3->tte = tte;
532 else
533 p5->tte = tte;
534
535 remove(rem_tte);
536 return;
537 }
538 else
539 {
540 // The path is partial there. Create as much as we need, based on
541 // the page size (ps) of the TTE to be inserted.
542
543 if (p5 == fail_page5)
544 {
545 if (n3 == fail_node3)
546 {
547 if (n2 == fail_node2)
548 {
549 n2 = new_node2();
550 n1->insert(va,n2);
551 }
552 n3 = new_node3();
553 n2->insert(va,n3);
554 }
555 p5 = new_page5();
556 n3->insert(va,p5);
557 }
558
559 if (ps == 5)
560 {
561 p5->tte = tte;
562 }
563 else
564 {
565 if (p3 == fail_page3)
566 {
567 p3 = new_page3();
568 p5->insert(va,p3);
569 }
570
571 if (ps == 3)
572 {
573 p3->tte = tte;
574 }
575 else
576 {
577 if (p1 == fail_page1)
578 {
579 p1 = new_page1();
580 p3->insert(va,p1);
581 }
582
583 if (ps == 1)
584 p1->tte = tte;
585 else
586 p1->insert(va,tte);
587 }
588 }
589 }
590
591 // Now invalidate all the TTEs that got autodemapped.
592 // However, don't invalidate the TTE that is selected
593 // by the replacement algorithm to make place for the
594 // new TTE.
595
596 if (p0_tte == rem_tte)
597 rem_tte = 0;
598 else if (p0_tte)
599 {
600 tlb->clr_used(p0_tte->index);
601 tlb->invalidate_tte(strand,p0_tte);
602 }
603
604 if (p1_tte == rem_tte)
605 rem_tte = 0;
606 else if (p1_tte)
607 {
608 tlb->clr_used(p1_tte->index);
609 tlb->invalidate_tte(strand,p1_tte);
610 }
611
612 if (p3_tte == rem_tte)
613 rem_tte = 0;
614 else if (p3_tte)
615 {
616 tlb->clr_used(p3_tte->index);
617 tlb->invalidate_tte(strand,p3_tte);
618 }
619
620 if (p5_tte == rem_tte)
621 rem_tte = 0;
622 else if (p5_tte)
623 {
624 tlb->clr_used(p5_tte->index);
625 tlb->invalidate_tte(strand,p5_tte);
626 }
627
628 // Free up the pages that got copied to make auto-demap
629 // an atomic operation. Note we don;t clear the tte pointers
630 // and we don't demolish the p5 to p3 to p1 path. We
631 // do this so that lookup can detect multi hits properly.
632
633 if (p5_new)
634 del_page5(p5);
635 if (p3_new)
636 del_page3(p3);
637 if (p1_new)
638 del_page1(p1);
639
640 remove(rem_tte);
641}
642/*}}}*/
643void N2_TrieTlb::remove( SS_Tte* tte )/*{{{*/
644{
645 Node1* n1;
646
647 if (tte == 0)
648 return;
649 else if (tte->is_virt())
650 n1 = virt[tte->pid()][tte->context()];
651 else if (tte->is_real())
652 n1 = real[tte->pid()];
653 else
654 return;
655
656 SS_Vaddr va = tte->virt_page;
657 uint_t ps = tte->page_size();
658
659 Node2* n2 = n1->at(va);
660 Node3* n3 = n2->at(va);
661 Page5* p5 = n3->at(va);
662 Page3* p3 = p5->at(va);
663 Page1* p1 = p3->at(va);
664
665 assert(n1 != fail_node1);
666 assert(n2 != fail_node2);
667 assert(n3 != fail_node3);
668 assert(p5 != fail_page5);
669
670 if (ps == 5)
671 {
672 assert((p5->tte == tte) || (p5->tte == 0));
673 p5->tte = 0;
674 }
675 else
676 {
677 assert(p3 != fail_page3);
678
679 if (ps == 3)
680 {
681 assert((p3->tte == tte) || (p3->tte == 0));
682 p3->tte = 0;
683 }
684 else
685 {
686 assert(p1 != fail_page1);
687
688 if (ps == 1)
689 {
690 assert((p1->tte == tte) || (p1->tte == 0));
691 p1->tte = 0;
692 }
693 else
694 {
695 assert(ps == 0);
696 assert((p1->at(va) == tte) || (p1->at(va) == 0));
697 p1->remove(va,0);
698 }
699
700 if (p1->is_empty())
701 {
702 p3->remove(va,fail_page1);
703 del_page1(p1);
704 }
705 }
706
707 if (p3->is_empty())
708 {
709 p5->remove(va,fail_page3);
710 del_page3(p3);
711 }
712 }
713
714 if (p5->is_empty())
715 {
716 n3->remove(va,fail_page5);
717 del_page5(p5);
718
719 if (n3->is_empty())
720 {
721 n2->remove(va,fail_node3);
722 del_node3(n3);
723
724 if (n2->is_empty())
725 {
726 n1->remove(va,fail_node2);
727 del_node2(n2);
728
729 if (n1->is_empty())
730 {
731 if (tte->is_real())
732 real[tte->pid()] = fail_node1;
733 else
734 virt[tte->pid()][tte->context()] = fail_node1;
735 del_node1(n1);
736 }
737 }
738 }
739 }
740}
741/*}}}*/
742
743// demap_trie() remove TTEs from a Trie in an atomic fashion.
744//
745// Lookup searches with va from largest TTE to smaller TTE.
746// When demapping we remove TTEs from smaller to largest.
747// This way the TTE found by lookup is always the largest or
748// one that persist after the demap, e.g. it makes the demap
749// appear atomic.
750
751bool N2_TrieTlb::demap_trie( SS_Strand* strand, Node1* n1, SS_Vaddr va )/*{{{*/
752{
753 Node2* n2 = n1->at(va);
754 Node3* n3 = n2->at(va);
755 Page5* p5 = n3->at(va);
756 Page3* p3 = p5->at(va);
757 Page1* p1 = p3->at(va);
758
759 SS_Tte* tte;
760
761 if ((tte = p1->at(va)))
762 {
763 p1->remove(va,0);
764 tlb->clr_used(tte->index);
765 tlb->invalidate_tte(strand,tte);
766 }
767
768 if ((tte = p1->tte))
769 {
770 p1->tte = 0;
771 tlb->clr_used(tte->index);
772 tlb->invalidate_tte(strand,tte);
773 }
774
775 if (p1->is_empty())
776 {
777 p3->remove(va,fail_page1);
778 del_page1(p1);
779 }
780
781 if ((tte = p3->tte))
782 {
783 p3->tte = 0;
784 tlb->clr_used(tte->index);
785 tlb->invalidate_tte(strand,tte);
786 }
787
788 if (p3->is_empty())
789 {
790 p5->remove(va,fail_page3);
791 del_page3(p3);
792 }
793
794 if ((tte = p5->tte))
795 {
796 p5->tte = 0;
797 tlb->clr_used(tte->index);
798 tlb->invalidate_tte(strand,tte);
799 }
800
801 if (p5->is_empty())
802 {
803 n3->remove(va,fail_page5);
804 del_page5(p5);
805 }
806
807 if (n3->is_empty())
808 {
809 n2->remove(va,fail_node3);
810 del_node3(n3);
811 }
812
813 if (n2->is_empty())
814 {
815 n1->remove(va,fail_node2);
816 del_node2(n2);
817 }
818
819 if (n1->is_empty())
820 {
821 del_node1(n1);
822 return true;
823 }
824
825 return false;
826}
827/*}}}*/
828
829void N2_TrieTlb::demap_trie( SS_Strand* strand, Node1* n1 )/*{{{*/
830{
831 assert(n1 != fail_node1);
832
833 if (!n1->is_empty_trie())
834 {
835 for (uint_t i=0; i < Node1::SIZE; i++)
836 {
837 Node2* n2 = n1->idx(i);
838 if (n2 == fail_node2)
839 continue;
840 n1->remove(i,fail_node2);
841 demap_trie(strand,n2);
842 }
843 }
844
845 del_node1(n1);
846}
847/*}}}*/
848void N2_TrieTlb::demap_trie( SS_Strand* strand, Node2* n2 )/*{{{*/
849{
850 assert(n2 != fail_node2);
851
852 if (!n2->is_empty_trie())
853 {
854 for (uint_t i=0; i < Node2::SIZE; i++)
855 {
856 Node3* n3 = n2->idx(i);
857 if (n3 == fail_node3)
858 continue;
859 n2->remove(i,fail_node3);
860 demap_trie(strand,n3);
861 }
862 }
863
864 del_node2(n2);
865}
866/*}}}*/
867void N2_TrieTlb::demap_trie( SS_Strand* strand, Node3* n3 )/*{{{*/
868{
869 assert(n3 != fail_node3);
870
871 if (!n3->is_empty_trie())
872 {
873 for (uint_t i=0; i < Node3::SIZE; i++)
874 {
875 Page5* p5 = n3->idx(i);
876 if (p5 == fail_page5)
877 continue;
878 n3->remove(i,fail_page5);
879 demap_trie(strand,p5);
880 }
881 }
882
883 del_node3(n3);
884}
885/*}}}*/
886void N2_TrieTlb::demap_trie( SS_Strand* strand, Page5* p5 )/*{{{*/
887{
888 assert(p5 != fail_page5);
889
890 SS_Tte* tte;
891
892 if (!p5->is_empty_trie())
893 {
894 for (uint_t i=0; i < Page5::SIZE; i++)
895 {
896 Page3* p3 = p5->idx(i);
897 if (p3 == fail_page3)
898 continue;
899 p5->remove(i,fail_page3);
900 demap_trie(strand,p3);
901 }
902 }
903
904 if ((tte = p5->tte))
905 {
906 p5->tte = 0;
907 if (strand)
908 {
909 tlb->clr_used(tte->index);
910 tlb->invalidate_tte(strand,tte);
911 }
912 }
913
914 del_page5(p5);
915}
916/*}}}*/
917void N2_TrieTlb::demap_trie( SS_Strand* strand, Page3* p3 )/*{{{*/
918{
919 assert(p3 != fail_page3);
920
921 SS_Tte* tte;
922
923 if (!p3->is_empty_trie())
924 {
925 for (uint_t i=0; i < Page3::SIZE; i++)
926 {
927 Page1* p1 = p3->idx(i);
928 if (p1 == fail_page1)
929 continue;
930 p3->remove(i,fail_page1);
931 demap_trie(strand,p1);
932 }
933 }
934
935 if ((tte = p3->tte))
936 {
937 p3->tte = 0;
938 if (strand)
939 {
940 tlb->clr_used(tte->index);
941 tlb->invalidate_tte(strand,tte);
942 }
943 }
944
945 del_page3(p3);
946}
947/*}}}*/
948void N2_TrieTlb::demap_trie( SS_Strand* strand, Page1* p1 )/*{{{*/
949{
950 assert(p1 != fail_page1);
951
952 SS_Tte* tte;
953
954 if (!p1->is_empty_trie())
955 {
956 for (uint_t i=0; i < Page1::SIZE; i++)
957 {
958 if ((tte = p1->idx(i)))
959 {
960 p1->remove(i,0);
961 if (strand)
962 {
963 tlb->clr_used(tte->index);
964 tlb->invalidate_tte(strand,tte);
965 }
966 }
967 }
968 }
969
970 if ((tte = p1->tte))
971 {
972 p1->tte = 0;
973 if (strand)
974 {
975 tlb->clr_used(tte->index);
976 tlb->invalidate_tte(strand,tte);
977 }
978 }
979
980 del_page1(p1);
981}
982/*}}}*/
983
984void N2_TrieTlb::demap_virt( SS_Strand* strand, uint_t pid, uint_t ctx, SS_Vaddr va )/*{{{*/
985{
986 Node1* n1 = virt[pid][ctx];
987 if (demap_trie(strand,n1,va))
988 virt[pid][ctx] = fail_node1;
989}
990/*}}}*/
991void N2_TrieTlb::demap_virt( SS_Strand* strand, uint_t pid, uint_t ctx )/*{{{*/
992{
993 Node1* n1 = virt[pid][ctx];
994 virt[pid][ctx] = fail_node1;
995 if (n1 != fail_node1)
996 demap_trie(strand,n1);
997}
998/*}}}*/
999void N2_TrieTlb::demap_virt( SS_Strand* strand, uint_t pid )/*{{{*/
1000{
1001 for (uint_t ctx=0; ctx < CTX_SIZE; ctx++)
1002 demap_virt(strand,pid,ctx);
1003}
1004/*}}}*/
1005
1006void N2_TrieTlb::demap_real( SS_Strand* strand, uint_t pid, SS_Vaddr ra )/*{{{*/
1007{
1008 Node1* n1 = real[pid];
1009 if (demap_trie(strand,n1,ra))
1010 real[pid] = fail_node1;
1011}
1012/*}}}*/
1013void N2_TrieTlb::demap_real( SS_Strand* strand, uint_t pid )/*{{{*/
1014{
1015 Node1* n1 = real[pid];
1016 real[pid] = fail_node1;
1017 if (n1 != fail_node1)
1018 demap_trie(strand,n1);
1019}
1020/*}}}*/
1021
1022void N2_TrieTlb::demap_all( SS_Strand* strand, uint_t pid )/*{{{*/
1023{
1024 demap_virt(strand,pid);
1025 demap_real(strand,pid);
1026}
1027/*}}}*/