Max OS 0.3
Loading...
Searching...
No Matches
MaxOS::system::CPU Class Reference

Manages the CPU and its cores. More...

#include <cpu.h>

Public Member Functions

 CPU (GlobalDescriptorTable *gdt, Multiboot *multiboot)
 Constructor for the CPU class.
 
void find_cores () const
 Search the madt for cores and store them.
 
void init_cores ()
 Wake up all the cores.
 

Static Public Member Functions

static cpu_status_tprepare_for_panic (cpu_status_t *status=nullptr, const string &msg="")
 Ensure the CPU must panic and prepare for it if so.
 
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.
 
static void halt ()
 Halts the CPU indefinitely.
 
static Coreexecuting_core ()
 Gets the core that is currently executing.
 
static bool check_nx ()
 Checks if the No Execute page flag is supported.
 
static void get_status (cpu_status_t *status)
 Gets the current CPU status into the provided structure.
 
static void set_status (cpu_status_t *status)
 Sets the CPU registers from the provided structure.
 
static void print_registers (cpu_status_t *status)
 Prints the CPU registers from the provided structure.
 
static uint64_t read_msr (uint32_t msr)
 Reads the value of the specified MSR.
 
static void write_msr (uint32_t msr, uint64_t value)
 Writes the specified value to the specified MSR.
 
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 pointers.
 
static bool check_cpu_feature (CPU_FEATURE_ECX feature)
 Checks if a CPU feature is supported (ECX Register)
 
static bool check_cpu_feature (CPU_FEATURE_EDX feature)
 Checks if a CPU feature is supported (EDX Register)
 
static void stack_trace (size_t)
 Prints a stack trace up to the specified level.
 

Public Attributes

hardwarecommunication::AdvancedConfigurationAndPowerInterface acpi
 The ACPI interface for the CPU.
 
hardwarecommunication::AdvancedProgrammableInterruptController apic
 The APIC interface for the CPU.
 

Static Public Attributes

static Corepanic_core = nullptr
 The core that triggered the panic.
 
static common::Spinlock panic_lock
 Lock to prevent multiple panics at once.
 
static common::Vector< Core * > cores
 The list of CPU cores in the system (populated during initialization, includes the BSP and cores that failed to start)
 

Detailed Description

Manages the CPU and its cores.

Definition at line 253 of file cpu.h.

Constructor & Destructor Documentation

◆ CPU()

CPU::CPU ( GlobalDescriptorTable gdt,
Multiboot multiboot 
)

Constructor for the CPU class.

Parameters
gdtThe global descriptor table
multibootThe multiboot information struct

Definition at line 252 of file cpu.cpp.

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}
static Logger INFO()
Gets active logger set to info level.
Definition logger.cpp:171
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
hardwarecommunication::AdvancedConfigurationAndPowerInterface acpi
The ACPI interface for the CPU.
Definition cpu.h:260
hardwarecommunication::AdvancedProgrammableInterruptController apic
The APIC interface for the CPU.
Definition cpu.h:261
void find_cores() const
Search the madt for cores and store them.
Definition cpu.cpp:527
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

References apic, cores, find_cores(), MaxOS::Logger::INFO(), and MaxOS::hardwarecommunication::AdvancedProgrammableInterruptController::local_apic().

Member Function Documentation

◆ check_cpu_feature() [1/2]

bool CPU::check_cpu_feature ( CPU_FEATURE_ECX  feature)
static

Checks if a CPU feature is supported (ECX Register)

Parameters
featureThe feature to check
Returns
If the feature is supported

Definition at line 575 of file cpu.cpp.

575 {
576
577 // Get the CPUID
579 cpuid(0x1, &eax, &ebx, &ecx, &edx);
580
581 // Check the feature
582 return ecx & (uint32_t) feature;
583}
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

References cpuid().

Referenced by MaxOS::system::Core::init_sse().

◆ check_cpu_feature() [2/2]

bool CPU::check_cpu_feature ( CPU_FEATURE_EDX  feature)
static

Checks if a CPU feature is supported (EDX Register)

Parameters
featureThe feature to check
Returns
True if the feature is supported

Definition at line 591 of file cpu.cpp.

591 {
592
593 // Get the CPUID
595 cpuid(0x1, &eax, &ebx, &ecx, &edx);
596
597 // Check the feature
598 return edx & (uint32_t) feature;
599}

References cpuid().

◆ check_nx()

bool CPU::check_nx ( )
static

Checks if the No Execute page flag is supported.

Returns
True if the NX flag is supported

Definition at line 605 of file cpu.cpp.

605 {
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}
static Logger DEBUG()
Gets active logger set to DEBUG level.
Definition logger.cpp:193
static uint64_t read_msr(uint32_t msr)
Reads the value of the specified MSR.
Definition cpu.cpp:372

