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

Handles the IO APIC in the system (one per system) More...

#include <apic.h>

Public Member Functions

 IOAPIC (AdvancedConfigurationAndPowerInterface *acpi)
 Construct a new IO APIC object. Maps the IO APIC registers and reads the MADT to get information about the IO APICs and interrupt source overrides.
 
uint32_t read (uint32_t reg) const
 read a value from a IO Apic register
 
void write (uint32_t reg, uint32_t value) const
 write a value to an IO Apic register
 
void set_redirect (interrupt_redirect_t *redirect)
 Redirect a system interrupt to a different IRQ.
 
void set_redirect_mask (uint8_t index, bool mask)
 Enables/Disables an interrupt redirect by masking it.
 
MADTEntryget_madt_item (MADT_TYPE type, uint8_t index)
 Get an item in the MADT.
 

Detailed Description

Handles the IO APIC in the system (one per system)

Definition at line 193 of file apic.h.

Constructor & Destructor Documentation

◆ IOAPIC()

IOAPIC::IOAPIC ( AdvancedConfigurationAndPowerInterface acpi)
explicit

Construct a new IO APIC object. Maps the IO APIC registers and reads the MADT to get information about the IO APICs and interrupt source overrides.

Parameters
acpiThe ACPI interface to get the MADT from

Definition at line 198 of file apic.cpp.

199: m_acpi(acpi)
200{
201
202 // Get the information about the IO APIC
203 m_madt = (MADT*) m_acpi->find("APIC");
204 MADTEntry* io_apic_item = get_madt_item(MADT_TYPE::IO_APIC, 0);
205
206 // Get the IO APIC
207 auto* io_apic = (MADT_IO_APIC*) PhysicalMemoryManager::to_io_region((uint64_t) io_apic_item + sizeof(MADTEntry));
208 PhysicalMemoryManager::s_current_manager->map((physical_address_t*) io_apic_item, (virtual_address_t*) (io_apic - sizeof(MADTEntry)), PRESENT | WRITE);
209
210 // Map the IO APIC address to the higher half
211 m_address = io_apic->io_apic_address;
212 m_address_high = (uint64_t) PhysicalMemoryManager::to_io_region(m_address);
213 PhysicalMemoryManager::s_current_manager->map((physical_address_t*) m_address, (virtual_address_t*) m_address_high, PRESENT | WRITE);
214 Logger::DEBUG() << "IO APIC Address: phy=0x" << m_address << ", virt=0x" << m_address_high << "\n";
215
216 // Get the IO APIC version and max redirection entry
217 m_version = read(0x1);
218 m_max_redirect_entry = (uint8_t) (m_version >> 16);
219
220 // Log the IO APIC information
221 Logger::DEBUG() << "IO APIC Version: 0x" << (uint64_t) (m_version & 0xFF) << "\n";
222 Logger::DEBUG() << "IO APIC Max Redirection Entry: 0x" << (uint64_t) m_max_redirect_entry << "\n";
223
224 // Get the source override item
225 MADTEntry* source_override_item = get_madt_item(MADT_TYPE::IO_APIC, m_override_array_size);
226 uint32_t total_length = sizeof(MADT);
227 while (total_length < m_madt->header.length && m_override_array_size < 0x10) { // 0x10 is the max items
228
229 total_length += source_override_item->length;
230
231 // If there is an override, populate the array
232 if (source_override_item != nullptr && source_override_item->type == 2) {
233
234 // Get the override and populate the array
235 auto* override = (Override*) (source_override_item + 1);
236 m_override_array[m_override_array_size].bus = override->bus;
237 m_override_array[m_override_array_size].source = override->source;
238 m_override_array[m_override_array_size].global_system_interrupt = override->global_system_interrupt;
239 m_override_array[m_override_array_size].flags = override->flags;
240 m_override_array_size++;
241 }
242
243 // Get the next item
244 source_override_item = get_madt_item(MADT_TYPE::IO_APIC, m_override_array_size);
245 if (source_override_item == nullptr)
246 break;
247 }
248
249 Logger::DEBUG() << "IO APIC Source Overrides: 0x" << m_override_array_size << "\n";
250}
static Logger DEBUG()
Gets active logger set to DEBUG level.
Definition logger.cpp:193
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
acpi_sdt_header_t * find(const char *signature)
Finds a table with the given signature.
Definition acpi.cpp:163
MADTEntry * get_madt_item(MADT_TYPE type, uint8_t index)
Get an item in the MADT.
Definition apic.cpp:261
uint32_t read(uint32_t reg) const
read a value from a IO Apic register
Definition apic.cpp:297
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:915
virtual_address_t * map(virtual_address_t *virtual_address, size_t flags)
Allocates a physical address to a virtual address.
Definition physical.cpp:538
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:185
An item in the MADT table.
Definition apic.h:68
uint8_t type
The type of the MADT entry (see MADT_TYPE)
Definition apic.h:69
uint8_t length
How many bytes this entry takes up (including the type and length fields)
Definition apic.h:70
An entry in the MADT table describing an IO APIC.
Definition apic.h:96
Multiple APIC Description Table (MADT) (ACPI 2 or higher). Provides information about the APICs in th...
Definition apic.h:55
Specifies how a specific interrupt source is mapped to a global system interrupt.
Definition apic.h:180
uint8_t source
The interrupt source number on the specified bus.
Definition apic.h:183
uint32_t global_system_interrupt
The global system interrupt that the source is mapped to.
Definition apic.h:184
uint8_t bus
Identifies the hardware bus the interrupt comes from (0 = ISA, 1 = PCI)
Definition apic.h:182
uint16_t flags
Flags describing the polarity and trigger mode of the interrupt source (see MADT override flags)
Definition apic.h:185

