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.
 
MADTEntry * get_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 205 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 245 of file apic.cpp.

246: m_acpi(acpi)
247{
248
249 // Get the information about the IO APIC
250 m_madt = (MADT*) m_acpi->find("APIC");
251 MADTEntry* io_apic_item = get_madt_item(MADT_TYPE::IO_APIC, 0);
252
253 // Get the IO APIC
254 auto* io_apic = (MADT_IO_APIC*) PhysicalMemoryManager::to_io_region((uint64_t) io_apic_item + sizeof(MADTEntry));
255 PhysicalMemoryManager::s_current_manager->map((physical_address_t*) io_apic_item, (virtual_address_t*) (io_apic - sizeof(MADTEntry)), PRESENT | WRITE);
256
257 // Map the IO APIC address to the higher half
258 m_address = io_apic->io_apic_address;
259 m_address_high = (uint64_t) PhysicalMemoryManager::to_io_region(m_address);
260 PhysicalMemoryManager::s_current_manager->map((physical_address_t*) m_address, (virtual_address_t*) m_address_high, PRESENT | WRITE);
261 Logger::DEBUG() << "IO APIC Address: phy=0x" << m_address << ", virt=0x" << m_address_high << "\n";
262
263 // Get the IO APIC version and max redirection entry
264 m_version = read(0x1);
265 m_max_redirect_entry = (uint8_t) (m_version >> 16);
266
267 // Log the IO APIC information
268 Logger::DEBUG() << "IO APIC Version: 0x" << (uint64_t) (m_version & 0xFF) << "\n";
269 Logger::DEBUG() << "IO APIC Max Redirection Entry: 0x" << (uint64_t) m_max_redirect_entry << "\n";
270
271 // Get the source override item
272 MADTEntry* source_override_item = get_madt_item(MADT_TYPE::IO_APIC, m_override_array_size);
273 uint32_t total_length = sizeof(MADT);
274 while (total_length < m_madt->header.length && m_override_array_size < 0x10) { // 0x10 is the max items
275
276 total_length += source_override_item->length;
277
278 // If there is an override, populate the array
279 if (source_override_item != nullptr && source_override_item->type == 2) {
280
281 // Get the override and populate the array
282 auto* override = (Override*) (source_override_item + 1);
283 m_override_array[m_override_array_size].bus = override->bus;
284 m_override_array[m_override_array_size].source = override->source;
285 m_override_array[m_override_array_size].global_system_interrupt = override->global_system_interrupt;
286 m_override_array[m_override_array_size].flags = override->flags;
287 m_override_array_size++;
288 }
289
290 // Get the next item
291 source_override_item = get_madt_item(MADT_TYPE::IO_APIC, m_override_array_size);
292 if (source_override_item == nullptr)
293 break;
294 }
295
296 Logger::DEBUG() << "IO APIC Source Overrides: 0x" << m_override_array_size << "\n";
297}
static LogRecord DEBUG()
Gets the active logger for debug logs.
Definition logger.cpp:204
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:308
uint32_t read(uint32_t reg) const
read a value from a IO Apic register
Definition apic.cpp:344
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
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
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
An item in the MADT table.
Definition apic.h:80
uint8_t type
The type of the MADT entry (see MADT_TYPE)
Definition apic.h:81
uint8_t length
How many bytes this entry takes up (including the type and length fields)
Definition apic.h:82
An entry in the MADT table describing an IO APIC.
Definition apic.h:108
Multiple APIC Description Table (MADT) (ACPI 2 or higher). Provides information about the APICs in th...
Definition apic.h:67
Specifies how a specific interrupt source is mapped to a global system interrupt.
Definition apic.h:192
uint8_t source
The interrupt source number on the specified bus.
Definition apic.h:195
uint32_t global_system_interrupt
The global system interrupt that the source is mapped to.
Definition apic.h:196
uint8_t bus
Identifies the hardware bus the interrupt comes from (0 = ISA, 1 = PCI)
Definition apic.h:194
uint16_t flags
Flags describing the polarity and trigger mode of the interrupt source (see MADT override flags)
Definition apic.h:197

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 308 of file apic.cpp.

308 {
309
310 // The item starts at the start of the MADT
311 auto* item = (MADTEntry*) ((uint64_t) m_madt + sizeof(MADT));
312 uint64_t total_length = 0;
313 uint8_t current_index = 0;
314
315 // Loop through the items
316 while (total_length + sizeof(MADT) < m_madt->header.length && current_index <= index) {
317
318 // Correct type
319 if (item->type == (uint8_t)type) {
320
321 // Correct index means found
322 if (current_index == index)
323 return item;
324
325 // Right type wrong index so move on
326 current_index++;
327 }
328
329 // Increment the total length
330 total_length += item->length;
331 item = (MADTEntry*) ((uint64_t) item + item->length);
332 }
333
334 // No item found
335 return nullptr;
336}
uint32_t length
The size of the entire table, including the header, in bytes.
Definition acpi.h:64
ACPISDTHeader header
Common ACPI SDT header.
Definition apic.h:68

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 344 of file apic.cpp.

344 {
345
346 // Tell the APIC what register to read from
347 *(volatile uint32_t*) (m_address_high + 0x00) = reg;
348
349 // Read the value
350 return *(volatile uint32_t*) (m_address_high + 0x10);
351}

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 412 of file apic.cpp.

412 {
413
414 // Create the redirection entry
415 RedirectionEntry entry = {};
416 entry.raw = redirect->flags | (redirect->interrupt & 0xFF);
417 entry.destination = redirect->destination;
418 entry.mask = redirect->mask;
419
420 // Check if a global system interrupt is used
421 for (uint8_t i = 0; i < m_override_array_size; i++) {
422
423 if (m_override_array[i].source != redirect->type)
424 continue;
425
426 // Set the lower 4 bits of the pin
427 entry.pin_polarity = ((m_override_array[i].flags & 0b11) == 2) ? 0b1 : 0b0;
428 entry.pin_polarity = (((m_override_array[i].flags >> 2) & 0b11) == 2) ? 0b1 : 0b0;
429
430 // Set the trigger mode
431 entry.trigger_mode = (((m_override_array[i].flags >> 2) & 0b11) == 2);
432 break;
433
434 }
435
436 // Write the redirect
437 write_redirect(redirect->index, &entry);
438}
uint8_t index
Where in the IO APIC redirection table this redirect should be placed.
Definition apic.h:177
uint8_t interrupt
The interrupt number to trigger when this redirect is used.
Definition apic.h:178
uint32_t flags
Configuration flags for the interrupt (see MADT override flags)
Definition apic.h:180
bool mask
Should the interrupt be disabled initially.
Definition apic.h:181
uint8_t type
The type of redirect (should be 0 for normal interrupts)
Definition apic.h:176
uint8_t destination
The ID of the core the interrupt should be sent to.
Definition apic.h:179
An IO APIC redirection entry. Describes how an interrupt is routed.
Definition apic.h:135
uint64_t raw
The raw 64-bit value of the redirection entry.
Definition apic.h:149

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 446 of file apic.cpp.

446 {
447
448 // Read the current entry
449 RedirectionEntry entry = {};
450 read_redirect(index, &entry);
451
452 // Set the mask
453 entry.mask = mask;
454 write_redirect(index, &entry);
455}

◆ 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 359 of file apic.cpp.

359 {
360
361 // Write the register
362 *(volatile uint32_t*) (m_address_high + 0x00) = reg;
363
364 // Write the value
365 *(volatile uint32_t*) (m_address_high + 0x10) = value;
366}

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