References MaxOS::Logger::DEBUG(), and read_msr().

Referenced by MaxOS::memory::PhysicalMemoryManager::PhysicalMemoryManager().

◆ cpuid()

void CPU::cpuid ( uint32_t  leaf,
uint32_t eax,
uint32_t ebx,
uint32_t ecx,
uint32_t edx 
)
static

Executes the CPUID instruction with the specified leaf and returns the results in the provided pointers.

Parameters
leafThe CPUID leaf to query
eaxThe pointer to store the EAX result
ebxThe pointer to store the EBX result
ecxThe pointer to store the ECX result
edxThe pointer to store the EDX result

Definition at line 403 of file cpu.cpp.

403 {
404
405 // Call the cpuid instruction
407}

Referenced by check_cpu_feature(), check_cpu_feature(), executing_core(), and MaxOS::hardwarecommunication::LocalAPIC::LocalAPIC().

◆ executing_core()

Core * CPU::executing_core ( )
static

Gets the core that is currently executing.

Returns
The currently executing core

Definition at line 623 of file cpu.cpp.

623 {
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}

References cores, and cpuid().

Referenced by core_main(), MaxOS::processes::GlobalScheduler::core_scheduler(), MaxOS::hardwarecommunication::InterruptManager::handle_interrupt_request(), prepare_for_panic(), MaxOS::processes::GlobalScheduler::print_running_header(), MaxOS::processes::Thread::restore_sse_state(), MaxOS::processes::Thread::save_sse_state(), and MaxOS::processes::Thread::Thread().

◆ find_cores()

void CPU::find_cores ( ) const

Search the madt for cores and store them.

Todo:
Support for x2apic

Definition at line 527 of file cpu.cpp.

527 {
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}
struct PACKED MaxOS::hardwarecommunication::MADT_PROCESSOR_APIC madt_processor_apic_t
Alias for MADT_PROCESSOR_APIC struct.
MADTEntry * get_madt_item(MADT_TYPE type, uint8_t index)
Get an item in the MADT.
Definition apic.cpp:261
Represents a CPU core in the system.
Definition cpu.h:213
An item in the MADT table.
Definition apic.h:68

References apic, cores, MaxOS::hardwarecommunication::IOAPIC::get_madt_item(), and MaxOS::hardwarecommunication::AdvancedProgrammableInterruptController::io_apic().

Referenced by CPU().

◆ get_status()

void CPU::get_status ( cpu_status_t status)
static

Gets the current CPU status into the provided structure.

Parameters
statusThe structure to fill with the CPU status

Definition at line 287 of file cpu.cpp.

287 {
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}

Referenced by PANIC().

◆ halt()

void CPU::halt ( )
static

Halts the CPU indefinitely.

Definition at line 276 of file cpu.cpp.

276 {
277
278 while (true)
279 asm volatile("hlt");
280}

Referenced by PANIC().

◆ init_cores()

void CPU::init_cores ( )

Wake up all the cores.

Definition at line 551 of file cpu.cpp.

551 {
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");
557 PhysicalMemoryManager::s_current_manager->identity_map((physical_address_t*)0x8000, PRESENT | WRITE);
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}
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
void core_start()
The entry point for the core startup assembly code.
struct PACKED MaxOS::system::CoreBootInfo core_boot_info_t
Alias for CoreBootInfo struct.
uint8_t core_boot_info[]
The boot info structure for the core being started.
Definition kernel.cpp:43
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
Definition logger.h:100
volatile PAGE_ALIGNED unsigned char p4_table[]
The PML4 table setup in loader.s.

References ASSERT, core_boot_info, core_start(), cores, MaxOS::Logger::INFO(), p4_table, MaxOS::memory::PRESENT, MaxOS::memory::PhysicalMemoryManager::s_current_manager, MaxOS::memory::PhysicalMemoryManager::to_lower_region(), and MaxOS::memory::WRITE.

◆ PANIC()

void CPU::PANIC ( const char message,
cpu_status_t status = nullptr 
)
static

Puts the CPU into a panic state and halts it. Dumps the stack trace and registers.

Parameters
messageThe panic message
statusThe CPU status at the time of the panic (if available, otherwise will be fetched)

Definition at line 439 of file cpu.cpp.

439 {
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}
static Logger ERROR()
Gets active logger set to ERROR level.
Definition logger.cpp:216
static Scheduler * core_scheduler()
Gets the scheduler for the currently executing core.
static Process * current_process()
Gets the process on the currently executing core.
A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address ...
Definition process.h:85
static void print_registers(cpu_status_t *status)
Prints the CPU registers from the provided structure.
Definition cpu.cpp:338
static void halt()
Halts the CPU indefinitely.
Definition cpu.cpp:276
static void get_status(cpu_status_t *status)
Gets the current CPU status into the provided structure.
Definition cpu.cpp:287
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 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
struct PACKED MaxOS::system::CPUStatus cpu_status_t
Alias for CPUStatus struct.

