diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-08 17:07:27 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-08 17:07:27 +0200 |
| commit | 1ecc0c223a1bacfa1aee183a3573f57c265318df (patch) | |
| tree | 5913f2fb456d646733ce9e70338f0b8bf1245512 /arch/x86_64/src | |
| parent | f36cbd54bb6319050404165e8a3280ccbda05cf3 (diff) | |
| download | teachos-1ecc0c223a1bacfa1aee183a3573f57c265318df.tar.xz teachos-1ecc0c223a1bacfa1aee183a3573f57c265318df.zip | |
x86_64: extend LAPIC initialization
Diffstat (limited to 'arch/x86_64/src')
| -rw-r--r-- | arch/x86_64/src/devices/local_apic.cpp | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/arch/x86_64/src/devices/local_apic.cpp b/arch/x86_64/src/devices/local_apic.cpp index e24e1d4..54d87a6 100644 --- a/arch/x86_64/src/devices/local_apic.cpp +++ b/arch/x86_64/src/devices/local_apic.cpp @@ -7,18 +7,73 @@ #include <cstddef> #include <cstdint> +#include <utility> namespace arch::devices { namespace { - constexpr auto lapic_sivr_register = 0x00F0uz; - constexpr auto lapic_enable_bit = 0x100u; constexpr auto spurious_interrupt_vector = 0xFFu; + + constexpr auto offset_of_version = 0u; + constexpr auto offset_of_max_lvt_entry = 16u; + constexpr auto offset_of_eoi_suppression = 24u; + } // namespace + enum struct local_apic::registers : std::ptrdiff_t + { + id = 0x020, + version = 0x030, + task_priority = 0x080, + arbitration_priority = 0x090, + processor_priority = 0x0a0, + eoi = 0x0b0, + remote_read = 0x0c0, + logical_destination = 0x0d0, + destination_format = 0x0e0, + spurious_interrupt_vector = 0x0f0, + in_service_0 = 0x100, + in_service_1 = 0x110, + in_service_2 = 0x120, + in_service_3 = 0x130, + in_service_4 = 0x140, + in_service_5 = 0x150, + in_service_6 = 0x160, + in_service_7 = 0x170, + trigger_mode_0 = 0x180, + trigger_mode_1 = 0x190, + trigger_mode_2 = 0x1a0, + trigger_mode_3 = 0x1b0, + trigger_mode_4 = 0x1c0, + trigger_mode_5 = 0x1d0, + trigger_mode_6 = 0x1e0, + trigger_mode_7 = 0x1f0, + interrupt_request_0 = 0x200, + interrupt_request_1 = 0x210, + interrupt_request_2 = 0x220, + interrupt_request_3 = 0x230, + interrupt_request_4 = 0x240, + interrupt_request_5 = 0x250, + interrupt_request_6 = 0x260, + interrupt_request_7 = 0x270, + error_status = 0x280, + lvt_corrected_machine_check_interrupt = 0x2f0, + interrupt_command_0 = 0x300, + interrupt_command_1 = 0x310, + lvt_timer = 0x320, + lvt_thermal_sensors = 0x330, + lvt_performance_monitoring_counters = 0x340, + lvt_local_interrupt_0 = 0x350, + lvt_local_interrupt_1 = 0x360, + lvt_error = 0x370, + initial_count = 0x380, + current_count = 0x390, + divide_configuration = 0x3e0, + }; + local_apic::local_apic(std::size_t major, std::size_t minor, std::uint64_t hardware_id, kapi::memory::physical_address base, bool is_bsp) : kapi::devices::device{major, minor, "lapic"} @@ -46,9 +101,15 @@ namespace arch::devices if (m_is_bsp) { - write_register(lapic_sivr_register, lapic_enable_bit | spurious_interrupt_vector); + auto raw_version = read_register(registers::version); + m_version = (raw_version >> offset_of_version) & 0xff; + m_highest_lvt_entry_index = (raw_version >> offset_of_max_lvt_entry) & 0xff; + m_supports_eoi_broadcast_suppression = (raw_version >> offset_of_eoi_suppression) & 0x1; + + write_register(registers::spurious_interrupt_vector, lapic_enable_bit | spurious_interrupt_vector); - kstd::println("[x86_64:DEV] LAPIC {} initialized. {:#018x}@{:#018x}", m_hardware_id, m_base, m_virtual_base); + kstd::println("[x86_64:DEV] LAPIC initialized. version: {#x} | max_lvt_entry: {} | eoi_suppresion: {:s}", + m_version, m_highest_lvt_entry_index, m_supports_eoi_broadcast_suppression); } else { @@ -58,15 +119,15 @@ namespace arch::devices return true; } - auto local_apic::read_register(std::size_t offset) const -> std::uint32_t + auto local_apic::read_register(registers id) const -> std::uint32_t { - auto reg = static_cast<std::uint32_t volatile *>(m_virtual_base + offset); + auto reg = static_cast<std::uint32_t volatile *>(m_virtual_base + std::to_underlying(id)); return *reg; } - auto local_apic::write_register(std::size_t offset, std::uint32_t value) -> void + auto local_apic::write_register(registers id, std::uint32_t value) -> void { - auto reg = static_cast<std::uint32_t volatile *>(m_virtual_base + offset); + auto reg = static_cast<std::uint32_t volatile *>(m_virtual_base + std::to_underlying(id)); *reg = value; } |
