PatchworkOS
Loading...
Searching...
No Matches

Advanced Programmable Interrupt Controller. More...

Data Structures

struct  ioapic_version_t
 IO APIC Version Structure. More...
 
struct  ioapic_redirect_entry_t
 IO APIC Redirection Entry Structure. More...
 

Macros

#define LAPIC_REG_ICR1_ID_OFFSET   24
 The offset at which the lapic id is stored in the LAPIC_REG_ID register.
 
#define IOAPIC_REG_REDIRECTION(pin, high)   (0x10 + (pin) * 2 + (high))
 Macro to get the redirection entry register for a specific pin.
 
#define APIC_TIMER_TICKS_FIXED_POINT_OFFSET   32
 APIC Timer Ticks Fixed Point Offset.
 

Typedefs

typedef uint8_t lapic_id_t
 Local APIC ID type.
 
typedef uint32_t ioapic_gsi_t
 IO APIC Global System Interrupt type.
 

Enumerations

enum  apic_timer_mode_t {
  APIC_TIMER_MASKED = 0x10000 ,
  APIC_TIMER_PERIODIC = 0x20000 ,
  APIC_TIMER_ONE_SHOT = 0x00000
}
 APIC Timer Modes. More...
 
enum  apic_timer_divider_t {
  APIC_TIMER_DIV_16 = 0x3 ,
  APIC_TIMER_DIV_32 = 0x4 ,
  APIC_TIMER_DIV_64 = 0x5 ,
  APIC_TIMER_DIV_128 = 0x6 ,
  APIC_TIMER_DIV_DEFAULT = APIC_TIMER_DIV_16
}
 APIC Timer Divider Values. More...
 
enum  lapic_msr_flags_t {
  LAPIC_MSR_ENABLE = 0x800 ,
  LAPIC_MSR_BSP = 0x100
}
 Local APIC MSR Flags. More...
 
enum  lapic_register_t {
  LAPIC_REG_ID = 0x020 ,
  LAPIC_REG_VERSION = 0x030 ,
  LAPIC_REG_TASK_PRIORITY = 0x080 ,
  LAPIC_REG_ARBITRATION_PRIORITY = 0x090 ,
  LAPIC_REG_PROCESSOR_PRIORITY = 0x0A0 ,
  LAPIC_REG_EOI = 0x0B0 ,
  LAPIC_REG_REMOTE_READ = 0x0C0 ,
  LAPIC_REG_LOGICAL_DEST = 0x0D0 ,
  LAPIC_REG_DEST_FORMAT = 0x0E0 ,
  LAPIC_REG_SPURIOUS = 0x0F0 ,
  LAPIC_REG_ISR_BASE = 0x100 ,
  LAPIC_REG_TMR_BASE = 0x180 ,
  LAPIC_REG_IRR_BASE = 0x200 ,
  LAPIC_REG_ERROR_STATUS = 0x280 ,
  LAPIC_REG_LVT_CMCI = 0x2F0 ,
  LAPIC_REG_ICR0 = 0x300 ,
  LAPIC_REG_ICR1 = 0x310 ,
  LAPIC_REG_LVT_TIMER = 0x320 ,
  LAPIC_REG_LVT_THERMAL = 0x330 ,
  LAPIC_REG_LVT_PERFCTR = 0x340 ,
  LAPIC_REG_LVT_LINT0 = 0x350 ,
  LAPIC_REG_LVT_LINT1 = 0x360 ,
  LAPIC_REG_LVT_ERROR = 0x370 ,
  LAPIC_REG_TIMER_INITIAL_COUNT = 0x380 ,
  LAPIC_REG_TIMER_CURRENT_COUNT = 0x390 ,
  LAPIC_REG_TIMER_DIVIDER = 0x3E0
}
 Local APIC Registers. More...
 
enum  lapic_flags_t {
  LAPIC_SPURIOUS_ENABLE = (1 << 8) ,
  LAPIC_LVT_MASKED = (1 << 16)
}
 Local APIC Flags. More...
 
