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",
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](
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.");
331 "Int port not connected to anything!");
333 "Pio port of %s not connected to anything!",
name());
349 TriggerIntMessage message = pkt->
getRaw<TriggerIntMessage>();
351 "Got Trigger Interrupt message with vector %#x.\n",
355 message.deliveryMode, message.trigger);
359 panic(
"Local apic got unknown interrupt message at offset %#x.\n",
374 low.deliveryStatus = 0;
377 DPRINTF(LocalApic,
"ICR is now idle.\n");
408 panic(
"Local APIC Trigger Mode registers are unimplemented.\n");
412 panic(
"Local APIC Arbitration Priority register unimplemented.\n");
415 panic(
"Local APIC Processor Priority register unimplemented.\n");
422 if (apicTimerEvent.scheduled()) {
427 uint64_t
val = apicTimerEvent.when() -
curTick();
429 val = (
val + ticksPerCount - 1) / ticksPerCount;
444 uint32_t newVal =
val;
447 panic(
"Local APIC In-Service registers are unimplemented.\n");
451 panic(
"Local APIC Trigger Mode registers are unimplemented.\n");
455 panic(
"Local APIC Interrupt Request registers "
456 "are unimplemented.\n");
469 panic(
"Local APIC Arbitration Priority register unimplemented.\n");
472 panic(
"Local APIC Processor Priority register unimplemented.\n");
480 newVal =
val & 0xFF000000;
483 newVal =
val | 0x0FFFFFFF;
489 warn(
"Focus processor checking not implemented.\n");
507 if (low.deliveryStatus) {
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;
521 int numContexts =
sys->threads.size();
522 switch (low.destShorthand) {
524 if (message.deliveryMode == delivery_mode::LowestPriority) {
525 panic(
"Lowest priority delivery mode "
526 "IPIs aren't implemented.\n");
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++) {
537 if (message.destination == 0xFF) {
538 for (
int i = 0;
i < numContexts;
i++) {
541 message.deliveryMode, message.trigger);
549 message.deliveryMode, message.trigger);
551 apics.push_back(message.destination);
559 message.deliveryMode, message.trigger);
563 message.deliveryMode, message.trigger);
567 for (
int i = 0;
i < numContexts;
i++) {
577 low.deliveryStatus = 1;
581 for (
auto id: apics) {
584 [
this](
PacketPtr pkt) { completeIPI(pkt); });
596 uint64_t readOnlyMask = (1 << 12) | (1 << 14);
597 newVal = (
val & ~readOnlyMask) |
605 uint64_t newCount = newVal *
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)
644 memset(regs, 0,
sizeof(regs));
670 DPRINTF(LocalApic,
"Reported pending unmaskable interrupt.\n");
675 DPRINTF(LocalApic,
"Reported pending external interrupt.\n");
680 DPRINTF(LocalApic,
"Reported pending regular interrupt.\n");
703 DPRINTF(LocalApic,
"Generated SMI fault object.\n");
704 return std::make_shared<SystemManagementInterrupt>();
706 DPRINTF(LocalApic,
"Generated NMI fault object.\n");
707 return std::make_shared<NonMaskableInterrupt>(
nmiVector);
709 DPRINTF(LocalApic,
"Generated INIT fault object.\n");
710 return std::make_shared<InitInterrupt>(
initVector);
712 DPRINTF(LocalApic,
"Generating SIPI fault object.\n");
715 panic(
"pendingUnmaskableInt set, but no unmaskable "
716 "ints were pending.\n");
720 DPRINTF(LocalApic,
"Generated external interrupt fault object.\n");
721 return std::make_shared<ExternalInterrupt>(
extIntVector);
723 DPRINTF(LocalApic,
"Generated regular interrupt fault object.\n");
725 return std::make_shared<ExternalInterrupt>(
IRRV);
735 DPRINTF(LocalApic,
"SMI sent to core.\n");
738 DPRINTF(LocalApic,
"NMI sent to core.\n");
741 DPRINTF(LocalApic,
"Init sent to core.\n");
745 DPRINTF(LocalApic,
"SIPI sent to core.\n");
754 DPRINTF(LocalApic,
"Interrupt %d sent to core.\n",
IRRV);
783 bool apicTimerEventScheduled = apicTimerEvent.scheduled();
785 Tick apicTimerEventTick = apicTimerEvent.when();
808 bool apicTimerEventScheduled;
810 if (apicTimerEventScheduled) {
811 Tick apicTimerEventTick;
813 if (apicTimerEvent.scheduled()) {
814 reschedule(apicTimerEvent, apicTimerEventTick,
true);
816 schedule(apicTimerEvent, apicTimerEventTick);
BaseInterrupts(const Params &p)
virtual void setThreadContext(ThreadContext *_tc)
virtual std::string name() const
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
T getRaw() const
Get the data in the packet without byte swapping.
void makeAtomicResponse()
MemCmd cmd
The command field of the packet.
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.
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.
Interrupts(const Params &p)
void processApicTimerEvent()
void completeIPI(PacketPtr pkt)
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
bool triggerTimerInterrupt()
bool checkInterrupts() const override
void setRegArrayBit(ApicRegIndex base, uint8_t vector)
AddrRangeList getIntAddrRange() const
Bitfield< 10, 8 > deliveryMode
void setReg(ApicRegIndex reg, uint32_t val)
AddrRangeList getAddrRanges() const
X86LocalApicParams Params
IntRequestPort< Interrupts > intRequestPort
bool getRegArrayBit(ApicRegIndex base, uint8_t vector)
uint32_t regs[NUM_APIC_REGS]
void updateIntrInfo() override
bool checkInterruptsRaw() const
Check if there are pending interrupts without ignoring the interrupts disabled flag.
Tick recvMessage(PacketPtr pkt)
void raiseInterruptPin(int number)
bool pendingUnmaskableInt
void clearRegArrayBit(ApicRegIndex base, uint8_t vector)
void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level)
PioPort< Interrupts > pioPort
ClockDomain & clockDomain
void serialize(CheckpointOut &cp) const override
Serialize an object.
Tick write(PacketPtr pkt)
void setThreadContext(ThreadContext *_tc) override
IntResponsePort< Interrupts > intResponsePort
Fault getInterrupt() override
uint32_t readReg(ApicRegIndex miscReg)
void lowerInterruptPin(int number)
AddrRange RangeEx(Addr start, Addr end)
AddrRange RangeSize(Addr start, Addr size)
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
void schedule(Event &event, Tick when)
void reschedule(Event &event, Tick when, bool always=false)
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
static ApicRegIndex APIC_TRIGGER_MODE(int index)
static PacketPtr buildIntAcknowledgePacket()
const Addr PhysAddrAPICRangeSize
static PacketPtr buildIntTriggerPacket(int id, TriggerIntMessage message)
@ APIC_LOGICAL_DESTINATION
@ APIC_INTERRUPT_COMMAND_HIGH
@ APIC_DESTINATION_FORMAT
@ APIC_INTERRUPT_REQUEST_BASE
@ APIC_INTERRUPT_COMMAND_LOW
@ APIC_LVT_THERMAL_SENSOR
@ APIC_PROCESSOR_PRIORITY
@ APIC_ARBITRATION_PRIORITY
@ APIC_SPURIOUS_INTERRUPT_VECTOR
@ APIC_DIVIDE_CONFIGURATION
@ APIC_LVT_PERFORMANCE_MONITORING_COUNTERS
static ApicRegIndex APIC_INTERRUPT_REQUEST(int index)
static ApicRegIndex APIC_IN_SERVICE(int index)
static Addr x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
ApicRegIndex decodeAddr(Addr paddr)
static Addr x86InterruptAddress(const uint8_t id, const uint16_t addr)
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< FaultBase > Fault
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
int divideFromConf(uint32_t conf)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
uint64_t Tick
Tick count type.
constexpr decltype(nullptr) NoFault
Declaration of top level class for PC platform components.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const std::string & name()