Max OS 0.3
Loading...
Searching...
No Matches
MaxOS::hardwarecommunication::LocalAPIC Class Reference

Handles the local APIC for the current core. More...

#include <apic.h>

Public Member Functions

 LocalAPIC ()
 Construct a new Local APIC object and map the APIC base address to the higher half if needed as well as enabling the APIC.
 
uint32_t read (uint32_t reg) const
 read a value from the apic register using the MSR or memory I/O depending on the local apic version
 
void write (uint32_t reg, uint32_t value) const
 write a value to the apic register using the MSR or memory I/O depending on the local apic version
 
uint32_t id () const
 Get the id of the local apic.
 
void send_eoi () const
 Acknowledge that the interrupt has been handled, allowing the PIC to process the next interrupt.
 
void send_icr (uint32_t icr_low, uint32_t icr_high, bool use_shorthand) const
 Send an Interrupt Command Register (ICR) to the local apic.
 
void send_init (uint8_t apic_id, bool assert) const
 send the init IPI to another apic
 
void send_startup (uint8_t apic_id, uint8_t vector) const
 Send the start up IPI to another apic.
 
void send_interrupt (uint8_t apic_id, uint8_t vector, size_t flags) const
 Send an interrupt to a specific core.
 

Detailed Description

Handles the local APIC for the current core.

Definition at line 34 of file apic.h.

Constructor & Destructor Documentation

◆ LocalAPIC()

LocalAPIC::LocalAPIC ( )

Construct a new Local APIC object and map the APIC base address to the higher half if needed as well as enabling the APIC.

Definition at line 21 of file apic.cpp.

21 {
22
23 // Get the APIC base address
24 uint64_t msr_info = CPU::read_msr(0x1B);
25 m_apic_base = msr_info & 0xFFFFF000;
26
27 // Reserve the base address once
28 static bool bsp_setup = false;
29 if(!bsp_setup)
31
32 // Check if the APIC supports x2APIC
33 uint32_t ignored, xleaf, x2leaf;
34 CPU::cpuid(0x01, &ignored, &ignored, &x2leaf, &xleaf);
35
36 if (x2leaf & (1 << 21)) {
37
38 // Enable x2APIC
39 m_x2apic = true;
40 msr_info |= (1 << 10);
41 CPU::write_msr(0x1B, msr_info);
42 Logger::DEBUG() << "CPU supports x2APIC\n";
43
44 } else if (xleaf & (1 << 9)) {
45
46 m_x2apic = false;
47 Logger::DEBUG() << "CPU supports xAPIC\n";
48
49 // Map the APIC base address to the higher half
50 m_apic_base_high = (uint64_t) PhysicalMemoryManager::to_io_region(m_apic_base);
51 PhysicalMemoryManager::s_current_manager->map((physical_address_t*) m_apic_base, (virtual_address_t*) m_apic_base_high, PRESENT | WRITE);
52 Logger::DEBUG() << "APIC Base: phy=0x" << m_apic_base << ", virt=0x" << m_apic_base_high << "\n";
53 } else {
54 ASSERT(false, "CPU does not support xAPIC");
55 }
56
57 if (!(msr_info & (1 << 11))) {
58 Logger::WARNING() << "APIC is not enabled\n";
59 return;
60 }
61
62 // Enable the APIC
63 write(0xF0, (1 << 8) | 0x100);
64 bsp_setup = true;
65 Logger::DEBUG() << "APIC Enabled\n";
66}
static LogRecord DEBUG()
Gets the active logger for debug logs.
Definition logger.cpp:204
static LogRecord WARNING()
Gets the active logger for warnings.
Definition logger.cpp:213
void write(uint32_t reg, uint32_t value) const
write a value to the apic register using the MSR or memory I/O depending on the local apic version
Definition apic.cpp:91
static void * to_io_region(uintptr_t physical_address)
Converts a physical address to an IO region address if it is in the lower region using the higher hal...
Definition physical.cpp:914
void reserve(uint64_t address)
Reserves a physical address.
Definition physical.cpp:774
virtual_address_t * map(virtual_address_t *virtual_address, size_t flags)
Allocates a physical address to a virtual address.
Definition physical.cpp:535
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:183
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Executes the CPUID instruction with the specified leaf and returns the results in the provided pointe...
Definition cpu.cpp:402
static uint64_t read_msr(uint32_t msr)
Reads the value of the specified MSR.
Definition cpu.cpp:371
static void write_msr(uint32_t msr, uint64_t value)
Writes the specified value to the specified MSR.
Definition cpu.cpp:387
void virtual_address_t
A type representing a virtual address (used for readability)
Definition physical.h:30
void physical_address_t
A type representing a physical address (used for readability)
Definition physical.h:31

