mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 09:07:35 +00:00
Kernel: Abstract IRQ controller handling from Interrupt handlers
Now we don't send raw numbers, but we let the IRQController object to figure out the correct IRQ number. This helps in a situation when we have 2 or more IOAPICs, so if IOAPIC 1 is assigned for IRQs 0-23 and IOAPIC 2 is assigned for IRQs 24-47, if an IRQHandler of IRQ 25 invokes disable() for example, it will call his responsible IRQController (IOAPIC 2), and the IRQController will subtract the IRQ number with his assigned offset, and the result is that the second redirection entry in IOAPIC 2 will be masked.
This commit is contained in:
parent
666990fbcb
commit
f86be46c98
11 changed files with 97 additions and 45 deletions
|
@ -48,11 +48,11 @@ IOAPIC::IOAPIC(ioapic_mmio_regs& regs, u32 gsi_base)
|
|||
, m_gsi_base(gsi_base)
|
||||
, m_id((read_register(0x0) >> 24) & 0xFF)
|
||||
, m_version(read_register(0x1) & 0xFF)
|
||||
, m_redirection_entries((read_register(0x1) >> 16) + 1)
|
||||
, m_redirection_entries_count((read_register(0x1) >> 16) + 1)
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
klog() << "IOAPIC ID: 0x" << String::format("%x", m_id);
|
||||
klog() << "IOAPIC Version: 0x" << String::format("%x", m_version) << ", Redirection Entries count - " << m_redirection_entries;
|
||||
klog() << "IOAPIC Version: 0x" << String::format("%x", m_version) << ", Redirection Entries count - " << m_redirection_entries_count;
|
||||
klog() << "IOAPIC Arbitration ID 0x" << String::format("%x", read_register(0x2));
|
||||
mask_all_redirection_entries();
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ void IOAPIC::map_interrupt_redirection(u8 interrupt_vector)
|
|||
trigger_level_mode = true;
|
||||
break;
|
||||
}
|
||||
configure_redirection_entry(redirection_override->gsi(), InterruptManagement::acquire_mapped_interrupt_number(redirection_override->source()) + IRQ_VECTOR_BASE, DeliveryMode::Normal, false, active_low, trigger_level_mode, true, 0);
|
||||
configure_redirection_entry(redirection_override->gsi() - gsi_base(), InterruptManagement::acquire_mapped_interrupt_number(redirection_override->source()) + IRQ_VECTOR_BASE, DeliveryMode::Normal, false, active_low, trigger_level_mode, true, 0);
|
||||
return;
|
||||
}
|
||||
isa_identity_map(interrupt_vector);
|
||||
|
@ -117,11 +117,21 @@ void IOAPIC::map_pci_interrupts()
|
|||
configure_redirection_entry(11, 11 + IRQ_VECTOR_BASE, DeliveryMode::Normal, false, false, true, true, 0);
|
||||
}
|
||||
|
||||
void IOAPIC::spurious_eoi(const GenericInterruptHandler& handler) const
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
ASSERT(handler.type() == HandlerType::SpuriousInterruptHandler);
|
||||
ASSERT(handler.interrupt_number() == APIC::spurious_interrupt_vector());
|
||||
klog() << "IOAPIC::spurious_eoi - Spurious Interrupt occurred";
|
||||
}
|
||||
|
||||
void IOAPIC::map_isa_interrupts()
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
for (auto redirection_override : InterruptManagement::the().isa_overrides()) {
|
||||
ASSERT(!redirection_override.is_null());
|
||||
if ((redirection_override->gsi() < gsi_base()) || (redirection_override->gsi() >= (gsi_base() + m_redirection_entries_count)))
|
||||
continue;
|
||||
bool active_low;
|
||||
// See ACPI spec Version 6.2, page 205 to learn more about Interrupt Overriding Flags.
|
||||
switch ((redirection_override->flags() & 0b11)) {
|
||||
|
@ -153,14 +163,14 @@ void IOAPIC::map_isa_interrupts()
|
|||
trigger_level_mode = true;
|
||||
break;
|
||||
}
|
||||
configure_redirection_entry(redirection_override->gsi(), InterruptManagement::acquire_mapped_interrupt_number(redirection_override->source()) + IRQ_VECTOR_BASE, 0, false, active_low, trigger_level_mode, true, 0);
|
||||
configure_redirection_entry(redirection_override->gsi() - gsi_base(), InterruptManagement::acquire_mapped_interrupt_number(redirection_override->source()) + IRQ_VECTOR_BASE, 0, false, active_low, trigger_level_mode, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void IOAPIC::reset_all_redirection_entries() const
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
for (size_t index = 0; index < m_redirection_entries; index++)
|
||||
for (size_t index = 0; index < m_redirection_entries_count; index++)
|
||||
reset_redirection_entry(index);
|
||||
}
|
||||
|
||||
|
@ -180,7 +190,7 @@ void IOAPIC::reset_redirection_entry(int index) const
|
|||
void IOAPIC::configure_redirection_entry(int index, u8 interrupt_vector, u8 delivery_mode, bool logical_destination, bool active_low, bool trigger_level_mode, bool masked, u8 destination) const
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
ASSERT((u32)index < m_redirection_entries);
|
||||
ASSERT((u32)index < m_redirection_entries_count);
|
||||
u32 redirection_entry1 = interrupt_vector | (delivery_mode & 0b111) << 8 | logical_destination << 11 | active_low << 13 | trigger_level_mode << 15 | masked << 16;
|
||||
u32 redirection_entry2 = destination << 24;
|
||||
write_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET, redirection_entry1);
|
||||
|
@ -196,26 +206,26 @@ void IOAPIC::configure_redirection_entry(int index, u8 interrupt_vector, u8 deli
|
|||
void IOAPIC::mask_all_redirection_entries() const
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
for (size_t index = 0; index < m_redirection_entries; index++)
|
||||
for (size_t index = 0; index < m_redirection_entries_count; index++)
|
||||
mask_redirection_entry(index);
|
||||
}
|
||||
|
||||
void IOAPIC::mask_redirection_entry(u8 index) const
|
||||
{
|
||||
ASSERT((u32)index < m_redirection_entries);
|
||||
ASSERT((u32)index < m_redirection_entries_count);
|
||||
u32 redirection_entry = read_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET) | (1 << 16);
|
||||
write_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET, redirection_entry);
|
||||
}
|
||||
|
||||
bool IOAPIC::is_redirection_entry_masked(u8 index) const
|
||||
{
|
||||
ASSERT((u32)index < m_redirection_entries);
|
||||
ASSERT((u32)index < m_redirection_entries_count);
|
||||
return (read_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET) & (1 << 16)) != 0;
|
||||
}
|
||||
|
||||
void IOAPIC::unmask_redirection_entry(u8 index) const
|
||||
{
|
||||
ASSERT((u32)index < m_redirection_entries);
|
||||
ASSERT((u32)index < m_redirection_entries_count);
|
||||
u32 redirection_entry = read_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET);
|
||||
write_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET, redirection_entry & ~(1 << 16));
|
||||
}
|
||||
|
@ -228,24 +238,26 @@ bool IOAPIC::is_vector_enabled(u8 interrupt_vector) const
|
|||
|
||||
u8 IOAPIC::read_redirection_entry_vector(u8 index) const
|
||||
{
|
||||
ASSERT((u32)index < m_redirection_entries);
|
||||
ASSERT((u32)index < m_redirection_entries_count);
|
||||
return (read_register((index << 1) + IOAPIC_REDIRECTION_ENTRY_OFFSET) & 0xFF);
|
||||
}
|
||||
|
||||
int IOAPIC::find_redirection_entry_by_vector(u8 vector) const
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
for (size_t index = 0; index < m_redirection_entries; index++) {
|
||||
for (size_t index = 0; index < m_redirection_entries_count; index++) {
|
||||
if (read_redirection_entry_vector(index) == (InterruptManagement::acquire_mapped_interrupt_number(vector) + IRQ_VECTOR_BASE))
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void IOAPIC::disable(u8 interrupt_vector)
|
||||
void IOAPIC::disable(const GenericInterruptHandler& handler)
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
ASSERT(!is_hard_disabled());
|
||||
u8 interrupt_vector = handler.interrupt_number();
|
||||
ASSERT(interrupt_vector >= gsi_base() && interrupt_vector < interrupt_vectors_count());
|
||||
int index = find_redirection_entry_by_vector(interrupt_vector);
|
||||
if (index == (-1)) {
|
||||
map_interrupt_redirection(interrupt_vector);
|
||||
|
@ -255,10 +267,12 @@ void IOAPIC::disable(u8 interrupt_vector)
|
|||
mask_redirection_entry(index);
|
||||
}
|
||||
|
||||
void IOAPIC::enable(u8 interrupt_vector)
|
||||
void IOAPIC::enable(const GenericInterruptHandler& handler)
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
ASSERT(!is_hard_disabled());
|
||||
u8 interrupt_vector = handler.interrupt_number();
|
||||
ASSERT(interrupt_vector >= gsi_base() && interrupt_vector < interrupt_vectors_count());
|
||||
int index = find_redirection_entry_by_vector(interrupt_vector);
|
||||
if (index == (-1)) {
|
||||
map_interrupt_redirection(interrupt_vector);
|
||||
|
@ -268,10 +282,12 @@ void IOAPIC::enable(u8 interrupt_vector)
|
|||
unmask_redirection_entry(index);
|
||||
}
|
||||
|
||||
void IOAPIC::eoi(u8) const
|
||||
void IOAPIC::eoi(const GenericInterruptHandler& handler) const
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
ASSERT(!is_hard_disabled());
|
||||
ASSERT(handler.interrupt_number() >= gsi_base() && handler.interrupt_number() < interrupt_vectors_count());
|
||||
ASSERT(handler.type() != HandlerType::SpuriousInterruptHandler);
|
||||
APIC::eoi();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue