aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kapi/platform.cpp
blob: 2e7c7e4592046ea39ad30b4574b57a8413b7df0c (plain)
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
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "kapi/platform.hpp"

#include "kapi/acpi.hpp"
#include "kapi/devices.hpp"
#include "kapi/memory.hpp"

#include "arch/devices/local_apic.hpp"

#include <kstd/memory>
#include <kstd/print>

#include <cstddef>
#include <cstdint>

namespace kapi::platform
{

  namespace
  {
    constexpr auto default_lapic_address = kapi::memory::physical_address{0xFEE0'0000};
  }

  auto discover_cpu_topology(kapi::devices::bus & bus) -> bool
  {
    auto madt = kapi::acpi::get_table("APIC");
    if (!madt)
    {
      kstd::println("[x86_64:PLT] Failed to find ACPI APIC table");
      return false;
    }

    auto const * current = reinterpret_cast<std::byte const *>(madt.get()) + sizeof(kapi::acpi::madt_header);
    auto const * end = reinterpret_cast<std::byte const *>(madt.get()) + madt->length();

    auto bsp_found = false;
    auto core_count = 0uz;

    while (current < end)
    {
      auto const * sub_table = reinterpret_cast<kapi::acpi::madt_subtable_header const *>(current);
      if (sub_table->type() == 0)
      {
        auto const * local_apic = reinterpret_cast<kapi::acpi::madt_local_apic const *>(sub_table);
        if (local_apic->flags() & 0b11)
        {
          auto is_bsp = !bsp_found;
          bsp_found = true;

          if (kapi::platform::cpu_detected(bus, local_apic->processor_id(), is_bsp))
          {
            ++core_count;
          }
        }
      }

      current += sub_table->length();
    }

    kstd::println("[x86_64:PLT] Found {} CPU cores", core_count);

    return core_count > 0;
  }

  auto create_core_interrupt_controller(std::size_t major, std::size_t minor, std::uint64_t hardware_id)
      -> kstd::unique_ptr<devices::device>
  {
    return kstd::make_unique<arch::devices::local_apic>(major, minor, hardware_id, default_lapic_address);
  }

}  // namespace kapi::platform