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>
12#include <console/framebuffer.h>
15#include <common/symbols.h>
16
17using namespace MaxOS;
18using namespace MaxOS::system;
19using namespace MaxOS::common;
20using namespace MaxOS::console;
21using namespace MaxOS::hardwarecommunication;
22using namespace MaxOS::processes;
23using namespace MaxOS::memory;
24
25extern uint64_t stack[];
26volatile extern PAGE_ALIGNED unsigned char p4_table[];
27
28extern "C" void core_start();
29extern "C" uint8_t core_boot_info[];
30
37: m_madt(madt_item)
38{
39
40 id = m_madt->processor_id;
41 m_apic_id = m_madt->apic_id;
42
43 m_enabled = (m_madt->flags & 0x1) != 0;
44 m_can_enable = (m_madt->flags & 0x2) != 0;
45
47
48 Logger::DEBUG() << "Found CPU ID: " << id << " with APIC ID: " << m_apic_id << " (enabled = " << (string)m_enabled << ", can be enabled = " << (string)m_can_enable << ")\n";
49
50}
51
52Core::~Core() = default;
53
60void Core::wake_up(CPU* cpu) {
61
62 // Boot core is already setup
63 if(m_bsp){
64 Logger::DEBUG() << "BSP Already setup\n";
65 return;
66 }
67
68 Logger::DEBUG() << "Starting core: " << id << "\n";
69
70 // Core specific boot info
71 volatile 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);
82
83 // Send tow SIPIs
84 for (int i = 0; i < 2; ++i) {
85
86 // Send the start up IPI
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
109
110 // The reserved have to be 0
111 tss.reserved0 = 0;
112 tss.reserved1 = 0;
113 tss.reserved2 = 0;
114 tss.reserved3 = 0;
115
116 // Kernel stack (scheduler will set the threads stack)
117 tss.rsp0 = (uint64_t)m_stack + BOOT_STACK_SIZE;
118 tss.rsp1 = 0;
119 tss.rsp2 = 0;
120
121 // Interrupt stacks can all be 0 (@todo implment)
122 tss.ist1 = 0;
123 tss.ist2 = 0;
124 tss.ist3 = 0;
125 tss.ist4 = 0;
126 tss.ist5 = 0;
127 tss.ist6 = 0;
128 tss.ist7 = 0;
129
130 // All ports denied by default
131 memset(&tss.io_bitmap, 0xFF, sizeof(tss.io_bitmap));
132 tss.io_bitmap[IO_BITMAP_SIZE] = 0xFF;
133 tss.io_bitmap_offset = offsetof(tss_t, io_bitmap);
134
135 // Split the base into 4 parts (16 bits, 8 bits, 8 bits, 32 bits)
136 auto base = (uint64_t) &tss;
137 uint16_t base_1 = base & 0xFFFF;
138 uint8_t base_2 = (base >> 16) & 0xFF;
139 uint8_t base_3 = (base >> 24) & 0xFF;
140 uint32_t base_4 = (base >> 32) & 0xFFFFFFFF;
141
142 auto limit_low = (uint16_t)(sizeof(tss) - 1);
143
144 // Flags: 1 - Type = 0x9, Descriptor Privilege Level = 0, Present = 1, 2 - Available = 0, Granularity = 0
145 uint8_t flags_1 = 0x89;
146 uint8_t flags_2 = 0;
147
148 // Create the TSS descriptors
149 uint64_t tss_descriptor_low = (uint64_t) base_3 << 56 | (uint64_t) flags_2 << 48 | (uint64_t) flags_1 << 40 | (uint64_t) base_2 << 32 | (uint64_t) base_1 << 16 | (uint64_t) limit_low;
150 uint64_t tss_descriptor_high = base_4;
151
152 // Store in the GDT
153 gdt -> table[5] = tss_descriptor_low;
154 gdt -> table[6] = tss_descriptor_high;
155 gdt -> load();
156
157 // Load the TSS
158 Logger::DEBUG() << "Loading TSS: 0x0" << tss_descriptor_low << " 0x0" << tss_descriptor_high << " at 0x" << (uint64_t) &tss << "\n";
159 asm volatile("ltr %%ax" : : "a" (0x28));
160
161}
162
167
168 // Get the CR0 register
169 uint64_t cr0;
170 asm volatile("mov %%cr0, %0" : "=r" (cr0));
171
172 // Get the CR4 register
173 uint64_t cr4;
174 asm volatile("mov %%cr4, %0" : "=r" (cr4));
175
176 // Check if FPU is supported
177 ASSERT(CPU::check_cpu_feature(CPU_FEATURE_EDX::FPU), "FPU not supported - needed for SSE");
178
179 // Clear the emulation flag, task switch flags and enable the monitor coprocessor, native exception bits
180 cr0 |= (1 << 1);
181 cr0 &= ~(1 << 2);
182 cr0 &= ~(1 << 3);
183 cr0 |= (1 << 5);
184 asm volatile("mov %0, %%cr0" : : "r" (cr0));
185
186 // Enable the FPU
187 asm volatile("fninit");
188
189 // Check if SSE is supported
190 ASSERT(CPU::check_cpu_feature(CPU_FEATURE_EDX::SSE), "SSE not supported");
191
192 // Enable FSAVE, FSTORE and SSE instructions
193 cr4 |= (1 << 9);
194 cr4 |= (1 << 10);
195 asm volatile("mov %0, %%cr4" : : "r" (cr4));
196
197 // Check if XSAVE is supported
198 xsave_enabled = CPU::check_cpu_feature(CPU_FEATURE_ECX::XSAVE) && CPU::check_cpu_feature(CPU_FEATURE_ECX::OSXSAVE);
199 Logger::DEBUG() << "XSAVE: " << (xsave_enabled ? "Supported" : "Not Supported") << "\n";
200 if (!xsave_enabled) return;
201
202 // Enable the XSAVE and XRESTORE instructions
203 cr4 |= (1 << 18);
204 asm volatile("mov %0, %%cr4" : : "r" (cr4));
205
206 // Set the SSE and x87 bits
207 uint64_t xcr0;
208 asm volatile("xgetbv" : "=a" (xcr0) : "c" (0));
209 xcr0 |= 0x7;
210 asm volatile("xsetbv" : : "c" (0), "a" (xcr0));
211
212 // Check if AVX is supported
213 avx_enabled = CPU::check_cpu_feature(CPU_FEATURE_ECX::AVX);
214 Logger::DEBUG() << "AVX: " << (avx_enabled ? "Supported" : "Not Supported") << "\n";
215 if (!avx_enabled) return;
216
217 // Enable the AVX instructions
218 cr4 |= (1 << 14);
219 asm volatile("mov %0, %%cr4" : : "r" (cr4));
220
221 Logger::DEBUG() << "SSE Enabled\n";
222}
223
228
229 // Load the kernel IDT & GDT
232
233 // Setup this core's clock
234 local_apic = new LocalAPIC;
236
237 // Delegate large initiation
238 init_sse();
239 init_tss();
240
241 active = true;
242}
243
244
252: acpi(multiboot),
253 apic(&acpi)
254{
255
256 Logger::INFO() << "Setting up CPU \n";
257 find_cores();
258
259 // Manually set up the BSP
260 auto bsp = cores[0];
261 bsp -> m_bsp = true;
262 bsp -> active = true;
263 bsp -> gdt = gdt;
264 bsp -> local_apic = apic.local_apic();
265 bsp -> init_tss();
266 bsp -> init_sse();
267
268}
269
270CPU::~CPU() = default;
271
275[[noreturn]] void CPU::halt() {
276
277 while (true)
278 asm volatile("hlt");
279}
280
287
288 // Get the registers
289 asm volatile("mov %%r15, %0" : "=r" (status->r15));
290 asm volatile("mov %%r14, %0" : "=r" (status->r14));
291 asm volatile("mov %%r13, %0" : "=r" (status->r13));
292 asm volatile("mov %%r12, %0" : "=r" (status->r12));
293 asm volatile("mov %%r11, %0" : "=r" (status->r11));
294 asm volatile("mov %%r10, %0" : "=r" (status->r10));
295 asm volatile("mov %%r9, %0" : "=r" (status->r9));
296 asm volatile("mov %%r8, %0" : "=r" (status->r8));
297 asm volatile("mov %%rdi, %0" : "=r" (status->rdi));
298 asm volatile("mov %%rsi, %0" : "=r" (status->rsi));
299 asm volatile("mov %%rbp, %0" : "=r" (status->rbp));
300 asm volatile("mov %%rdx, %0" : "=r" (status->rdx));
301 asm volatile("mov %%rcx, %0" : "=r" (status->rcx));
302 asm volatile("mov %%rbx, %0" : "=r" (status->rbx));
303 asm volatile("mov %%rax, %0" : "=r" (status->rax));
304}
305
312
313 // Set the registers
314 asm volatile("mov %0, %%r15" : : "r" (status->r15));
315 asm volatile("mov %0, %%r14" : : "r" (status->r14));
316 asm volatile("mov %0, %%r13" : : "r" (status->r13));
317 asm volatile("mov %0, %%r12" : : "r" (status->r12));
318 asm volatile("mov %0, %%r11" : : "r" (status->r11));
319 asm volatile("mov %0, %%r10" : : "r" (status->r10));
320 asm volatile("mov %0, %%r9" : : "r" (status->r9));
321 asm volatile("mov %0, %%r8" : : "r" (status->r8));
322 asm volatile("mov %0, %%rdi" : : "r" (status->rdi));
323 asm volatile("mov %0, %%rsi" : : "r" (status->rsi));
324 asm volatile("mov %0, %%rbp" : : "r" (status->rbp));
325 asm volatile("mov %0, %%rdx" : : "r" (status->rdx));
326 asm volatile("mov %0, %%rcx" : : "r" (status->rcx));
327 asm volatile("mov %0, %%rbx" : : "r" (status->rbx));
328 asm volatile("mov %0, %%rax" : : "r" (status->rax));
329
330}
331
338
339 // Print the registers
340 Logger::ERROR() << "R15: \t0x" << status->r15 << "\n";
341 Logger::ERROR() << "R14: \t0x" << status->r14 << "\n";
342 Logger::ERROR() << "R13: \t0x" << status->r13 << "\n";
343 Logger::ERROR() << "R12: \t0x" << status->r12 << "\n";
344 Logger::ERROR() << "R11: \t0x" << status->r11 << "\n";
345 Logger::ERROR() << "R10: \t0x" << status->r10 << "\n";
346 Logger::ERROR() << "R9: \t0x" << status->r9 << "\n";
347 Logger::ERROR() << "R8: \t0x" << status->r8 << "\n";
348 Logger::ERROR() << "RDI: \t0x" << status->rdi << "\n";
349 Logger::ERROR() << "RSI: \t0x" << status->rsi << "\n";
350 Logger::ERROR() << "RBP: \t0x" << status->rbp << "\n";
351 Logger::ERROR() << "RDX: \t0x" << status->rdx << "\n";
352 Logger::ERROR() << "RCX: \t0x" << status->rcx << "\n";
353 Logger::ERROR() << "RBX: \t0x" << status->rbx << "\n";
354 Logger::ERROR() << "RAX: \t0x" << status->rax << "\n";
355 Logger::ERROR() << "INT: \t0x" << status->interrupt_number << "\n";
356 Logger::ERROR() << "ERRCD: \t0x" << status->error_code << "\n";
357 Logger::ERROR() << "RIP: \t0x" << status->rip << "\n";
358 Logger::ERROR() << "CS: \t0x" << status->cs << "\n";
359 Logger::ERROR() << "RFlGS: \t0x" << status->rflags << "\n";
360 Logger::ERROR() << "RSP: \t0x" << status->rsp << "\n";
361 Logger::ERROR() << "SS: \t0x" << status->ss << "\n";
362
363}
364
371uint64_t CPU::read_msr(uint32_t msr) {
372
373 // Read the MSR
374 uint32_t low, high;
375 asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
376
377 // Return the value
378 return (uint64_t) low | ((uint64_t) high << 32);
379}
380
387void CPU::write_msr(uint32_t msr, uint64_t value) {
388
389 // Write the MSR
390 asm volatile("wrmsr" : : "a" ((uint32_t) value), "d" ((uint32_t) (value >> 32)), "c" (msr));
391}
392
402void CPU::cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
403
404 // Call the cpuid instruction
405 __get_cpuid(leaf, eax, ebx, ecx, edx);
406}
407
414void CPU::stack_trace(size_t level, cpu_status_t* status) {
415
416 auto* frame = status ? (stack_frame_t*)status->rbp : (stack_frame_t*) __builtin_frame_address(0);
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
433void CPU::enable_write_protect() {
434
435 // Read the current state
436 uint64_t cr0;
437 asm volatile("mov %%cr0, %0" : "=r"(cr0));
438
439 // Update to have WP bit enabled
440 cr0 |= (1ULL << 16);
441 asm volatile("mov %0, %%cr0" : : "r"(cr0));
442
443}
444
445void CPU::disable_write_protect() {
446
447 // Read the current state
448 uint64_t cr0;
449 asm volatile("mov %%cr0, %0" : "=r"(cr0));
450
451 // Update to have WP bit disabled
452 cr0 &= ~(1ULL << 16);
453 asm volatile("mov %0, %%cr0" : : "r"(cr0));
454
455}
456
463void CPU::PANIC(char const* message, cpu_status_t* status) {
464
465 // Ensure ready to panic - At this point it is not an issue if it is possible can avoid the panic as it is most
466 // likely called by a place that cant switch to the avoidable state
468 panic_lock.lock();
469
470 // Get the current process
472
473 // Print using the backend
474 Logger::Out() << "\n";
475 Logger::ERROR() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n";
476 Logger::ERROR() << "Kernel Panic: " << message;
477 Logger::ERROR() << "On Core: " << (panic_core ? panic_core->id : 0) << "\n";
478
479 // Info about the running process
480 Logger::ERROR() << "Process: " << (process ? process->name.c_str() : "Kernel") << "\n";
481 if (process)
482 Logger::ERROR() << "After running for " << process->total_ticks() << " ticks (system uptime: " << GlobalScheduler::core_scheduler()->ticks() << " ticks)\n";
483
484 // Stack trace
485 Logger::ERROR() << "----------------------------\n";
486 Logger::ERROR() << "Stack Trace:\n";
487 stack_trace(20, status);
488
489 // Register dump
490 Logger::ERROR() << "----------------------------\n";
491 Logger::ERROR() << "Register Dump:\n";
492
493 // Log the regs
494 cpu_status_t new_status{};
495 if (!status) {
496 get_status(&new_status);
497 status = &new_status;
498 }
499 print_registers(status);
500
501 // Print some text to the user
502 Logger::ERROR() << "----------------------------\n";
503 Logger::ERROR() << "There has been a fatal error in MaxOS and the system has been halted.\n";
504 Logger::ERROR() << "Please check the logs for more info.\n"; // TODO: save to a file
505 Logger::ERROR() << "Please restart the system.\n";
506
507 // Print the logo
508 Logger::ERROR() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n";
509
510 // Halt
511 halt();
512}
513
522 panic_lock.lock();
523
524 // If it may have occurred in a process, switch to the avoidable state
526
527 // Get the current process
529
530 // If the faulting address is in lower half just kill the process and move on
531 if (status && !memory::PhysicalMemoryManager::in_higher_region(status->rip)) {
532 Logger::Out() << "\n";
533 Logger::ERROR() << msg;
534 Logger::ERROR() << "CPU Panicked (i " << (int)status->interrupt_number << ") in process " << process->name.c_str() << " at 0x" << status->rip << " - killing process\n";
535 panic_lock.unlock();
537 }
538
539 // Otherwise occurred whilst the kernel was doing something for the process, thus a fault in the kernel fault
540 // and is unrecoverable
541 }
542
543 // Kill the others to make sure everything else stops
545 executing_core()->local_apic->send_interrupt(0, 0x81, EXCLUDE_SELF);
547 }
548
549 // Prepare for printing debug messages
551 Logger::active_logger() -> enable_all_log_writers();
552
553 // Unresumable state
554 panic_lock.unlock();
556 return nullptr;
557}
558
564void CPU::find_cores() const {
565
566 // Now that memory is set up the vector can be used
567 cores.reserve(1);
568
569 // Search and setup each core
570 int index = 0;
571 while (true){
572
573 // Try to find a processor
574 MADTEntry* processor_madt = apic.io_apic()->get_madt_item(MADT_TYPE::PROCESSOR_APIC, index);
575 if(!processor_madt)
576 break;
577
578 // Create a cpu
579 auto* processor_apic = (madt_processor_apic_t*) ((uint64_t) processor_madt + sizeof(MADTEntry));
580 cores.push_back(new Core(processor_apic));
581 index++;
582 }
583}
584
589
590 Logger::INFO() << "Waking up cores: \n";
591
592 // Make sure core_start is accessible
593 ASSERT((void*)&core_start == (void*)0x8000, "Core start not at expected address");
595
596 // Set up the boot info
597 auto info = (core_boot_info_t*)(core_boot_info);
598 info->p4_table = (uint64_t)PhysicalMemoryManager::to_lower_region((uintptr_t)p4_table);
599
600 // Start each core
601 for(const auto& core : cores)
602 core->wake_up(this);
603}
604
605
613
614 // Get the CPUID
615 uint32_t eax, ebx, ecx, edx;
616 cpuid(0x1, &eax, &ebx, &ecx, &edx);
617
618 // Check the feature
619 return ecx & (uint32_t) feature;
620}
621
629
630 // Get the CPUID
631 uint32_t eax, ebx, ecx, edx;
632 cpuid(0x1, &eax, &ebx, &ecx, &edx);
633
634 // Check the feature
635 return edx & (uint32_t) feature;
636}
637
643
644 // Get the EFER MSR
645 uint64_t efer = read_msr(0xC0000080);
646
647 // Check if the NX flag is supported (bit 11)
648 bool supported = efer & (1 << 11);
649 Logger::DEBUG() << "NX: " << (supported ? "Supported" : "Not Supported") << "\n";
650
651 // Return if the NX flag is supported
652 return supported;
653}
654
661
662 // No cores?
663 if(cores.empty())
664 return nullptr;
665
666 // Get the id of this core
667 uint32_t eax, ebx, ecx, edx;
668 CPU::cpuid(1, &eax, &ebx, &ecx, &edx);
669 uint32_t core_id = (ebx >> 24) & 0xFF;
670
671 return cores[core_id];
672}
struct PACKED MaxOS::hardwarecommunication::MADT_PROCESSOR_APIC madt_processor_apic_t
Alias for MADT_PROCESSOR_APIC struct.
static LogRecord ERROR()
Gets the active logger for error logs.
Definition logger.cpp:222
static Logger * active_logger()
Gets the active logger (to be used to modify the logger)
Definition logger.cpp:240
static LogRecord DEBUG()
Gets the active logger for debug logs.
Definition logger.cpp:204
static LogRecord INFO()
Gets the active logger for info logs.
Definition logger.cpp:195
static LogRecord WARNING()
Gets the active logger for warnings.
Definition logger.cpp:213
static LogRecord Out()
Gets the active logger.
Definition logger.cpp:176
static void print_logo(bool is_panic=false)
Prints the logo to the center of the screen.
void setup_apic_clock(LocalAPIC *local_apic) const
Sets up the APIC clock to fire interrupts at the desired rate.
Definition clock.cpp:137
void delay(uint32_t milliseconds) const
Delays the program for a specified number of milliseconds (rounded up to the nearest degree of accura...
Definition clock.cpp:102
static Clock * active_clock()
Gets the currently active clock.
Definition clock.cpp:182
MADTEntry * get_madt_item(MADT_TYPE type, uint8_t index)
Get an item in the MADT.
Definition apic.cpp:308
static void load_current()
Tell the processor to use the current InterruptManager.
Handles the local APIC for the current core.
Definition apic.h:34
void send_startup(uint8_t apic_id, uint8_t vector) const
Send the start up IPI to another apic.
Definition apic.cpp:190
void send_interrupt(uint8_t apic_id, uint8_t vector, size_t flags) const
Send an interrupt to a specific core.
Definition apic.cpp:213
void send_init(uint8_t apic_id, bool assert) const
send the init IPI to another apic
Definition apic.cpp:165
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:898
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:183
void identity_map(physical_address_t *physical_address, size_t flags)
Maps a physical address to its virtual address counter-part.
Definition physical.cpp:579
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
Definition physical.cpp:960
static Scheduler * core_scheduler()
Gets the scheduler for the currently executing core.
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
Definition scheduler.cpp:55
static Process * current_process()
Gets the process on the currently executing core.
static void deactivate()
Deactivates each core's scheduler.
static bool is_active()
Checks if the global scheduler is active.
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:94
uint64_t total_ticks()
Gets the total ticks of the threads in the process (not this does not include any past killed threads...
Definition process.cpp:439
string name
The name of the process.
Definition process.h:118
uint64_t ticks() const
Gets how long the system has been running for.
Manages the CPU and its cores.
Definition cpu.h:256
static void print_registers(cpu_status_t *status)
Prints the CPU registers from the provided structure.
Definition cpu.cpp:337
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:463
static void halt()
Halts the CPU indefinitely.
Definition cpu.cpp:275
CPU(GlobalDescriptorTable *gdt, Multiboot *multiboot)
Constructor for the CPU class.
Definition cpu.cpp:251
static void get_status(cpu_status_t *status)
Gets the current CPU status into the provided structure.
Definition cpu.cpp:286
void init_cores()
Wake up all the cores.
Definition cpu.cpp:588
static bool check_cpu_feature(CPU_FEATURE_ECX feature)
Checks if a CPU feature is supported (ECX Register)
Definition cpu.cpp:612
hardwarecommunication::AdvancedProgrammableInterruptController apic
The APIC interface for the CPU.
Definition cpu.h:264
static void stack_trace(size_t, cpu_status_t *status=nullptr)
Prints a stack trace up to the specified level.
Definition cpu.cpp:414
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:402
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:521
static void set_status(cpu_status_t *status)
Sets the CPU registers from the provided structure.
Definition cpu.cpp:311
void find_cores() const
Search the madt for cores and store them.
Definition cpu.cpp:564
static uint64_t read_msr(uint32_t msr)
Reads the value of the specified MSR.
Definition cpu.cpp:371
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:273
static Core * executing_core()
Gets the core that is currently executing.
Definition cpu.cpp:660
static void write_msr(uint32_t msr, uint64_t value)
Writes the specified value to the specified MSR.
Definition cpu.cpp:387
static Core * panic_core
The core that triggered the panic.
Definition cpu.h:266
static common::Spinlock panic_lock
Lock to prevent multiple panics at once.
Definition cpu.h:267
static bool check_nx()
Checks if the No Execute page flag is supported.
Definition cpu.cpp:642
Represents a CPU core in the system.
Definition cpu.h:216
void wake_up(CPU *cpu)
Wakes up the core by sending the appropriate IPIs. (see core_loader.s for startup code)
Definition cpu.cpp:60
void init_tss()
Initialises the task state segment for this cor.
Definition cpu.cpp:108
uint64_t m_stack
The stack pointer for this core.
Definition cpu.h:228
bool m_bsp
Whether this core is the bootstrap processor.
Definition cpu.h:225
void init_sse()
Initialises the SSE instructions.
Definition cpu.cpp:166
GlobalDescriptorTable * gdt
The GDT for this core.
Definition cpu.h:248
Core(hardwarecommunication::madt_processor_apic_t *madt_item)
Constructs a new Core object from the MADT entry.
Definition cpu.cpp:36
void init()
Initialises the core by setting up the GDT, IDT, TSS, SSE and APIC.
Definition cpu.cpp:227
uint8_t id
The ID of this core.
Definition cpu.h:243
bool active
Whether this core is active.
Definition cpu.h:245
hardwarecommunication::LocalAPIC * local_apic
The local APIC for this core.
Definition cpu.h:247
uint8_t m_apic_id
The ID of the apic for this core.
Definition cpu.h:227
bool xsave_enabled
Whether XSAVE is enabled.
Definition cpu.h:237
bool m_enabled
Whether the core is enabled.
Definition cpu.h:223
bool avx_enabled
Whether AVX is enabled.
Definition cpu.h:238
bool m_can_enable
Whether the core can be enabled.
Definition cpu.h:224
hardwarecommunication::madt_processor_apic_t * m_madt
The MADT entry for this core.
Definition cpu.h:221
tss_t tss
The Task State Segment for this core.
Definition cpu.h:244
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:29
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 IO_BITMAP_SIZE
The size of the IO bitmap to track 65536 ports.
Definition cpu.h:67
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:208
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:103
CPU_FEATURE_EDX
CPU features indicated by the EDX register after calling CPUID with EAX = 1.
Definition cpu.h:143
struct PACKED MaxOS::system::TaskStateSegment tss_t
Alias for TaskStateSegment struct.
Defines the VESABootConsole driver for handling console output during boot using an VESA framebuffer.
uint8_t core_boot_info[]
The boot info structure for the core being started.
Definition kernel.cpp:31
Defines a Logger class for logging messages with different severity levels to multiple output streams...
Defines a MemoryManager class for handling memory allocation and deallocation.
volatile PAGE_ALIGNED unsigned char p4_table[]
The PML4 table setup in loader.s.
void physical_address_t
A type representing a physical address (used for readability)
Definition physical.h:31
@ PRESENT
The page is present in memory.
Definition physical.h:44
@ WRITE
Memory in this page is writable.
Definition physical.h:45
Defines a GlobalScheduler and Scheduler for managing processes and threads.
An item in the MADT table.
Definition apic.h:80
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