enum  lapic_icr_delivery_mode_t {
  LAPIC_ICR_FIXED = (0 << 8) ,
  LAPIC_ICR_LOWEST_PRIORITY = (1 << 8) ,
  LAPIC_ICR_SMI = (2 << 8) ,
  LAPIC_ICR_NMI = (4 << 8) ,
  LAPIC_ICR_INIT = (5 << 8) ,
  LAPIC_ICR_STARTUP = (6 << 8)
}
 Local APIC ICR Delivery Modes. More...
 
enum  lapic_icr_flags_t { LAPIC_ICR_CLEAR_INIT_LEVEL = (1 << 14) }
 Local APIC ICR Flags. More...
 
enum  ioapic_mmio_register_t {
  IOAPIC_MMIO_REG_SELECT = 0x00 ,
  IOAPIC_MMIO_REG_DATA = 0x10
}
 IO APIC Memory Mapped Registers. More...
 
enum  ioapic_register_t { IOAPIC_REG_VERSION = 0x01 }
 IO APIC Registers. More...
 
enum  ioapic_delivery_mode_t {
  IOAPIC_DELIVERY_NORMAL = 0 ,
  IOAPIC_DELIVERY_LOW_PRIO = 1 ,
  IOAPIC_DELIVERY_SMI = 2 ,
  IOAPIC_DELIVERY_NMI = 4 ,
  IOAPIC_DELIVERY_INIT = 5 ,
  IOAPIC_DELIVERY_EXTERNAL = 7
}
 IO APIC Delivery Modes. More...
 
enum  ioapic_destination_mode_t {
  IOAPIC_DESTINATION_PHYSICAL = 0 ,
  IOAPIC_DESTINATION_LOGICAL = 1
}
 IO APIC Destination Modes. More...
 
enum  ioapic_trigger_mode_t {
  IOAPIC_TRIGGER_EDGE = 0 ,
  IOAPIC_TRIGGER_LEVEL = 1
}
 IO APIC Trigger Modes. More...
 
enum  ioapic_polarity_t {
  IOAPIC_POLARITY_HIGH = 0 ,
  IOAPIC_POLARITY_LOW = 1
}
 IO APIC Polarity Modes. More...
 

Functions

void apic_timer_one_shot (interrupt_t vector, uint32_t ticks)
 Configure the apic timer in one-shot mode.
 
uint64_t apic_timer_ticks_per_ns (void)
 Apic timer ticks per nanosecond.
 
void lapic_cpu_init (void)
 Initialize the local apic for the current cpu.
 
lapic_id_t lapic_self_id (void)
 Get the lapic id of the current cpu.
 
void lapic_write (lapic_register_t reg, uint32_t value)
 Write to a local apic register.
 
uint32_t lapic_read (lapic_register_t reg)
 Read from a local apic register.
 
void lapic_send_init (lapic_id_t id)
 Send an INIT IPI to a local apic.
 
void lapic_send_sipi (lapic_id_t id, void *entryPoint)
 Send a Startup IPI to a local apic.
 
void lapic_send_ipi (lapic_id_t id, interrupt_t vector)
 Send an Inter-Processor Interrupt (IPI) to a local apic.
 
void lapic_eoi (void)
 Send an End Of Interrupt (EOI) signal to the local apic.
 
uint32_t ioapic_read (ioapic_t *ioapic, ioapic_register_t reg)
 Read from an IOAPIC register.
 
void ioapic_write (ioapic_t *ioapic, ioapic_register_t reg, uint32_t value)
 Write to an IOAPIC register.
 
ioapic_version_t ioapic_get_version (ioapic_t *ioapic)
 Get the IOAPIC version.
 
ioapic_tioapic_from_gsi (ioapic_gsi_t gsi)
 Get the IOAPIC id responsible for a given GSI.
 
void ioapic_set_redirect (interrupt_t vector, ioapic_gsi_t gsi, ioapic_delivery_mode_t deliveryMode, ioapic_polarity_t polarity, ioapic_trigger_mode_t triggerMode, cpu_t *cpu, bool enable)
 Set an IOAPIC redirection entry.
 

