kernel
Loading...
Searching...
No Matches
kernel.c
Go to the documentation of this file.
1/*
2 * PROJECT: MatanelOS Kernel
3 * LICENSE: GPLv3
4 * PURPOSE: Core Kernel Entry Point for MatanelOS.
5 */
6
7#include "kernel.h"
8#ifndef _MSC_VER
9_Static_assert(sizeof(void*) == 8, "This Kernel is 64 bit only! The 32bit version is deprecated.");
10#endif
11
15
16/*
17Kernel Specific
18*/
19bool isBugChecking = false;
20bool allApsInitialized = false;
21PROCESSOR cpu0; // In UP Mode - Will be the place the CPU struct lives permanently, however in SMP mode, the struct transfers to cpus[my_id] after initializing SMP.
22
23/*
24Boot Parameters
25*/
28
29/*
30AHCI Specifications
31*/
32#define MAX_AHCI_CONTROLLERS 32
34
35
39
40
41#define MAX_MEMORY_MAP_SIZE 0x8000 // 32 KB, enough for ~512 descriptors (this shouldn't be used, since we init the PFN db with the ptr from original UEFI, but eh, whatevs)
42
44
45void copy_memory_map(BOOT_INFO* boot_info) {
46 if (!boot_info || !boot_info->MemoryMap) return;
47 if (boot_info->MapSize > MAX_MEMORY_MAP_SIZE) {
48 // handle error, memory map too big
50 }
51
52 // Copy the entire memory map into the static buffer
53 kmemcpy(memory_map_copy, boot_info->MemoryMap, boot_info->MapSize);
54
55 boot_info_local.MemoryMap = memory_map_copy;
56 boot_info_local.MapSize = boot_info->MapSize;
57 boot_info_local.DescriptorSize = boot_info->DescriptorSize;
58 boot_info_local.DescriptorVersion = boot_info->DescriptorVersion;
59}
60
61void copy_gop(BOOT_INFO* boot_info) {
62 if (!boot_info || !boot_info->Gop.FrameBufferBase) return;
63
64 // Copy the GOP data to a local global variable
65 gop_local = (boot_info->Gop);
66
67 // Update all relevant pointers to point to the local copy
69}
70
71
72void init_boot_info(BOOT_INFO* boot_info) {
73 if (!boot_info) return;
74
75 copy_memory_map(boot_info);
76 copy_gop(boot_info);
77 if (boot_info->AhciCount > MAX_AHCI_CONTROLLERS) {
79 }
80 for (uint32_t i = 0; i < boot_info->AhciCount; i++) {
81 ahci_bases_local[i] = boot_info->AhciBarBases[i];
82 }
83 // Copy the local array into local boot info.
85 boot_info_local.AhciCount = boot_info->AhciCount;
86 boot_info_local.KernelStackTop = boot_info->KernelStackTop;
87 boot_info_local.Pml4Phys = boot_info->Pml4Phys;
88 boot_info_local.AcpiRsdpPhys = boot_info->AcpiRsdpPhys;
89}
90
91static inline bool interrupts_enabled(void) {
92 unsigned long flags;
93 __asm__ __volatile__("pushfq; popq %0"
94 : "=r"(flags)
95 :
96 : "memory", "cc");
97 return (flags & (1UL << 9)) != 0; // IF is bit 9
98}
99
101 gop_printf(0xFF000FF0, "Reached the idle thread!\n");
102 // Reaching the idle thread with interrupts off means something did not have the RFLAGS IF Bit set.
103 if (!interrupts_enabled()) {
104 gop_printf(COLOR_RED, "**Interrupts aren't enabled..\n Stack Trace:\n");
105 FREEZE();
106 }
107 while (1) {
108 if (MeGetCurrentProcessor()->ZombieThread) {
109 // Delete the last thread.
110 Schedule();
111 }
112 __hlt();
113 //Schedule();
114 }
115}
116
117static void test(MUTEX* mut) {
118 PETHREAD currentThread = PsGetCurrentThread();
119 gop_printf_forced(0xFF00FF00, "Hit Test! test thread ptr: %p\n", currentThread);
120 gop_printf(COLOR_GREEN, "(test) Acquiring Mutex Object: %p\n", mut);
122 volatile uint64_t z = 0;
123#ifdef GDB
124 for (uint64_t i = 0; i < 0xA; i++) {
125#else
126 for (uint64_t i = 0; i < 0xFFFFFFF; i++) {
127#endif
128 z++;
129 }
130 gop_printf(COLOR_GREEN, "(test) Releasing Mutex Object: %p\n", mut);
132 gop_printf_forced(0xFFA020F0, "**Ended Test.**\n");
133}
134
135static void MeCreateInitialUserModeProcess(void) {
136 gop_printf(COLOR_OLIVE, "Starting initial user mode process.\n");
137 HANDLE hProcess;
138 PsCreateProcess("terminateMyself.mtexe", &hProcess, MT_PROCESS_ALL_ACCESS, 0);
139 // Always free handles, important.
140 MTSTATUS st = HtClose(hProcess);
141 assert(MT_SUCCEEDED(st));
142 UNREFERENCED_PARAMETER(hProcess);
143}
144
145// All CPUs
147uint32_t cpu_count = 0;
150
153#ifdef DEBUG
154// Stack Canary GCC
155volatile uintptr_t __stack_chk_guard;
156
157__attribute__((noreturn))
158void __stack_chk_fail(void) {
159 __cli();
160 MeBugCheckEx(KERNEL_STACK_OVERFLOWN, (void*)__builtin_return_address(0), NULL, NULL, NULL);
161}
162#endif
163
164// TODO allocate dynamically (use PsCreateProcess)
166
167static void InitSystemProcess(void) {
168 // TODO Setup system process like PsCreateProcess, and modify the func.
170 PsInitialSystemProcess.PID = 4; // Initial PID, reserved.
171 PsInitialSystemProcess.ParentProcess = 0; // No creator process
172 kstrncpy(PsInitialSystemProcess.ImageName, "mtoskrnl.mtexe", sizeof(PsInitialSystemProcess.ImageName)); // Name for the process
173 PsInitialSystemProcess.priority = 0; // TODO
174 PsInitialSystemProcess.InternalProcess.PageDirectoryPhysical = __read_cr3(); // The PML4 of the system process, is our kernel PML4.
175 PsInitialSystemProcess.CreationTime = MeGetEpoch();
176 PsInitialSystemProcess.MainThread = MeGetCurrentProcessor()->idleThread; // The main thread for the SYSTEM process is the BSP's idle thread.
180}
181
182extern uint8_t bss_start;
183extern uint8_t bss_end;
184
186__attribute__((noreturn))
187void kernel_main(BOOT_INFO* boot_info) {
188 // 1. CORE SYSTEM INITIALIZATION
189 __writemsr(IA32_GS_BASE, (uint64_t)&cpu0);
190 __cli();
191 // Zero the BSS.
192 size_t len = &bss_end - &bss_start;
194 // Create the local boot struct.
195 init_boot_info(boot_info);
196 gop_clear_screen(&gop_local, 0); // 0 is just black. (0x0000000)
197 // Initialize the global CPU struct.
198 MeInitializeProcessor(&cpu0, false, false);
199 // Initialize interrupts & exceptions.
201 // Initialize the memory manager
203
204 // Initialize the TSS & GDT & New IDT with TSS
205 MeInitializeProcessor(&cpu0, true, false);
206 // Initialize ACPI after initializing Mm (since page faults will happen on pfn db if not).
208 if (MT_FAILURE(st)) {
209 gop_printf(COLOR_RED, "InitializeACPI Failure: %x\n", st);
210 __hlt();
211 }
212
213 // Move all UEFI Pointers to kernel higher half (after physical memory offset)
214 // To allow copying PML4 of kernel to processes.
216
217 // Initialize the object manager subsystem.
218 ObInitialize();
219
220 // Initialize Ps subsystem.
222 if (MT_FAILURE(st)) {
223 MeBugCheckEx(PSMGR_INIT_FAILED, (void*)(uintptr_t)st, NULL, NULL, NULL);
224 }
225
226 // Initiate section type initializer (must be called after Ob)
227 st = MmInitSections();
228 if (MT_FAILURE(st)) {
231 (void*)(uintptr_t)st,
232 NULL,
233 NULL,
234 NULL
235 );
236 }
237
238 // And, initialize our system process.
239 InitSystemProcess();
241
242#ifdef DEBUG
243 {
244 uint64_t temp_canary = 0;
245 bool rdrand_ok = false;
246 for (int n = 0; n < 64; n++) {
247 if (__rdrand64(&temp_canary)) {
248 rdrand_ok = true;
249 break;
250 }
251 }
252
253 if (rdrand_ok) {
254 __stack_chk_guard = temp_canary;
255 }
256 else {
257 // rdrand didnt give a value, use timestamp of CPU cycles.
258 __stack_chk_guard = __rdtsc();
259 }
260
261 // The canary should never be zero.
262 if (__stack_chk_guard == 0) {
263 __stack_chk_guard = 0xDEADC0DEDEADC0DE; // fallback
264 }
265 }
266#endif
267
268 /* Initiate Scheduler */
270
271 uint64_t rip;
272 __asm__ volatile (
273 "lea 1f(%%rip), %0\n\t" // Calculate the address of label 1 relative to RIP
274 "1:" // The label whose address we want
275 : "=r"(rip) // Output to the 'rip' variable
276 );
277
278 gop_printf_forced(0xFFFFFF00, "Current RIP: %p\n", (void*)(uintptr_t)rip);
279
280 if (rip >= KernelVaStart) {
281 gop_printf_forced(0x00FF00FF, "**[+] Running in higher-half**\n");
282 }
283 else {
284 gop_printf_forced(0xFF0000FF, "[-] Still identity-mapped\n");
285 }
286
287 // Initialize worker threads. (all thread creation must be after sched init)
289
290 MTSTATUS status = FsInitialize();
291 if (MT_FAILURE(status)) {
293 }
294
295 /* SYSTEM IS FULLY INITIALIZED. (except SMP and APIC) */
296
297 void* buf = MmAllocatePoolWithTag(NonPagedPool, 64, 'buf1');
298 gop_printf_forced(0xFFFFFF00, "buf addr: %p\n", buf);
299 void* buf2 = MmAllocatePoolWithTag(NonPagedPool, 128, 'buf2');
300 gop_printf_forced(0xFFFFFF00, "buf2 addr: %p\n", buf2);
301 MmFreePool(buf2);
302 void* buf3 = MmAllocatePoolWithTag(NonPagedPool, 128, 'buf3');
303 gop_printf_forced(0xFFFFFF00, "buf3 addr (should be same as buf2): %p\n", buf3);
304 void* buf4 = MmAllocatePoolWithTag(NonPagedPool, 2048, 'buf4');
305 gop_printf_forced(0xFF964B00, "buf4 addr (should reside after buf3, allocated 2048 bytes): %p\n", buf4);
306 void* buf5 = MmAllocatePoolWithTag(NonPagedPool, 64, 'buf5');
307 gop_printf_forced(0xFF964B00, "buf5 addr (should be a larger addr): %p\n", buf5);
308 void* buf6 = MmAllocatePoolWithTag(NonPagedPool, 5000, 'buf6');
309 gop_printf_forced(0xFFFFFF00, "buf6 addr (should use dynamic memory): %p\n", buf6);
310 void* buf7 = MmAllocatePoolWithTag(NonPagedPool, 10000, 'buf7');
311 gop_printf_forced(0xFFFFFF00, "buf7 addr (should use dynamic memory, extremely larger): %p\n", buf7);
312
313 if (checkcpuid()) {
314 char str[256];
315 getCpuName(str);
316 gop_printf(COLOR_GREEN, "CPU Identified: %s\n", str);
317 }
318
319 TIME_ENTRY currTime = get_time();
320#define ISRAEL_UTC_OFFSET 3
321 gop_printf(COLOR_GREEN, "Current Time: (YY:MM:DD:hh:mm:ss) %d/%d/%d | %d:%d:%d\n", currTime.year, currTime.month, currTime.day, currTime.hour + ISRAEL_UTC_OFFSET, currTime.minute, currTime.second);
322 MUTEX* sharedMutex = MmAllocatePoolWithTag(NonPagedPool, sizeof(MUTEX), ' TUM');
323 if (!sharedMutex) { gop_printf(COLOR_RED, "It's null\n"); __hlt(); }
324 status = MsInitializeMutexObject(sharedMutex);
326 PsCreateSystemThread((ThreadEntry)MeCreateInitialUserModeProcess, NULL, DEFAULT_TIMESLICE_TICKS, NULL); // I have tested 5+ threads, works perfectly as it should. ( SMP UPDATED - Tested with 4 threads, MUTEX and scheduling works perfectly :) )
327 /* Enable LAPIC & SMP Now. */
329 lapic_enable(); // call again.
331 init_lapic_timer(100); // 10ms, must be called before other APs
332#ifndef MT_UP
333 /* Enable SMP */
334 status = MhParseLAPICs((uint8_t*)apic_list, MAX_CPUS, &cpu_count, &lapicAddress);
335 if (MT_FAILURE(status)) {
336 gop_printf(COLOR_RED, "**[MTSTATUS-FAILURE]** ParseLAPICs status returned: %x, continuing in UP mode.\n", status);
337 }
338 else {
340 IPI_PARAMS dummy = { 0 }; // zero-initialize the struct
342 allApsInitialized = true; // Toggle this flag after all CPUs printed their ID, since thats when it marks that all CPUs in the apic list have initialized fully.
343 }
344#else
345 gop_printf(COLOR_RED, "System configured to run in UP mode.\n");
346#endif
347 // __sti(); STI Call commented out, this is what caused the scheduler assertion to fail, and guess how much time it took to debug? 2 days
348 // Thread creations (including idle threads) must come with the IF flag set.
349 Schedule();
351}
BOOT_INFO boot_info_local
Definition kernel.c:27
MTSTATUS MhParseLAPICs(uint8_t *buffer, size_t maxCPUs, uint32_t *cpuCount, uint32_t *lapicAddress)
Definition acpi.c:132
MTSTATUS MhInitializeACPI(void)
Definition acpi.c:167
#define UNREACHABLE_CODE()
Definition annotations.h:72
void lapic_timer_calibrate(void)
Definition apic.c:171
int init_lapic_timer(uint32_t hz)
Definition apic.c:179
void lapic_init_cpu(void)
Definition apic.c:113
void lapic_enable(void)
Definition apic.c:98
#define assert(...)
Definition assert.h:57
NORETURN void MeBugCheck(IN enum _BUGCHECK_CODES BugCheckCode)
Definition bugcheck.c:220
bool smpInitialized
Definition kernel.c:149
bool isBugChecking
Definition kernel.c:19
NORETURN void MeBugCheckEx(IN enum _BUGCHECK_CODES BugCheckCode, IN void *BugCheckParameter1, IN void *BugCheckParameter2, IN void *BugCheckParameter3, IN void *BugCheckParameter4)
Definition bugcheck.c:245
GOP_PARAMS gop_local
Definition gop.c:223
struct _EPROCESS EPROCESS
Definition core.h:51
struct _PROCESSOR PROCESSOR
Definition core.h:47
@ PASSIVE_LEVEL
Definition core.h:15
int32_t HANDLE
Definition core.h:58
ETHREAD * PETHREAD
Definition core.h:44
struct _GOP_PARAMS GOP_PARAMS
struct _BOOT_INFO BOOT_INFO
struct _EFI_MEMORY_DESCRIPTOR EFI_MEMORY_DESCRIPTOR
void gop_printf(uint32_t color, const char *fmt,...)
Definition gop.c:633
char * kstrncpy(char *dst, const char *src, size_t n)
Definition gop.c:365
void gop_clear_screen(GOP_PARAMS *gop, uint32_t color)
Definition gop.c:225
PHANDLE_TABLE HtCreateHandleTable(IN PEPROCESS Process)
Definition handle.c:90
MTSTATUS HtClose(IN HANDLE Handle)
Definition handle.c:536
FORCEINLINE void __writemsr(uint32_t msr, uint64_t value)
Definition intrin.h:215
FORCEINLINE uint64_t __rdtsc(void)
Definition intrin.h:278
FORCEINLINE bool __rdrand64(uint64_t *out)
Definition intrin.h:269
FORCEINLINE void __hlt(void)
Definition intrin.h:65
#define UNREFERENCED_PARAMETER(x)
Definition intrin.h:29
FORCEINLINE void __cli(void)
Definition intrin.h:43
#define IA32_GS_BASE
Definition intrin.h:20
FORCEINLINE uint64_t __read_cr3(void)
Definition intrin.h:93
void _MeSetIrql(IN IRQL NewIrql)
Definition irql.c:158
void init_interrupts()
Definition isr.c:185
void init_boot_info(BOOT_INFO *boot_info)
Definition kernel.c:72
void copy_memory_map(BOOT_INFO *boot_info)
Definition kernel.c:45
uint8_t bss_end
#define ISRAEL_UTC_OFFSET
uint64_t ahci_bases_local[MAX_AHCI_CONTROLLERS]
Definition kernel.c:33
uint8_t apic_list[MAX_CPUS]
Definition kernel.c:146
void copy_gop(BOOT_INFO *boot_info)
Definition kernel.c:61
void kernel_idle_checks(void)
Definition kernel.c:100
#define MAX_AHCI_CONTROLLERS
Definition kernel.c:32
uint32_t cpu_count
Definition kernel.c:147
#define MAX_MEMORY_MAP_SIZE
Definition kernel.c:41
uint8_t bss_start
void kernel_main(BOOT_INFO *boot_info)
#define gop_printf_forced(color, fmt,...)
Definition kernel.h:49
#define FREEZE()
Definition macros.h:64
@ FILESYSTEM_PANIC
Definition me.h:94
@ PSMGR_INIT_FAILED
Definition me.h:130
@ MEMORY_MAP_SIZE_OVERRUN
Custom ones.
Definition me.h:89
@ KERNEL_STACK_OVERFLOWN
Definition me.h:117
@ BAD_AHCI_COUNT
Definition me.h:102
@ MANUALLY_INITIATED_CRASH2
Definition me.h:129
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
Definition me.h:369
@ DEFAULT_TIMESLICE_TICKS
Definition me.h:48
void MeInitializeProcessor(IN PPROCESSOR CPU, IN bool InitializeStandardRoutine, IN bool AreYouAP)
Definition meinit.c:172
#define COLOR_OLIVE
Definition mg.h:48
#define COLOR_RED
Colors definitions for easier access.
Definition mg.h:30
#define COLOR_GREEN
Definition mg.h:31
bool checkcpuid(void)
@ CPU_ACTION_PRINT_ID
Definition mh.h:90
struct _IPI_PARAMS IPI_PARAMS
typedef __attribute__
Definition fat32.h:64
uint32_t flags
Definition mh.h:2
bool allApsInitialized
Definition kernel.c:20
#define MAX_CPUS
Definition mh.h:409
FORCEINLINE void getCpuName(char *name)
Definition mh.h:496
uint32_t lapicAddress
Definition mh.h:1
@ SYSTEM_PHASE_INITIALIZE_ALL
Definition mm.h:413
@ NonPagedPool
Definition mm.h:355
#define KernelVaStart
Definition mm.h:55
FORCEINLINE void * kmemcpy(void *dest, const void *src, size_t len)
Definition mm.h:669
FORCEINLINE void * kmemset(void *dest, int64_t val, uint64_t len)
Definition mm.h:655
void MiMoveUefiDataToHigherHalf(IN PBOOT_INFO BootInfo)
Definition mminit.c:176
bool MmInitSystem(IN uint8_t Phase, IN PBOOT_INFO BootInformation)
Definition mminit.c:77
MTSTATUS MmInitSections(void)
Definition mminit.c:58
FORCEINLINE void InitializeListHead(PDOUBLY_LINKED_LIST Head)
Definition ms.h:223
struct _MUTEX MUTEX
#define MT_FAILURE(Status)
Definition mtstatus.h:16
int32_t MTSTATUS
Definition mtstatus.h:12
#define MT_SUCCEEDED(Status)
Macros to test status.
Definition mtstatus.h:15
MTSTATUS MsReleaseMutexObject(IN PMUTEX mut)
Definition mutex.c:135
MTSTATUS MsInitializeMutexObject(IN PMUTEX mut)
Definition mutex.c:13
MTSTATUS MsAcquireMutexObject(IN PMUTEX mut)
Definition mutex.c:73
void ObInitialize(void)
Definition ob.c:34
void MmFreePool(IN void *buf)
Definition pool.c:632
void * MmAllocatePoolWithTag(IN enum _POOL_TYPE PoolType, IN size_t NumberOfBytes, IN uint32_t Tag)
Definition pool.c:443
MTSTATUS PsCreateProcess(IN const char *ExecutablePath, OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, _In_Opt HANDLE ParentProcess)
Definition process.c:181
@ PS_PHASE_INITIALIZE_SYSTEM
Definition ps.h:56
@ PS_PHASE_INITIALIZE_WORKER_THREADS
Definition ps.h:57
void(* ThreadEntry)(THREAD_PARAMETER)
Definition ps.h:218
#define MT_PROCESS_ALL_ACCESS
Definition ps.h:89
@ ProcessBreakOnTermination
Definition ps.h:92
MTSTATUS PsInitializeSystem(IN enum _PS_PHASE_ROUTINE Phase)
Definition psmgr.c:93
FORCEINLINE void RtlZeroMemory(IN void *Destination, IN size_t Length)
Definition rtl.h:31
NORETURN void Schedule(void)
Definition scheduler.c:110
EPROCESS PsInitialSystemProcess
Definition kernel.c:165
void InitScheduler(void)
Definition scheduler.c:27
PROCESSOR cpu0
Definition kernel.c:21
void MhInitializeSMP(uint8_t *apic_list, uint32_t cpu_count, uint32_t lapicAddress)
Definition smp.c:132
void MhSendActionToCpusAndWait(CPU_ACTION action, IPI_PARAMS parameter)
Definition smp.c:231
uintptr_t Pml4Phys
Definition efi.h:61
size_t AhciCount
Definition efi.h:58
EFI_MEMORY_DESCRIPTOR * MemoryMap
Definition efi.h:54
uint64_t AhciBarBases[32]
Definition efi.h:59
uint64_t KernelStackTop
Definition efi.h:60
uintptr_t AcpiRsdpPhys
Definition efi.h:62
size_t DescriptorSize
Definition efi.h:56
GOP_PARAMS Gop
Definition efi.h:53
uint32_t DescriptorVersion
Definition efi.h:57
size_t MapSize
Definition efi.h:55
uint64_t FrameBufferBase
Definition efi.h:43
struct _ETHREAD * idleThread
Definition me.h:298
uint8_t month
Definition time.h:23
uint16_t year
Definition time.h:24
uint8_t day
Definition time.h:22
uint8_t second
Definition time.h:19
uint8_t minute
Definition time.h:20
uint8_t hour
Definition time.h:21
PETHREAD PsGetCurrentThread(void)
Definition thread.c:279
MTSTATUS PsCreateSystemThread(ThreadEntry entry, THREAD_PARAMETER parameter, TimeSliceTicks TIMESLICE, _Out_Opt PETHREAD *OutThread)
Definition thread.c:196
MTSTATUS FsInitialize(void)
Definition vfs.c:81