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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/* -------------------------------------------
Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
#include <ArchKit/ArchKit.h>
#include <CFKit/Property.h>
#include <FirmwareKit/EFI/API.h>
#include <FirmwareKit/EFI/EFI.h>
#include <KernelKit/CodeMgr.h>
#include <KernelKit/HardwareThreadScheduler.h>
#include <KernelKit/ProcessScheduler.h>
#include <KernelKit/Timer.h>
#include <NetworkKit/IPC.h>
#include <StorageKit/AHCI.h>
#include <modules/ACPI/ACPIFactoryInterface.h>
#include <modules/CoreGfx/TextGfx.h>
EXTERN_C Kernel::VoidPtr kInterruptVectorTable[];
STATIC Kernel::Void hal_pre_init_scheduler() noexcept {
for (Kernel::SizeT i = 0U;
i < Kernel::UserProcessScheduler::The().CurrentTeam().AsArray().Count(); ++i) {
Kernel::UserProcessScheduler::The().CurrentTeam().AsArray()[i] = Kernel::USER_PROCESS();
}
}
/// @brief Kernel init procedure.
EXTERN_C Int32 hal_init_platform(Kernel::HEL::BootInfoHeader* handover_hdr) {
if (handover_hdr->f_Magic != kHandoverMagic && handover_hdr->f_Version != kHandoverVersion) {
return kEfiFail;
}
kHandoverHeader = handover_hdr;
FB::fb_clear_video();
fw_init_efi((EfiSystemTable*) handover_hdr->f_FirmwareCustomTables[1]);
Boot::ExitBootServices(handover_hdr->f_HardwareTables.f_ImageKey,
handover_hdr->f_HardwareTables.f_ImageHandle);
/************************************** */
/* INITIALIZE BIT MAP. */
/************************************** */
kKernelBitMpSize = kHandoverHeader->f_BitMapSize;
kKernelBitMpStart = reinterpret_cast<Kernel::VoidPtr>(
reinterpret_cast<Kernel::UIntPtr>(kHandoverHeader->f_BitMapStart));
/************************************** */
/* INITIALIZE GDT AND SEGMENTS. */
/************************************** */
STATIC CONST auto kGDTEntriesCount = 6;
/* GDT, mostly descriptors for user and kernel segments. */
STATIC Kernel::HAL::Detail::NE_GDT_ENTRY ALIGN(0x08) kGDTArray[kGDTEntriesCount] = {
{.fLimitLow = 0,
.fBaseLow = 0,
.fBaseMid = 0,
.fAccessByte = 0x00,
.fFlags = 0x00,
.fBaseHigh = 0}, // Null entry
{.fLimitLow = 0x0,
.fBaseLow = 0,
.fBaseMid = 0,
.fAccessByte = 0x9A,
.fFlags = 0xAF,
.fBaseHigh = 0}, // Kernel code
{.fLimitLow = 0x0,
.fBaseLow = 0,
.fBaseMid = 0,
.fAccessByte = 0x92,
.fFlags = 0xCF,
.fBaseHigh = 0}, // Kernel data
{.fLimitLow = 0x0,
.fBaseLow = 0,
.fBaseMid = 0,
.fAccessByte = 0xFA,
.fFlags = 0xAF,
.fBaseHigh = 0}, // User code
{.fLimitLow = 0x0,
.fBaseLow = 0,
.fBaseMid = 0,
.fAccessByte = 0xF2,
.fFlags = 0xCF,
.fBaseHigh = 0}, // User data
};
// Load memory descriptors.
Kernel::HAL::Register64 gdt_reg;
gdt_reg.Base = reinterpret_cast<Kernel::UIntPtr>(kGDTArray);
gdt_reg.Limit = (sizeof(Kernel::HAL::Detail::NE_GDT_ENTRY) * kGDTEntriesCount) - 1;
//! GDT will load hal_read_init after it successfully loads the segments.
Kernel::HAL::GDTLoader gdt_loader;
gdt_loader.Load(gdt_reg);
return kEfiFail;
}
EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept {
hal_pre_init_scheduler();
Kernel::HeFS::fs_init_hefs();
Kernel::HAL::mp_init_cores(kHandoverHeader->f_HardwareTables.f_VendorPtr);
Kernel::HAL::Register64 idt_reg;
idt_reg.Base = (Kernel::UIntPtr) kInterruptVectorTable;
Kernel::HAL::IDTLoader idt_loader;
idt_loader.Load(idt_reg);
/// after the scheduler runs, we must look over teams, every 5000s in order to schedule every
/// process according to their affinity fairly.
auto constexpr kSchedTeamSwitchMS = 5U; /// @brief Team switch time in milliseconds.
Kernel::HardwareTimer timer(rtl_milliseconds(kSchedTeamSwitchMS));
STATIC Kernel::Array<UserProcessTeam, kSchedTeamCount> kTeams;
SizeT team_index = 0U;
/// @brief This just loops over the teams and switches between them.
/// @details Not even round-robin, just a simple loop in this boot core we're at.
while (YES) {
if (team_index > (kSchedTeamCount - 1)) {
team_index = 0U;
}
while (!UserProcessScheduler::The().SwitchTeam(kTeams[team_index]));
timer.Wait();
++team_index;
}
}
|