Detailed Description

Advanced Programmable Interrupt Controller.

See also
ACPI Specification Version 6.6

Macro Definition Documentation

◆ APIC_TIMER_TICKS_FIXED_POINT_OFFSET

#define APIC_TIMER_TICKS_FIXED_POINT_OFFSET   32

APIC Timer Ticks Fixed Point Offset.

Used for fixed point arithmetic when returning the apic timer ticks per nanosecond.

Definition at line 176 of file apic.h.

◆ IOAPIC_REG_REDIRECTION

#define IOAPIC_REG_REDIRECTION (   pin,
  high 
)    (0x10 + (pin) * 2 + (high))

Macro to get the redirection entry register for a specific pin.

This is used since a redirect entry is 64 bits (a qword/two dwords) and each register is 32 bits (a dword), so each pin uses two registers.

Parameters
pinThe pin number as in the gsi - the ioapics base gsi.
high0 for the low dword, 1 for the high dword.
Returns
The register number.

Definition at line 169 of file apic.h.

◆ LAPIC_REG_ICR1_ID_OFFSET

#define LAPIC_REG_ICR1_ID_OFFSET   24

The offset at which the lapic id is stored in the LAPIC_REG_ID register.

Definition at line 105 of file apic.h.

Typedef Documentation

◆ ioapic_gsi_t

IO APIC Global System Interrupt type.

This identifies a interrupt "globally" across all IO APICs in the system and can be thought of as the "inpur" interrupt that is then routed to a specific CPU's local APIC.

Definition at line 32 of file apic.h.

◆ lapic_id_t

Local APIC ID type.

Definition at line 24 of file apic.h.

Enumeration Type Documentation

◆ apic_timer_divider_t

APIC Timer Divider Values.

Enumerator
APIC_TIMER_DIV_16 
APIC_TIMER_DIV_32 
APIC_TIMER_DIV_64 
APIC_TIMER_DIV_128 
APIC_TIMER_DIV_DEFAULT 

Definition at line 49 of file apic.h.

◆ apic_timer_mode_t

APIC Timer Modes.

Enumerator
APIC_TIMER_MASKED 

Timer is masked (disabled)

APIC_TIMER_PERIODIC 
APIC_TIMER_ONE_SHOT 

Definition at line 38 of file apic.h.

◆ ioapic_delivery_mode_t

IO APIC Delivery Modes.

Enumerator
IOAPIC_DELIVERY_NORMAL 
IOAPIC_DELIVERY_LOW_PRIO 
IOAPIC_DELIVERY_SMI 
IOAPIC_DELIVERY_NMI 
IOAPIC_DELIVERY_INIT 
IOAPIC_DELIVERY_EXTERNAL 

Definition at line 202 of file apic.h.

◆ ioapic_destination_mode_t

IO APIC Destination Modes.

Enumerator
IOAPIC_DESTINATION_PHYSICAL 
IOAPIC_DESTINATION_LOGICAL 

Definition at line 216 of file apic.h.

◆ ioapic_mmio_register_t

IO APIC Memory Mapped Registers.

Enumerator
IOAPIC_MMIO_REG_SELECT 
IOAPIC_MMIO_REG_DATA 

Definition at line 144 of file apic.h.

◆ ioapic_polarity_t

IO APIC Polarity Modes.

Enumerator
IOAPIC_POLARITY_HIGH 
IOAPIC_POLARITY_LOW 

Definition at line 236 of file apic.h.

◆ ioapic_register_t

IO APIC Registers.

Enumerator
IOAPIC_REG_VERSION 

Definition at line 154 of file apic.h.

◆ ioapic_trigger_mode_t

IO APIC Trigger Modes.

Enumerator
IOAPIC_TRIGGER_EDGE 
IOAPIC_TRIGGER_LEVEL 

Definition at line 226 of file apic.h.

◆ lapic_flags_t

Local APIC Flags.

Enumerator
LAPIC_SPURIOUS_ENABLE 
LAPIC_LVT_MASKED 

