2 * Copyright (c) 2009 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "arch/sparc/asi.hh"
32 #include "arch/sparc/isa.hh"
33 #include "base/bitfield.hh"
34 #include "base/trace.hh"
35 #include "config/full_system.hh"
36 #include "cpu/base.hh"
37 #include "cpu/thread_context.hh"
44 PSTATE_MASK
= (((1 << 4) - 1) << 1) | (((1 << 4) - 1) << 6) | (1 << 12)
60 memset(tpc
, 0, sizeof(tpc
));
61 memset(tnpc
, 0, sizeof(tnpc
));
62 memset(tstate
, 0, sizeof(tstate
));
63 memset(tt
, 0, sizeof(tt
));
74 //In a T1, bit 11 is apparently always 1
76 memset(htstate
, 0, sizeof(htstate
));
80 //This is set this way in Legion for some reason
81 strandStatusReg
= 0x50000;
89 memset(scratchPad
, 0, sizeof(scratchPad
));
98 ISA::readMiscRegNoEffect(int miscReg
)
101 // The three miscRegs are moved up from the switch statement
102 // due to more frequent calls.
104 if (miscReg
== MISCREG_GL
)
106 if (miscReg
== MISCREG_CWP
)
108 if (miscReg
== MISCREG_TLB_DATA
) {
109 /* Package up all the data for the tlb:
110 * 6666555555555544444444443333333333222222222211111111110000000000
111 * 3210987654321098765432109876543210987654321098765432109876543210
112 * secContext | priContext | |tl|partid| |||||^hpriv
119 return bits((uint64_t)hpstate
,2,2) |
120 bits((uint64_t)hpstate
,5,5) << 1 |
121 bits((uint64_t)pstate
,3,2) << 2 |
122 bits((uint64_t)lsuCtrlReg
,3,2) << 4 |
123 bits((uint64_t)partId
,7,0) << 8 |
124 bits((uint64_t)tl
,2,0) << 16 |
125 (uint64_t)priContext
<< 32 |
126 (uint64_t)secContext
<< 48;
130 //case MISCREG_TLB_DATA:
131 // [original contents see above]
143 panic("PCR not implemented\n");
145 panic("PIC not implemented\n");
148 case MISCREG_SOFTINT
:
150 case MISCREG_TICK_CMPR
:
154 case MISCREG_STICK_CMPR
:
157 /** Privilged Registers */
166 case MISCREG_PRIVTICK
:
167 panic("Priviliged access to tick registers not implemented\n");
179 //case MISCREG_CANSAVE:
181 //case MISCREG_CANRESTORE:
182 // return canrestore;
183 //case MISCREG_CLEANWIN:
185 //case MISCREG_OTHERWIN:
187 //case MISCREG_WSTATE:
192 /** Hyper privileged registers */
193 case MISCREG_HPSTATE
:
195 case MISCREG_HTSTATE
:
196 return htstate
[tl
-1];
201 case MISCREG_STRAND_STS_REG
:
202 return strandStatusReg
;
203 case MISCREG_HSTICK_CMPR
:
206 /** Floating Point Status Register */
208 DPRINTF(MiscRegs
, "FSR read as: %#x\n", fsr
);
211 case MISCREG_MMU_P_CONTEXT
:
213 case MISCREG_MMU_S_CONTEXT
:
215 case MISCREG_MMU_PART_ID
:
217 case MISCREG_MMU_LSU_CTRL
:
220 case MISCREG_SCRATCHPAD_R0
:
221 return scratchPad
[0];
222 case MISCREG_SCRATCHPAD_R1
:
223 return scratchPad
[1];
224 case MISCREG_SCRATCHPAD_R2
:
225 return scratchPad
[2];
226 case MISCREG_SCRATCHPAD_R3
:
227 return scratchPad
[3];
228 case MISCREG_SCRATCHPAD_R4
:
229 return scratchPad
[4];
230 case MISCREG_SCRATCHPAD_R5
:
231 return scratchPad
[5];
232 case MISCREG_SCRATCHPAD_R6
:
233 return scratchPad
[6];
234 case MISCREG_SCRATCHPAD_R7
:
235 return scratchPad
[7];
236 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
237 return cpu_mondo_head
;
238 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
239 return cpu_mondo_tail
;
240 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
241 return dev_mondo_head
;
242 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
243 return dev_mondo_tail
;
244 case MISCREG_QUEUE_RES_ERROR_HEAD
:
245 return res_error_head
;
246 case MISCREG_QUEUE_RES_ERROR_TAIL
:
247 return res_error_tail
;
248 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
249 return nres_error_head
;
250 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
251 return nres_error_tail
;
253 panic("Miscellaneous register %d not implemented\n", miscReg
);
258 ISA::readMiscReg(int miscReg
, ThreadContext
* tc
)
261 // tick and stick are aliased to each other in niagra
262 // well store the tick data in stick and the interrupt bit in tick
265 case MISCREG_PRIVTICK
:
266 // I'm not sure why legion ignores the lowest two bits, but we'll go
268 // change from curCycle() to instCount() until we're done with legion
269 DPRINTF(Timer
, "Instruction Count when TICK read: %#X stick=%#X\n",
270 tc
->getCpuPtr()->instCount(), stick
);
271 return mbits(tc
->getCpuPtr()->instCount() + (int64_t)stick
,62,2) |
274 // in legion if fp is enabled du and dl are set
278 panic("Performance Instrumentation not impl\n");
279 case MISCREG_SOFTINT_CLR
:
280 case MISCREG_SOFTINT_SET
:
281 panic("Can read from softint clr/set\n");
282 case MISCREG_SOFTINT
:
283 case MISCREG_TICK_CMPR
:
284 case MISCREG_STICK_CMPR
:
286 case MISCREG_HTSTATE
:
289 case MISCREG_STRAND_STS_REG
:
290 case MISCREG_HSTICK_CMPR
:
291 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
292 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
293 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
294 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
295 case MISCREG_QUEUE_RES_ERROR_HEAD
:
296 case MISCREG_QUEUE_RES_ERROR_TAIL
:
297 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
298 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
300 case MISCREG_HPSTATE
:
301 return readFSReg(miscReg
, tc
);
303 case MISCREG_HPSTATE
:
304 //HPSTATE is special because because sometimes in privilege
305 //checks for instructions it will read HPSTATE to make sure
306 //the priv. level is ok So, we'll just have to tell it it
307 //isn't, instead of panicing.
310 panic("Accessing Fullsystem register %d in SE mode\n", miscReg
);
314 return readMiscRegNoEffect(miscReg
);
318 ISA::setMiscRegNoEffect(int miscReg
, MiscReg val
)
337 panic("PCR not implemented\n");
339 panic("PIC not implemented\n");
343 case MISCREG_SOFTINT
:
346 case MISCREG_TICK_CMPR
:
352 case MISCREG_STICK_CMPR
:
356 /** Privilged Registers */
369 case MISCREG_PRIVTICK
:
370 panic("Priviliged access to tick regesiters not implemented\n");
372 // clear lower 7 bits on writes.
373 tba
= val
& ULL(~0x7FFF);
376 pstate
= (val
& PSTATE_MASK
);
387 // case MISCREG_CANSAVE:
390 // case MISCREG_CANRESTORE:
393 // case MISCREG_CLEANWIN:
396 // case MISCREG_OTHERWIN:
399 // case MISCREG_WSTATE:
406 /** Hyper privileged registers */
407 case MISCREG_HPSTATE
:
410 case MISCREG_HTSTATE
:
418 case MISCREG_STRAND_STS_REG
:
419 strandStatusReg
= val
;
421 case MISCREG_HSTICK_CMPR
:
425 /** Floating Point Status Register */
428 DPRINTF(MiscRegs
, "FSR written with: %#x\n", fsr
);
431 case MISCREG_MMU_P_CONTEXT
:
434 case MISCREG_MMU_S_CONTEXT
:
437 case MISCREG_MMU_PART_ID
:
440 case MISCREG_MMU_LSU_CTRL
:
444 case MISCREG_SCRATCHPAD_R0
:
447 case MISCREG_SCRATCHPAD_R1
:
450 case MISCREG_SCRATCHPAD_R2
:
453 case MISCREG_SCRATCHPAD_R3
:
456 case MISCREG_SCRATCHPAD_R4
:
459 case MISCREG_SCRATCHPAD_R5
:
462 case MISCREG_SCRATCHPAD_R6
:
465 case MISCREG_SCRATCHPAD_R7
:
468 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
469 cpu_mondo_head
= val
;
471 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
472 cpu_mondo_tail
= val
;
474 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
475 dev_mondo_head
= val
;
477 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
478 dev_mondo_tail
= val
;
480 case MISCREG_QUEUE_RES_ERROR_HEAD
:
481 res_error_head
= val
;
483 case MISCREG_QUEUE_RES_ERROR_TAIL
:
484 res_error_tail
= val
;
486 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
487 nres_error_head
= val
;
489 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
490 nres_error_tail
= val
;
493 panic("Miscellaneous register %d not implemented\n", miscReg
);
498 ISA::setMiscReg(int miscReg
, MiscReg val
, ThreadContext
* tc
)
500 MiscReg new_val
= val
;
505 // stick and tick are same thing on niagra
506 // use stick for offset and tick for holding intrrupt bit
507 stick
= mbits(val
,62,0) - tc
->getCpuPtr()->instCount();
508 tick
= mbits(val
,63,63);
509 DPRINTF(Timer
, "Writing TICK=%#X\n", val
);
512 //Configure the fpu based on the fprs
515 //Set up performance counting based on pcr value
518 pstate
= val
& PSTATE_MASK
;
523 if (hpstate
& HPSTATE::tlz
&& tl
== 0 && !(hpstate
& HPSTATE::hpriv
))
524 tc
->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
526 tc
->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
530 new_val
= val
>= NWindows
? NWindows
- 1 : val
;
532 new_val
= NWindows
- 1;
537 case MISCREG_SOFTINT
:
538 case MISCREG_SOFTINT_SET
:
539 case MISCREG_SOFTINT_CLR
:
540 case MISCREG_TICK_CMPR
:
541 case MISCREG_STICK_CMPR
:
543 case MISCREG_HTSTATE
:
546 case MISCREG_STRAND_STS_REG
:
547 case MISCREG_HSTICK_CMPR
:
548 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
549 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
550 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
551 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
552 case MISCREG_QUEUE_RES_ERROR_HEAD
:
553 case MISCREG_QUEUE_RES_ERROR_TAIL
:
554 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
555 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
557 case MISCREG_HPSTATE
:
558 setFSReg(miscReg
, val
, tc
);
561 case MISCREG_HPSTATE
:
562 //HPSTATE is special because normal trap processing saves HPSTATE when
563 //it goes into a trap, and restores it when it returns.
565 panic("Accessing Fullsystem register %d to %#x in SE mode\n",
569 setMiscRegNoEffect(miscReg
, new_val
);
573 ISA::serialize(EventManager
*em
, std::ostream
&os
)
575 SERIALIZE_SCALAR(asi
);
576 SERIALIZE_SCALAR(tick
);
577 SERIALIZE_SCALAR(fprs
);
578 SERIALIZE_SCALAR(gsr
);
579 SERIALIZE_SCALAR(softint
);
580 SERIALIZE_SCALAR(tick_cmpr
);
581 SERIALIZE_SCALAR(stick
);
582 SERIALIZE_SCALAR(stick_cmpr
);
583 SERIALIZE_ARRAY(tpc
,MaxTL
);
584 SERIALIZE_ARRAY(tnpc
,MaxTL
);
585 SERIALIZE_ARRAY(tstate
,MaxTL
);
586 SERIALIZE_ARRAY(tt
,MaxTL
);
587 SERIALIZE_SCALAR(tba
);
588 SERIALIZE_SCALAR(pstate
);
589 SERIALIZE_SCALAR(tl
);
590 SERIALIZE_SCALAR(pil
);
591 SERIALIZE_SCALAR(cwp
);
592 SERIALIZE_SCALAR(gl
);
593 SERIALIZE_SCALAR(hpstate
);
594 SERIALIZE_ARRAY(htstate
,MaxTL
);
595 SERIALIZE_SCALAR(hintp
);
596 SERIALIZE_SCALAR(htba
);
597 SERIALIZE_SCALAR(hstick_cmpr
);
598 SERIALIZE_SCALAR(strandStatusReg
);
599 SERIALIZE_SCALAR(fsr
);
600 SERIALIZE_SCALAR(priContext
);
601 SERIALIZE_SCALAR(secContext
);
602 SERIALIZE_SCALAR(partId
);
603 SERIALIZE_SCALAR(lsuCtrlReg
);
604 SERIALIZE_ARRAY(scratchPad
,8);
605 SERIALIZE_SCALAR(cpu_mondo_head
);
606 SERIALIZE_SCALAR(cpu_mondo_tail
);
607 SERIALIZE_SCALAR(dev_mondo_head
);
608 SERIALIZE_SCALAR(dev_mondo_tail
);
609 SERIALIZE_SCALAR(res_error_head
);
610 SERIALIZE_SCALAR(res_error_tail
);
611 SERIALIZE_SCALAR(nres_error_head
);
612 SERIALIZE_SCALAR(nres_error_tail
);
614 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
615 ThreadContext
*tc
= NULL
;
618 bool tick_intr_sched
= true;
621 tc
= tickCompare
->getTC();
622 else if (sTickCompare
)
623 tc
= sTickCompare
->getTC();
624 else if (hSTickCompare
)
625 tc
= hSTickCompare
->getTC();
627 tick_intr_sched
= false;
629 SERIALIZE_SCALAR(tick_intr_sched
);
632 cpu
= tc
->getCpuPtr();
633 tc_num
= cpu
->findContext(tc
);
634 if (tickCompare
&& tickCompare
->scheduled())
635 tick_cmp
= tickCompare
->when();
636 if (sTickCompare
&& sTickCompare
->scheduled())
637 stick_cmp
= sTickCompare
->when();
638 if (hSTickCompare
&& hSTickCompare
->scheduled())
639 hstick_cmp
= hSTickCompare
->when();
641 SERIALIZE_OBJPTR(cpu
);
642 SERIALIZE_SCALAR(tc_num
);
643 SERIALIZE_SCALAR(tick_cmp
);
644 SERIALIZE_SCALAR(stick_cmp
);
645 SERIALIZE_SCALAR(hstick_cmp
);
651 ISA::unserialize(EventManager
*em
, Checkpoint
*cp
, const std::string
§ion
)
653 UNSERIALIZE_SCALAR(asi
);
654 UNSERIALIZE_SCALAR(tick
);
655 UNSERIALIZE_SCALAR(fprs
);
656 UNSERIALIZE_SCALAR(gsr
);
657 UNSERIALIZE_SCALAR(softint
);
658 UNSERIALIZE_SCALAR(tick_cmpr
);
659 UNSERIALIZE_SCALAR(stick
);
660 UNSERIALIZE_SCALAR(stick_cmpr
);
661 UNSERIALIZE_ARRAY(tpc
,MaxTL
);
662 UNSERIALIZE_ARRAY(tnpc
,MaxTL
);
663 UNSERIALIZE_ARRAY(tstate
,MaxTL
);
664 UNSERIALIZE_ARRAY(tt
,MaxTL
);
665 UNSERIALIZE_SCALAR(tba
);
666 UNSERIALIZE_SCALAR(pstate
);
667 UNSERIALIZE_SCALAR(tl
);
668 UNSERIALIZE_SCALAR(pil
);
669 UNSERIALIZE_SCALAR(cwp
);
670 UNSERIALIZE_SCALAR(gl
);
671 UNSERIALIZE_SCALAR(hpstate
);
672 UNSERIALIZE_ARRAY(htstate
,MaxTL
);
673 UNSERIALIZE_SCALAR(hintp
);
674 UNSERIALIZE_SCALAR(htba
);
675 UNSERIALIZE_SCALAR(hstick_cmpr
);
676 UNSERIALIZE_SCALAR(strandStatusReg
);
677 UNSERIALIZE_SCALAR(fsr
);
678 UNSERIALIZE_SCALAR(priContext
);
679 UNSERIALIZE_SCALAR(secContext
);
680 UNSERIALIZE_SCALAR(partId
);
681 UNSERIALIZE_SCALAR(lsuCtrlReg
);
682 UNSERIALIZE_ARRAY(scratchPad
,8);
683 UNSERIALIZE_SCALAR(cpu_mondo_head
);
684 UNSERIALIZE_SCALAR(cpu_mondo_tail
);
685 UNSERIALIZE_SCALAR(dev_mondo_head
);
686 UNSERIALIZE_SCALAR(dev_mondo_tail
);
687 UNSERIALIZE_SCALAR(res_error_head
);
688 UNSERIALIZE_SCALAR(res_error_tail
);
689 UNSERIALIZE_SCALAR(nres_error_head
);
690 UNSERIALIZE_SCALAR(nres_error_tail
);
693 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
694 ThreadContext
*tc
= NULL
;
697 bool tick_intr_sched
;
698 UNSERIALIZE_SCALAR(tick_intr_sched
);
699 if (tick_intr_sched
) {
700 UNSERIALIZE_OBJPTR(cpu
);
702 UNSERIALIZE_SCALAR(tc_num
);
703 UNSERIALIZE_SCALAR(tick_cmp
);
704 UNSERIALIZE_SCALAR(stick_cmp
);
705 UNSERIALIZE_SCALAR(hstick_cmp
);
706 tc
= cpu
->getContext(tc_num
);
709 tickCompare
= new TickCompareEvent(this, tc
);
710 em
->schedule(tickCompare
, tick_cmp
);
713 sTickCompare
= new STickCompareEvent(this, tc
);
714 em
->schedule(sTickCompare
, stick_cmp
);
717 hSTickCompare
= new HSTickCompareEvent(this, tc
);
718 em
->schedule(hSTickCompare
, hstick_cmp
);
727 ISA::flattenIntIndex(int reg
)
729 int gl
= readMiscRegNoEffect(MISCREG_GL
);
730 int cwp
= readMiscRegNoEffect(MISCREG_CWP
);
731 //DPRINTF(RegisterWindows, "Global Level = %d, Current Window Pointer = %d\n", gl, cwp);
733 //The total number of global registers
734 int numGlobals
= (MaxGL
+ 1) * 8;
738 //Put it in the appropriate set of globals
739 newReg
= reg
+ gl
* 8;
741 else if(reg
< NumIntArchRegs
)
743 //Regular windowed register
744 //Put it in the window pointed to by cwp
745 newReg
= numGlobals
+
746 ((reg
- 8 - cwp
* 16 + NWindows
* 16) % (NWindows
* 16));
748 else if(reg
< NumIntArchRegs
+ NumMicroIntRegs
)
751 //Displace from the end of the regular registers
752 newReg
= reg
- NumIntArchRegs
+ numGlobals
+ NWindows
* 16;
754 else if(reg
< 2 * NumIntArchRegs
+ NumMicroIntRegs
)
756 reg
-= (NumIntArchRegs
+ NumMicroIntRegs
);
759 //Global register from the next window
760 //Put it in the appropriate set of globals
761 newReg
= reg
+ gl
* 8;
765 //Windowed register from the previous window
766 //Put it in the window before the one pointed to by cwp
767 newReg
= numGlobals
+
768 ((reg
- 8 - (cwp
- 1) * 16 + NWindows
* 16) % (NWindows
* 16));
771 else if(reg
< 3 * NumIntArchRegs
+ NumMicroIntRegs
)
773 reg
-= (2 * NumIntArchRegs
+ NumMicroIntRegs
);
776 //Global register from the previous window
777 //Put it in the appropriate set of globals
778 newReg
= reg
+ gl
* 8;
782 //Windowed register from the next window
783 //Put it in the window after the one pointed to by cwp
784 newReg
= numGlobals
+
785 ((reg
- 8 - (cwp
+ 1) * 16 + NWindows
* 16) % (NWindows
* 16));
789 panic("Tried to flatten invalid register index %d!\n", reg
);
790 DPRINTF(RegisterWindows
, "Flattened register %d to %d.\n", reg
, newReg
);