References MaxOS::processes::GlobalScheduler::core_scheduler(), MaxOS::processes::GlobalScheduler::current_process(), MaxOS::Logger::ERROR(), get_status(), halt(), panic_core, panic_lock, prepare_for_panic(), print_registers(), and stack_trace().

Referenced by MaxOS::Logger::ASSERT(), and MaxOS::hardwarecommunication::InterruptManager::HandleInterrupt().

◆ prepare_for_panic()

cpu_status_t * CPU::prepare_for_panic ( cpu_status_t status = nullptr,
const string msg = "" 
)
static

Ensure the CPU must panic and prepare for it if so.

Parameters
statusThe status of the CPU (if available)
msgThe message to print to diagnose the cause of the panic (prints when close program)
Returns
A CPU status to avoid having to panic or a nullptr if the CPU must panic

Definition at line 495 of file cpu.cpp.

495 {
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}
static void print_logo(bool is_panic=false)
Prints the logo to the center of the screen.
Definition vesaboot.cpp:250
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
Definition physical.cpp:961
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
Definition scheduler.cpp:50
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.
static Core * executing_core()
Gets the core that is currently executing.
Definition cpu.cpp:623

References MaxOS::processes::GlobalScheduler::current_process(), MaxOS::Logger::ERROR(), executing_core(), MaxOS::processes::GlobalScheduler::force_remove_process(), MaxOS::memory::PhysicalMemoryManager::in_higher_region(), panic_core, panic_lock, MaxOS::drivers::console::VESABootConsole::print_logo(), and MaxOS::processes::GlobalScheduler::system_scheduler().

Referenced by PANIC().

◆ print_registers()

void CPU::print_registers ( cpu_status_t status)
static

Prints the CPU registers from the provided structure.

Parameters
statusThe structure containing the CPU status

Definition at line 338 of file cpu.cpp.

338 {
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}

References MaxOS::Logger::ERROR().

Referenced by PANIC().

◆ read_msr()

uint64_t CPU::read_msr ( uint32_t  msr)
static

Reads the value of the specified MSR.

Parameters
msrThe MSR to read
Returns
The value of the MSR

Definition at line 372 of file cpu.cpp.

372 {
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}

Referenced by check_nx(), MaxOS::hardwarecommunication::LocalAPIC::LocalAPIC(), and MaxOS::hardwarecommunication::LocalAPIC::read().

◆ set_status()

void CPU::set_status ( cpu_status_t status)
static

Sets the CPU registers from the provided structure.

Parameters
statusThe structure containing the CPU status

Definition at line 312 of file cpu.cpp.

312 {
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}

◆ stack_trace()

void CPU::stack_trace ( size_t  level)
static

Prints a stack trace up to the specified level.

Parameters
levelThe number of stack frames to print

Definition at line 414 of file cpu.cpp.

414 {
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}
struct PACKED MaxOS::system::StackFrame stack_frame_t
Alias for StackFrame struct.
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

References MaxOS::Logger::ERROR(), and MaxOS::common::resolve_symbol().

Referenced by PANIC().

◆ write_msr()

void CPU::write_msr ( uint32_t  msr,
uint64_t  value 
)
static

Writes the specified value to the specified MSR.

Parameters
msrThe MSR to write to
valueThe value to write

Definition at line 388 of file cpu.cpp.

388 {
389
390 // Write the MSR
391 asm volatile("wrmsr" : : "a" ((uint32_t) value), "d" ((uint32_t) (value >> 32)), "c" (msr));
392}

Referenced by MaxOS::hardwarecommunication::LocalAPIC::LocalAPIC(), MaxOS::hardwarecommunication::LocalAPIC::send_init(), MaxOS::hardwarecommunication::LocalAPIC::send_startup(), and MaxOS::hardwarecommunication::LocalAPIC::write().

Member Data Documentation

◆ acpi

The ACPI interface for the CPU.

Definition at line 260 of file cpu.h.

◆ apic

The APIC interface for the CPU.

Definition at line 261 of file cpu.h.

Referenced by CPU(), and find_cores().

◆ cores

◆ panic_core

Core* MaxOS::system::CPU::panic_core = nullptr
inlinestatic

The core that triggered the panic.

Definition at line 263 of file cpu.h.

Referenced by PANIC(), and prepare_for_panic().

◆ panic_lock

common::Spinlock MaxOS::system::CPU::panic_lock
inlinestatic

The documentation for this class was generated from the following files: