gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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/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/full_system.hh"
39 #include "sim/system.hh"
40 
41 using namespace SparcISA;
42 using namespace std;
43 
44 
45 void
47 {
48  BaseCPU *cpu = tc->getCpuPtr();
49 
50  // If PIL < 14, copy over the tm and sm bits
51  if (pil < 14 && softint & 0x10000)
52  cpu->postInterrupt(0, IT_SOFT_INT, 16);
53  else
54  cpu->clearInterrupt(0, IT_SOFT_INT, 16);
55  if (pil < 14 && softint & 0x1)
56  cpu->postInterrupt(0, IT_SOFT_INT, 0);
57  else
58  cpu->clearInterrupt(0, IT_SOFT_INT, 0);
59 
60  // Copy over any of the other bits that are set
61  for (int bit = 15; bit > 0; --bit) {
62  if (1 << bit & softint && bit > pil)
63  cpu->postInterrupt(0, IT_SOFT_INT, bit);
64  else
65  cpu->clearInterrupt(0, IT_SOFT_INT, bit);
66  }
67 }
68 
69 // These functions map register indices to names
70 static inline string
72 {
73  static string miscRegName[NumMiscRegs] =
74  {/*"y", "ccr",*/ "asi", "tick", "fprs", "pcr", "pic",
75  "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
76  "stick", "stick_cmpr",
77  "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
78  "pil", "cwp", /*"cansave", "canrestore", "cleanwin", "otherwin",
79  "wstate",*/ "gl",
80  "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
81  "hstick_cmpr",
82  "fsr", "prictx", "secctx", "partId", "lsuCtrlReg",
83  "scratch0", "scratch1", "scratch2", "scratch3", "scratch4",
84  "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail",
85  "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail",
86  "nresErrorHead", "nresErrorTail", "TlbData" };
87  return miscRegName[index];
88 }
89 
90 void
91 ISA::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
92 {
93  BaseCPU *cpu = tc->getCpuPtr();
94 
95  int64_t time;
96  switch (miscReg) {
97  /* Full system only ASRs */
98  case MISCREG_SOFTINT:
99  setMiscRegNoEffect(miscReg, val);;
100  checkSoftInt(tc);
101  break;
102  case MISCREG_SOFTINT_CLR:
103  return setMiscReg(MISCREG_SOFTINT, ~val & softint, tc);
104  case MISCREG_SOFTINT_SET:
105  return setMiscReg(MISCREG_SOFTINT, val | softint, tc);
106 
107  case MISCREG_TICK_CMPR:
108  if (tickCompare == NULL)
109  tickCompare = new TickCompareEvent(this, tc);
110  setMiscRegNoEffect(miscReg, val);
111  if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
112  cpu->deschedule(tickCompare);
113  time = (tick_cmpr & mask(63)) - (tick & mask(63));
114  if (!(tick_cmpr & ~mask(63)) && time > 0) {
115  if (tickCompare->scheduled())
116  cpu->deschedule(tickCompare);
117  cpu->schedule(tickCompare, cpu->clockEdge(Cycles(time)));
118  }
119  DPRINTF(Timer, "writing to TICK compare register value %#X\n", val);
120  break;
121 
122  case MISCREG_STICK_CMPR:
123  if (sTickCompare == NULL)
124  sTickCompare = new STickCompareEvent(this, tc);
125  setMiscRegNoEffect(miscReg, val);
126  if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
127  cpu->deschedule(sTickCompare);
128  time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
129  cpu->instCount();
130  if (!(stick_cmpr & ~mask(63)) && time > 0) {
131  if (sTickCompare->scheduled())
132  cpu->deschedule(sTickCompare);
133  cpu->schedule(sTickCompare, cpu->clockEdge(Cycles(time)));
134  }
135  DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
136  break;
137 
138  case MISCREG_PSTATE:
139  setMiscRegNoEffect(miscReg, val);
140 
141  case MISCREG_PIL:
142  setMiscRegNoEffect(miscReg, val);
143  checkSoftInt(tc);
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, tc);
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
218  cpu->clearInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
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  if (FullSystem && tc->getKernelStats())
234  tc->getKernelStats()->quiesce();
235  }
236  break;
237 
238  default:
239  panic("Invalid write to FS misc register %s\n",
240  getMiscRegName(miscReg));
241  }
242 }
243 
244 MiscReg
245 ISA::readFSReg(int miscReg, ThreadContext * tc)
246 {
247  uint64_t temp;
248 
249  switch (miscReg) {
250  /* Privileged registers. */
259  case MISCREG_SOFTINT:
260  case MISCREG_TICK_CMPR:
261  case MISCREG_STICK_CMPR:
262  case MISCREG_PIL:
263  case MISCREG_HPSTATE:
264  case MISCREG_HINTP:
265  case MISCREG_HTSTATE:
266  case MISCREG_HSTICK_CMPR:
267  return readMiscRegNoEffect(miscReg) ;
268 
269  case MISCREG_HTBA:
270  return readMiscRegNoEffect(miscReg) & ULL(~0x7FFF);
271  case MISCREG_HVER:
272  // XXX set to match Legion
273  return ULL(0x3e) << 48 |
274  ULL(0x23) << 32 |
275  ULL(0x20) << 24 |
276  // MaxGL << 16 | XXX For some reason legion doesn't set GL
277  MaxTL << 8 |
278  (NWindows -1) << 0;
279 
281  System *sys;
282  int x;
283  sys = tc->getSystemPtr();
284 
285  temp = readMiscRegNoEffect(miscReg) & (STS::active | STS::speculative);
286  // Check that the CPU array is fully populated
287  // (by calling getNumCPus())
288  assert(sys->numContexts() > tc->contextId());
289 
290  temp |= tc->contextId() << STS::shft_id;
291 
292  for (x = tc->contextId() & ~3; x < sys->threadContexts.size(); x++) {
293  switch (sys->threadContexts[x]->status()) {
295  temp |= STS::st_run << (STS::shft_fsm0 -
296  ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
297  break;
299  // should this be idle?
300  temp |= STS::st_idle << (STS::shft_fsm0 -
301  ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
302  break;
304  temp |= STS::st_halt << (STS::shft_fsm0 -
305  ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
306  break;
307  default:
308  panic("What state are we in?!\n");
309  } // switch
310  } // for
311 
312  return temp;
313  default:
314  panic("Invalid read to FS misc register\n");
315  }
316 }
317 
318 void
320 {
321  panic("tick compare not implemented\n");
322 }
323 
324 void
326 {
327  BaseCPU *cpu = tc->getCpuPtr();
328 
329  // since our microcode instructions take two cycles we need to check if
330  // we're actually at the correct cycle or we need to wait a little while
331  // more
332  int delay;
333  delay = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
334  cpu->instCount();
335  assert(delay >= 0 && "stick compare missed interrupt cycle");
336 
337  if (delay == 0 || tc->status() == ThreadContext::Suspended) {
338  DPRINTF(Timer, "STick compare cycle reached at %#x\n",
339  (stick_cmpr & mask(63)));
340  if (!(tc->readMiscRegNoEffect(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
341  setMiscReg(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
342  }
343  } else {
344  cpu->schedule(sTickCompare, cpu->clockEdge(Cycles(delay)));
345  }
346 }
347 
348 void
350 {
351  BaseCPU *cpu = tc->getCpuPtr();
352 
353  // since our microcode instructions take two cycles we need to check if
354  // we're actually at the correct cycle or we need to wait a little while
355  // more
356  int delay;
357  if ( tc->status() == ThreadContext::Halted)
358  return;
359 
360  delay = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
361  cpu->instCount();
362  assert(delay >= 0 && "hstick compare missed interrupt cycle");
363 
364  if (delay == 0 || tc->status() == ThreadContext::Suspended) {
365  DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
366  (stick_cmpr & mask(63)));
367  if (!(tc->readMiscRegNoEffect(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
368  setMiscReg(MISCREG_HINTP, 1, tc);
369  }
370  // Need to do something to cause interrupt to happen here !!! @todo
371  } else {
372  cpu->schedule(hSTickCompare, cpu->clockEdge(Cycles(delay)));
373  }
374 }
375 
#define DPRINTF(x,...)
Definition: trace.hh:212
virtual System * getSystemPtr()=0
Bitfield< 30, 0 > index
void setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
Definition: ua2005.cc:91
MiscReg readFSReg(int miscReg, ThreadContext *tc)
Definition: ua2005.cc:245
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
#define panic(...)
Definition: misc.hh:153
uint16_t RegIndex
Definition: registers.hh:62
const int NumMiscRegs
Definition: miscregs.hh:158
void processSTickCompare(ThreadContext *tc)
Definition: ua2005.cc:325
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:146
Definition: system.hh:83
virtual BaseCPU * getCpuPtr()=0
const char *const miscRegName[]
Definition: miscregs.hh:739
ThreadContext is the external interface to all thread state for anything outside of the CPU...
Bitfield< 63 > val
Definition: misc.hh:770
void processTickCompare(ThreadContext *tc)
Process a tick compare event and generate an interrupt on the cpu if appropriate. ...
Definition: ua2005.cc:319
Bitfield< 23, 20 > tl
void processHSTickCompare(ThreadContext *tc)
Definition: ua2005.cc:349
Hyper privileged registers.
Definition: miscregs.hh:77
static string getMiscRegName(RegIndex index)
Definition: ua2005.cc:71
std::vector< ThreadContext * > threadContexts
Definition: system.hh:199
virtual void suspend()=0
Set the status to Suspended.
#define ULL(N)
uint64_t constant
Definition: types.hh:50
int numContexts()
Definition: system.hh:208
const int MaxTL
Definition: sparc_traits.hh:38
Permanently shut down.
const int NWindows
Definition: sparc_traits.hh:43
virtual int contextId() const =0
uint64_t MiscReg
Definition: registers.hh:48
virtual Status status() const =0
Bitfield< 3, 0 > mask
Definition: types.hh:64
Temporarily inactive.
void checkSoftInt(ThreadContext *tc)
Definition: ua2005.cc:46
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:67
Bitfield< 1 > x
Definition: types.hh:105
virtual TheISA::Kernel::Statistics * getKernelStats()=0

Generated on Fri Jun 9 2017 13:03:40 for gem5 by doxygen 1.8.6