References MaxOS::hardwarecommunication::Override::bus, MaxOS::Logger::DEBUG(), MaxOS::hardwarecommunication::AdvancedConfigurationAndPowerInterface::find(), MaxOS::hardwarecommunication::Override::flags, get_madt_item(), MaxOS::hardwarecommunication::Override::global_system_interrupt, MaxOS::hardwarecommunication::MADTEntry::length, MaxOS::memory::PhysicalMemoryManager::map(), MaxOS::memory::PRESENT, read(), MaxOS::memory::PhysicalMemoryManager::s_current_manager, MaxOS::hardwarecommunication::Override::source, MaxOS::memory::PhysicalMemoryManager::to_io_region(), MaxOS::hardwarecommunication::MADTEntry::type, and MaxOS::memory::WRITE.

Member Function Documentation

◆ get_madt_item()

MADTEntry * IOAPIC::get_madt_item ( MADT_TYPE  type,
uint8_t  index 
)

Get an item in the MADT.

Parameters
typeThe type of item
indexThe index of the item
Returns
The item or null if not found

Definition at line 261 of file apic.cpp.

261 {
262
263 // The item starts at the start of the MADT
264 auto* item = (MADTEntry*) ((uint64_t) m_madt + sizeof(MADT));
265 uint64_t total_length = 0;
266 uint8_t current_index = 0;
267
268 // Loop through the items
269 while (total_length + sizeof(MADT) < m_madt->header.length && current_index <= index) {
270
271 // Correct type
272 if (item->type == (uint8_t)type) {
273
274 // Correct index means found
275 if (current_index == index)
276 return item;
277
278 // Right type wrong index so move on
279 current_index++;
280 }
281
282 // Increment the total length
283 total_length += item->length;
284 item = (MADTEntry*) ((uint64_t) item + item->length);
285 }
286
287 // No item found
288 return nullptr;
289}
uint32_t length
The size of the entire table, including the header, in bytes.
Definition acpi.h:61
ACPISDTHeader header
Common ACPI SDT header.
Definition apic.h:56

References MaxOS::hardwarecommunication::MADT::header, MaxOS::hardwarecommunication::ACPISDTHeader::length, and MaxOS::hardwarecommunication::MADTEntry::length.

Referenced by MaxOS::system::CPU::find_cores(), and IOAPIC().