Definition at line 111 of file apic.h.

◆ lapic_icr_delivery_mode_t

Local APIC ICR Delivery Modes.

Enumerator
LAPIC_ICR_FIXED 
LAPIC_ICR_LOWEST_PRIORITY 
LAPIC_ICR_SMI 
LAPIC_ICR_NMI 
LAPIC_ICR_INIT 
LAPIC_ICR_STARTUP 

Definition at line 121 of file apic.h.

◆ lapic_icr_flags_t

Local APIC ICR Flags.

Enumerator
LAPIC_ICR_CLEAR_INIT_LEVEL 

Definition at line 135 of file apic.h.

◆ lapic_msr_flags_t

Local APIC MSR Flags.

Enumerator
LAPIC_MSR_ENABLE 
LAPIC_MSR_BSP 

Definition at line 62 of file apic.h.

◆ lapic_register_t

Local APIC Registers.

Enumerator
LAPIC_REG_ID 
LAPIC_REG_VERSION 
LAPIC_REG_TASK_PRIORITY 
LAPIC_REG_ARBITRATION_PRIORITY 
LAPIC_REG_PROCESSOR_PRIORITY 
LAPIC_REG_EOI 
LAPIC_REG_REMOTE_READ 
LAPIC_REG_LOGICAL_DEST 
LAPIC_REG_DEST_FORMAT 
LAPIC_REG_SPURIOUS 
LAPIC_REG_ISR_BASE 
LAPIC_REG_TMR_BASE 
LAPIC_REG_IRR_BASE 
LAPIC_REG_ERROR_STATUS 
LAPIC_REG_LVT_CMCI 
LAPIC_REG_ICR0 
LAPIC_REG_ICR1 
LAPIC_REG_LVT_TIMER 
LAPIC_REG_LVT_THERMAL 
LAPIC_REG_LVT_PERFCTR 
LAPIC_REG_LVT_LINT0 
LAPIC_REG_LVT_LINT1 
LAPIC_REG_LVT_ERROR 
LAPIC_REG_TIMER_INITIAL_COUNT 
LAPIC_REG_TIMER_CURRENT_COUNT 
LAPIC_REG_TIMER_DIVIDER 

Definition at line 72 of file apic.h.

Function Documentation

◆ apic_timer_one_shot()

void apic_timer_one_shot ( interrupt_t  vector,
uint32_t  ticks 
)

Configure the apic timer in one-shot mode.

Cnfigures the apic timer on the caller cpu to fire a single interrupt after the specified amount of ticks.

Parameters
vectorThe interrupt vector to fire when the timer expires.
ticksThe amount of ticks to wait before firing the interrupt.

Definition at line 105 of file apic.c.

References APIC_TIMER_DIV_DEFAULT, APIC_TIMER_MASKED, APIC_TIMER_ONE_SHOT, initialized, LAPIC_REG_LVT_TIMER, LAPIC_REG_TIMER_DIVIDER, LAPIC_REG_TIMER_INITIAL_COUNT, lapic_write(), NULL, and panic().

Referenced by timer_one_shot().

◆ apic_timer_ticks_per_ns()

uint64_t apic_timer_ticks_per_ns ( void  )

Apic timer ticks per nanosecond.

Retrieves the ticks that occur every nanosecond in the apic timer on the caller cpu. Due to the fact that this amount of ticks is very small, most likely less then 1, we used fixed point arithmetic to store the result, the offset used for this is APIC_TIMER_TICKS_FIXED_POINT_OFFSET.

Returns
The number of ticks per nanosecond, stored using fixed point arithmetic.

Definition at line 119 of file apic.c.

References APIC_TIMER_DIV_DEFAULT, APIC_TIMER_MASKED, APIC_TIMER_TICKS_FIXED_POINT_OFFSET, CLOCKS_PER_SEC, hpet_wait(), initialized, interrupt_disable(), interrupt_enable(), lapic_read(), LAPIC_REG_LVT_TIMER, LAPIC_REG_TIMER_CURRENT_COUNT, LAPIC_REG_TIMER_DIVIDER, LAPIC_REG_TIMER_INITIAL_COUNT, lapic_write(), LOG_DEBUG, NULL, panic(), and UINT32_MAX.