References MaxOS::system::CPU::cpuid(), MaxOS::Logger::DEBUG(), MaxOS::memory::PhysicalMemoryManager::map(), MaxOS::memory::PRESENT, MaxOS::system::CPU::read_msr(), MaxOS::memory::PhysicalMemoryManager::reserve(), MaxOS::memory::PhysicalMemoryManager::s_current_manager, MaxOS::memory::PhysicalMemoryManager::to_io_region(), MaxOS::Logger::WARNING(), write(), MaxOS::memory::WRITE, and MaxOS::system::CPU::write_msr().

Member Function Documentation

◆ id()

uint32_t LocalAPIC::id ( ) const

Get the id of the local apic.

Returns
The id of the local apic

Definition at line 108 of file apic.cpp.

108 {
109
110 // Read the id
111 uint32_t id = read(0x20);
112
113 // Return the id
114 return m_x2apic ? id : (id >> 24);
115}
uint32_t id() const
Get the id of the local apic.
Definition apic.cpp:108
uint32_t read(uint32_t reg) const
read a value from the apic register using the MSR or memory I/O depending on the local apic version
Definition apic.cpp:76

References id(), and read().

Referenced by id().

◆ read()

uint32_t LocalAPIC::read ( uint32_t  reg) const

read a value from the apic register using the MSR or memory I/O depending on the local apic version

Parameters
regThe register to read
Returns
The value of the register

Definition at line 76 of file apic.cpp.

76 {
77
78 // If x2APIC is enabled I/O is done through the MSR
79 if (m_x2apic)
80 return (uint32_t) CPU::read_msr((reg >> 4) + 0x800);
81
82 return *(volatile uint32_t*) ((uintptr_t) m_apic_base_high + reg);
83}

References MaxOS::system::CPU::read_msr().

Referenced by id(), and send_icr().

◆ send_eoi()

void LocalAPIC::send_eoi ( ) const

Acknowledge that the interrupt has been handled, allowing the PIC to process the next interrupt.

Definition at line 120 of file apic.cpp.

120 {
121
122 write(0xB0, 0);
123}

References write().

Referenced by MaxOS::hardwarecommunication::InterruptManager::handle_interrupt_request().

◆ send_icr()

void LocalAPIC::send_icr ( uint32_t  icr_low,
uint32_t  icr_high,
bool  use_shorthand 
) const

Send an Interrupt Command Register (ICR) to the local apic.

Parameters
icr_lowLower 32 bits of the ICR (vector, delivery mode, shorthand).
icr_highUpper 32 bits of the ICR (destination APIC ID, if used).
use_shorthandTrue if a destination shorthand is encoded in icr_low (icr_high is ignored).

Definition at line 132 of file apic.cpp.

132 {
133
134 if (!m_x2apic) {
135
136 // Select target core
137 if (!use_shorthand)
138 write(0x310, icr_high << 24);
139
140 // Send the interrupt
141 write(0x300, icr_low);
142
143 // Wait for delivery
144 while (read(0x300) & (1 << 12))
145 asm volatile("pause");
146
147 } else {
148
149 // x2APIC: pack and write the full 64-bit ICR
150 uint64_t icr = icr_low;
151 if (!use_shorthand)
152 icr |= (uint64_t)icr_high << 32;
153
154 CPU::write_msr(0x830, icr);
155 }
156
157}

