gem5  v20.1.0.0
ua2005.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006 The Regents of The University of Michigan
3  * All rights reserved.
4  *
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.
15  *
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.
27  */
28 
29 #include "arch/sparc/interrupts.hh"
30 #include "arch/sparc/isa.hh"
31 #include "arch/sparc/registers.hh"
32 #include "base/bitfield.hh"
33 #include "base/trace.hh"
34 #include "cpu/base.hh"
35 #include "cpu/thread_context.hh"
36 #include "debug/Quiesce.hh"
37 #include "debug/Timer.hh"
38 #include "sim/system.hh"
39 
40 using namespace SparcISA;
41 using namespace std;
42 
43 
44 void
46 {
47  BaseCPU *cpu = tc->getCpuPtr();
48 
49  // If PIL < 14, copy over the tm and sm bits
50  if (pil < 14 && softint & 0x10000)
51  cpu->postInterrupt(0, IT_SOFT_INT, 16);
52  else
53  cpu->clearInterrupt(0, IT_SOFT_INT, 16);
54  if (pil < 14 && softint & 0x1)
55  cpu->postInterrupt(0, IT_SOFT_INT, 0);
56  else
57  cpu->clearInterrupt(0, IT_SOFT_INT, 0);
58 
59  // Copy over any of the other bits that are set
60  for (int bit = 15; bit > 0; --bit) {
61  if (1 << bit & softint && bit > pil)
62  cpu->postInterrupt(0, IT_SOFT_INT, bit);
63  else
64  cpu->clearInterrupt(0, IT_SOFT_INT, bit);
65  }
66 }
67 
68 // These functions map register indices to names
69 static inline string
71 {
72  static string miscRegName[NumMiscRegs] =
73  {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic",
74  "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
75  "stick", "stick_cmpr",
76  "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
77  "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin",
78  "wstate",*/ "gl",
79  "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
80  "hstick_cmpr",
81  "fsr", "prictx", "secctx", "partId", "lsuCtrlReg",
82  "scratch0", "scratch1", "scratch2", "scratch3", "scratch4",
83  "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail",
84  "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail",
85  "nresErrorHead", "nresErrorTail", "TlbData" };
86  return miscRegName[index];
87 }
88 
89 void
90 ISA::setFSReg(int miscReg, RegVal val)
91 {
92  BaseCPU *cpu = tc->getCpuPtr();
93 
94  int64_t time;
95  switch (miscReg) {
96  /* Full system only ASRs */
97  case MISCREG_SOFTINT:
98  setMiscRegNoEffect(miscReg, val);
99  checkSoftInt();
100  break;
101  case MISCREG_SOFTINT_CLR:
102  return setMiscReg(MISCREG_SOFTINT, ~val & softint);
103  case MISCREG_SOFTINT_SET:
104  return setMiscReg(MISCREG_SOFTINT, val | softint);
105 
106  case MISCREG_TICK_CMPR:
107  if (tickCompare == NULL)
108  tickCompare = new TickCompareEvent(this);
109  setMiscRegNoEffect(miscReg, val);
110  if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
111  cpu->deschedule(tickCompare);
112  time = (tick_cmpr & mask(63)) - (tick & mask(63));
113  if (!(tick_cmpr & ~mask(63)) && time > 0) {
114  if (tickCompare->scheduled())
115  cpu->deschedule(tickCompare);
116  cpu->schedule(tickCompare, cpu->clockEdge(Cycles(time)));
117  }
118  DPRINTF(Timer, "writing to TICK compare register value %#X\n", val);
119  break;
120 
121  case MISCREG_STICK_CMPR:
122  if (sTickCompare == NULL)
123  sTickCompare = new STickCompareEvent(this);
124  setMiscRegNoEffect(miscReg, val);
125  if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
126  cpu->deschedule(sTickCompare);
127  time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
128  cpu->instCount();
129  if (!(stick_cmpr & ~mask(63)) && time > 0) {
130  if (sTickCompare->scheduled())
131  cpu->deschedule(sTickCompare);
132  cpu->schedule(sTickCompare, cpu->clockEdge(Cycles(time)));
133  }
134  DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
135  break;
136 
137  case MISCREG_PSTATE:
138  setMiscRegNoEffect(miscReg, val);
139  break;
140 
141  case MISCREG_PIL:
142  setMiscRegNoEffect(miscReg, val);
143  checkSoftInt();
144  break;
145 
146  case MISCREG_HVER:
147  panic("Shouldn't be writing HVER\n");
148 
149  case MISCREG_HINTP:
150  setMiscRegNoEffect(miscReg, val);
151  if (hintp)
152  cpu->postInterrupt(0, IT_HINTP, 0);
153  else
154  cpu->clearInterrupt(0, IT_HINTP, 0);
155  break;
156 
157  case MISCREG_HTBA:
158  // clear lower 7 bits on writes.
159  setMiscRegNoEffect(miscReg, val & ULL(~0x7FFF));
160  break;
161 
164  setMiscRegNoEffect(miscReg, val);
165  if (cpu_mondo_head != cpu_mondo_tail)
166  cpu->postInterrupt(0, IT_CPU_MONDO, 0);
167  else
168  cpu->clearInterrupt(0, IT_CPU_MONDO, 0);
169  break;
172  setMiscRegNoEffect(miscReg, val);
173  if (dev_mondo_head != dev_mondo_tail)
174  cpu->postInterrupt(0, IT_DEV_MONDO, 0);
175  else
176  cpu->clearInterrupt(0, IT_DEV_MONDO, 0);
177  break;
180  setMiscRegNoEffect(miscReg, val);
181  if (res_error_head != res_error_tail)
182  cpu->postInterrupt(0, IT_RES_ERROR, 0);
183  else
184  cpu->clearInterrupt(0, IT_RES_ERROR, 0);
185  break;
188  setMiscRegNoEffect(miscReg, val);
189  // This one doesn't have an interrupt to report to the guest OS
190  break;
191 
192  case MISCREG_HSTICK_CMPR:
193  if (hSTickCompare == NULL)
194  hSTickCompare = new HSTickCompareEvent(this);
195  setMiscRegNoEffect(miscReg, val);
196  if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
197  cpu->deschedule(hSTickCompare);
198  time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
199  cpu->instCount();
200  if (!(hstick_cmpr & ~mask(63)) && time > 0) {
201  if (hSTickCompare->scheduled())
202  cpu->deschedule(hSTickCompare);
203  cpu->schedule(hSTickCompare, cpu->clockEdge(Cycles(time)));
204  }
205  DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
206  break;
207 
208  case MISCREG_HPSTATE:
209  {
210  HPSTATE newVal = val;
211  newVal.id = 1;
212  // T1000 spec says impl. dependent val must always be 1
213  setMiscRegNoEffect(miscReg, newVal);
214  newVal = hpstate;
215  if (newVal.tlz && tl == 0 && !newVal.hpriv)
216  cpu->postInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
217  else
219  break;
220  }
221  case MISCREG_HTSTATE:
222  setMiscRegNoEffect(miscReg, val);
223  break;
224 
226  if (bits(val,2,2))
227  panic("No support for setting spec_en bit\n");
228  setMiscRegNoEffect(miscReg, bits(val,0,0));
229  if (!bits(val,0,0)) {
230  DPRINTF(Quiesce, "Cpu executed quiescing instruction\n");
231  // Time to go to sleep
232  tc->suspend();
233  auto *workload = tc->getSystemPtr()->workload;
234  if (workload)
235  workload->recordQuiesce();
236  }
237  break;
238 
239  default:
240  panic("Invalid write to FS misc register %s\n",
241  getMiscRegName(miscReg));
242  }
243 }
244 
245 RegVal
246 ISA::readFSReg(int miscReg)
247 {
248  uint64_t temp;
249 
250  switch (miscReg) {
251  /* Privileged registers. */
260  case MISCREG_SOFTINT:
261  case MISCREG_TICK_CMPR:
262  case MISCREG_STICK_CMPR:
263  case MISCREG_PIL:
264  case MISCREG_HPSTATE:
265  case MISCREG_HINTP:
266  case MISCREG_HTSTATE:
267  case MISCREG_HSTICK_CMPR:
268  return readMiscRegNoEffect(miscReg) ;
269 
270  case MISCREG_HTBA:
271  return readMiscRegNoEffect(miscReg) & ULL(~0x7FFF);
272  case MISCREG_HVER:
273  // XXX set to match Legion
274  return ULL(0x3e) << 48 |
275  ULL(0x23) << 32 |
276  ULL(0x20) << 24 |
277  // MaxGL << 16 | XXX For some reason legion doesn't set GL
278  MaxTL << 8 |
279  (NWindows -1) << 0;
280 
282  System *sys;
283  int x;
284  sys = tc->getSystemPtr();
285 
286  temp = readMiscRegNoEffect(miscReg) & (STS::active | STS::speculative);
287  // Check that the CPU array is fully populated
288  // (by calling getNumCPus())
289  assert(sys->threads.size() > tc->contextId());
290 
291  temp |= tc->contextId() << STS::shft_id;
292 
293  for (x = tc->contextId() & ~3; x < sys->threads.size(); x++) {
294  switch (sys->threads[x]->status()) {
296  temp |= STS::st_run << (STS::shft_fsm0 -
297  ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
298  break;
300  // should this be idle?
301  temp |= STS::st_idle << (STS::shft_fsm0 -
302  ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
303  break;
305  temp |= STS::st_halt << (STS::shft_fsm0 -
306  ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
307  break;
308  default:
309  panic("What state are we in?!\n");
310  } // switch
311  } // for
312 
313  return temp;
314  default:
315  panic("Invalid read to FS misc register\n");
316  }
317 }
318 
319 void
321 {
322  panic("tick compare not implemented\n");
323 }
324 
325 void
327 {
328  BaseCPU *cpu = tc->getCpuPtr();
329 
330  // since our microcode instructions take two cycles we need to check if
331  // we're actually at the correct cycle or we need to wait a little while
332  // more
333  int delay;
334  delay = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
335  cpu->instCount();
336  assert(delay >= 0 && "stick compare missed interrupt cycle");
337 
338  if (delay == 0 || tc->status() == ThreadContext::Suspended) {
339  DPRINTF(Timer, "STick compare cycle reached at %#x\n",
340  (stick_cmpr & mask(63)));
341  if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
342  setMiscReg(MISCREG_SOFTINT, softint | (ULL(1) << 16));
343  }
344  } else {
345  cpu->schedule(sTickCompare, cpu->clockEdge(Cycles(delay)));
346  }
347 }
348 
349 void
351 {
352  BaseCPU *cpu = tc->getCpuPtr();
353 
354  // since our microcode instructions take two cycles we need to check if
355  // we're actually at the correct cycle or we need to wait a little while
356  // more
357  int delay;
358  if ( tc->status() == ThreadContext::Halted)
359  return;
360 
361  delay = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
362  cpu->instCount();
363  assert(delay >= 0 && "hstick compare missed interrupt cycle");
364 
365  if (delay == 0 || tc->status() == ThreadContext::Suspended) {
366  DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
367  (stick_cmpr & mask(63)));
368  if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
369  setMiscReg(MISCREG_HINTP, 1);
370  }
371  // Need to do something to cause interrupt to happen here !!! @todo
372  } else {
373  cpu->schedule(hSTickCompare, cpu->clockEdge(Cycles(delay)));
374  }
375 }
376 
SparcISA::MISCREG_PSTATE
@ MISCREG_PSTATE
Definition: miscregs.hh:62
SparcISA::MISCREG_QUEUE_CPU_MONDO_TAIL
@ MISCREG_QUEUE_CPU_MONDO_TAIL
Definition: miscregs.hh:103
system.hh
SparcISA::MISCREG_TICK_CMPR
@ MISCREG_TICK_CMPR
Definition: miscregs.hh:51
MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:44
SparcISA::MISCREG_PIL
@ MISCREG_PIL
Definition: miscregs.hh:64
SparcISA::MISCREG_HINTP
@ MISCREG_HINTP
Definition: miscregs.hh:76
SparcISA::MISCREG_HTSTATE
@ MISCREG_HTSTATE
Definition: miscregs.hh:75
SparcISA::IT_CPU_MONDO
@ IT_CPU_MONDO
Definition: interrupts.hh:49
EventWrapper
Definition: eventq.hh:1070
SparcISA::ISA::processSTickCompare
void processSTickCompare()
Definition: ua2005.cc:326
SparcISA::MISCREG_SOFTINT
@ MISCREG_SOFTINT
Definition: miscregs.hh:50
BaseCPU::postInterrupt
void postInterrupt(ThreadID tid, int int_num, int index)
Definition: base.cc:189
SparcISA::MISCREG_QUEUE_DEV_MONDO_HEAD
@ MISCREG_QUEUE_DEV_MONDO_HEAD
Definition: miscregs.hh:104
SparcISA::NWindows
const int NWindows
Definition: sparc_traits.hh:41
ArmISA::miscRegName
const char *const miscRegName[]
Definition: miscregs.hh:1159
SparcISA::ISA::setFSReg
void setFSReg(int miscReg, RegVal val)
Definition: ua2005.cc:90
SparcISA::MISCREG_QUEUE_DEV_MONDO_TAIL
@ MISCREG_QUEUE_DEV_MONDO_TAIL
Definition: miscregs.hh:105
getMiscRegName
static string getMiscRegName(RegIndex index)
Definition: ua2005.cc:70
SparcISA::ISA::processHSTickCompare
void processHSTickCompare()
Definition: ua2005.cc:350
SparcISA::MISCREG_SOFTINT_CLR
@ MISCREG_SOFTINT_CLR
Definition: miscregs.hh:49
SparcISA
Definition: asi.cc:31
SparcISA::IT_TRAP_LEVEL_ZERO
@ IT_TRAP_LEVEL_ZERO
Definition: interrupts.hh:46
SparcISA::MISCREG_QUEUE_NRES_ERROR_TAIL
@ MISCREG_QUEUE_NRES_ERROR_TAIL
Definition: miscregs.hh:109
bitfield.hh
System
Definition: system.hh:73
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
ThreadContext::Halted
@ Halted
Permanently shut down.
Definition: thread_context.hh:115
SparcISA::IT_DEV_MONDO
@ IT_DEV_MONDO
Definition: interrupts.hh:50
SparcISA::MISCREG_SOFTINT_SET
@ MISCREG_SOFTINT_SET
Definition: miscregs.hh:48
BaseCPU::clearInterrupt
void clearInterrupt(ThreadID tid, int int_num, int index)
Definition: base.hh:234
SparcISA::ISA::checkSoftInt
void checkSoftInt()
Definition: ua2005.cc:45
MipsISA::tl
Bitfield< 23, 20 > tl
Definition: pra_constants.hh:251
SparcISA::NumMiscRegs
const int NumMiscRegs
Definition: miscregs.hh:170
SparcISA::IT_SOFT_INT
@ IT_SOFT_INT
Definition: interrupts.hh:52
SparcISA::MISCREG_QUEUE_CPU_MONDO_HEAD
@ MISCREG_QUEUE_CPU_MONDO_HEAD
Definition: miscregs.hh:102
System::Threads::size
int size() const
Definition: system.hh:204
RiscvISA::x
Bitfield< 3 > x
Definition: pagetable.hh:69
SparcISA::MISCREG_QUEUE_RES_ERROR_HEAD
@ MISCREG_QUEUE_RES_ERROR_HEAD
Definition: miscregs.hh:106
SparcISA::MISCREG_STRAND_STS_REG
@ MISCREG_STRAND_STS_REG
Definition: miscregs.hh:79
X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:769
SparcISA::MISCREG_STICK_CMPR
@ MISCREG_STICK_CMPR
Definition: miscregs.hh:53
SparcISA::MISCREG_HSTICK_CMPR
@ MISCREG_HSTICK_CMPR
Definition: miscregs.hh:80
BaseCPU
Definition: cpu_dummy.hh:43
SparcISA::MISCREG_HPSTATE
@ MISCREG_HPSTATE
Hyper privileged registers.
Definition: miscregs.hh:74
System::threads
Threads threads
Definition: system.hh:309
ThreadContext::Suspended
@ Suspended
Temporarily inactive.
Definition: thread_context.hh:106
SparcISA::IT_RES_ERROR
@ IT_RES_ERROR
Definition: interrupts.hh:51
base.hh
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
SparcISA::ISA::processTickCompare
void processTickCompare()
Process a tick compare event and generate an interrupt on the cpu if appropriate.
Definition: ua2005.cc:320
RegIndex
uint16_t RegIndex
Definition: types.hh:52
SparcISA::MISCREG_QUEUE_NRES_ERROR_HEAD
@ MISCREG_QUEUE_NRES_ERROR_HEAD
Definition: miscregs.hh:108
SparcISA::MISCREG_HTBA
@ MISCREG_HTBA
Definition: miscregs.hh:77
interrupts.hh
SparcISA::MISCREG_QUEUE_RES_ERROR_TAIL
@ MISCREG_QUEUE_RES_ERROR_TAIL
Definition: miscregs.hh:107
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
ThreadContext::Active
@ Active
Running.
Definition: thread_context.hh:102
registers.hh
trace.hh
BaseCPU::instCount
Tick instCount()
Definition: base.hh:212
SparcISA::ISA::readFSReg
RegVal readFSReg(int miscReg)
Definition: ua2005.cc:246
isa.hh
SparcISA::MISCREG_HVER
@ MISCREG_HVER
Definition: miscregs.hh:78
thread_context.hh
ULL
#define ULL(N)
uint64_t constant
Definition: types.hh:50
RegVal
uint64_t RegVal
Definition: types.hh:168
SparcISA::IT_HINTP
@ IT_HINTP
Definition: interrupts.hh:47
ArmISA::mask
Bitfield< 28, 24 > mask
Definition: miscregs_types.hh:711
SparcISA::MaxTL
const int MaxTL
Definition: sparc_traits.hh:36
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
bits
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:75

Generated on Wed Sep 30 2020 14:02:07 for gem5 by doxygen 1.8.17