59 #include "debug/LocalApic.hh"
73 int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
74 shift = (shift + 1) % 8;
183 panic(
"Accessed reserved register field %#x.\n", paddr);
196 panic(
"Accessed more than one register at a time in the APIC!\n");
200 "Reading Local APIC register %d at offset %#x as %#x.\n",
202 pkt->
setData(((uint8_t *)&val) + (offset &
mask(3)));
213 panic(
"Accessed more than one register at a time in the APIC!\n");
218 "Writing Local APIC register %d at offset %#x as %#x.\n",
219 reg, offset,
gtoh(val));
220 setReg(reg,
gtoh(val));
233 if (deliveryMode == DeliveryMode::Fixed ||
234 deliveryMode == DeliveryMode::LowestPriority) {
235 DPRINTF(LocalApic,
"Interrupt is an %s.\n",
236 DeliveryMode::names[deliveryMode]);
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;
254 }
else if (deliveryMode == DeliveryMode::NMI && !pendingNmi) {
255 pendingUnmaskableInt = pendingNmi =
true;
257 }
else if (deliveryMode == DeliveryMode::ExtInt && !pendingExtInt) {
258 pendingExtInt =
true;
260 }
else if (deliveryMode == DeliveryMode::INIT && !pendingInit) {
261 pendingUnmaskableInt = pendingInit =
true;
263 }
else if (deliveryMode == DeliveryMode::SIPI &&
264 !pendingStartup && !startedUp) {
265 pendingUnmaskableInt = pendingStartup =
true;
278 if (cpu != NULL && cpu->cpuId() != newCPU->cpuId()) {
279 panic(
"Local APICs can't be moved between CPUs"
280 " with different IDs.\n");
283 initialApicId = cpu->cpuId();
284 regs[
APIC_ID] = (initialApicId << 24);
302 intSlavePort.sendRangeChange();
315 TriggerIntMessage message = pkt->
get<TriggerIntMessage>();
317 "Got Trigger Interrupt message with vector %#x.\n",
320 requestInterrupt(message.vector,
321 message.deliveryMode, message.trigger);
325 panic(
"Local apic got unknown interrupt message at offset %#x.\n",
339 if (--pendingIPIs == 0) {
342 low.deliveryStatus = 0;
345 DPRINTF(LocalApic,
"ICR is now idle.\n");
366 panic(
"Local APIC Trigger Mode registers are unimplemented.\n");
370 panic(
"Local APIC Arbitration Priority register unimplemented.\n");
373 panic(
"Local APIC Processor Priority register unimplemented.\n");
380 if (apicTimerEvent.scheduled()) {
382 uint64_t ticksPerCount = clockPeriod() *
385 uint64_t
val = apicTimerEvent.when() -
curTick();
387 val = (val + ticksPerCount - 1) / ticksPerCount;
402 uint32_t newVal =
val;
405 panic(
"Local APIC In-Service registers are unimplemented.\n");
409 panic(
"Local APIC Trigger Mode registers are unimplemented.\n");
413 panic(
"Local APIC Interrupt Request registers "
414 "are unimplemented.\n");
427 panic(
"Local APIC Arbitration Priority register unimplemented.\n");
430 panic(
"Local APIC Processor Priority register unimplemented.\n");
438 newVal = val & 0xFF000000;
441 newVal = val | 0x0FFFFFFF;
447 warn(
"Focus processor checking not implemented.\n");
465 if (low.deliveryStatus) {
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;
479 int numContexts = sys->numContexts();
480 switch (low.destShorthand) {
482 if (message.deliveryMode == DeliveryMode::LowestPriority) {
483 panic(
"Lowest priority delivery mode "
484 "IPIs aren't implemented.\n");
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++) {
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);
505 if (message.destination == initialApicId) {
506 requestInterrupt(message.vector,
507 message.deliveryMode, message.trigger);
509 apics.push_back(message.destination);
516 requestInterrupt(message.vector,
517 message.deliveryMode, message.trigger);
520 requestInterrupt(message.vector,
521 message.deliveryMode, message.trigger);
525 for (
int i = 0;
i < numContexts;
i++) {
526 if (
i != initialApicId) {
535 low.deliveryStatus = 1;
536 pendingIPIs += apics.size();
539 intMasterPort.sendMessage(apics, message, sys->isTimingMode());
550 uint64_t readOnlyMask = (1 << 12) | (1 << 14);
551 newVal = (val & ~readOnlyMask) |
552 (regs[reg] & readOnlyMask);
557 newVal =
bits(val, 31, 0);
559 uint64_t newCount = newVal *
564 reschedule(apicTimerEvent,
566 clockPeriod() - offset,
true);
569 reschedule(apicTimerEvent,
571 clockPeriod(),
true);
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)
613 if (pendingUnmaskableInt) {
614 DPRINTF(LocalApic,
"Reported pending unmaskable interrupt.\n");
619 DPRINTF(LocalApic,
"Reported pending external interrupt.\n");
622 if (IRRV > ISRV &&
bits(IRRV, 7, 4) >
624 DPRINTF(LocalApic,
"Reported pending regular interrupt.\n");
634 return pendingUnmaskableInt || pendingExtInt ||
635 (IRRV > ISRV &&
bits(IRRV, 7, 4) >
642 assert(checkInterrupts(tc));
645 if (pendingUnmaskableInt) {
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);
659 panic(
"pendingUnmaskableInt set, but no unmaskable "
660 "ints were pending.\n");
663 }
else if (pendingExtInt) {
664 DPRINTF(LocalApic,
"Generated external interrupt fault object.\n");
665 return std::make_shared<ExternalInterrupt>(extIntVector);
667 DPRINTF(LocalApic,
"Generated regular interrupt fault object.\n");
669 return std::make_shared<ExternalInterrupt>(IRRV);
676 assert(checkInterrupts(tc));
677 if (pendingUnmaskableInt) {
679 DPRINTF(LocalApic,
"SMI sent to core.\n");
681 }
else if (pendingNmi) {
682 DPRINTF(LocalApic,
"NMI sent to core.\n");
684 }
else if (pendingInit) {
685 DPRINTF(LocalApic,
"Init sent to core.\n");
688 }
else if (pendingStartup) {
689 DPRINTF(LocalApic,
"SIPI sent to core.\n");
690 pendingStartup =
false;
693 if (!(pendingSmi || pendingNmi || pendingInit || pendingStartup))
694 pendingUnmaskableInt =
false;
695 }
else if (pendingExtInt) {
696 pendingExtInt =
false;
698 DPRINTF(LocalApic,
"Interrupt %d sent to core.\n", IRRV);
727 bool apicTimerEventScheduled = apicTimerEvent.scheduled();
729 Tick apicTimerEventTick = apicTimerEvent.when();
752 bool apicTimerEventScheduled;
754 if (apicTimerEventScheduled) {
755 Tick apicTimerEventTick;
757 if (apicTimerEvent.scheduled()) {
758 reschedule(apicTimerEvent, apicTimerEventTick,
true);
760 schedule(apicTimerEvent, apicTimerEventTick);
766 X86LocalApicParams::create()
decltype(nullptr) constexpr NoFault
const std::string & name()
void setCPU(BaseCPU *newCPU)
uint32_t readReg(ApicRegIndex miscReg)
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
Tick recvResponse(PacketPtr pkt) override
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
AddrRangeList getIntAddrRange() const override
void updateIntrInfo(ThreadContext *tc)
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
void setReg(ApicRegIndex reg, uint32_t val)
int divideFromConf(uint32_t conf)
ThreadContext is the external interface to all thread state for anything outside of the CPU...
void writeData(uint8_t *p) const
Copy data from the packet to the provided block pointer, which is aligned to the given block size...
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
Tick recvMessage(PacketPtr pkt) override
#define UNSERIALIZE_SCALAR(scalar)
Tick curTick()
The current simulated tick.
Fault getInterrupt(ThreadContext *tc)
const Addr PhysAddrAPICRangeSize
X86LocalApicParams Params
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
static Addr x86InterruptAddress(const uint8_t id, const uint16_t addr)
void makeAtomicResponse()
uint64_t Tick
Tick count type.
void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level)
#define SERIALIZE_ARRAY(member, size)
ApicRegIndex decodeAddr(Addr paddr)
bool checkInterruptsRaw() const
Check if there are pending interrupts without ignoring the interrupts disabled flag.
static ApicRegIndex APIC_TRIGGER_MODE(int index)
uint32_t regs[NUM_APIC_REGS]
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
#define ULL(N)
uint64_t constant
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Declaration of top level class for PC platform components.
#define SERIALIZE_SCALAR(scalar)
#define UNSERIALIZE_ARRAY(member, size)
AddrRange RangeEx(Addr start, Addr end)
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
void serialize(CheckpointOut &cp) const override
Serialize an object.
static ApicRegIndex APIC_IN_SERVICE(int index)
std::ostream CheckpointOut
MemCmd cmd
The command field of the packet.
bool checkInterrupts(ThreadContext *tc) const
Tick pioDelay
Delay that the device experinces on an access.
Bitfield< 18, 16 > deliveryMode
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
static Addr x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
Addr pioAddr
Address that the device listens to.
std::shared_ptr< FaultBase > Fault
static ApicRegIndex APIC_INTERRUPT_REQUEST(int index)