gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 <list>
55 #include <memory>
56 
57 #include "arch/x86/intmessage.hh"
58 #include "arch/x86/regs/apic.hh"
59 #include "cpu/base.hh"
60 #include "debug/LocalApic.hh"
61 #include "dev/x86/i82094aa.hh"
62 #include "dev/x86/pc.hh"
63 #include "dev/x86/south_bridge.hh"
64 #include "mem/packet_access.hh"
65 #include "sim/full_system.hh"
66 #include "sim/system.hh"
67 
68 int
69 divideFromConf(uint32_t conf)
70 {
71  // This figures out what division we want from the division configuration
72  // register in the local APIC. The encoding is a little odd but it can
73  // be deciphered fairly easily.
74  int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
75  shift = (shift + 1) % 8;
76  return 1 << shift;
77 }
78 
79 namespace X86ISA
80 {
81 
84 {
85  ApicRegIndex regNum;
86  paddr &= ~mask(3);
87  switch (paddr)
88  {
89  case 0x20:
90  regNum = APIC_ID;
91  break;
92  case 0x30:
93  regNum = APIC_VERSION;
94  break;
95  case 0x80:
96  regNum = APIC_TASK_PRIORITY;
97  break;
98  case 0x90:
100  break;
101  case 0xA0:
102  regNum = APIC_PROCESSOR_PRIORITY;
103  break;
104  case 0xB0:
105  regNum = APIC_EOI;
106  break;
107  case 0xD0:
108  regNum = APIC_LOGICAL_DESTINATION;
109  break;
110  case 0xE0:
111  regNum = APIC_DESTINATION_FORMAT;
112  break;
113  case 0xF0:
115  break;
116  case 0x100:
117  case 0x110:
118  case 0x120:
119  case 0x130:
120  case 0x140:
121  case 0x150:
122  case 0x160:
123  case 0x170:
124  regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x10);
125  break;
126  case 0x180:
127  case 0x190:
128  case 0x1A0:
129  case 0x1B0:
130  case 0x1C0:
131  case 0x1D0:
132  case 0x1E0:
133  case 0x1F0:
134  regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x10);
135  break;
136  case 0x200:
137  case 0x210:
138  case 0x220:
139  case 0x230:
140  case 0x240:
141  case 0x250:
142  case 0x260:
143  case 0x270:
144  regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x10);
145  break;
146  case 0x280:
147  regNum = APIC_ERROR_STATUS;
148  break;
149  case 0x300:
151  break;
152  case 0x310:
154  break;
155  case 0x320:
156  regNum = APIC_LVT_TIMER;
157  break;
158  case 0x330:
159  regNum = APIC_LVT_THERMAL_SENSOR;
160  break;
161  case 0x340:
163  break;
164  case 0x350:
165  regNum = APIC_LVT_LINT0;
166  break;
167  case 0x360:
168  regNum = APIC_LVT_LINT1;
169  break;
170  case 0x370:
171  regNum = APIC_LVT_ERROR;
172  break;
173  case 0x380:
174  regNum = APIC_INITIAL_COUNT;
175  break;
176  case 0x390:
177  regNum = APIC_CURRENT_COUNT;
178  break;
179  case 0x3E0:
180  regNum = APIC_DIVIDE_CONFIGURATION;
181  break;
182  default:
183  // A reserved register field.
184  panic("Accessed reserved register field %#x.\n", paddr);
185  break;
186  }
187  return regNum;
188 }
189 }
190 
191 Tick
193 {
194  Addr offset = pkt->getAddr() - pioAddr;
195  // Make sure we're at least only accessing one register.
196  if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
197  panic("Accessed more than one register at a time in the APIC!\n");
198  ApicRegIndex reg = decodeAddr(offset);
199  uint32_t val = htole(readReg(reg));
200  DPRINTF(LocalApic,
201  "Reading Local APIC register %d at offset %#x as %#x.\n",
202  reg, offset, val);
203  pkt->setData(((uint8_t *)&val) + (offset & mask(3)));
204  pkt->makeAtomicResponse();
205  return pioDelay;
206 }
207 
208 Tick
210 {
211  Addr offset = pkt->getAddr() - pioAddr;
212  // Make sure we're at least only accessing one register.
213  if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
214  panic("Accessed more than one register at a time in the APIC!\n");
215  ApicRegIndex reg = decodeAddr(offset);
216  uint32_t val = regs[reg];
217  pkt->writeData(((uint8_t *)&val) + (offset & mask(3)));
218  DPRINTF(LocalApic,
219  "Writing Local APIC register %d at offset %#x as %#x.\n",
220  reg, offset, letoh(val));
221  setReg(reg, letoh(val));
222  pkt->makeAtomicResponse();
223  return pioDelay;
224 }
225 void
227  uint8_t deliveryMode, bool level)
228 {
229  /*
230  * Fixed and lowest-priority delivery mode interrupts are handled
231  * using the IRR/ISR registers, checking against the TPR, etc.
232  * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through.
233  */
234  if (deliveryMode == DeliveryMode::Fixed ||
235  deliveryMode == DeliveryMode::LowestPriority) {
236  DPRINTF(LocalApic, "Interrupt is an %s.\n",
237  DeliveryMode::names[deliveryMode]);
238  // Queue up the interrupt in the IRR.
239  if (vector > IRRV)
240  IRRV = vector;
241  if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) {
242  setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector);
243  if (level) {
244  setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
245  } else {
246  clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
247  }
248  }
249  } else if (!DeliveryMode::isReserved(deliveryMode)) {
250  DPRINTF(LocalApic, "Interrupt is an %s.\n",
251  DeliveryMode::names[deliveryMode]);
252  if (deliveryMode == DeliveryMode::SMI && !pendingSmi) {
253  pendingUnmaskableInt = pendingSmi = true;
254  smiVector = vector;
255  } else if (deliveryMode == DeliveryMode::NMI && !pendingNmi) {
256  pendingUnmaskableInt = pendingNmi = true;
257  nmiVector = vector;
258  } else if (deliveryMode == DeliveryMode::ExtInt && !pendingExtInt) {
259  pendingExtInt = true;
260  extIntVector = vector;
261  } else if (deliveryMode == DeliveryMode::INIT && !pendingInit) {
262  pendingUnmaskableInt = pendingInit = true;
263  initVector = vector;
264  } else if (deliveryMode == DeliveryMode::SIPI &&
265  !pendingStartup && !startedUp) {
266  pendingUnmaskableInt = pendingStartup = true;
267  startupVector = vector;
268  }
269  }
270  if (FullSystem)
271  cpu->wakeup(0);
272 }
273 
274 
275 void
277 {
278  assert(newCPU);
279  if (cpu != NULL && cpu->cpuId() != newCPU->cpuId()) {
280  panic("Local APICs can't be moved between CPUs"
281  " with different IDs.\n");
282  }
283  cpu = newCPU;
284  initialApicId = cpu->cpuId();
285  regs[APIC_ID] = (initialApicId << 24);
286  pioAddr = x86LocalAPICAddress(initialApicId, 0);
287 }
288 
289 
290 void
292 {
293  panic_if(!intMasterPort.isConnected(),
294  "Int port not connected to anything!");
295  panic_if(!pioPort.isConnected(),
296  "Pio port of %s not connected to anything!", name());
297 
298  intSlavePort.sendRangeChange();
299  pioPort.sendRangeChange();
300 }
301 
302 
303 Tick
305 {
306  Addr offset = pkt->getAddr() - x86InterruptAddress(initialApicId, 0);
307  assert(pkt->cmd == MemCmd::WriteReq);
308  switch(offset)
309  {
310  case 0:
311  {
312  TriggerIntMessage message = pkt->getRaw<TriggerIntMessage>();
313  DPRINTF(LocalApic,
314  "Got Trigger Interrupt message with vector %#x.\n",
315  message.vector);
316 
317  requestInterrupt(message.vector,
318  message.deliveryMode, message.trigger);
319  }
320  break;
321  default:
322  panic("Local apic got unknown interrupt message at offset %#x.\n",
323  offset);
324  break;
325  }
326  pkt->makeAtomicResponse();
327  return pioDelay;
328 }
329 
330 
331 void
333 {
334  if (--pendingIPIs == 0) {
335  InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
336  // Record that the ICR is now idle.
337  low.deliveryStatus = 0;
338  regs[APIC_INTERRUPT_COMMAND_LOW] = low;
339  }
340  DPRINTF(LocalApic, "ICR is now idle.\n");
341  delete pkt;
342 }
343 
344 
347 {
348  assert(cpu);
349  AddrRangeList ranges;
350  ranges.push_back(RangeSize(pioAddr, PageBytes));
351  return ranges;
352 }
353 
354 
357 {
358  AddrRangeList ranges;
359  ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0),
360  x86InterruptAddress(initialApicId, 0) +
362  return ranges;
363 }
364 
365 
366 uint32_t
368 {
369  if (reg >= APIC_TRIGGER_MODE(0) &&
370  reg <= APIC_TRIGGER_MODE(15)) {
371  panic("Local APIC Trigger Mode registers are unimplemented.\n");
372  }
373  switch (reg) {
375  panic("Local APIC Arbitration Priority register unimplemented.\n");
376  break;
378  panic("Local APIC Processor Priority register unimplemented.\n");
379  break;
380  case APIC_ERROR_STATUS:
381  regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
382  break;
383  case APIC_CURRENT_COUNT:
384  {
385  if (apicTimerEvent.scheduled()) {
386  // Compute how many m5 ticks happen per count.
387  uint64_t ticksPerCount = clockPeriod() *
389  // Compute how many m5 ticks are left.
390  uint64_t val = apicTimerEvent.when() - curTick();
391  // Turn that into a count.
392  val = (val + ticksPerCount - 1) / ticksPerCount;
393  return val;
394  } else {
395  return 0;
396  }
397  }
398  default:
399  break;
400  }
401  return regs[reg];
402 }
403 
404 void
406 {
407  uint32_t newVal = val;
408  if (reg >= APIC_IN_SERVICE(0) &&
409  reg <= APIC_IN_SERVICE(15)) {
410  panic("Local APIC In-Service registers are unimplemented.\n");
411  }
412  if (reg >= APIC_TRIGGER_MODE(0) &&
413  reg <= APIC_TRIGGER_MODE(15)) {
414  panic("Local APIC Trigger Mode registers are unimplemented.\n");
415  }
416  if (reg >= APIC_INTERRUPT_REQUEST(0) &&
417  reg <= APIC_INTERRUPT_REQUEST(15)) {
418  panic("Local APIC Interrupt Request registers "
419  "are unimplemented.\n");
420  }
421  switch (reg) {
422  case APIC_ID:
423  newVal = val & 0xFF;
424  break;
425  case APIC_VERSION:
426  // The Local APIC Version register is read only.
427  return;
428  case APIC_TASK_PRIORITY:
429  newVal = val & 0xFF;
430  break;
432  panic("Local APIC Arbitration Priority register unimplemented.\n");
433  break;
435  panic("Local APIC Processor Priority register unimplemented.\n");
436  break;
437  case APIC_EOI:
438  // Remove the interrupt that just completed from the local apic state.
439  clearRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
440  updateISRV();
441  return;
443  newVal = val & 0xFF000000;
444  break;
446  newVal = val | 0x0FFFFFFF;
447  break;
449  regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
450  regs[APIC_INTERNAL_STATE] |= val & (1 << 8);
451  if (val & (1 << 9))
452  warn("Focus processor checking not implemented.\n");
453  break;
454  case APIC_ERROR_STATUS:
455  {
456  if (regs[APIC_INTERNAL_STATE] & 0x1) {
457  regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
458  newVal = 0;
459  } else {
460  regs[APIC_INTERNAL_STATE] |= ULL(0x1);
461  return;
462  }
463 
464  }
465  break;
467  {
468  InterruptCommandRegLow low = regs[APIC_INTERRUPT_COMMAND_LOW];
469  // Check if we're already sending an IPI.
470  if (low.deliveryStatus) {
471  newVal = low;
472  break;
473  }
474  low = val;
475  InterruptCommandRegHigh high = regs[APIC_INTERRUPT_COMMAND_HIGH];
476  TriggerIntMessage message = 0;
477  message.destination = high.destination;
478  message.vector = low.vector;
479  message.deliveryMode = low.deliveryMode;
480  message.destMode = low.destMode;
481  message.level = low.level;
482  message.trigger = low.trigger;
483  std::list<int> apics;
484  int numContexts = sys->numContexts();
485  switch (low.destShorthand) {
486  case 0:
487  if (message.deliveryMode == DeliveryMode::LowestPriority) {
488  panic("Lowest priority delivery mode "
489  "IPIs aren't implemented.\n");
490  }
491  if (message.destMode == 1) {
492  int dest = message.destination;
493  hack_once("Assuming logical destinations are 1 << id.\n");
494  for (int i = 0; i < numContexts; i++) {
495  if (dest & 0x1)
496  apics.push_back(i);
497  dest = dest >> 1;
498  }
499  } else {
500  if (message.destination == 0xFF) {
501  for (int i = 0; i < numContexts; i++) {
502  if (i == initialApicId) {
503  requestInterrupt(message.vector,
504  message.deliveryMode, message.trigger);
505  } else {
506  apics.push_back(i);
507  }
508  }
509  } else {
510  if (message.destination == initialApicId) {
511  requestInterrupt(message.vector,
512  message.deliveryMode, message.trigger);
513  } else {
514  apics.push_back(message.destination);
515  }
516  }
517  }
518  break;
519  case 1:
520  newVal = val;
521  requestInterrupt(message.vector,
522  message.deliveryMode, message.trigger);
523  break;
524  case 2:
525  requestInterrupt(message.vector,
526  message.deliveryMode, message.trigger);
527  // Fall through
528  case 3:
529  {
530  for (int i = 0; i < numContexts; i++) {
531  if (i != initialApicId) {
532  apics.push_back(i);
533  }
534  }
535  }
536  break;
537  }
538  // Record that an IPI is being sent if one actually is.
539  if (apics.size()) {
540  low.deliveryStatus = 1;
541  pendingIPIs += apics.size();
542  }
543  regs[APIC_INTERRUPT_COMMAND_LOW] = low;
544  for (auto id: apics) {
545  PacketPtr pkt = buildIntTriggerPacket(id, message);
546  intMasterPort.sendMessage(pkt, sys->isTimingMode(),
547  [this](PacketPtr pkt) { completeIPI(pkt); });
548  }
549  newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
550  }
551  break;
552  case APIC_LVT_TIMER:
555  case APIC_LVT_LINT0:
556  case APIC_LVT_LINT1:
557  case APIC_LVT_ERROR:
558  {
559  uint64_t readOnlyMask = (1 << 12) | (1 << 14);
560  newVal = (val & ~readOnlyMask) |
561  (regs[reg] & readOnlyMask);
562  }
563  break;
564  case APIC_INITIAL_COUNT:
565  {
566  newVal = bits(val, 31, 0);
567  // Compute how many timer ticks we're being programmed for.
568  uint64_t newCount = newVal *
570  // Schedule on the edge of the next tick plus the new count.
571  Tick offset = curTick() % clockPeriod();
572  if (offset) {
573  reschedule(apicTimerEvent,
574  curTick() + (newCount + 1) *
575  clockPeriod() - offset, true);
576  } else {
577  if (newCount)
578  reschedule(apicTimerEvent,
579  curTick() + newCount *
580  clockPeriod(), true);
581  }
582  }
583  break;
584  case APIC_CURRENT_COUNT:
585  //Local APIC Current Count register is read only.
586  return;
588  newVal = val & 0xB;
589  break;
590  default:
591  break;
592  }
593  regs[reg] = newVal;
594  return;
595 }
596 
597 
599  : BaseInterrupts(p), sys(p->system), clockDomain(*p->clk_domain),
600  apicTimerEvent([this]{ processApicTimerEvent(); }, name()),
601  pendingSmi(false), smiVector(0),
602  pendingNmi(false), nmiVector(0),
603  pendingExtInt(false), extIntVector(0),
604  pendingInit(false), initVector(0),
605  pendingStartup(false), startupVector(0),
606  startedUp(false), pendingUnmaskableInt(false),
607  pendingIPIs(0), cpu(NULL),
608  intSlavePort(name() + ".int_slave", this, this),
609  intMasterPort(name() + ".int_master", this, this, p->int_latency),
610  pioPort(this), pioDelay(p->pio_latency)
611 {
612  memset(regs, 0, sizeof(regs));
613  //Set the local apic DFR to the flat model.
614  regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
615  ISRV = 0;
616  IRRV = 0;
617 
618  regs[APIC_VERSION] = (5 << 16) | 0x14;
619 }
620 
621 
622 bool
624 {
625  RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS);
626  if (pendingUnmaskableInt) {
627  DPRINTF(LocalApic, "Reported pending unmaskable interrupt.\n");
628  return true;
629  }
630  if (rflags.intf) {
631  if (pendingExtInt) {
632  DPRINTF(LocalApic, "Reported pending external interrupt.\n");
633  return true;
634  }
635  if (IRRV > ISRV && bits(IRRV, 7, 4) >
636  bits(regs[APIC_TASK_PRIORITY], 7, 4)) {
637  DPRINTF(LocalApic, "Reported pending regular interrupt.\n");
638  return true;
639  }
640  }
641  return false;
642 }
643 
644 bool
646 {
648  (IRRV > ISRV && bits(IRRV, 7, 4) >
649  bits(regs[APIC_TASK_PRIORITY], 7, 4));
650 }
651 
652 Fault
654 {
655  assert(checkInterrupts(tc));
656  // These are all probably fairly uncommon, so we'll make them easier to
657  // check for.
658  if (pendingUnmaskableInt) {
659  if (pendingSmi) {
660  DPRINTF(LocalApic, "Generated SMI fault object.\n");
661  return std::make_shared<SystemManagementInterrupt>();
662  } else if (pendingNmi) {
663  DPRINTF(LocalApic, "Generated NMI fault object.\n");
664  return std::make_shared<NonMaskableInterrupt>(nmiVector);
665  } else if (pendingInit) {
666  DPRINTF(LocalApic, "Generated INIT fault object.\n");
667  return std::make_shared<InitInterrupt>(initVector);
668  } else if (pendingStartup) {
669  DPRINTF(LocalApic, "Generating SIPI fault object.\n");
670  return std::make_shared<StartupInterrupt>(startupVector);
671  } else {
672  panic("pendingUnmaskableInt set, but no unmaskable "
673  "ints were pending.\n");
674  return NoFault;
675  }
676  } else if (pendingExtInt) {
677  DPRINTF(LocalApic, "Generated external interrupt fault object.\n");
678  return std::make_shared<ExternalInterrupt>(extIntVector);
679  } else {
680  DPRINTF(LocalApic, "Generated regular interrupt fault object.\n");
681  // The only thing left are fixed and lowest priority interrupts.
682  return std::make_shared<ExternalInterrupt>(IRRV);
683  }
684 }
685 
686 void
688 {
689  assert(checkInterrupts(tc));
690  if (pendingUnmaskableInt) {
691  if (pendingSmi) {
692  DPRINTF(LocalApic, "SMI sent to core.\n");
693  pendingSmi = false;
694  } else if (pendingNmi) {
695  DPRINTF(LocalApic, "NMI sent to core.\n");
696  pendingNmi = false;
697  } else if (pendingInit) {
698  DPRINTF(LocalApic, "Init sent to core.\n");
699  pendingInit = false;
700  startedUp = false;
701  } else if (pendingStartup) {
702  DPRINTF(LocalApic, "SIPI sent to core.\n");
703  pendingStartup = false;
704  startedUp = true;
705  }
707  pendingUnmaskableInt = false;
708  } else if (pendingExtInt) {
709  pendingExtInt = false;
710  } else {
711  DPRINTF(LocalApic, "Interrupt %d sent to core.\n", IRRV);
712  // Mark the interrupt as "in service".
713  ISRV = IRRV;
715  // Clear it out of the IRR.
717  updateIRRV();
718  }
719 }
720 
721 void
723 {
740  bool apicTimerEventScheduled = apicTimerEvent.scheduled();
741  SERIALIZE_SCALAR(apicTimerEventScheduled);
742  Tick apicTimerEventTick = apicTimerEvent.when();
743  SERIALIZE_SCALAR(apicTimerEventTick);
744 }
745 
746 void
748 {
765  bool apicTimerEventScheduled;
766  UNSERIALIZE_SCALAR(apicTimerEventScheduled);
767  if (apicTimerEventScheduled) {
768  Tick apicTimerEventTick;
769  UNSERIALIZE_SCALAR(apicTimerEventTick);
770  if (apicTimerEvent.scheduled()) {
771  reschedule(apicTimerEvent, apicTimerEventTick, true);
772  } else {
773  schedule(apicTimerEvent, apicTimerEventTick);
774  }
775  }
776 }
777 
779 X86LocalApicParams::create()
780 {
781  return new X86ISA::Interrupts(this);
782 }
783 
784 void
786  if (triggerTimerInterrupt())
788 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:584
offset
Definition: misc.hh:1026
Bitfield< 5, 3 > reg
Definition: types.hh:89
decltype(nullptr) constexpr NoFault
Definition: types.hh:245
const std::string & name()
Definition: trace.cc:54
void setCPU(BaseCPU *newCPU) override
Definition: interrupts.cc:276
Bitfield< 7 > i
IntMasterPort< Interrupts > intMasterPort
Definition: interrupts.hh:182
void completeIPI(PacketPtr pkt)
Definition: interrupts.cc:332
uint32_t readReg(ApicRegIndex miscReg)
Definition: interrupts.cc:367
void updateIntrInfo(ThreadContext *tc) override
Definition: interrupts.cc:687
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:136
void setReg(ApicRegIndex reg, uint32_t val)
Definition: interrupts.cc:405
int divideFromConf(uint32_t conf)
Definition: interrupts.cc:69
const Addr PageBytes
Definition: isa_traits.hh:53
T letoh(T value)
Definition: byteswap.hh:145
Definition: cprintf.cc:42
int cpuId() const
Reads this CPU&#39;s ID.
Definition: base.hh:183
AddrRangeList getAddrRanges() const
Definition: interrupts.cc:346
ThreadContext is the external interface to all thread state for anything outside of the CPU...
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: interrupts.cc:291
Bitfield< 63 > val
Definition: misc.hh:771
unsigned getSize() const
Definition: packet.hh:736
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
T htole(T value)
Definition: byteswap.hh:144
Tick curTick()
The current simulated tick.
Definition: core.hh:47
const Addr PhysAddrAPICRangeSize
Definition: x86_traits.hh:78
Interrupts(Params *p)
Definition: interrupts.cc:598
bool checkInterrupts(ThreadContext *tc) const override
Definition: interrupts.cc:623
Fault getInterrupt(ThreadContext *tc) override
Definition: interrupts.cc:653
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1158
static Addr x86InterruptAddress(const uint8_t id, const uint16_t addr)
Definition: x86_traits.hh:100
#define hack_once(...)
Definition: logging.hh:218
void makeAtomicResponse()
Definition: packet.hh:949
void setRegArrayBit(ApicRegIndex base, uint8_t vector)
Definition: interrupts.hh:155
uint64_t Tick
Tick count type.
Definition: types.hh:63
Bitfield< 6, 5 > shift
Definition: types.hh:127
mask
Definition: misc.hh:798
PioPort< Interrupts > pioPort
Definition: interrupts.hh:185
void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level)
Definition: interrupts.cc:226
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:658
Addr getAddr() const
Definition: packet.hh:726
ApicRegIndex decodeAddr(Addr paddr)
Definition: interrupts.cc:83
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition: packet.hh:1187
static ApicRegIndex APIC_TRIGGER_MODE(int index)
Definition: apic.hh:81
uint32_t regs[NUM_APIC_REGS]
Definition: interrupts.hh:83
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
virtual const std::string name() const
Definition: sim_object.hh:120
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
Bitfield< 15, 8 > vector
Definition: intmessage.hh:46
Tick recvMessage(PacketPtr pkt)
Definition: interrupts.cc:304
Bitfield< 15 > system
Definition: misc.hh:999
ApicRegIndex
Definition: apic.hh:38
Declaration of top level class for PC platform components.
Tick read(PacketPtr pkt)
Definition: interrupts.cc:192
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
Bitfield< 20 > level
Definition: intmessage.hh:49
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:661
bool checkInterruptsRaw() const
Check if there are pending interrupts without ignoring the interrupts disabled flag.
Definition: interrupts.cc:645
AddrRange RangeEx(Addr start, Addr end)
Definition: addr_range.hh:576
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:756
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: interrupts.cc:722
static ApicRegIndex APIC_IN_SERVICE(int index)
Definition: apic.hh:75
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
std::ostream CheckpointOut
Definition: serialize.hh:68
This is exposed globally, independent of the ISA.
Definition: acpi.hh:57
MemCmd cmd
The command field of the packet.
Definition: packet.hh:322
Tick write(PacketPtr pkt)
Definition: interrupts.cc:209
T getRaw() const
Get the data in the packet without byte swapping.
BaseInterruptsParams Params
Definition: interrupts.hh:45
IntSlavePort< Interrupts > intSlavePort
Definition: interrupts.hh:181
Bitfield< 18, 16 > deliveryMode
Definition: intmessage.hh:47
void schedule(Event &event, Tick when)
Definition: eventq.hh:744
static PacketPtr buildIntTriggerPacket(int id, TriggerIntMessage message)
Definition: intmessage.hh:81
Bitfield< 0 > p
Definition: pagetable.hh:152
#define warn(...)
Definition: logging.hh:212
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: interrupts.cc:747
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:72
bool triggerTimerInterrupt()
Definition: interrupts.hh:221
static Addr x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
Definition: x86_traits.hh:93
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
void processApicTimerEvent()
Definition: interrupts.cc:785
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
void clearRegArrayBit(ApicRegIndex base, uint8_t vector)
Definition: interrupts.hh:161
static ApicRegIndex APIC_INTERRUPT_REQUEST(int index)
Definition: apic.hh:87
AddrRangeList getIntAddrRange() const
Definition: interrupts.cc:356

Generated on Fri Feb 28 2020 16:26:56 for gem5 by doxygen 1.8.13