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)
50 installGlobals(gl
, CurrentGlobalsOffset
);
51 installWindow(cwp
, CurrentWindowOffset
);
52 // Microcode registers.
53 for (int i
= 0; i
< NumMicroIntRegs
; i
++)
54 intRegMap
[MicroIntOffset
+ i
] = i
+ TotalGlobals
+ NWindows
* 16;
55 installGlobals(gl
, NextGlobalsOffset
);
56 installWindow(cwp
- 1, NextWindowOffset
);
57 installGlobals(gl
, PreviousGlobalsOffset
);
58 installWindow(cwp
+ 1, PreviousWindowOffset
);
62 ISA::installWindow(int cwp
, int offset
)
64 assert(offset
>= 0 && offset
+ NumWindowedRegs
<= NumIntRegs
);
65 RegIndex
*mapChunk
= intRegMap
+ offset
;
66 for (int i
= 0; i
< NumWindowedRegs
; i
++)
67 mapChunk
[i
] = TotalGlobals
+
68 ((i
- cwp
* RegsPerWindow
+ TotalWindowed
) % (TotalWindowed
));
72 ISA::installGlobals(int gl
, int offset
)
74 assert(offset
>= 0 && offset
+ NumGlobalRegs
<= NumIntRegs
);
75 RegIndex
*mapChunk
= intRegMap
+ offset
;
77 for (int i
= 1; i
< NumGlobalRegs
; i
++)
78 mapChunk
[i
] = i
+ gl
* NumGlobalRegs
;
98 memset(tpc
, 0, sizeof(tpc
));
99 memset(tnpc
, 0, sizeof(tnpc
));
100 memset(tstate
, 0, sizeof(tstate
));
101 memset(tt
, 0, sizeof(tt
));
110 //In a T1, bit 11 is apparently always 1
112 memset(htstate
, 0, sizeof(htstate
));
116 //This is set this way in Legion for some reason
117 strandStatusReg
= 0x50000;
125 memset(scratchPad
, 0, sizeof(scratchPad
));
129 hSTickCompare
= NULL
;
134 ISA::readMiscRegNoEffect(int miscReg
)
137 // The three miscRegs are moved up from the switch statement
138 // due to more frequent calls.
140 if (miscReg
== MISCREG_GL
)
142 if (miscReg
== MISCREG_CWP
)
144 if (miscReg
== MISCREG_TLB_DATA
) {
145 /* Package up all the data for the tlb:
146 * 6666555555555544444444443333333333222222222211111111110000000000
147 * 3210987654321098765432109876543210987654321098765432109876543210
148 * secContext | priContext | |tl|partid| |||||^hpriv
155 return bits((uint64_t)hpstate
,2,2) |
156 bits((uint64_t)hpstate
,5,5) << 1 |
157 bits((uint64_t)pstate
,3,2) << 2 |
158 bits((uint64_t)lsuCtrlReg
,3,2) << 4 |
159 bits((uint64_t)partId
,7,0) << 8 |
160 bits((uint64_t)tl
,2,0) << 16 |
161 (uint64_t)priContext
<< 32 |
162 (uint64_t)secContext
<< 48;
166 //case MISCREG_TLB_DATA:
167 // [original contents see above]
179 panic("PCR not implemented\n");
181 panic("PIC not implemented\n");
184 case MISCREG_SOFTINT
:
186 case MISCREG_TICK_CMPR
:
190 case MISCREG_STICK_CMPR
:
193 /** Privilged Registers */
202 case MISCREG_PRIVTICK
:
203 panic("Priviliged access to tick registers not implemented\n");
215 //case MISCREG_CANSAVE:
217 //case MISCREG_CANRESTORE:
218 // return canrestore;
219 //case MISCREG_CLEANWIN:
221 //case MISCREG_OTHERWIN:
223 //case MISCREG_WSTATE:
228 /** Hyper privileged registers */
229 case MISCREG_HPSTATE
:
231 case MISCREG_HTSTATE
:
232 return htstate
[tl
-1];
237 case MISCREG_STRAND_STS_REG
:
238 return strandStatusReg
;
239 case MISCREG_HSTICK_CMPR
:
242 /** Floating Point Status Register */
244 DPRINTF(MiscRegs
, "FSR read as: %#x\n", fsr
);
247 case MISCREG_MMU_P_CONTEXT
:
249 case MISCREG_MMU_S_CONTEXT
:
251 case MISCREG_MMU_PART_ID
:
253 case MISCREG_MMU_LSU_CTRL
:
256 case MISCREG_SCRATCHPAD_R0
:
257 return scratchPad
[0];
258 case MISCREG_SCRATCHPAD_R1
:
259 return scratchPad
[1];
260 case MISCREG_SCRATCHPAD_R2
:
261 return scratchPad
[2];
262 case MISCREG_SCRATCHPAD_R3
:
263 return scratchPad
[3];
264 case MISCREG_SCRATCHPAD_R4
:
265 return scratchPad
[4];
266 case MISCREG_SCRATCHPAD_R5
:
267 return scratchPad
[5];
268 case MISCREG_SCRATCHPAD_R6
:
269 return scratchPad
[6];
270 case MISCREG_SCRATCHPAD_R7
:
271 return scratchPad
[7];
272 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
273 return cpu_mondo_head
;
274 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
275 return cpu_mondo_tail
;
276 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
277 return dev_mondo_head
;
278 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
279 return dev_mondo_tail
;
280 case MISCREG_QUEUE_RES_ERROR_HEAD
:
281 return res_error_head
;
282 case MISCREG_QUEUE_RES_ERROR_TAIL
:
283 return res_error_tail
;
284 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
285 return nres_error_head
;
286 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
287 return nres_error_tail
;
289 panic("Miscellaneous register %d not implemented\n", miscReg
);
294 ISA::readMiscReg(int miscReg
, ThreadContext
* tc
)
297 // tick and stick are aliased to each other in niagra
298 // well store the tick data in stick and the interrupt bit in tick
301 case MISCREG_PRIVTICK
:
302 // I'm not sure why legion ignores the lowest two bits, but we'll go
304 // change from curCycle() to instCount() until we're done with legion
305 DPRINTF(Timer
, "Instruction Count when TICK read: %#X stick=%#X\n",
306 tc
->getCpuPtr()->instCount(), stick
);
307 return mbits(tc
->getCpuPtr()->instCount() + (int64_t)stick
,62,2) |
310 // in legion if fp is enabled du and dl are set
314 panic("Performance Instrumentation not impl\n");
315 case MISCREG_SOFTINT_CLR
:
316 case MISCREG_SOFTINT_SET
:
317 panic("Can read from softint clr/set\n");
318 case MISCREG_SOFTINT
:
319 case MISCREG_TICK_CMPR
:
320 case MISCREG_STICK_CMPR
:
322 case MISCREG_HTSTATE
:
325 case MISCREG_STRAND_STS_REG
:
326 case MISCREG_HSTICK_CMPR
:
327 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
328 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
329 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
330 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
331 case MISCREG_QUEUE_RES_ERROR_HEAD
:
332 case MISCREG_QUEUE_RES_ERROR_TAIL
:
333 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
334 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
336 case MISCREG_HPSTATE
:
337 return readFSReg(miscReg
, tc
);
339 case MISCREG_HPSTATE
:
340 //HPSTATE is special because because sometimes in privilege
341 //checks for instructions it will read HPSTATE to make sure
342 //the priv. level is ok So, we'll just have to tell it it
343 //isn't, instead of panicing.
346 panic("Accessing Fullsystem register %d in SE mode\n", miscReg
);
350 return readMiscRegNoEffect(miscReg
);
354 ISA::setMiscRegNoEffect(int miscReg
, MiscReg val
)
373 panic("PCR not implemented\n");
375 panic("PIC not implemented\n");
379 case MISCREG_SOFTINT
:
382 case MISCREG_TICK_CMPR
:
388 case MISCREG_STICK_CMPR
:
392 /** Privilged Registers */
405 case MISCREG_PRIVTICK
:
406 panic("Priviliged access to tick regesiters not implemented\n");
408 // clear lower 7 bits on writes.
409 tba
= val
& ULL(~0x7FFF);
412 pstate
= (val
& PSTATE_MASK
);
423 // case MISCREG_CANSAVE:
426 // case MISCREG_CANRESTORE:
429 // case MISCREG_CLEANWIN:
432 // case MISCREG_OTHERWIN:
435 // case MISCREG_WSTATE:
442 /** Hyper privileged registers */
443 case MISCREG_HPSTATE
:
446 case MISCREG_HTSTATE
:
454 case MISCREG_STRAND_STS_REG
:
455 strandStatusReg
= val
;
457 case MISCREG_HSTICK_CMPR
:
461 /** Floating Point Status Register */
464 DPRINTF(MiscRegs
, "FSR written with: %#x\n", fsr
);
467 case MISCREG_MMU_P_CONTEXT
:
470 case MISCREG_MMU_S_CONTEXT
:
473 case MISCREG_MMU_PART_ID
:
476 case MISCREG_MMU_LSU_CTRL
:
480 case MISCREG_SCRATCHPAD_R0
:
483 case MISCREG_SCRATCHPAD_R1
:
486 case MISCREG_SCRATCHPAD_R2
:
489 case MISCREG_SCRATCHPAD_R3
:
492 case MISCREG_SCRATCHPAD_R4
:
495 case MISCREG_SCRATCHPAD_R5
:
498 case MISCREG_SCRATCHPAD_R6
:
501 case MISCREG_SCRATCHPAD_R7
:
504 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
505 cpu_mondo_head
= val
;
507 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
508 cpu_mondo_tail
= val
;
510 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
511 dev_mondo_head
= val
;
513 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
514 dev_mondo_tail
= val
;
516 case MISCREG_QUEUE_RES_ERROR_HEAD
:
517 res_error_head
= val
;
519 case MISCREG_QUEUE_RES_ERROR_TAIL
:
520 res_error_tail
= val
;
522 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
523 nres_error_head
= val
;
525 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
526 nres_error_tail
= val
;
529 panic("Miscellaneous register %d not implemented\n", miscReg
);
534 ISA::setMiscReg(int miscReg
, MiscReg val
, ThreadContext
* tc
)
536 MiscReg new_val
= val
;
541 // stick and tick are same thing on niagra
542 // use stick for offset and tick for holding intrrupt bit
543 stick
= mbits(val
,62,0) - tc
->getCpuPtr()->instCount();
544 tick
= mbits(val
,63,63);
545 DPRINTF(Timer
, "Writing TICK=%#X\n", val
);
548 //Configure the fpu based on the fprs
551 //Set up performance counting based on pcr value
554 pstate
= val
& PSTATE_MASK
;
559 if (hpstate
& HPSTATE::tlz
&& tl
== 0 && !(hpstate
& HPSTATE::hpriv
))
560 tc
->getCpuPtr()->postInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
562 tc
->getCpuPtr()->clearInterrupt(IT_TRAP_LEVEL_ZERO
, 0);
566 new_val
= val
>= NWindows
? NWindows
- 1 : val
;
568 new_val
= NWindows
- 1;
570 installWindow(new_val
, CurrentWindowOffset
);
571 installWindow(new_val
- 1, NextWindowOffset
);
572 installWindow(new_val
+ 1, PreviousWindowOffset
);
575 installGlobals(val
, CurrentGlobalsOffset
);
576 installGlobals(val
, NextGlobalsOffset
);
577 installGlobals(val
, PreviousGlobalsOffset
);
580 case MISCREG_SOFTINT
:
581 case MISCREG_SOFTINT_SET
:
582 case MISCREG_SOFTINT_CLR
:
583 case MISCREG_TICK_CMPR
:
584 case MISCREG_STICK_CMPR
:
586 case MISCREG_HTSTATE
:
589 case MISCREG_STRAND_STS_REG
:
590 case MISCREG_HSTICK_CMPR
:
591 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
592 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
593 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
594 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
595 case MISCREG_QUEUE_RES_ERROR_HEAD
:
596 case MISCREG_QUEUE_RES_ERROR_TAIL
:
597 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
598 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
600 case MISCREG_HPSTATE
:
601 setFSReg(miscReg
, val
, tc
);
604 case MISCREG_HPSTATE
:
605 //HPSTATE is special because normal trap processing saves HPSTATE when
606 //it goes into a trap, and restores it when it returns.
608 panic("Accessing Fullsystem register %d to %#x in SE mode\n",
612 setMiscRegNoEffect(miscReg
, new_val
);
616 ISA::serialize(EventManager
*em
, std::ostream
&os
)
618 SERIALIZE_SCALAR(asi
);
619 SERIALIZE_SCALAR(tick
);
620 SERIALIZE_SCALAR(fprs
);
621 SERIALIZE_SCALAR(gsr
);
622 SERIALIZE_SCALAR(softint
);
623 SERIALIZE_SCALAR(tick_cmpr
);
624 SERIALIZE_SCALAR(stick
);
625 SERIALIZE_SCALAR(stick_cmpr
);
626 SERIALIZE_ARRAY(tpc
,MaxTL
);
627 SERIALIZE_ARRAY(tnpc
,MaxTL
);
628 SERIALIZE_ARRAY(tstate
,MaxTL
);
629 SERIALIZE_ARRAY(tt
,MaxTL
);
630 SERIALIZE_SCALAR(tba
);
631 SERIALIZE_SCALAR(pstate
);
632 SERIALIZE_SCALAR(tl
);
633 SERIALIZE_SCALAR(pil
);
634 SERIALIZE_SCALAR(cwp
);
635 SERIALIZE_SCALAR(gl
);
636 SERIALIZE_SCALAR(hpstate
);
637 SERIALIZE_ARRAY(htstate
,MaxTL
);
638 SERIALIZE_SCALAR(hintp
);
639 SERIALIZE_SCALAR(htba
);
640 SERIALIZE_SCALAR(hstick_cmpr
);
641 SERIALIZE_SCALAR(strandStatusReg
);
642 SERIALIZE_SCALAR(fsr
);
643 SERIALIZE_SCALAR(priContext
);
644 SERIALIZE_SCALAR(secContext
);
645 SERIALIZE_SCALAR(partId
);
646 SERIALIZE_SCALAR(lsuCtrlReg
);
647 SERIALIZE_ARRAY(scratchPad
,8);
648 SERIALIZE_SCALAR(cpu_mondo_head
);
649 SERIALIZE_SCALAR(cpu_mondo_tail
);
650 SERIALIZE_SCALAR(dev_mondo_head
);
651 SERIALIZE_SCALAR(dev_mondo_tail
);
652 SERIALIZE_SCALAR(res_error_head
);
653 SERIALIZE_SCALAR(res_error_tail
);
654 SERIALIZE_SCALAR(nres_error_head
);
655 SERIALIZE_SCALAR(nres_error_tail
);
657 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
658 ThreadContext
*tc
= NULL
;
661 bool tick_intr_sched
= true;
664 tc
= tickCompare
->getTC();
665 else if (sTickCompare
)
666 tc
= sTickCompare
->getTC();
667 else if (hSTickCompare
)
668 tc
= hSTickCompare
->getTC();
670 tick_intr_sched
= false;
672 SERIALIZE_SCALAR(tick_intr_sched
);
675 cpu
= tc
->getCpuPtr();
676 tc_num
= cpu
->findContext(tc
);
677 if (tickCompare
&& tickCompare
->scheduled())
678 tick_cmp
= tickCompare
->when();
679 if (sTickCompare
&& sTickCompare
->scheduled())
680 stick_cmp
= sTickCompare
->when();
681 if (hSTickCompare
&& hSTickCompare
->scheduled())
682 hstick_cmp
= hSTickCompare
->when();
684 SERIALIZE_OBJPTR(cpu
);
685 SERIALIZE_SCALAR(tc_num
);
686 SERIALIZE_SCALAR(tick_cmp
);
687 SERIALIZE_SCALAR(stick_cmp
);
688 SERIALIZE_SCALAR(hstick_cmp
);
694 ISA::unserialize(EventManager
*em
, Checkpoint
*cp
, const std::string
§ion
)
696 UNSERIALIZE_SCALAR(asi
);
697 UNSERIALIZE_SCALAR(tick
);
698 UNSERIALIZE_SCALAR(fprs
);
699 UNSERIALIZE_SCALAR(gsr
);
700 UNSERIALIZE_SCALAR(softint
);
701 UNSERIALIZE_SCALAR(tick_cmpr
);
702 UNSERIALIZE_SCALAR(stick
);
703 UNSERIALIZE_SCALAR(stick_cmpr
);
704 UNSERIALIZE_ARRAY(tpc
,MaxTL
);
705 UNSERIALIZE_ARRAY(tnpc
,MaxTL
);
706 UNSERIALIZE_ARRAY(tstate
,MaxTL
);
707 UNSERIALIZE_ARRAY(tt
,MaxTL
);
708 UNSERIALIZE_SCALAR(tba
);
709 UNSERIALIZE_SCALAR(pstate
);
710 UNSERIALIZE_SCALAR(tl
);
711 UNSERIALIZE_SCALAR(pil
);
712 UNSERIALIZE_SCALAR(cwp
);
713 UNSERIALIZE_SCALAR(gl
);
715 UNSERIALIZE_SCALAR(hpstate
);
716 UNSERIALIZE_ARRAY(htstate
,MaxTL
);
717 UNSERIALIZE_SCALAR(hintp
);
718 UNSERIALIZE_SCALAR(htba
);
719 UNSERIALIZE_SCALAR(hstick_cmpr
);
720 UNSERIALIZE_SCALAR(strandStatusReg
);
721 UNSERIALIZE_SCALAR(fsr
);
722 UNSERIALIZE_SCALAR(priContext
);
723 UNSERIALIZE_SCALAR(secContext
);
724 UNSERIALIZE_SCALAR(partId
);
725 UNSERIALIZE_SCALAR(lsuCtrlReg
);
726 UNSERIALIZE_ARRAY(scratchPad
,8);
727 UNSERIALIZE_SCALAR(cpu_mondo_head
);
728 UNSERIALIZE_SCALAR(cpu_mondo_tail
);
729 UNSERIALIZE_SCALAR(dev_mondo_head
);
730 UNSERIALIZE_SCALAR(dev_mondo_tail
);
731 UNSERIALIZE_SCALAR(res_error_head
);
732 UNSERIALIZE_SCALAR(res_error_tail
);
733 UNSERIALIZE_SCALAR(nres_error_head
);
734 UNSERIALIZE_SCALAR(nres_error_tail
);
737 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
738 ThreadContext
*tc
= NULL
;
741 bool tick_intr_sched
;
742 UNSERIALIZE_SCALAR(tick_intr_sched
);
743 if (tick_intr_sched
) {
744 UNSERIALIZE_OBJPTR(cpu
);
746 UNSERIALIZE_SCALAR(tc_num
);
747 UNSERIALIZE_SCALAR(tick_cmp
);
748 UNSERIALIZE_SCALAR(stick_cmp
);
749 UNSERIALIZE_SCALAR(hstick_cmp
);
750 tc
= cpu
->getContext(tc_num
);
753 tickCompare
= new TickCompareEvent(this, tc
);
754 em
->schedule(tickCompare
, tick_cmp
);
757 sTickCompare
= new STickCompareEvent(this, tc
);
758 em
->schedule(sTickCompare
, stick_cmp
);
761 hSTickCompare
= new HSTickCompareEvent(this, tc
);
762 em
->schedule(hSTickCompare
, hstick_cmp
);