Referenced by timer_ctx_init().

◆ ioapic_from_gsi()

ioapic_t * ioapic_from_gsi ( ioapic_gsi_t  gsi)

Get the IOAPIC id responsible for a given GSI.

Parameters
gsiThe GSI to get the IOAPIC id for.
Returns
The IOAPIC responsible for the GSI.

Definition at line 282 of file apic.c.

References ioapic_t::globalSystemInterruptBase, ioapic_t::header, initialized, INTERRUPT_CONTROLLER_IO_APIC, ioapic_get_version(), madt, MADT_FOR_EACH, ioapic_version_t::maxRedirs, NULL, panic(), and interrupt_controller_header_t::type.

Referenced by ioapic_set_redirect().

◆ ioapic_get_version()

ioapic_version_t ioapic_get_version ( ioapic_t ioapic)

Get the IOAPIC version.

Parameters
ioapicThe IOAPIC to get the version for.
Returns
The IOAPIC version.

Definition at line 270 of file apic.c.

References initialized, ioapic_read(), IOAPIC_REG_VERSION, NULL, panic(), and ioapic_version_t::raw.

Referenced by ioapic_all_init(), and ioapic_from_gsi().

◆ ioapic_read()

uint32_t ioapic_read ( ioapic_t ioapic,
ioapic_register_t  reg 
)

Read from an IOAPIC register.

Parameters
ioapicThe IOAPIC to read from.
regThe register to read.
Returns
The value read from the register.

Definition at line 246 of file apic.c.

References initialized, IOAPIC_MMIO_REG_DATA, IOAPIC_MMIO_REG_SELECT, ioapic_t::ioApicAddress, NULL, panic(), PML_LOWER_TO_HIGHER, READ_32, and WRITE_32.

Referenced by ioapic_get_version().

◆ ioapic_set_redirect()

void ioapic_set_redirect ( interrupt_t  vector,
ioapic_gsi_t  gsi,
ioapic_delivery_mode_t  deliveryMode,
ioapic_polarity_t  polarity,
ioapic_trigger_mode_t  triggerMode,
cpu_t cpu,
bool  enable 
)

Set an IOAPIC redirection entry.

When an interrupt is triggered on the given GSI, the IOAPIC will use the redirection entry to determine how and where to send the interrupt.

Say we recieve a GSI 1 interrupt (this would usually be a interrupt from the first ps/2 port), and we have a redirection entry which sends it to vector 0x21 (we usually want to avoid using vectors 0x00-0x20 as those are reserved for exceptions) to the CPU with id 0, the IOAPIC will then send an interrupt to CPU 0 with vector 0x21.

Parameters
vectorThe interrupt vector to set.
gsiThe GSI to set the redirection for.
deliveryModeThe delivery mode to use.
polarityThe polarity to use.
triggerModeThe trigger mode to use.
cpuThe target cpu to send the interrupt to.
enableWhether to enable or disable the redirection.

Definition at line 307 of file apic.c.

References ioapic_t::globalSystemInterruptBase, ioapic_redirect_entry_t::PACKED::high, cpu_t::id, initialized, ioapic_from_gsi(), IOAPIC_REG_REDIRECTION, ioapic_write(), cpu_t::lapicId, LOG_INFO, ioapic_redirect_entry_t::PACKED::low, NULL, panic(), and ioapic_redirect_entry_t::raw.

Referenced by irq_install().

◆ ioapic_write()

void ioapic_write ( ioapic_t ioapic,
ioapic_register_t  reg,
uint32_t  value 
)

Write to an IOAPIC register.

Parameters
ioapicThe IOAPIC to write to.
regThe register to write.
valueThe value to write.

Definition at line 258 of file apic.c.

References initialized, IOAPIC_MMIO_REG_DATA, IOAPIC_MMIO_REG_SELECT, ioapic_t::ioApicAddress, NULL, panic(), PML_LOWER_TO_HIGHER, and WRITE_32.

