aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/kapi/system.cpp
blob: ca4418e2fb55225c340444c12bfde234e17fbc4f (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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "kapi/system.hpp"

#include "arch/cpu/global_descriptor_table.hpp"
#include "arch/cpu/segment_descriptor.hpp"
#include "arch/cpu/task_state_segment.hpp"

#include <kstd/print>

#include <bit>
#include <cstdint>

namespace kapi::system
{

  namespace
  {
    constexpr auto gdt_null_descriptor = arch::cpu::segment_descriptor{};

    constexpr auto gdt_kernel_code_descriptor = arch::cpu::segment_descriptor{
      .limit_low = 0xffff,
      .base_low = 0,
      .accessed = false,
      .read_write = false,
      .direction_or_conforming = false,
      .executable = true,
      .type = arch::cpu::segment_type::code_or_data,
      .privilege_level = 0,
      .present = true,
      .limit_high = 0xf,
      .long_mode = true,
      .protected_mode = false,
      .granularity = arch::cpu::segment_granularity::page,
      .base_high = 0,
    };

    constexpr auto gdt_kernel_data_descriptor = arch::cpu::segment_descriptor{
      .limit_low = 0xffff,
      .base_low = 0,
      .accessed = false,
      .read_write = true,
      .direction_or_conforming = false,
      .executable = false,
      .type = arch::cpu::segment_type::code_or_data,
      .privilege_level = 0,
      .present = true,
      .limit_high = 0xf,
      .long_mode = false,
      .protected_mode = true,
      .granularity = arch::cpu::segment_granularity::page,
      .base_high = 0,
    };

    constexpr auto gdt_user_code_descriptor = arch::cpu::segment_descriptor{
      .limit_low = 0xffff,
      .base_low = 0,
      .accessed = false,
      .read_write = false,
      .direction_or_conforming = false,
      .executable = true,
      .type = arch::cpu::segment_type::code_or_data,
      .privilege_level = 3,
      .present = true,
      .limit_high = 0xf,
      .long_mode = true,
      .protected_mode = false,
      .granularity = arch::cpu::segment_granularity::page,
      .base_high = 0,
    };

    constexpr auto gdt_user_data_descriptor = arch::cpu::segment_descriptor{
      .limit_low = 0xffff,
      .base_low = 0,
      .accessed = false,
      .read_write = true,
      .direction_or_conforming = false,
      .executable = false,
      .type = arch::cpu::segment_type::code_or_data,
      .privilege_level = 3,
      .present = true,
      .limit_high = 0xf,
      .long_mode = false,
      .protected_mode = false,
      .granularity = arch::cpu::segment_granularity::page,
      .base_high = 0,
    };
  }  // namespace

  auto memory_initialized() -> void
  {
    auto static tss = arch::cpu::task_state_segment{};
    auto static tss_descriptor = arch::cpu::system_segment_descriptor{
      {
       .limit_low = (sizeof(tss) - 1) & 0xffff,                     // NOLINT(readability-magic-numbers)
        .base_low = std::bit_cast<std::uintptr_t>(&tss) & 0xffffff,  // NOLINT(readability-magic-numbers)
        .accessed = false,
       .read_write = false,
       .direction_or_conforming = false,
       .executable = false,
       .type = arch::cpu::segment_type::system,
       .privilege_level = 0,
       .present = true,
       .limit_high = ((sizeof(tss) - 1) >> 16) & 0xf,  // NOLINT(readability-magic-numbers)
        .long_mode = false,
       .protected_mode = false,
       .granularity = arch::cpu::segment_granularity::byte,
       .base_high = (std::bit_cast<std::uintptr_t>(&tss) >> 24) & 0xff,  // NOLINT(readability-magic-numbers)
      },
      (std::bit_cast<std::uintptr_t>(&tss) >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers)
    };

    auto static gdt = arch::cpu::global_descriptor_table{
      gdt_null_descriptor,      gdt_kernel_code_descriptor, gdt_kernel_data_descriptor,
      gdt_user_code_descriptor, gdt_user_data_descriptor,   tss_descriptor,
    };

    kstd::println("[x86_64:SYS] Reloading Global Descriptor Table.");
    gdt.load(1, 2);

    kstd::println("[x86_64:SYS] TODO: initialize Interrupt Descriptor Table.");
  }

}  // namespace kapi::system