◆ read()

uint32_t IOAPIC::read ( uint32_t  reg) const

read a value from a IO Apic register

Parameters
regThe register to read from
Returns
The value at the register

Definition at line 297 of file apic.cpp.

297 {
298
299 // Tell the APIC what register to read from
300 *(volatile uint32_t*) (m_address_high + 0x00) = reg;
301
302 // Read the value
303 return *(volatile uint32_t*) (m_address_high + 0x10);
304}

Referenced by IOAPIC().

◆ set_redirect()

void IOAPIC::set_redirect ( interrupt_redirect_t redirect)

Redirect a system interrupt to a different IRQ.

Parameters
redirectThe redirection entry

Definition at line 365 of file apic.cpp.

365 {
366
367 // Create the redirection entry
368 RedirectionEntry entry = {};
369 entry.raw = redirect->flags | (redirect->interrupt & 0xFF);
370 entry.destination = redirect->destination;
371 entry.mask = redirect->mask;
372
373 // Check if a global system interrupt is used
374 for (uint8_t i = 0; i < m_override_array_size; i++) {
375
376 if (m_override_array[i].source != redirect->type)
377 continue;
378
379 // Set the lower 4 bits of the pin
380 entry.pin_polarity = ((m_override_array[i].flags & 0b11) == 2) ? 0b1 : 0b0;
381 entry.pin_polarity = (((m_override_array[i].flags >> 2) & 0b11) == 2) ? 0b1 : 0b0;
382
383 // Set the trigger mode
384 entry.trigger_mode = (((m_override_array[i].flags >> 2) & 0b11) == 2);
385 break;
386
387 }
388
389 // Write the redirect
390 write_redirect(redirect->index, &entry);
391}
uint8_t index
Where in the IO APIC redirection table this redirect should be placed.
Definition apic.h:165
uint8_t interrupt
The interrupt number to trigger when this redirect is used.
Definition apic.h:166
uint32_t flags
Configuration flags for the interrupt (see MADT override flags)
Definition apic.h:168
bool mask
Should the interrupt be disabled initially.
Definition apic.h:169
uint8_t type
The type of redirect (should be 0 for normal interrupts)
Definition apic.h:164
uint8_t destination
The ID of the core the interrupt should be sent to.
Definition apic.h:167
An IO APIC redirection entry. Describes how an interrupt is routed.
Definition apic.h:123
uint64_t raw
The raw 64-bit value of the redirection entry.
Definition apic.h:137

References MaxOS::hardwarecommunication::InterruptRedirect::destination, MaxOS::hardwarecommunication::InterruptRedirect::flags, MaxOS::hardwarecommunication::Override::flags, MaxOS::hardwarecommunication::InterruptRedirect::index, MaxOS::hardwarecommunication::InterruptRedirect::interrupt, MaxOS::hardwarecommunication::InterruptRedirect::mask, MaxOS::hardwarecommunication::RedirectionEntry::raw, and MaxOS::hardwarecommunication::InterruptRedirect::type.

Referenced by MaxOS::hardwarecommunication::InterruptHandler::InterruptHandler().

◆ set_redirect_mask()

void IOAPIC::set_redirect_mask ( uint8_t  index,
bool  mask 
)

Enables/Disables an interrupt redirect by masking it.

Parameters
indexThe index of the redirect mask
maskTrue = masked = disabled, False = unmasked = enabled

Definition at line 399 of file apic.cpp.

399 {
400
401 // Read the current entry
402 RedirectionEntry entry = {};
403 read_redirect(index, &entry);
404
405 // Set the mask
406 entry.mask = mask;
407 write_redirect(index, &entry);
408}

◆ write()

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

write a value to an IO Apic register

Parameters
regThe register to write to
valueThe value to set the register to

Definition at line 312 of file apic.cpp.

312 {
313
314 // Write the register
315 *(volatile uint32_t*) (m_address_high + 0x00) = reg;
316
317 // Write the value
318 *(volatile uint32_t*) (m_address_high + 0x10) = value;
319}

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