References read(), write(), and MaxOS::system::CPU::write_msr().

Referenced by send_init(), send_interrupt(), and send_startup().

◆ send_init()

void LocalAPIC::send_init ( uint8_t  apic_id,
bool  assert 
) const

send the init IPI to another apic

Parameters
apic_idThe id of the apic to send to
assertIs this an assert code (drive / release the signal)

Definition at line 165 of file apic.cpp.

165 {
166
167 uint32_t icr_low = 0;
168 uint32_t icr_high = apic_id;
169
170 // Set delivery mode to INIT
171 icr_low |= (0b101 << 8);
172
173 // Set assert if needed
174 if (assert)
175 icr_low |= (1 << 14);
176
177 // Level triggered
178 icr_low |= (1 << 15);
179
180 // Send the init command
181 send_icr(icr_low, icr_high, false);
182}
void send_icr(uint32_t icr_low, uint32_t icr_high, bool use_shorthand) const
Send an Interrupt Command Register (ICR) to the local apic.
Definition apic.cpp:132

References send_icr().

Referenced by MaxOS::system::Core::wake_up().

◆ send_interrupt()

void LocalAPIC::send_interrupt ( uint8_t  apic_id,
uint8_t  vector,
size_t  flags 
) const

Send an interrupt to a specific core.

Parameters
apic_idThe core to send to (ignored if specfied in flags)
vectorThe interrupt vector
flagsFlags for how to send

Definition at line 213 of file apic.cpp.

213 {
214
215 uint32_t icr_low = 0;
216 uint32_t icr_high = 0;
217
218 // Vector (bits 0–7)
219 icr_low |= vector;
220
221 // Destination
222 bool use_shorthand = true;
223 if (flags & SEND_ALL) {
224 // All including self (11b)
225 icr_low |= (0b11 << 18);
226 } else if (flags & EXCLUDE_SELF) {
227 // All excluding self (10b)
228 icr_low |= (0b10 << 18);
229 } else {
230 // Specific core
231 icr_high = ((uint32_t)apic_id) << 24;
232 use_shorthand = false;
233 }
234
235 // Send the vector
236 send_icr(icr_low, icr_high, use_shorthand);
237
238}

References send_icr().

Referenced by MaxOS::system::CPU::prepare_for_panic().

◆ send_startup()

void LocalAPIC::send_startup ( uint8_t  apic_id,
uint8_t  vector 
) const

Send the start up IPI to another apic.

Parameters
apic_idThe apic to send it to
vectorWhere to start executing

Definition at line 190 of file apic.cpp.

190 {
191
192 uint32_t icr_low = 0;
193 uint32_t icr_high = apic_id;
194
195 // Vector being sent
196 icr_low |= vector;
197
198 // Set delivery mode to STARTUP
199 icr_low |= (0b110 << 8);
200
201 // Send the startup command
202 send_icr(icr_low, icr_high, false);
203}

References send_icr().

Referenced by MaxOS::system::Core::wake_up().

◆ write()

void LocalAPIC::write ( uint32_t  reg,
uint32_t  value 
) const

write a value to the apic register using the MSR or memory I/O depending on the local apic version

Parameters
regThe register to write to
valueThe value to write

Definition at line 91 of file apic.cpp.

91 {
92
93 // If x2APIC is enabled I/O is done through the MSR
94 if (m_x2apic){
95 CPU::write_msr((reg >> 4) + 0x800, value);
96 return;
97 }
98
99 // Default to memory I/O
100 *(volatile uint32_t*) ((uintptr_t) m_apic_base_high + reg) = value;
101}

References MaxOS::system::CPU::write_msr().

Referenced by LocalAPIC(), send_eoi(), send_icr(), and MaxOS::hardwarecommunication::Clock::setup_apic_clock().


The documentation for this class was generated from the following files: