My Project
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_lapic_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 scheduler!\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("loop.mtexe", &hProcess, MT_PROCESS_ALL_ACCESS, 0);
139 UNREFERENCED_PARAMETER(hProcess);
140}
141
142// All CPUs
144uint32_t cpu_count = 0;
147
150#ifdef DEBUG
151// Stack Canary GCC
152volatile uintptr_t __stack_chk_guard;
153
154__attribute__((noreturn))
155void __stack_chk_fail(void) {
156 __cli();
157 MeBugCheckEx(KERNEL_STACK_OVERFLOWN, (void*)__builtin_return_address(0), NULL, NULL, NULL);
158}
159#endif
160
161// TODO allocate dynamically (use PsCreateProcess)
163
164static void InitSystemProcess(void) {
165 PsInitialSystemProcess.PID = 4; // Initial PID, reserved.
166 PsInitialSystemProcess.ParentProcess = 0; // No creator process
167 kstrncpy(PsInitialSystemProcess.ImageName, "mtoskrnl.mtexe", sizeof(PsInitialSystemProcess.ImageName)); // Name for the process
168 PsInitialSystemProcess.priority = 0; // TODO
169 PsInitialSystemProcess.InternalProcess.PageDirectoryPhysical = __read_cr3(); // The PML4 of the system process, is our kernel PML4.
170 PsInitialSystemProcess.CreationTime = MeGetEpoch();
171 PsInitialSystemProcess.MainThread = MeGetCurrentProcessor()->idleThread; // The main thread for the SYSTEM process is the BSP's idle thread.
174}
175
176extern uint8_t bss_start;
177extern uint8_t bss_end;
178
180__attribute__((noreturn))
181void kernel_main(BOOT_INFO* boot_info) {
182 // 1. CORE SYSTEM INITIALIZATION
183 __writemsr(IA32_GS_BASE, (uint64_t)&cpu0);
184 __cli();
185 // Zero the BSS.
186 size_t len = &bss_end - &bss_start;
188 // Create the local boot struct.
189 init_boot_info(boot_info);
190 gop_clear_screen(&gop_local, 0); // 0 is just black. (0x0000000)
191 // Initialize the global CPU struct.
192 MeInitializeProcessor(&cpu0, false, false);
193 // Initialize interrupts & exceptions.
195 // Initialize the memory manager
197
198 // Initialize the TSS & GDT & New IDT with TSS
199 MeInitializeProcessor(&cpu0, true, false);
200
201 // Initialize ACPI after initializing Mm (since page faults will happen on pfn db if not).
203 if (MT_FAILURE(st)) {
204 gop_printf(COLOR_RED, "InitializeACPI Failure: %x\n", st);
205 __hlt();
206 }
207
208 // Move all UEFI Pointers to kernel higher half (after physical memory offset)
209 // To allow copying PML4 of kernel to processes.
211
212 // Initialize the object manager subsystem.
213 ObInitialize();
214
215 // Initialize Ps subsystem.
217 if (MT_FAILURE(st)) {
218 MeBugCheckEx(PSMGR_INIT_FAILED, (void*)(uintptr_t)st, NULL, NULL, NULL);
219 }
220
221 // And, initialize our system process.
222 InitSystemProcess();
224#ifdef DEBUG
225 {
226 uint64_t temp_canary = 0;
227 bool rdrand_ok = false;
228 for (int n = 0; n < 64; n++) {
229 if (__rdrand64(&temp_canary)) {
230 rdrand_ok = true;
231 break;
232 }
233 }
234
235 if (rdrand_ok) {
236 __stack_chk_guard = temp_canary;
237 }
238 else {
239 // rdrand didnt give a value, use timestamp of CPU cycles.
240 __stack_chk_guard = __rdtsc();
241 }
242
243 // The canary should never be zero.
244 if (__stack_chk_guard == 0) {
245 __stack_chk_guard = 0xDEADC0DEDEADC0DE; // fallback
246 }
247 }
248#endif
249 /* Initiate Scheduler */
251 uint64_t rip;
252 __asm__ volatile (
253 "lea 1f(%%rip), %0\n\t" // Calculate the address of label 1 relative to RIP
254 "1:" // The label whose address we want
255 : "=r"(rip) // Output to the 'rip' variable
256 );
257
258 gop_printf_forced(0xFFFFFF00, "Current RIP: %p\n", (void*)(uintptr_t)rip);
259
260 if (rip >= KernelVaStart) {
261 gop_printf_forced(0x00FF00FF, "**[+] Running in higher-half**\n");
262 }
263 else {
264 gop_printf_forced(0xFF0000FF, "[-] Still identity-mapped\n");
265 }
266
267 // Initialize worker threads. (all thread creation must be after sched init)
269
270 void* buf = MmAllocatePoolWithTag(NonPagedPool, 64, 'buf1');
271 gop_printf_forced(0xFFFFFF00, "buf addr: %p\n", buf);
272 void* buf2 = MmAllocatePoolWithTag(NonPagedPool, 128, 'buf2');
273 gop_printf_forced(0xFFFFFF00, "buf2 addr: %p\n", buf2);
274 MmFreePool(buf2);
275 void* buf3 = MmAllocatePoolWithTag(NonPagedPool, 128, 'buf3');
276 gop_printf_forced(0xFFFFFF00, "buf3 addr (should be same as buf2): %p\n", buf3);
277 void* buf4 = MmAllocatePoolWithTag(NonPagedPool, 2048, 'buf4');
278 gop_printf_forced(0xFF964B00, "buf4 addr (should reside after buf3, allocated 2048 bytes): %p\n", buf4);
279 void* buf5 = MmAllocatePoolWithTag(NonPagedPool, 64, 'buf5');
280 gop_printf_forced(0xFF964B00, "buf5 addr (should be a larger addr): %p\n", buf5);
281 void* buf6 = MmAllocatePoolWithTag(NonPagedPool, 5000, 'buf6');
282 gop_printf_forced(0xFFFFFF00, "buf6 addr (should use dynamic memory): %p\n", buf6);
283 void* buf7 = MmAllocatePoolWithTag(NonPagedPool, 10000, 'buf7');
284 gop_printf_forced(0xFFFFFF00, "buf7 addr (should use dynamic memory, extremely larger): %p\n", buf7);
285
286 if (checkcpuid()) {
287 char str[256];
288 getCpuName(str);
289 gop_printf(COLOR_GREEN, "CPU Identified: %s\n", str);
290 }
291
292 MTSTATUS status = vfs_init();
293 gop_printf(COLOR_RED, "vfs_init returned: %s\n", MT_SUCCEEDED(status) ? "Success" : "Unsuccessful");
294 if (MT_FAILURE(status)) {
296 }
297
298 TIME_ENTRY currTime = get_time();
299#define ISRAEL_UTC_OFFSET 3
300 gop_printf(COLOR_GREEN, "Current Time: %d/%d/%d | %d:%d:%d\n", currTime.year, currTime.month, currTime.day, currTime.hour + ISRAEL_UTC_OFFSET, currTime.minute, currTime.second);
301 char listings[256];
302 status = vfs_listdir("/", listings, sizeof(listings));
303 gop_printf(COLOR_RED, "vfs_listdir returned: %x\n", status);
304 gop_printf(COLOR_RED, "root directory is: %s\n", vfs_is_dir_empty("/") ? "Empty" : "Not Empty");
305 gop_printf(COLOR_CYAN, "%s", listings);
306 MUTEX* sharedMutex = MmAllocatePoolWithTag(NonPagedPool, sizeof(MUTEX), ' TUM');
307 if (!sharedMutex) { gop_printf(COLOR_RED, "It's null\n"); __hlt(); }
308 status = MsInitializeMutexObject(sharedMutex);
310 PsCreateSystemThread((ThreadEntry)MeCreateInitialUserModeProcess, NULL, DEFAULT_TIMESLICE_TICKS); // I have tested 5+ threads, works perfectly as it should. ( SMP UPDATED - Tested with 4 threads, MUTEX and scheduling works perfectly :) )
311 /* Enable LAPIC & SMP Now. */
313 lapic_enable(); // call again.
315 init_lapic_timer(100); // 10ms, must be called before other APs
316#ifndef MT_UP
317 /* Enable SMP */
318 status = MhParseLAPICs((uint8_t*)apic_list, MAX_CPUS, &cpu_count, &lapicAddress);
319 if (MT_FAILURE(status)) {
320 gop_printf(COLOR_RED, "**[MTSTATUS-FAILURE]** ParseLAPICs status returned: %x, continuing in UP mode.\n", status);
321 }
322 else {
324 IPI_PARAMS dummy = { 0 }; // zero-initialize the struct
326 allApsInitialized = true; // Toggle this flag after all CPUs printed their ID, since thats when it marks that all CPUs of the apic list have initialized fully.
327 }
328#else
329 gop_printf(COLOR_RED, "System configured to run in UP mode.\n");
330#endif
331 // __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
332 // Thread creations (including idle threads) must come with the IF flag set.
333 Schedule();
334 __builtin_unreachable();
335}
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:130
MTSTATUS MhInitializeACPI(void)
Definition acpi.c:164
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
NORETURN void MeBugCheck(IN enum _BUGCHECK_CODES BugCheckCode)
Definition bugcheck.c:214
bool smpInitialized
Definition kernel.c:146
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:305
GOP_PARAMS gop_local
Definition gop.c:247
struct _EPROCESS EPROCESS
Definition core.h:49
struct _PROCESSOR PROCESSOR
Definition core.h:45
@ PASSIVE_LEVEL
Definition core.h:13
ETHREAD * PETHREAD
Definition core.h:42
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:694
char * kstrncpy(char *dst, const char *src, size_t n)
Definition gop.c:416
void gop_clear_screen(GOP_PARAMS *gop, uint32_t color)
Definition gop.c:249
PHANDLE_TABLE HtCreateHandleTable(IN PEPROCESS Process)
Definition handle.c:87
int32_t HANDLE
Definition ht.h:59
FORCEINLINE void __writemsr(uint32_t msr, uint64_t value)
Definition intrin.h:200
FORCEINLINE uint64_t __rdtsc(void)
Definition intrin.h:263
FORCEINLINE bool __rdrand64(uint64_t *out)
Definition intrin.h:254
FORCEINLINE void __hlt(void)
Definition intrin.h:50
#define UNREFERENCED_PARAMETER(x)
Definition intrin.h:24
FORCEINLINE void __cli(void)
Definition intrin.h:38
#define IA32_GS_BASE
Definition intrin.h:20
FORCEINLINE uint64_t __read_cr3(void)
Definition intrin.h:78
void _MeSetIrql(IN IRQL NewIrql)
Definition irql.c:153
void init_interrupts()
Definition isr.c:168
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:143
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:144
#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:58
#define FREEZE()
Definition macros.h:49
@ 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
FORCEINLINE PPROCESSOR MeGetCurrentProcessor(void)
Definition me.h:356
@ DEFAULT_TIMESLICE_TICKS
Definition me.h:48
void MeInitializeProcessor(IN PPROCESSOR CPU, IN bool InitializeStandardRoutine, IN bool AreYouAP)
Definition meinit.c:164
#define COLOR_OLIVE
Definition mg.h:47
#define COLOR_CYAN
Definition mg.h:35
#define COLOR_RED
Colors definitions for easier access.
Definition mg.h:29
#define COLOR_GREEN
Definition mg.h:30
bool checkcpuid(void)
@ CPU_ACTION_PRINT_ID
Definition mh.h:93
struct _IPI_PARAMS IPI_PARAMS
typedef __attribute__
Definition fat32.h:63
uint32_t flags
Definition mh.h:2
bool allApsInitialized
Definition kernel.c:20
#define MAX_CPUS
Definition mh.h:408
FORCEINLINE void getCpuName(char *name)
Definition mh.h:495
uint32_t lapicAddress
Definition mh.h:1
@ SYSTEM_PHASE_INITIALIZE_ALL
Definition mm.h:375
@ NonPagedPool
Definition mm.h:316
#define KernelVaStart
Definition mm.h:55
FORCEINLINE void * kmemcpy(void *dest, const void *src, size_t len)
Definition mm.h:554
void MiMoveUefiDataToHigherHalf(IN PBOOT_INFO BootInfo)
Definition mminit.c:154
bool MmInitSystem(IN uint8_t Phase, IN PBOOT_INFO BootInformation)
Definition mminit.c:55
FORCEINLINE void InitializeListHead(PDOUBLY_LINKED_LIST Head)
Definition ms.h:166
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:33
void MmFreePool(IN void *buf)
Definition pool.c:586
void * MmAllocatePoolWithTag(IN enum _POOL_TYPE PoolType, IN size_t NumberOfBytes, IN uint32_t Tag)
Definition pool.c:427
MTSTATUS PsCreateProcess(IN const char *ExecutablePath, OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, _In_Opt HANDLE ParentProcess)
Definition process.c:50
@ PS_PHASE_INITIALIZE_SYSTEM
Definition ps.h:56
@ PS_PHASE_INITIALIZE_WORKER_THREADS
Definition ps.h:57
void(* ThreadEntry)(THREAD_PARAMETER)
Definition ps.h:147
#define MT_PROCESS_ALL_ACCESS
Definition ps.h:89
MTSTATUS PsInitializeSystem(IN enum _PS_PHASE_ROUTINE Phase)
Definition psmgr.c:97
FORCEINLINE void RtlZeroMemory(IN void *Destination, IN size_t Length)
Definition rtl.h:31
NORETURN void Schedule(void)
Definition scheduler.c:105
EPROCESS PsInitialSystemProcess
Definition kernel.c:162
void InitScheduler(void)
Definition scheduler.c:26
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:212
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:291
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
MTSTATUS PsCreateSystemThread(ThreadEntry entry, THREAD_PARAMETER parameter, TimeSliceTicks TIMESLICE)
Definition thread.c:122
PETHREAD PsGetCurrentThread(void)
Definition thread.c:191
MTSTATUS vfs_listdir(const char *path, char *listings, size_t max_len)
Lists the directory given.
Definition vfs.c:108
bool vfs_is_dir_empty(const char *path)
This function returns if the directory given to the function is empty (e.g, has only '....
Definition vfs.c:129
MTSTATUS vfs_init(void)
Initialize the Virtual File System (initializes other filesystem needed services as well)
Definition vfs.c:42