59 #include "debug/LocalApic.hh"
76 int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
186 panic(
"Accessed reserved register field %#x.\n", paddr);
199 panic(
"Accessed more than one register at a time in the APIC!\n");
203 "Reading Local APIC register %d at offset %#x as %#x.\n",
216 panic(
"Accessed more than one register at a time in the APIC!\n");
221 "Writing Local APIC register %d at offset %#x as %#x.\n",
238 DPRINTF(LocalApic,
"Interrupt is an %s.\n",
252 DPRINTF(LocalApic,
"Interrupt is an %s.\n",
255 pendingUnmaskableInt = pendingSmi =
true;
258 pendingUnmaskableInt = pendingNmi =
true;
261 pendingExtInt =
true;
264 pendingUnmaskableInt = pendingInit =
true;
267 !pendingStartup && !startedUp) {
268 pendingUnmaskableInt = pendingStartup =
true;
273 tc->getCpuPtr()->wakeup(0);
281 "Asked to raise unrecognized int pin %d.", number);
282 DPRINTF(LocalApic,
"Raised wired interrupt pin LINT%d.\n", number);
284 const LVTEntry entry =
288 DPRINTF(LocalApic,
"The interrupt was masked.\n");
293 auto on_completion = [
this,
dm=entry.deliveryMode,
trigger=entry.trigger](
298 intRequestPort.sendMessage(pkt, sys->isTimingMode(), on_completion);
306 "Asked to lower unrecognized int pin %d.", number);
307 DPRINTF(LocalApic,
"Lowered wired interrupt pin LINT%d.\n", number);
316 "Local APICs can't be moved between CPUs with different IDs.");
320 initialApicId = tc->cpuId();
321 regs[
APIC_ID] = (initialApicId << 24);
329 panic_if(!intRequestPort.isConnected(),
330 "Int port not connected to anything!");
332 "Pio port of %s not connected to anything!",
name());
334 intResponsePort.sendRangeChange();
335 pioPort.sendRangeChange();
348 TriggerIntMessage message = pkt->
getRaw<TriggerIntMessage>();
350 "Got Trigger Interrupt message with vector %#x.\n",
353 requestInterrupt(message.vector,
354 message.deliveryMode, message.trigger);
358 panic(
"Local apic got unknown interrupt message at offset %#x.\n",
370 if (--pendingIPIs == 0) {
373 low.deliveryStatus = 0;
376 DPRINTF(LocalApic,
"ICR is now idle.\n");
407 panic(
"Local APIC Trigger Mode registers are unimplemented.\n");
411 panic(
"Local APIC Arbitration Priority register unimplemented.\n");
414 panic(
"Local APIC Processor Priority register unimplemented.\n");
421 if (apicTimerEvent.scheduled()) {
423 uint64_t ticksPerCount = clockPeriod() *
426 uint64_t
val = apicTimerEvent.when() -
curTick();
428 val = (
val + ticksPerCount - 1) / ticksPerCount;
443 uint32_t newVal =
val;
446 panic(
"Local APIC In-Service registers are unimplemented.\n");
450 panic(
"Local APIC Trigger Mode registers are unimplemented.\n");
454 panic(
"Local APIC Interrupt Request registers "
455 "are unimplemented.\n");
468 panic(
"Local APIC Arbitration Priority register unimplemented.\n");
471 panic(
"Local APIC Processor Priority register unimplemented.\n");
479 newVal =
val & 0xFF000000;
482 newVal =
val | 0x0FFFFFFF;
488 warn(
"Focus processor checking not implemented.\n");
506 if (low.deliveryStatus) {
512 TriggerIntMessage message = 0;
513 message.destination =
high.destination;
514 message.vector = low.vector;
515 message.deliveryMode = low.deliveryMode;
516 message.destMode = low.destMode;
517 message.level = low.level;
518 message.trigger = low.trigger;
520 int numContexts = sys->threads.size();
521 switch (low.destShorthand) {
524 panic(
"Lowest priority delivery mode "
525 "IPIs aren't implemented.\n");
527 if (message.destMode == 1) {
528 int dest = message.destination;
529 hack_once(
"Assuming logical destinations are 1 << id.\n");
530 for (
int i = 0;
i < numContexts;
i++) {
536 if (message.destination == 0xFF) {
537 for (
int i = 0;
i < numContexts;
i++) {
538 if (
i == initialApicId) {
539 requestInterrupt(message.vector,
540 message.deliveryMode, message.trigger);
546 if (message.destination == initialApicId) {
547 requestInterrupt(message.vector,
548 message.deliveryMode, message.trigger);
550 apics.push_back(message.destination);
557 requestInterrupt(message.vector,
558 message.deliveryMode, message.trigger);
561 requestInterrupt(message.vector,
562 message.deliveryMode, message.trigger);
566 for (
int i = 0;
i < numContexts;
i++) {
567 if (
i != initialApicId) {
576 low.deliveryStatus = 1;
577 pendingIPIs += apics.size();
580 for (
auto id: apics) {
582 intRequestPort.sendMessage(pkt, sys->isTimingMode(),
583 [
this](
PacketPtr pkt) { completeIPI(pkt); });
595 uint64_t readOnlyMask = (1 << 12) | (1 << 14);
596 newVal = (
val & ~readOnlyMask) |
597 (regs[
reg] & readOnlyMask);
604 uint64_t newCount = newVal *
609 reschedule(apicTimerEvent,
611 clockPeriod() -
offset,
true);
614 reschedule(apicTimerEvent,
616 clockPeriod(),
true);
637 intResponsePort(
name() +
".int_responder",
this,
this),
638 intRequestPort(
name() +
".int_requestor",
this,
this,
p.int_latency),
639 lint0Pin(
name() +
".lint0", 0,
this, 0),
640 lint1Pin(
name() +
".lint1", 0,
this, 1),
641 pioPort(
this), pioDelay(
p.pio_latency)
643 memset(regs, 0,
sizeof(regs));
668 if (pendingUnmaskableInt) {
669 DPRINTF(LocalApic,
"Reported pending unmaskable interrupt.\n");
674 DPRINTF(LocalApic,
"Reported pending external interrupt.\n");
677 if (IRRV > ISRV &&
bits(IRRV, 7, 4) >
679 DPRINTF(LocalApic,
"Reported pending regular interrupt.\n");
689 return pendingUnmaskableInt || pendingExtInt ||
690 (IRRV > ISRV &&
bits(IRRV, 7, 4) >
697 assert(checkInterrupts());
700 if (pendingUnmaskableInt) {
702 DPRINTF(LocalApic,
"Generated SMI fault object.\n");
703 return std::make_shared<SystemManagementInterrupt>();
704 }
else if (pendingNmi) {
705 DPRINTF(LocalApic,
"Generated NMI fault object.\n");
706 return std::make_shared<NonMaskableInterrupt>(nmiVector);
707 }
else if (pendingInit) {
708 DPRINTF(LocalApic,
"Generated INIT fault object.\n");
709 return std::make_shared<InitInterrupt>(initVector);
710 }
else if (pendingStartup) {
711 DPRINTF(LocalApic,
"Generating SIPI fault object.\n");
712 return std::make_shared<StartupInterrupt>(startupVector);
714 panic(
"pendingUnmaskableInt set, but no unmaskable "
715 "ints were pending.\n");
718 }
else if (pendingExtInt) {
719 DPRINTF(LocalApic,
"Generated external interrupt fault object.\n");
720 return std::make_shared<ExternalInterrupt>(extIntVector);
722 DPRINTF(LocalApic,
"Generated regular interrupt fault object.\n");
724 return std::make_shared<ExternalInterrupt>(IRRV);
731 assert(checkInterrupts());
732 if (pendingUnmaskableInt) {
734 DPRINTF(LocalApic,
"SMI sent to core.\n");
736 }
else if (pendingNmi) {
737 DPRINTF(LocalApic,
"NMI sent to core.\n");
739 }
else if (pendingInit) {
740 DPRINTF(LocalApic,
"Init sent to core.\n");
743 }
else if (pendingStartup) {
744 DPRINTF(LocalApic,
"SIPI sent to core.\n");
745 pendingStartup =
false;
748 if (!(pendingSmi || pendingNmi || pendingInit || pendingStartup))
749 pendingUnmaskableInt =
false;
750 }
else if (pendingExtInt) {
751 pendingExtInt =
false;
753 DPRINTF(LocalApic,
"Interrupt %d sent to core.\n", IRRV);
782 bool apicTimerEventScheduled = apicTimerEvent.scheduled();
784 Tick apicTimerEventTick = apicTimerEvent.when();
807 bool apicTimerEventScheduled;
809 if (apicTimerEventScheduled) {
810 Tick apicTimerEventTick;
812 if (apicTimerEvent.scheduled()) {
813 reschedule(apicTimerEvent, apicTimerEventTick,
true);
815 schedule(apicTimerEvent, apicTimerEventTick);
823 if (triggerTimerInterrupt())