Referenced by ioapic_all_init(), and ioapic_set_redirect().

◆ lapic_cpu_init()

◆ lapic_eoi()

void lapic_eoi ( void  )

Send an End Of Interrupt (EOI) signal to the local apic.

Must be called after handling an interrupt to notify the local apic that the interrupt has been handled.

Definition at line 236 of file apic.c.

References initialized, LAPIC_REG_EOI, lapic_write(), NULL, and panic().

Referenced by interrupt_handler(), and irq_dispatch().

◆ lapic_read()

uint32_t lapic_read ( lapic_register_t  reg)

Read from a local apic register.

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

Definition at line 191 of file apic.c.

References initialized, lapicBase, NULL, panic(), and READ_32.

Referenced by apic_timer_ticks_per_ns(), lapic_cpu_init(), and lapic_self_id().

◆ lapic_self_id()

lapic_id_t lapic_self_id ( void  )

Get the lapic id of the current cpu.

Returns
The lapic id of the current cpu.

Definition at line 171 of file apic.c.

References initialized, lapic_read(), LAPIC_REG_ICR1_ID_OFFSET, LAPIC_REG_ID, NULL, and panic().

Referenced by cpu_init(), lapic_cpu_init(), smp_others_init(), and syscall_handler().

◆ lapic_send_init()

void lapic_send_init ( lapic_id_t  id)

Send an INIT IPI to a local apic.

Sending an INIT IPI will cause the target CPU to enter its initialization state which should be done before sending a SIPI.

Parameters
idThe lapic id to send the INIT IPI to.

Definition at line 201 of file apic.c.

References initialized, LAPIC_ICR_INIT, LAPIC_REG_ICR0, LAPIC_REG_ICR1, LAPIC_REG_ICR1_ID_OFFSET, lapic_write(), NULL, and panic().

Referenced by trampoline_send_startup_ipi().

◆ lapic_send_ipi()

void lapic_send_ipi ( lapic_id_t  id,
interrupt_t  vector 
)

Send an Inter-Processor Interrupt (IPI) to a local apic.

The effect of sending an IPI is the same as if asm volatile("int <vector>") was executed on the target CPU.

Parameters
idThe lapic id to send the IPI to.
vectorThe interrupt vector to send.

Definition at line 225 of file apic.c.

References initialized, LAPIC_ICR_CLEAR_INIT_LEVEL, LAPIC_REG_ICR0, LAPIC_REG_ICR1, LAPIC_REG_ICR1_ID_OFFSET, lapic_write(), NULL, and panic().

Referenced by smp_halt_others(), space_tlb_shootdown(), syscall_handler(), and timer_notify().

◆ lapic_send_sipi()

void lapic_send_sipi ( lapic_id_t  id,
void *  entryPoint 
)

Send a Startup IPI to a local apic.

Sending a SIPI will cause the target CPU to start executing at the specified entry point, its important to give a small delay after sending an INIT IPI before sending the SIPI to give the hardware time to process the INIT.

Parameters
idThe lapic id to send the SIPI to.
entryPointThe entry point to start executing at, must be page aligned.

Definition at line 212 of file apic.c.

References assert, initialized, LAPIC_ICR_STARTUP, LAPIC_REG_ICR0, LAPIC_REG_ICR1, LAPIC_REG_ICR1_ID_OFFSET, lapic_write(), NULL, PAGE_SIZE, and panic().

Referenced by trampoline_send_startup_ipi().

◆ lapic_write()

void lapic_write ( lapic_register_t  reg,
uint32_t  value 
)

Write to a local apic register.

Parameters
regThe register to write to.
valueThe value to write.

Definition at line 181 of file apic.c.

References initialized, lapicBase, NULL, panic(), and WRITE_32.

Referenced by apic_timer_one_shot(), apic_timer_ticks_per_ns(), lapic_cpu_init(), lapic_eoi(), lapic_send_init(), lapic_send_ipi(), and lapic_send_sipi().