gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
interrupts.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2008 The Hewlett-Packard Development Company
15  * All rights reserved.
16  *
17  * The license below extends only to copyright in the software and shall
18  * not be construed as granting a license to any other intellectual
19  * property including but not limited to intellectual property relating
20  * to a hardware implementation of the functionality of the software
21  * licensed hereunder. You may use the software subject to the license
22  * terms below provided that you ensure that this notice is replicated
23  * unmodified and in its entirety in all distributions of the software,
24  * modified or unmodified, in source code or in binary form.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions are
28  * met: redistributions of source code must retain the above copyright
29  * notice, this list of conditions and the following disclaimer;
30  * redistributions in binary form must reproduce the above copyright
31  * notice, this list of conditions and the following disclaimer in the
32  * documentation and/or other materials provided with the distribution;
33  * neither the name of the copyright holders nor the names of its
34  * contributors may be used to endorse or promote products derived from
35  * this software without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
38  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
40  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
41  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  *
49  * Authors: Gabe Black
50  */
51 
52 #include "arch/x86/interrupts.hh"
53 
54 #include <memory>
55 
56 #include "arch/x86/intmessage.hh"
57 #include "arch/x86/regs/apic.hh"
58 #include "cpu/base.hh"
59 #include "debug/LocalApic.hh"
60 #include "dev/x86/i82094aa.hh"
61 #include "dev/x86/pc.hh"
62 #include "dev/x86/south_bridge.hh"
63 #include "mem/packet_access.hh"
64 #include "sim/full_system.hh"
65 #include "sim/system.hh"
66 
67 int
68 divideFromConf(uint32_t conf)
69 {
70  // This figures out what division we want from the division configuration
71  // register in the local APIC. The encoding is a little odd but it can
72  // be deciphered fairly easily.
73  int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
74  shift = (shift + 1) % 8;
75  return 1 << shift;
76 }
77 
78 namespace X86ISA
79 {
80 
83 {
84  ApicRegIndex regNum;
85  paddr &= ~mask(3);
86  switch (paddr)
87  {
88  case 0x20:
89  regNum = APIC_ID;
90  break;
91  case 0x30:
92  regNum = APIC_VERSION;
93  break;
94  case 0x80:
95  regNum = APIC_TASK_PRIORITY;
96  break;
97  case 0x90:
99  break;
100  case 0xA0:
101  regNum = APIC_PROCESSOR_PRIORITY;
102  break;
103  case 0xB0:
104  regNum = APIC_EOI;
105  break;
106  case 0xD0:
107  regNum = APIC_LOGICAL_DESTINATION;
108  break;
109  case 0xE0:
110  regNum = APIC_DESTINATION_FORMAT;
111  break;
112  case 0xF0:
114  break;
115  case 0x100:
116  case 0x110:
117  case 0x120:
118  case 0x130:
119  case 0x140:
120  case 0x150:
121  case 0x160:
122  case 0x170:
123  regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x10);
124  break;
125  case 0x180:
126  case 0x190:
127  case 0x1A0:
128  case 0x1B0:
129  case 0x1C0:
130  case 0x1D0:
131  case 0x1E0:
132  case 0x1F0:
133  regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x10);
134  break;
135  case 0x200:
136  case 0x210:
137  case 0x220:
138  case 0x230:
139  case 0x240:
140  case 0x250:
141  case 0x260:
142  case 0x270:
143  regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x10);
144  break;
145  case 0x280:
146  regNum = APIC_ERROR_STATUS;
147  break;
148  case 0x300:
150  break;
151  case 0x310:
153  break;
154  case 0x320:
155  regNum = APIC_LVT_TIMER;
156  break;
157  case 0x330:
158  regNum = APIC_LVT_THERMAL_SENSOR;
159  break;
160  case 0x340:
162  break;
163  case 0x350:
164  regNum = APIC_LVT_LINT0;
165  break;
166  case 0x360:
167  regNum = APIC_LVT_LINT1;
168  break;
169  case 0x370:
170  regNum = APIC_LVT_ERROR;
171  break;
172  case 0x380:
173  regNum = APIC_INITIAL_COUNT;
174  break;
175  case 0x390:
176  regNum = APIC_CURRENT_COUNT;
177  break;
178  case 0x3E0:
179  regNum = APIC_DIVIDE_CONFIGURATION;
180  break;
181  default:
182  // A reserved register field.
183  panic("Accessed reserved register field %#x.\n", paddr);
184  break;
185  }
186  return regNum;
187 }
188 }
189 
190 Tick
192 {
193  Addr offset = pkt->getAddr() - pioAddr;
194  //Make sure we're at least only accessing one register.
195  if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
196  panic("Accessed more than one register at a time in the APIC!\n");
197  ApicRegIndex reg = decodeAddr(offset);
198  uint32_t val = htog(readReg(reg));
199  DPRINTF(LocalApic,
200  "Reading Local APIC register %d at offset %#x as %#x.\n",
201  reg, offset, val);
202  pkt->setData(((uint8_t *)&val) + (offset & mask(3)));
203  pkt->makeAtomicResponse();
204  return pioDelay;
205 }
206 
207 Tick
209 {
210  Addr offset = pkt->getAddr() - pioAddr;
211  //Make sure we're at least only accessing one register.
212  if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
213  panic("Accessed more than one register at a time in the APIC!\n");
214  ApicRegIndex reg = decodeAddr(offset);
215  uint32_t val = regs[reg];
216  pkt->writeData(((uint8_t *)&val) + (offset & mask(3)));
217  DPRINTF(LocalApic,
218  "Writing Local APIC register %d at offset %#x as %#x.\n",
219  reg, offset, gtoh(val));
220  setReg(reg, gtoh(val));
221  pkt->makeAtomicResponse();
222  return pioDelay;
223 }
224 void
226  uint8_t deliveryMode, bool level)
227 {
228  /*
229  * Fixed and lowest-priority delivery mode interrupts are handled
230  * using the IRR/ISR registers, checking against the TPR, etc.
231  * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through.
232  */
233  if (deliveryMode == DeliveryMode::Fixed ||
234  deliveryMode == DeliveryMode::LowestPriority) {
235  DPRINTF(LocalApic, "Interrupt is an %s.\n",
236  DeliveryMode::names[deliveryMode]);
237  // Queue up the interrupt in the IRR.
238  if (vector > IRRV)
239  IRRV = vector;
240  if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) {
241  setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector);
242  if (level) {
243  setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
244  } else {
245  clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
246  }
247  }
248  } else if (!DeliveryMode::isReserved(deliveryMode)) {
249  DPRINTF(LocalApic, "Interrupt is an %s.\n",
250  DeliveryMode::names[deliveryMode]);
251  if (deliveryMode == DeliveryMode::SMI && !pendingSmi) {
252  pendingUnmaskableInt = pendingSmi = true;
253  smiVector = vector;
254  } else if (deliveryMode == DeliveryMode::NMI && !pendingNmi) {
255  pendingUnmaskableInt = pendingNmi = true;
256  nmiVector = vector;
257  } else if (deliveryMode == DeliveryMode::ExtInt && !pendingExtInt) {
258  pendingExtInt = true;
259  extIntVector = vector;
260  } else if (deliveryMode == DeliveryMode::INIT && !pendingInit) {
261  pendingUnmaskableInt = pendingInit = true;
262  initVector = vector;
263  } else if (deliveryMode == DeliveryMode::SIPI &&
264  !pendingStartup && !startedUp) {
265  pendingUnmaskableInt = pendingStartup = true;
266  startupVector = vector;
267  }
268  }
269  if (FullSystem)
270  cpu->wakeup(0);
271 }
272 
273 
274 void
276 {
277  assert(newCPU);
278  if (cpu != NULL && cpu->cpuId() != newCPU->cpuId()) {
279  panic("Local APICs can't be moved between CPUs"
280  " with different IDs.\n");
281  }
282  cpu = newCPU;
283  initialApicId = cpu->cpuId();
284  regs[APIC_ID] = (initialApicId << 24);
285  pioAddr = x86LocalAPICAddress(initialApicId, 0);
286 }
287 
288 
289 void
291 {
292  //
293  // The local apic must register its address ranges on both its pio
294  // port via the basicpiodevice(piodevice) init() function and its
295  // int port that it inherited from IntDevice. Note IntDevice is
296  // not a SimObject itself.
297  //
299  IntDevice::init();
300 
301  // the slave port has a range so inform the connected master
302  intSlavePort.sendRangeChange();
303 }
304 
305 
306 Tick
308 {
309  Addr offset = pkt->getAddr() - x86InterruptAddress(initialApicId, 0);
310  assert(pkt->cmd == MemCmd::MessageReq);
311  switch(offset)
312  {
313  case 0:
314  {
315  TriggerIntMessage message = pkt->get<TriggerIntMessage>();
316  DPRINTF(LocalApic,
317  "Got Trigger Interrupt message with vector %#x.\n",
318  message.vector);
319 
320  requestInterrupt(message.vector,
321  message.deliveryMode, message.trigger);
322  }
323  break;
324  default:
325  panic("Local apic got unknown interrupt message at offset %#x.\n",
326  offset);
327  break;
328  }
329  pkt->makeAtomicResponse();
330  return pioDelay;
331 }
332 
333 
334 Tick
336 {
337  assert(!pkt->isError());
338  assert(pkt->cmd == MemCmd::MessageResp);
339  if (--pendingIPIs == 0) {
340  InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
341  // Record that the ICR is now idle.
342  low.deliveryStatus = 0;
343  regs[APIC_INTERRUPT_COMMAND_LOW] = low;
344  }
345  DPRINTF(LocalApic, "ICR is now idle.\n");
346  return 0;
347 }
348 
349 
352 {
353  AddrRangeList ranges;
354  ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
355  x86InterruptAddress(initialApicId, 0) +
357  return ranges;
358 }
359 
360 
361 uint32_t
363 {
364  if (reg >= APIC_TRIGGER_MODE(0) &&
365  reg <= APIC_TRIGGER_MODE(15)) {
366  panic("Local APIC Trigger Mode registers are unimplemented.\n");
367  }
368  switch (reg) {
370  panic("Local APIC Arbitration Priority register unimplemented.\n");
371  break;
373  panic("Local APIC Processor Priority register unimplemented.\n");
374  break;
375  case APIC_ERROR_STATUS:
376  regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
377  break;
378  case APIC_CURRENT_COUNT:
379  {
380  if (apicTimerEvent.scheduled()) {
381  // Compute how many m5 ticks happen per count.
382  uint64_t ticksPerCount = clockPeriod() *
384  // Compute how many m5 ticks are left.
385  uint64_t val = apicTimerEvent.when() - curTick();
386  // Turn that into a count.
387  val = (val + ticksPerCount - 1) / ticksPerCount;
388  return val;
389  } else {
390  return 0;
391  }
392  }
393  default:
394  break;
395  }
396  return regs[reg];
397 }
398 
399 void
401 {
402  uint32_t newVal = val;
403  if (reg >= APIC_IN_SERVICE(0) &&
404  reg <= APIC_IN_SERVICE(15)) {
405  panic("Local APIC In-Service registers are unimplemented.\n");
406  }
407  if (reg >= APIC_TRIGGER_MODE(0) &&
408  reg <= APIC_TRIGGER_MODE(15)) {
409  panic("Local APIC Trigger Mode registers are unimplemented.\n");
410  }
411  if (reg >= APIC_INTERRUPT_REQUEST(0) &&
412  reg <= APIC_INTERRUPT_REQUEST(15)) {
413  panic("Local APIC Interrupt Request registers "
414  "are unimplemented.\n");
415  }
416  switch (reg) {
417  case APIC_ID:
418  newVal = val & 0xFF;
419  break;
420  case APIC_VERSION:
421  // The Local APIC Version register is read only.
422  return;
423  case APIC_TASK_PRIORITY:
424  newVal = val & 0xFF;
425  break;
427  panic("Local APIC Arbitration Priority register unimplemented.\n");
428  break;
430  panic("Local APIC Processor Priority register unimplemented.\n");
431  break;
432  case APIC_EOI:
433  // Remove the interrupt that just completed from the local apic state.
434  clearRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
435  updateISRV();
436  return;
438  newVal = val & 0xFF000000;
439  break;
441  newVal = val | 0x0FFFFFFF;
442  break;
444  regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
445  regs[APIC_INTERNAL_STATE] |= val & (1 << 8);
446  if (val & (1 << 9))
447  warn("Focus processor checking not implemented.\n");
448  break;
449  case APIC_ERROR_STATUS:
450  {
451  if (regs[APIC_INTERNAL_STATE] & 0x1) {
452  regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
453  newVal = 0;
454  } else {
455  regs[APIC_INTERNAL_STATE] |= ULL(0x1);
456  return;
457  }
458 
459  }
460  break;
462  {
463  InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
464  // Check if we're already sending an IPI.
465  if (low.deliveryStatus) {
466  newVal = low;
467  break;
468  }
469  low = val;
470  InterruptCommandRegHigh high = regs[APIC_INTERRUPT_COMMAND_HIGH];
471  TriggerIntMessage message = 0;
472  message.destination = high.destination;
473  message.vector = low.vector;
474  message.deliveryMode = low.deliveryMode;
475  message.destMode = low.destMode;
476  message.level = low.level;
477  message.trigger = low.trigger;
478  ApicList apics;
479  int numContexts = sys->numContexts();
480  switch (low.destShorthand) {
481  case 0:
482  if (message.deliveryMode == DeliveryMode::LowestPriority) {
483  panic("Lowest priority delivery mode "
484  "IPIs aren't implemented.\n");
485  }
486  if (message.destMode == 1) {
487  int dest = message.destination;
488  hack_once("Assuming logical destinations are 1 << id.\n");
489  for (int i = 0; i < numContexts; i++) {
490  if (dest & 0x1)
491  apics.push_back(i);
492  dest = dest >> 1;
493  }
494  } else {
495  if (message.destination == 0xFF) {
496  for (int i = 0; i < numContexts; i++) {
497  if (i == initialApicId) {
498  requestInterrupt(message.vector,
499  message.deliveryMode, message.trigger);
500  } else {
501  apics.push_back(i);
502  }
503  }
504  } else {
505  if (message.destination == initialApicId) {
506  requestInterrupt(message.vector,
507  message.deliveryMode, message.trigger);
508  } else {
509  apics.push_back(message.destination);
510  }
511  }
512  }
513  break;
514  case 1:
515  newVal = val;
516  requestInterrupt(message.vector,
517  message.deliveryMode, message.trigger);
518  break;
519  case 2:
520  requestInterrupt(message.vector,
521  message.deliveryMode, message.trigger);
522  // Fall through
523  case 3:
524  {
525  for (int i = 0; i < numContexts; i++) {
526  if (i != initialApicId) {
527  apics.push_back(i);
528  }
529  }
530  }
531  break;
532  }
533  // Record that an IPI is being sent if one actually is.
534  if (apics.size()) {
535  low.deliveryStatus = 1;
536  pendingIPIs += apics.size();
537  }
538  regs[APIC_INTERRUPT_COMMAND_LOW] = low;
539  intMasterPort.sendMessage(apics, message, sys->isTimingMode());
540  newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
541  }
542  break;
543  case APIC_LVT_TIMER:
546  case APIC_LVT_LINT0:
547  case APIC_LVT_LINT1:
548  case APIC_LVT_ERROR:
549  {
550  uint64_t readOnlyMask = (1 << 12) | (1 << 14);
551  newVal = (val & ~readOnlyMask) |
552  (regs[reg] & readOnlyMask);
553  }
554  break;
555  case APIC_INITIAL_COUNT:
556  {
557  newVal = bits(val, 31, 0);
558  // Compute how many timer ticks we're being programmed for.
559  uint64_t newCount = newVal *
561  // Schedule on the edge of the next tick plus the new count.
562  Tick offset = curTick() % clockPeriod();
563  if (offset) {
564  reschedule(apicTimerEvent,
565  curTick() + (newCount + 1) *
566  clockPeriod() - offset, true);
567  } else {
568  if (newCount)
569  reschedule(apicTimerEvent,
570  curTick() + newCount *
571  clockPeriod(), true);
572  }
573  }
574  break;
575  case APIC_CURRENT_COUNT:
576  //Local APIC Current Count register is read only.
577  return;
579  newVal = val & 0xB;
580  break;
581  default:
582  break;
583  }
584  regs[reg] = newVal;
585  return;
586 }
587 
588 
590  : BasicPioDevice(p, PageBytes), IntDevice(this, p->int_latency),
591  apicTimerEvent(this),
592  pendingSmi(false), smiVector(0),
593  pendingNmi(false), nmiVector(0),
594  pendingExtInt(false), extIntVector(0),
595  pendingInit(false), initVector(0),
596  pendingStartup(false), startupVector(0),
597  startedUp(false), pendingUnmaskableInt(false),
598  pendingIPIs(0), cpu(NULL),
599  intSlavePort(name() + ".int_slave", this, this)
600 {
601  memset(regs, 0, sizeof(regs));
602  //Set the local apic DFR to the flat model.
603  regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
604  ISRV = 0;
605  IRRV = 0;
606 }
607 
608 
609 bool
611 {
612  RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS);
613  if (pendingUnmaskableInt) {
614  DPRINTF(LocalApic, "Reported pending unmaskable interrupt.\n");
615  return true;
616  }
617  if (rflags.intf) {
618  if (pendingExtInt) {
619  DPRINTF(LocalApic, "Reported pending external interrupt.\n");
620  return true;
621  }
622  if (IRRV > ISRV && bits(IRRV, 7, 4) >
623  bits(regs[APIC_TASK_PRIORITY], 7, 4)) {
624  DPRINTF(LocalApic, "Reported pending regular interrupt.\n");
625  return true;
626  }
627  }
628  return false;
629 }
630 
631 bool
633 {
634  return pendingUnmaskableInt || pendingExtInt ||
635  (IRRV > ISRV && bits(IRRV, 7, 4) >
636  bits(regs[APIC_TASK_PRIORITY], 7, 4));
637 }
638 
639 Fault
641 {
642  assert(checkInterrupts(tc));
643  // These are all probably fairly uncommon, so we'll make them easier to
644  // check for.
645  if (pendingUnmaskableInt) {
646  if (pendingSmi) {
647  DPRINTF(LocalApic, "Generated SMI fault object.\n");
648  return std::make_shared<SystemManagementInterrupt>();
649  } else if (pendingNmi) {
650  DPRINTF(LocalApic, "Generated NMI fault object.\n");
651  return std::make_shared<NonMaskableInterrupt>(nmiVector);
652  } else if (pendingInit) {
653  DPRINTF(LocalApic, "Generated INIT fault object.\n");
654  return std::make_shared<InitInterrupt>(initVector);
655  } else if (pendingStartup) {
656  DPRINTF(LocalApic, "Generating SIPI fault object.\n");
657  return std::make_shared<StartupInterrupt>(startupVector);
658  } else {
659  panic("pendingUnmaskableInt set, but no unmaskable "
660  "ints were pending.\n");
661  return NoFault;
662  }
663  } else if (pendingExtInt) {
664  DPRINTF(LocalApic, "Generated external interrupt fault object.\n");
665  return std::make_shared<ExternalInterrupt>(extIntVector);
666  } else {
667  DPRINTF(LocalApic, "Generated regular interrupt fault object.\n");
668  // The only thing left are fixed and lowest priority interrupts.
669  return std::make_shared<ExternalInterrupt>(IRRV);
670  }
671 }
672 
673 void
675 {
676  assert(checkInterrupts(tc));
677  if (pendingUnmaskableInt) {
678  if (pendingSmi) {
679  DPRINTF(LocalApic, "SMI sent to core.\n");
680  pendingSmi = false;
681  } else if (pendingNmi) {
682  DPRINTF(LocalApic, "NMI sent to core.\n");
683  pendingNmi = false;
684  } else if (pendingInit) {
685  DPRINTF(LocalApic, "Init sent to core.\n");
686  pendingInit = false;
687  startedUp = false;
688  } else if (pendingStartup) {
689  DPRINTF(LocalApic, "SIPI sent to core.\n");
690  pendingStartup = false;
691  startedUp = true;
692  }
693  if (!(pendingSmi || pendingNmi || pendingInit || pendingStartup))
694  pendingUnmaskableInt = false;
695  } else if (pendingExtInt) {
696  pendingExtInt = false;
697  } else {
698  DPRINTF(LocalApic, "Interrupt %d sent to core.\n", IRRV);
699  // Mark the interrupt as "in service".
700  ISRV = IRRV;
701  setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
702  // Clear it out of the IRR.
703  clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
704  updateIRRV();
705  }
706 }
707 
708 void
710 {
712  SERIALIZE_SCALAR(pendingSmi);
713  SERIALIZE_SCALAR(smiVector);
714  SERIALIZE_SCALAR(pendingNmi);
715  SERIALIZE_SCALAR(nmiVector);
716  SERIALIZE_SCALAR(pendingExtInt);
717  SERIALIZE_SCALAR(extIntVector);
718  SERIALIZE_SCALAR(pendingInit);
719  SERIALIZE_SCALAR(initVector);
720  SERIALIZE_SCALAR(pendingStartup);
721  SERIALIZE_SCALAR(startupVector);
722  SERIALIZE_SCALAR(startedUp);
723  SERIALIZE_SCALAR(pendingUnmaskableInt);
724  SERIALIZE_SCALAR(pendingIPIs);
725  SERIALIZE_SCALAR(IRRV);
726  SERIALIZE_SCALAR(ISRV);
727  bool apicTimerEventScheduled = apicTimerEvent.scheduled();
728  SERIALIZE_SCALAR(apicTimerEventScheduled);
729  Tick apicTimerEventTick = apicTimerEvent.when();
730  SERIALIZE_SCALAR(apicTimerEventTick);
731 }
732 
733 void
735 {
737  UNSERIALIZE_SCALAR(pendingSmi);
738  UNSERIALIZE_SCALAR(smiVector);
739  UNSERIALIZE_SCALAR(pendingNmi);
740  UNSERIALIZE_SCALAR(nmiVector);
741  UNSERIALIZE_SCALAR(pendingExtInt);
742  UNSERIALIZE_SCALAR(extIntVector);
743  UNSERIALIZE_SCALAR(pendingInit);
744  UNSERIALIZE_SCALAR(initVector);
745  UNSERIALIZE_SCALAR(pendingStartup);
746  UNSERIALIZE_SCALAR(startupVector);
747  UNSERIALIZE_SCALAR(startedUp);
748  UNSERIALIZE_SCALAR(pendingUnmaskableInt);
749  UNSERIALIZE_SCALAR(pendingIPIs);
750  UNSERIALIZE_SCALAR(IRRV);
751  UNSERIALIZE_SCALAR(ISRV);
752  bool apicTimerEventScheduled;
753  UNSERIALIZE_SCALAR(apicTimerEventScheduled);
754  if (apicTimerEventScheduled) {
755  Tick apicTimerEventTick;
756  UNSERIALIZE_SCALAR(apicTimerEventTick);
757  if (apicTimerEvent.scheduled()) {
758  reschedule(apicTimerEvent, apicTimerEventTick, true);
759  } else {
760  schedule(apicTimerEvent, apicTimerEventTick);
761  }
762  }
763 }
764 
766 X86LocalApicParams::create()
767 {
768  return new X86ISA::Interrupts(this);
769 }
#define DPRINTF(x,...)
Definition: trace.hh:212
offset
Definition: misc.hh:977
#define hack_once(...)
Definition: misc.hh:230
T htog(T value)
Definition: byteswap.hh:177
Bitfield< 5, 3 > reg
Definition: types.hh:89
decltype(nullptr) constexpr NoFault
Definition: types.hh:189
const std::string & name()
Definition: trace.cc:49
Bitfield< 7 > i
Definition: miscregs.hh:1378
#define panic(...)
Definition: misc.hh:153
void setCPU(BaseCPU *newCPU)
Definition: interrupts.cc:275
uint32_t readReg(ApicRegIndex miscReg)
Definition: interrupts.cc:362
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
Tick recvResponse(PacketPtr pkt) override
Definition: interrupts.cc:335
virtual void init()
Definition: intdev.cc:67
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:146
AddrRangeList getIntAddrRange() const override
Definition: interrupts.cc:351
void updateIntrInfo(ThreadContext *tc)
Definition: interrupts.cc:674
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: interrupts.cc:191
void setReg(ApicRegIndex reg, uint32_t val)
Definition: interrupts.cc:400
int divideFromConf(uint32_t conf)
Definition: interrupts.cc:68
const Addr PageBytes
Definition: isa_traits.hh:64
ThreadContext is the external interface to all thread state for anything outside of the CPU...
void init() override
Definition: interrupts.cc:290
void writeData(uint8_t *p) const
Copy data from the packet to the provided block pointer, which is aligned to the given block size...
Definition: packet.hh:1052
T gtoh(T value)
Definition: byteswap.hh:179
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
Bitfield< 63 > val
Definition: misc.hh:770
#define warn(...)
Definition: misc.hh:219
Tick recvMessage(PacketPtr pkt) override
Definition: interrupts.cc:307
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
Tick curTick()
The current simulated tick.
Definition: core.hh:47
Fault getInterrupt(ThreadContext *tc)
Definition: interrupts.cc:640
const Addr PhysAddrAPICRangeSize
Definition: x86_traits.hh:78
Interrupts(Params *p)
Definition: interrupts.cc:589
X86LocalApicParams Params
Definition: interrupts.hh:202
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1024
static Addr x86InterruptAddress(const uint8_t id, const uint16_t addr)
Definition: x86_traits.hh:100
void makeAtomicResponse()
Definition: packet.hh:857
uint64_t Tick
Tick count type.
Definition: types.hh:63
Bitfield< 6, 5 > shift
Definition: types.hh:122
mask
Definition: misc.hh:797
void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level)
Definition: interrupts.cc:225
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
ApicRegIndex decodeAddr(Addr paddr)
Definition: interrupts.cc:82
bool checkInterruptsRaw() const
Check if there are pending interrupts without ignoring the interrupts disabled flag.
Definition: interrupts.cc:632
static ApicRegIndex APIC_TRIGGER_MODE(int index)
Definition: apic.hh:81
uint32_t regs[NUM_APIC_REGS]
Definition: interrupts.hh:79
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
#define ULL(N)
uint64_t constant
Definition: types.hh:50
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
Bitfield< 15, 8 > vector
Definition: intmessage.hh:45
ApicRegIndex
Definition: apic.hh:38
Declaration of top level class for PC platform components.
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
Bitfield< 20 > level
Definition: intmessage.hh:48
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
AddrRange RangeEx(Addr start, Addr end)
Definition: addr_range.hh:390
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:83
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: interrupts.cc:709
static ApicRegIndex APIC_IN_SERVICE(int index)
Definition: apic.hh:75
std::ostream CheckpointOut
Definition: serialize.hh:67
bool isError() const
Definition: packet.hh:528
MemCmd cmd
The command field of the packet.
Definition: packet.hh:301
bool checkInterrupts(ThreadContext *tc) const
Definition: interrupts.cc:610
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:145
Bitfield< 18, 16 > deliveryMode
Definition: intmessage.hh:46
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: interrupts.cc:208
Bitfield< 0 > p
Definition: pagetable.hh:95
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: interrupts.cc:734
unsigned getSize() const
Definition: packet.hh:649
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
static Addr x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
Definition: x86_traits.hh:93
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:139
std::shared_ptr< FaultBase > Fault
Definition: types.hh:184
static ApicRegIndex APIC_INTERRUPT_REQUEST(int index)
Definition: apic.hh:87
Addr getAddr() const
Definition: packet.hh:639

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