Max OS 0.3
Loading...
Searching...
No Matches
cpu.cpp
Go to the documentation of this file.
1
9#include <system/cpu.h>
10#include <common/logger.h>
11#include <processes/scheduler.h>
14#include <drivers/clock/clock.h>
15#include <common/symbols.h>
16
17using namespace MaxOS;
18using namespace MaxOS::system;
19using namespace MaxOS::common;
20using namespace MaxOS::drivers;
21using namespace MaxOS::drivers::clock;
22using namespace MaxOS::hardwarecommunication;
23using namespace MaxOS::processes;
24using namespace MaxOS::memory;
25
26extern uint64_t stack[];
27volatile extern PAGE_ALIGNED unsigned char p4_table[];
28
29extern "C" void core_start();
30extern "C" uint8_t core_boot_info[];
31
38: m_madt(madt_item)
39{
40
41 id = m_madt->processor_id;
42 m_apic_id = m_madt->apic_id;
43
44 m_enabled = (m_madt->flags & 0x1) != 0;
45 m_can_enable = (m_madt->flags & 0x2) != 0;
46
47 Logger::DEBUG() << "Found CPU ID: " << id << " with APIC ID: " << m_apic_id << " (enabled = " << (string)m_enabled << ", can be enabled = " << (string)m_can_enable << ")\n";
48
49}
50
51Core::~Core() = default;
52
60
61 // Boot core is already setup
62 if(m_bsp){
63 Logger::DEBUG() << "BSP Already setup\n";
64 return;
65 }
66
67 Logger::DEBUG() << "Starting core: " << id << "\n";
69
70 // Core specific boot info
71 auto info = (core_boot_info_t*)(core_boot_info);
72 info->activated = false;
73 info->id = id;
74 info->stack = m_stack + BOOT_STACK_SIZE;
75
76 // Send init IPI
77 cpu->apic.local_apic()->send_init(m_apic_id, true);
78
79 // Send de-assert IPI
80 cpu->apic.local_apic()->send_init(m_apic_id, false);
81 Clock::active_clock()->delay(10);
82
83 // Send tow SIPIs
84 for (int i = 0; i < 2; ++i) {
85
86 // Send the start up IPI
87 cpu->apic.local_apic()->send_startup(m_apic_id, 0x8);
88 Clock::active_clock()->delay(200);
89
90 // Check if core started
91 if(info->activated){
92
93 // Wait for full init
94 while(!active)
95 asm("nop");
96
97 Logger::DEBUG() << "Core " << id << " started successfully \n";
98 return;
99 }
100 }
101
102 Logger::WARNING() << "Failed to start core: " << id << "\n";
103}
104
111
112 // The reserved have to be 0
113 tss.reserved0 = 0;
114 tss.reserved1 = 0;
115 tss.reserved2 = 0;
116 tss.reserved3 = 0;
117 tss.reserved4 = 0;
118
119 // The stacks
120 tss.rsp0 = (uint64_t)m_stack + BOOT_STACK_SIZE; // Kernel stack (scheduler will set the threads stack)
121 tss.rsp1 = 0;
122 tss.rsp2 = 0;
123
124 // Interrupt stacks can all be 0
125 tss.ist1 = 0;
126 tss.ist2 = 0;
127 tss.ist3 = 0;
128 tss.ist4 = 0;
129 tss.ist5 = 0;
130 tss.ist6 = 0;
131 tss.ist7 = 0;
132
133 // Ports
134 tss.io_bitmap_offset = 0;
135
136 // Split the base into 4 parts (16 bits, 8 bits, 8 bits, 32 bits)
137 auto base = (uint64_t) &tss;
138 uint16_t base_1 = base & 0xFFFF;
139 uint8_t base_2 = (base >> 16) & 0xFF;
140 uint8_t base_3 = (base >> 24) & 0xFF;
141 uint32_t base_4 = (base >> 32) & 0xFFFFFFFF;
142
143 auto limit_low = (uint16_t)(sizeof(tss) - 1);
144
145 // Flags: 1 - Type = 0x9, Descriptor Privilege Level = 0, Present = 1, 2 - Available = 0, Granularity = 0
146 uint8_t flags_1 = 0x89;
147 uint8_t flags_2 = 0;
148
149 // Create the TSS descriptors
152
153 // Store in the GDT
154 gdt -> table[5] = tss_descriptor_low;
155 gdt -> table[6] = tss_descriptor_high;
156 gdt -> load();
157
158 // Load the TSS
159 Logger::DEBUG() << "Loading TSS: 0x0" << tss_descriptor_low << " 0x0" << tss_descriptor_high << " at 0x" << (uint64_t) &tss << "\n";
160 asm volatile("ltr %%ax" : : "a" (0x28));
161
162}
163
168
169 // Get the CR0 register
171 asm volatile("mov %%cr0, %0" : "=r" (cr0));
172
173 // Get the CR4 register
175 asm volatile("mov %%cr4, %0" : "=r" (cr4));
176
177 // Check if FPU is supported
178 ASSERT(CPU::check_cpu_feature(CPU_FEATURE_EDX::FPU), "FPU not supported - needed for SSE");
179
180 // Clear the emulation flag, task switch flags and enable the monitor coprocessor, native exception bits
181 cr0 |= (1 << 1);
182 cr0 &= ~(1 << 2);
183 cr0 &= ~(1 << 3);
184 cr0 |= (1 << 5);
185 asm volatile("mov %0, %%cr0" : : "r" (cr0));
186
187 // Enable the FPU
188 asm volatile("fninit");
189
190 // Check if SSE is supported
191 ASSERT(CPU::check_cpu_feature(CPU_FEATURE_EDX::SSE), "SSE not supported");
192
193 // Enable FSAVE, FSTORE and SSE instructions
194 cr4 |= (1 << 9);
195 cr4 |= (1 << 10);
196 asm volatile("mov %0, %%cr4" : : "r" (cr4));
197
198 // Check if XSAVE is supported
199 xsave_enabled = CPU::check_cpu_feature(CPU_FEATURE_ECX::XSAVE) && CPU::check_cpu_feature(CPU_FEATURE_ECX::OSXSAVE);
200 Logger::DEBUG() << "XSAVE: " << (xsave_enabled ? "Supported" : "Not Supported") << "\n";
201 if (!xsave_enabled) return;
202
203 // Enable the XSAVE and XRESTORE instructions
204 cr4 |= (1 << 18);
205 asm volatile("mov %0, %%cr4" : : "r" (cr4));
206
207 // Set the SSE and x87 bits
209 asm volatile("xgetbv" : "=a" (xcr0) : "c" (0));
210 xcr0 |= 0x7;
211 asm volatile("xsetbv" : : "c" (0), "a" (xcr0));
212
213 // Check if AVX is supported
214 avx_enabled = CPU::check_cpu_feature(CPU_FEATURE_ECX::AVX);
215 Logger::DEBUG() << "AVX: " << (avx_enabled ? "Supported" : "Not Supported") << "\n";
216 if (!avx_enabled) return;
217
218 // Enable the AVX instructions
219 cr4 |= (1 << 14);
220 asm volatile("mov %0, %%cr4" : : "r" (cr4));
221
222 Logger::DEBUG() << "SSE Enabled\n";
223}
224
229
230 // Load the kernel IDT & GDT
233
234 // Setup this core's clock
235 local_apic = new LocalAPIC;
236 Clock::active_clock()->setup_apic_clock(local_apic);
237
238 // Delegate large initiation
239 init_sse();
240 init_tss();
241
242 active = true;
243}
244
245
253: acpi(multiboot),
254 apic(&acpi)
255{
256
257 Logger::INFO() << "Setting up CPU \n";
258 find_cores();
259
260 // Manually set up the BSP
261 auto bsp = cores[0];
262 bsp -> m_bsp = true;
263 bsp -> active = true;
264 bsp -> gdt = gdt;
265 bsp -> local_apic = apic.local_apic();
266 bsp -> init_tss();
267 bsp -> init_sse();
268
269}
270
271CPU::~CPU() = default;
272
276[[noreturn]] void CPU::halt() {
277
278 while (true)
279 asm volatile("hlt");
280}
281
288
289 // Get the registers
290 asm volatile("mov %%r15, %0" : "=r" (status->r15));
291 asm volatile("mov %%r14, %0" : "=r" (status->r14));
292 asm volatile("mov %%r13, %0" : "=r" (status->r13));
293 asm volatile("mov %%r12, %0" : "=r" (status->r12));
294 asm volatile("mov %%r11, %0" : "=r" (status->r11));
295 asm volatile("mov %%r10, %0" : "=r" (status->r10));
296 asm volatile("mov %%r9, %0" : "=r" (status->r9));
297 asm volatile("mov %%r8, %0" : "=r" (status->r8));
298 asm volatile("mov %%rdi, %0" : "=r" (status->rdi));
299 asm volatile("mov %%rsi, %0" : "=r" (status->rsi));
300 asm volatile("mov %%rbp, %0" : "=r" (status->rbp));
301 asm volatile("mov %%rdx, %0" : "=r" (status->rdx));
302 asm volatile("mov %%rcx, %0" : "=r" (status->rcx));
303 asm volatile("mov %%rbx, %0" : "=r" (status->rbx));
304 asm volatile("mov %%rax, %0" : "=r" (status->rax));
305}
306
313
314 // Set the registers
315 asm volatile("mov %0, %%r15" : : "r" (status->r15));
316 asm volatile("mov %0, %%r14" : : "r" (status->r14));
317 asm volatile("mov %0, %%r13" : : "r" (status->r13));
318 asm volatile("mov %0, %%r12" : : "r" (status->r12));
319 asm volatile("mov %0, %%r11" : : "r" (status->r11));
320 asm volatile("mov %0, %%r10" : : "r" (status->r10));
321 asm volatile("mov %0, %%r9" : : "r" (status->r9));
322 asm volatile("mov %0, %%r8" : : "r" (status->r8));
323 asm volatile("mov %0, %%rdi" : : "r" (status->rdi));
324 asm volatile("mov %0, %%rsi" : : "r" (status->rsi));
325 asm volatile("mov %0, %%rbp" : : "r" (status->rbp));
326 asm volatile("mov %0, %%rdx" : : "r" (status->rdx));
327 asm volatile("mov %0, %%rcx" : : "r" (status->rcx));
328 asm volatile("mov %0, %%rbx" : : "r" (status->rbx));
329 asm volatile("mov %0, %%rax" : : "r" (status->rax));
330
331}
332
339
340 // Print the registers
341 Logger::ERROR() << "R15: \t0x" << status->r15 << "\n";
342 Logger::ERROR() << "R14: \t0x" << status->r14 << "\n";
343 Logger::ERROR() << "R13: \t0x" << status->r13 << "\n";
344 Logger::ERROR() << "R12: \t0x" << status->r12 << "\n";
345 Logger::ERROR() << "R11: \t0x" << status->r11 << "\n";
346 Logger::ERROR() << "R10: \t0x" << status->r10 << "\n";
347 Logger::ERROR() << "R9: \t0x" << status->r9 << "\n";
348 Logger::ERROR() << "R8: \t0x" << status->r8 << "\n";
349 Logger::ERROR() << "RDI: \t0x" << status->rdi << "\n";
350 Logger::ERROR() << "RSI: \t0x" << status->rsi << "\n";
351 Logger::ERROR() << "RBP: \t0x" << status->rbp << "\n";
352 Logger::ERROR() << "RDX: \t0x" << status->rdx << "\n";
353 Logger::ERROR() << "RCX: \t0x" << status->rcx << "\n";
354 Logger::ERROR() << "RBX: \t0x" << status->rbx << "\n";
355 Logger::ERROR() << "RAX: \t0x" << status->rax << "\n";
356 Logger::ERROR() << "INT: \t0x" << status->interrupt_number << "\n";
357 Logger::ERROR() << "ERRCD: \t0x" << status->error_code << "\n";
358 Logger::ERROR() << "RIP: \t0x" << status->rip << "\n";
359 Logger::ERROR() << "CS: \t0x" << status->cs << "\n";
360 Logger::ERROR() << "RFlGS: \t0x" << status->rflags << "\n";
361 Logger::ERROR() << "RSP: \t0x" << status->rsp << "\n";
362 Logger::ERROR() << "SS: \t0x" << status->ss << "\n";
363
364}
365
373
374 // Read the MSR
376 asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
377
378 // Return the value
379 return (uint64_t) low | ((uint64_t) high << 32);
380}
381
389
390 // Write the MSR
391 asm volatile("wrmsr" : : "a" ((uint32_t) value), "d" ((uint32_t) (value >> 32)), "c" (msr));
392}
393
404
405 // Call the cpuid instruction
407}
408
415
417
418 // Loop through the frames logging
419 for (size_t current_level = 0; current_level < level; current_level++) {
420
421 // Print the frame
422 auto function = resolve_symbol(frame->rip);
423 Logger::ERROR() << "(" << current_level << "): " << (function ? function : "Unknown()") << " at 0x" << frame->rip << "\n";
424
425 // Next frame
426 frame = frame->next;
427 if (frame == nullptr)
428 break;
429
430 }
431}
432
439void CPU::PANIC(char const* message, cpu_status_t* status) {
440
441 // Ensure ready to panic - At this point it is not an issue if it is possible can avoid the panic as it is most
442 // likely called by a place that cant switch to the avoidable state
444 panic_lock.lock();
445
446 // Get the current process
448
449 // Print using the backend
450 Logger::ERROR() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n";
451 Logger::ERROR() << "Kernel Panic: " << message;
452 Logger::ERROR() << "On Core: " << (panic_core ? panic_core->id : 0) << "\n";
453
454 // Info about the running process
455 Logger::ERROR() << "Process: " << (process ? process->name.c_str() : "Kernel") << "\n";
456 if (process)
457 Logger::ERROR() << "After running for " << process->total_ticks() << " ticks (system uptime: " << GlobalScheduler::core_scheduler()->ticks() << " ticks)\n";
458
459 // Stack trace
460 Logger::ERROR() << "----------------------------\n";
461 Logger::ERROR() << "Stack Trace:\n";
462 stack_trace(10);
463
464 // Register dump
465 Logger::ERROR() << "----------------------------\n";
466 Logger::ERROR() << "Register Dump:\n";
467
468 // Log the regs
470 if (!status) {
472 status = &new_status;
473 }
474 print_registers(status);
475
476 // Print some text to the user
477 Logger::ERROR() << "----------------------------\n";
478 Logger::ERROR() << "There has been a fatal error in MaxOS and the system has been halted.\n";
479 Logger::ERROR() << "Please restart the system.\n";
480
481 // Print the logo
482 Logger::ERROR() << "----------------------------\n";
483
484 // Halt
485 halt();
486}
487
496 panic_lock.lock();
497
498 // If it may have occurred in a process, switch to the avoidable state
500
501 // Get the current process
503
504 // If the faulting address is in lower half just kill the process and move on
505 if (status && !memory::PhysicalMemoryManager::in_higher_region(status->rip)) {
506 Logger::ERROR() << "CPU Panicked (i " << (int)status->interrupt_number << ") in process " << process->name.c_str() << " at 0x" << status->rip << " - killing process\n";
507 Logger::ERROR() << msg;
508 panic_lock.unlock();
510 }
511
512 // Otherwise occurred whilst the kernel was doing something for the process
513 }
514
515 // We are panicking
518 panic_lock.unlock();
519 return nullptr;
520}
521
527void CPU::find_cores() const {
528
529 // Now that memory is set up the vector can be used
530 cores.reserve(1);
531
532 // Search and setup each core
533 int index = 0;
534 while (true){
535
536 // Try to find a processor
537 MADTEntry* processor_madt = apic.io_apic()->get_madt_item(MADT_TYPE::PROCESSOR_APIC, index);
538 if(!processor_madt)
539 break;
540
541 // Create a cpu
543 cores.push_back(new Core(processor_apic));
544 index++;
545 }
546}
547
552
553 Logger::INFO() << "Waking up cores: \n";
554
555 // Make sure core_start is accessible
556 ASSERT((void*)&core_start == (void*)0x8000, "Core start not at expected address");
558
559 // Set up the boot info
560 auto info = (core_boot_info_t*)(core_boot_info);
562
563 // Start each core
564 for(const auto& core : cores)
565 core->wake_up(this);
566}
567
568
576
577 // Get the CPUID
579 cpuid(0x1, &eax, &ebx, &ecx, &edx);
580
581 // Check the feature
582 return ecx & (uint32_t) feature;
583}
584
592
593 // Get the CPUID
595 cpuid(0x1, &eax, &ebx, &ecx, &edx);
596
597 // Check the feature
598 return edx & (uint32_t) feature;
599}
600
606
607 // Get the EFER MSR
608 uint64_t efer = read_msr(0xC0000080);
609
610 // Check if the NX flag is supported (bit 11)
611 bool supported = efer & (1 << 11);
612 Logger::DEBUG() << "NX: " << (supported ? "Supported" : "Not Supported") << "\n";
613
614 // Return if the NX flag is supported
615 return supported;
616}
617
624
625 // No cores?
626 if(cores.empty())
627 return nullptr;
628
629 // Get the id of this core
631 CPU::cpuid(1, &eax, &ebx, &ecx, &edx);
632 uint32_t core_id = (ebx >> 24) & 0xFF;
633
634 return cores[core_id];
635}
struct PACKED MaxOS::hardwarecommunication::MADT_PROCESSOR_APIC madt_processor_apic_t
Alias for MADT_PROCESSOR_APIC struct.
static Logger DEBUG()
Gets active logger set to DEBUG level.
Definition logger.cpp:193
static Logger WARNING()
Gets active logger set to WARNING level.
Definition logger.cpp:205
static Logger INFO()
Gets active logger set to info level.
Definition logger.cpp:171
static Logger ERROR()
Gets active logger set to ERROR level.
Definition logger.cpp:216
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
static Clock * active_clock()
Gets the currently active clock.
Definition clock.cpp:208
static void print_logo(bool is_panic=false)
Prints the logo to the center of the screen.
Definition vesaboot.cpp:250
MADTEntry * get_madt_item(MADT_TYPE type, uint8_t index)
Get an item in the MADT.
Definition apic.cpp:261
static void load_current()
Tell the processor to use the current InterruptManager.
Handles the local APIC for the current core.
Definition apic.h:24
static void * kmalloc(size_t size)
Allocates a block of memory in the KERNEL space.
static void * to_lower_region(uintptr_t virtual_address)
Converts a virtual address to a lower region address if it is in the higher region using the higher h...
Definition physical.cpp:899
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:185
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
Definition physical.cpp:961
static Scheduler * core_scheduler()
Gets the scheduler for the currently executing core.
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
Definition scheduler.cpp:50
static Process * current_process()
Gets the process on the currently executing core.
static system::cpu_status_t * force_remove_process(Process *process)
Removes a process from the scheduler and deletes all threads, begins running the next process.
A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address ...
Definition process.h:85
Manages the CPU and its cores.
Definition cpu.h:253
static void print_registers(cpu_status_t *status)
Prints the CPU registers from the provided structure.
Definition cpu.cpp:338
static void PANIC(const char *message, cpu_status_t *status=nullptr)
Puts the CPU into a panic state and halts it. Dumps the stack trace and registers.
Definition cpu.cpp:439
static void halt()
Halts the CPU indefinitely.
Definition cpu.cpp:276
CPU(GlobalDescriptorTable *gdt, Multiboot *multiboot)
Constructor for the CPU class.
Definition cpu.cpp:252
static void get_status(cpu_status_t *status)
Gets the current CPU status into the provided structure.
Definition cpu.cpp:287
void init_cores()
Wake up all the cores.
Definition cpu.cpp:551
static bool check_cpu_feature(CPU_FEATURE_ECX feature)
Checks if a CPU feature is supported (ECX Register)
Definition cpu.cpp:575
hardwarecommunication::AdvancedProgrammableInterruptController apic
The APIC interface for the CPU.
Definition cpu.h:261
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Executes the CPUID instruction with the specified leaf and returns the results in the provided pointe...
Definition cpu.cpp:403
static cpu_status_t * prepare_for_panic(cpu_status_t *status=nullptr, const string &msg="")
Ensure the CPU must panic and prepare for it if so.
Definition cpu.cpp:495
static void set_status(cpu_status_t *status)
Sets the CPU registers from the provided structure.
Definition cpu.cpp:312
void find_cores() const
Search the madt for cores and store them.
Definition cpu.cpp:527
static uint64_t read_msr(uint32_t msr)
Reads the value of the specified MSR.
Definition cpu.cpp:372
static common::Vector< Core * > cores
The list of CPU cores in the system (populated during initialization, includes the BSP and cores that...
Definition cpu.h:270
static Core * executing_core()
Gets the core that is currently executing.
Definition cpu.cpp:623
static void write_msr(uint32_t msr, uint64_t value)
Writes the specified value to the specified MSR.
Definition cpu.cpp:388
static Core * panic_core
The core that triggered the panic.
Definition cpu.h:263
static void stack_trace(size_t)
Prints a stack trace up to the specified level.
Definition cpu.cpp:414
static common::Spinlock panic_lock
Lock to prevent multiple panics at once.
Definition cpu.h:264
static bool check_nx()
Checks if the No Execute page flag is supported.
Definition cpu.cpp:605
Represents a CPU core in the system.
Definition cpu.h:213
void wake_up(CPU *cpu)
Wakes up the core by sending the appropriate IPIs. (see core_loader.s for startup code)
Definition cpu.cpp:59
void init_tss()
Initialises the task state segment for this core.
Definition cpu.cpp:110
uint64_t m_stack
The stack pointer for this core.
Definition cpu.h:225
bool m_bsp
Whether this core is the bootstrap processor.
Definition cpu.h:222
void init_sse()
Initialises the SSE instructions.
Definition cpu.cpp:167
GlobalDescriptorTable * gdt
The GDT for this core.
Definition cpu.h:245
Core(hardwarecommunication::madt_processor_apic_t *madt_item)
Constructs a new Core object from the MADT entry.
Definition cpu.cpp:37
void init()
Initialises the core by setting up the GDT, IDT, TSS, SSE and APIC.
Definition cpu.cpp:228
uint8_t id
The ID of this core.
Definition cpu.h:240
bool active
Whether this core is active.
Definition cpu.h:242
hardwarecommunication::LocalAPIC * local_apic
The local APIC for this core.
Definition cpu.h:244
uint8_t m_apic_id
The ID of the apic for this core.
Definition cpu.h:224
bool xsave_enabled
Whether XSAVE is enabled.
Definition cpu.h:234
bool m_enabled
Whether the core is enabled.
Definition cpu.h:220
bool avx_enabled
Whether AVX is enabled.
Definition cpu.h:235
bool m_can_enable
Whether the core can be enabled.
Definition cpu.h:221
hardwarecommunication::madt_processor_apic_t * m_madt
The MADT entry for this core.
Definition cpu.h:218
tss_t tss
The Task State Segment for this core.
Definition cpu.h:241
Sets up the GDT in the CPU.
Definition gdt.h:53
Parses and provides access to Multiboot 2 information.
Definition multiboot.h:518
Defines drivers for the Programmable Interval Timer (PIT) and APIC Clock.
void core_start()
The entry point for the core startup assembly code.
volatile PAGE_ALIGNED unsigned char p4_table[]
The PML4 table setup in loader.s.
uint8_t core_boot_info[]
The info passed between the bsp c++ and booting core assembly code.
Definition cpu.cpp:30
uint64_t stack[]
The stack setup for the core in loader.s.
Defines Central Processing Unit (CPU) structures and functions for managing CPU state and features.
constexpr size_t BOOT_STACK_SIZE
The size of the stack allocated for booting a core (should align with the startup assembly code for t...
Definition cpu.h:205
struct PACKED MaxOS::system::CPUStatus cpu_status_t
Alias for CPUStatus struct.
struct PACKED MaxOS::system::StackFrame stack_frame_t
Alias for StackFrame struct.
struct PACKED MaxOS::system::CoreBootInfo core_boot_info_t
Alias for CoreBootInfo struct.
CPU_FEATURE_ECX
CPU features indicated by the ECX register after calling CPUID with EAX = 1.
Definition cpu.h:100
CPU_FEATURE_EDX
CPU features indicated by the EDX register after calling CPUID with EAX = 1.
Definition cpu.h:140
uint8_t core_boot_info[]
The boot info structure for the core being started.
Definition kernel.cpp:43
Defines a Logger class for logging messages with different severity levels to multiple output streams...
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
Definition logger.h:100
Defines a MemoryManager class for handling memory allocation and deallocation.
volatile PAGE_ALIGNED unsigned char p4_table[]
The PML4 table setup in loader.s.
@ PRESENT
The page is present in memory.
Definition physical.h:43
@ WRITE
Memory in this page is writable.
Definition physical.h:44
Defines a GlobalScheduler and Scheduler for managing processes and threads.
class MaxOS::String string
Typedef for String.
An item in the MADT table.
Definition apic.h:68
const char * resolve_symbol(uintptr_t rip, uintptr_t link_base, uintptr_t load_base)
resolve an instruction pointer (rip) to a symbol name and optional offset.
Definition symbols.cpp:23
Defines the VESABootConsole driver for handling console output during boot using an VESA framebuffer.