aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-04-08 17:07:27 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-04-08 17:07:27 +0200
commit1ecc0c223a1bacfa1aee183a3573f57c265318df (patch)
tree5913f2fb456d646733ce9e70338f0b8bf1245512 /arch
parentf36cbd54bb6319050404165e8a3280ccbda05cf3 (diff)
downloadteachos-1ecc0c223a1bacfa1aee183a3573f57c265318df.tar.xz
teachos-1ecc0c223a1bacfa1aee183a3573f57c265318df.zip
x86_64: extend LAPIC initialization
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/include/arch/devices/local_apic.hpp9
-rw-r--r--arch/x86_64/src/devices/local_apic.cpp77
2 files changed, 76 insertions, 10 deletions
diff --git a/arch/x86_64/include/arch/devices/local_apic.hpp b/arch/x86_64/include/arch/devices/local_apic.hpp
index 7ae0a02..946e4af 100644
--- a/arch/x86_64/include/arch/devices/local_apic.hpp
+++ b/arch/x86_64/include/arch/devices/local_apic.hpp
@@ -18,13 +18,18 @@ namespace arch::devices
auto init() -> bool override;
private:
- [[nodiscard]] auto read_register(std::size_t offset) const -> std::uint32_t;
- auto write_register(std::size_t offset, std::uint32_t value) -> void;
+ enum struct registers : std::ptrdiff_t;
+
+ [[nodiscard]] auto read_register(registers id) const -> std::uint32_t;
+ auto write_register(registers id, std::uint32_t value) -> void;
std::uint64_t m_hardware_id{};
kapi::memory::physical_address m_base{};
kapi::memory::linear_address m_virtual_base{};
bool m_is_bsp{};
+ std::uint8_t m_version{};
+ std::uint8_t m_highest_lvt_entry_index{};
+ bool m_supports_eoi_broadcast_suppression{};
};
} // namespace arch::devices
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;
}