mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 13:57:35 +00:00
Kernel: Allow switching to IOAPIC mode even without enabling SMP
This small change allows to use the IOAPIC by default without to enable SMP mode, which emulates Uni-Processor setup with IOAPIC instead of using the PIC. This opens the opportunity to utilize other types of interrupts like MSI and MSI-X interrupts.
This commit is contained in:
parent
f57900a41b
commit
ac7953f945
5 changed files with 41 additions and 29 deletions
|
@ -111,6 +111,16 @@ UNMAP_AFTER_INIT bool CommandLine::is_smp_enabled() const
|
||||||
return lookup("smp"sv).value_or("off"sv) == "on"sv;
|
return lookup("smp"sv).value_or("off"sv) == "on"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNMAP_AFTER_INIT bool CommandLine::is_ioapic_enabled() const
|
||||||
|
{
|
||||||
|
auto value = lookup("enable_ioapic"sv).value_or("on"sv);
|
||||||
|
if (value == "on"sv)
|
||||||
|
return true;
|
||||||
|
if (value == "off"sv)
|
||||||
|
return false;
|
||||||
|
PANIC("Unknown enable_ioapic setting: {}", value);
|
||||||
|
}
|
||||||
|
|
||||||
UNMAP_AFTER_INIT bool CommandLine::is_vmmouse_enabled() const
|
UNMAP_AFTER_INIT bool CommandLine::is_vmmouse_enabled() const
|
||||||
{
|
{
|
||||||
return lookup("vmmouse"sv).value_or("on"sv) == "on"sv;
|
return lookup("vmmouse"sv).value_or("on"sv) == "on"sv;
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] bool is_boot_profiling_enabled() const;
|
[[nodiscard]] bool is_boot_profiling_enabled() const;
|
||||||
[[nodiscard]] bool is_ide_enabled() const;
|
[[nodiscard]] bool is_ide_enabled() const;
|
||||||
|
[[nodiscard]] bool is_ioapic_enabled() const;
|
||||||
[[nodiscard]] bool is_smp_enabled() const;
|
[[nodiscard]] bool is_smp_enabled() const;
|
||||||
[[nodiscard]] bool is_physical_networking_disabled() const;
|
[[nodiscard]] bool is_physical_networking_disabled() const;
|
||||||
[[nodiscard]] bool is_vmmouse_enabled() const;
|
[[nodiscard]] bool is_vmmouse_enabled() const;
|
||||||
|
|
|
@ -270,29 +270,32 @@ UNMAP_AFTER_INIT bool APIC::init_bsp()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto madt = Memory::map_typed<ACPI::Structures::MADT>(madt_address.value());
|
if (kernel_command_line().is_smp_enabled()) {
|
||||||
size_t entry_index = 0;
|
auto madt = Memory::map_typed<ACPI::Structures::MADT>(madt_address.value());
|
||||||
size_t entries_length = madt->h.length - sizeof(ACPI::Structures::MADT);
|
size_t entry_index = 0;
|
||||||
auto* madt_entry = madt->entries;
|
size_t entries_length = madt->h.length - sizeof(ACPI::Structures::MADT);
|
||||||
while (entries_length > 0) {
|
auto* madt_entry = madt->entries;
|
||||||
size_t entry_length = madt_entry->length;
|
while (entries_length > 0) {
|
||||||
if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::LocalAPIC) {
|
size_t entry_length = madt_entry->length;
|
||||||
auto* plapic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalAPIC*)madt_entry;
|
if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::LocalAPIC) {
|
||||||
dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, xAPIC ID: {}, flags: {:#08x}", entry_index, plapic_entry->acpi_processor_id, plapic_entry->apic_id, plapic_entry->flags);
|
auto* plapic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalAPIC*)madt_entry;
|
||||||
m_processor_cnt++;
|
dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, xAPIC ID: {}, flags: {:#08x}", entry_index, plapic_entry->acpi_processor_id, plapic_entry->apic_id, plapic_entry->flags);
|
||||||
if ((plapic_entry->flags & 0x1) != 0)
|
m_processor_cnt++;
|
||||||
m_processor_enabled_cnt++;
|
if ((plapic_entry->flags & 0x1) != 0)
|
||||||
} else if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::Local_x2APIC) {
|
m_processor_enabled_cnt++;
|
||||||
// Only used for APID IDs >= 255
|
} else if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::Local_x2APIC) {
|
||||||
auto* plx2apic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalX2APIC*)madt_entry;
|
// Only used for APID IDs >= 255
|
||||||
dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, x2APIC ID: {}, flags: {:#08x}", entry_index, plx2apic_entry->acpi_processor_id, plx2apic_entry->apic_id, plx2apic_entry->flags);
|
auto* plx2apic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalX2APIC*)madt_entry;
|
||||||
m_processor_cnt++;
|
dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, x2APIC ID: {}, flags: {:#08x}", entry_index, plx2apic_entry->acpi_processor_id, plx2apic_entry->apic_id, plx2apic_entry->flags);
|
||||||
if ((plx2apic_entry->flags & 0x1) != 0)
|
m_processor_cnt++;
|
||||||
m_processor_enabled_cnt++;
|
if ((plx2apic_entry->flags & 0x1) != 0)
|
||||||
|
m_processor_enabled_cnt++;
|
||||||
|
}
|
||||||
|
madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
|
||||||
|
entries_length -= entry_length;
|
||||||
|
entry_index++;
|
||||||
}
|
}
|
||||||
madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
|
dbgln("APIC processors found: {}, enabled: {}", m_processor_cnt, m_processor_enabled_cnt);
|
||||||
entries_length -= entry_length;
|
|
||||||
entry_index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_processor_enabled_cnt < 1)
|
if (m_processor_enabled_cnt < 1)
|
||||||
|
@ -300,8 +303,6 @@ UNMAP_AFTER_INIT bool APIC::init_bsp()
|
||||||
if (m_processor_cnt < 1)
|
if (m_processor_cnt < 1)
|
||||||
m_processor_cnt = 1;
|
m_processor_cnt = 1;
|
||||||
|
|
||||||
dbgln("APIC processors found: {}, enabled: {}", m_processor_cnt, m_processor_enabled_cnt);
|
|
||||||
|
|
||||||
enable(0);
|
enable(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,10 @@ UNMAP_AFTER_INIT void InterruptManagement::initialize()
|
||||||
VERIFY(!InterruptManagement::initialized());
|
VERIFY(!InterruptManagement::initialized());
|
||||||
s_interrupt_management = new InterruptManagement();
|
s_interrupt_management = new InterruptManagement();
|
||||||
|
|
||||||
if (kernel_command_line().is_smp_enabled())
|
if (!kernel_command_line().is_ioapic_enabled() && !kernel_command_line().is_smp_enabled())
|
||||||
InterruptManagement::the().switch_to_ioapic_mode();
|
|
||||||
else
|
|
||||||
InterruptManagement::the().switch_to_pic_mode();
|
InterruptManagement::the().switch_to_pic_mode();
|
||||||
|
else
|
||||||
|
InterruptManagement::the().switch_to_ioapic_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptManagement::enumerate_interrupt_handlers(Function<void(GenericInterruptHandler&)> callback)
|
void InterruptManagement::enumerate_interrupt_handlers(Function<void(GenericInterruptHandler&)> callback)
|
||||||
|
@ -220,7 +220,7 @@ UNMAP_AFTER_INIT void InterruptManagement::locate_apic_data()
|
||||||
dbgln("Interrupts: Overriding INT {:#x} with GSI {}, for bus {:#x}",
|
dbgln("Interrupts: Overriding INT {:#x} with GSI {}, for bus {:#x}",
|
||||||
interrupt_override_entry->source,
|
interrupt_override_entry->source,
|
||||||
global_system_interrupt,
|
global_system_interrupt,
|
||||||
flags);
|
interrupt_override_entry->bus);
|
||||||
}
|
}
|
||||||
madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
|
madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
|
||||||
entries_length -= entry_length;
|
entries_length -= entry_length;
|
||||||
|
|
|
@ -271,7 +271,7 @@ void init_stage2(void*)
|
||||||
|
|
||||||
WorkQueue::initialize();
|
WorkQueue::initialize();
|
||||||
|
|
||||||
if (APIC::initialized() && APIC::the().enabled_processor_count() > 1) {
|
if (kernel_command_line().is_smp_enabled() && APIC::initialized() && APIC::the().enabled_processor_count() > 1) {
|
||||||
// We can't start the APs until we have a scheduler up and running.
|
// We can't start the APs until we have a scheduler up and running.
|
||||||
// We need to be able to process ICI messages, otherwise another
|
// We need to be able to process ICI messages, otherwise another
|
||||||
// core may send too many and end up deadlocking once the pool is
|
// core may send too many and end up deadlocking once the pool is
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue