1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
#include "arch/devices/local_apic.hpp"
#include "kapi/devices.hpp"
#include "kapi/memory.hpp"
#include <kstd/print>
#include <cstddef>
#include <cstdint>
namespace arch::devices
{
namespace
{
constexpr auto lapic_sivr_register = 0x00F0uz;
constexpr auto lapic_enable_bit = 0x100u;
constexpr auto spurious_interrupt_vector = 0xFFu;
} // namespace
local_apic::local_apic(std::size_t major, std::size_t minor, std::uint64_t hardware_id,
kapi::memory::physical_address base)
: kapi::devices::device{major, minor, "lapic"}
, m_hardware_id{hardware_id}
, m_base{base}
{}
auto local_apic::init() -> bool
{
m_virtual_base = kapi::memory::allocate_mmio_region(1);
if (!kapi::memory::map_mmio_region(m_virtual_base, m_base, kapi::memory::page_mapper::flags::writable))
{
kstd::println("[x86_64:DEV] LAPIC {} MMIO mapping failed!", m_hardware_id);
return false;
}
write_register(lapic_sivr_register, lapic_enable_bit | spurious_interrupt_vector);
kstd::println("[x86_64:DEV] LAPIC {} initialized. {:#018x}@{:#018x}", m_hardware_id, m_base, m_virtual_base);
return true;
}
auto local_apic::read_register(std::size_t offset) const -> std::uint32_t
{
auto reg = static_cast<std::uint32_t volatile *>(m_virtual_base + offset);
return *reg;
}
auto local_apic::write_register(std::size_t offset, std::uint32_t value) -> void
{
auto reg = static_cast<std::uint32_t volatile *>(m_virtual_base + offset);
*reg = value;
}
} // namespace arch::devices
|