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

Generated on Wed Dec 21 2022 10:22:24 for gem5 by doxygen 1.9.1