15#include <common/symbols.h>
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;
27volatile extern PAGE_ALIGNED
unsigned char p4_table[];
51Core::~Core() =
default;
72 info->activated =
false;
84 for (
int i = 0; i < 2; ++i) {
97 Logger::DEBUG() <<
"Core " <<
id <<
" started successfully \n";
134 tss.io_bitmap_offset = 0;
160 asm volatile(
"ltr %%ax" : :
"a" (0x28));
171 asm volatile(
"mov %%cr0, %0" :
"=r" (
cr0));
175 asm volatile(
"mov %%cr4, %0" :
"=r" (
cr4));
185 asm volatile(
"mov %0, %%cr0" : :
"r" (
cr0));
188 asm volatile(
"fninit");
196 asm volatile(
"mov %0, %%cr4" : :
"r" (
cr4));
205 asm volatile(
"mov %0, %%cr4" : :
"r" (
cr4));
209 asm volatile(
"xgetbv" :
"=a" (
xcr0) :
"c" (0));
211 asm volatile(
"xsetbv" : :
"c" (0),
"a" (
xcr0));
220 asm volatile(
"mov %0, %%cr4" : :
"r" (
cr4));
263 bsp -> active =
true;
271CPU::~CPU() =
default;
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));
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));
356 Logger::ERROR() <<
"INT: \t0x" << status->interrupt_number <<
"\n";
357 Logger::ERROR() <<
"ERRCD: \t0x" << status->error_code <<
"\n";
376 asm volatile(
"rdmsr" :
"=a" (
low),
"=d" (
high) :
"c" (
msr));
427 if (
frame ==
nullptr)
478 Logger::ERROR() <<
"There has been a fatal error in MaxOS and the system has been halted.\n";
506 Logger::ERROR() <<
"CPU Panicked (i " << (
int)status->interrupt_number <<
") in process " <<
process->name.c_str() <<
" at 0x" << status->rip <<
" - killing process\n";
556 ASSERT((
void*)&
core_start == (
void*)0x8000,
"Core start not at expected address");
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.
static Logger WARNING()
Gets active logger set to WARNING level.
static Logger INFO()
Gets active logger set to info level.
static Logger ERROR()
Gets active logger set to ERROR level.
Stores the left, top, width and height of a rectangle.
static Clock * active_clock()
Gets the currently active clock.
static void print_logo(bool is_panic=false)
Prints the logo to the center of the screen.
IOAPIC * io_apic() const
Get the io apic.
LocalAPIC * local_apic() const
Get the local apic.
MADTEntry * get_madt_item(MADT_TYPE type, uint8_t index)
Get an item in the MADT.
static void load_current()
Tell the processor to use the current InterruptManager.
Handles the local APIC for the current core.
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...
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
static Scheduler * core_scheduler()
Gets the scheduler for the currently executing core.
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
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 ...
Manages the CPU and its cores.
static void print_registers(cpu_status_t *status)
Prints the CPU registers from the provided structure.
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.
CPU(GlobalDescriptorTable *gdt, Multiboot *multiboot)
Constructor for the CPU class.
static void get_status(cpu_status_t *status)
Gets the current CPU status into the provided structure.
void init_cores()
Wake up all the cores.
static bool check_cpu_feature(CPU_FEATURE_ECX feature)
Checks if a CPU feature is supported (ECX Register)
hardwarecommunication::AdvancedProgrammableInterruptController apic
The APIC interface for the CPU.
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...
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.
static void set_status(cpu_status_t *status)
Sets the CPU registers from the provided structure.
void find_cores() const
Search the madt for cores and store them.
static uint64_t read_msr(uint32_t msr)
Reads the value of the specified MSR.
static common::Vector< Core * > cores
The list of CPU cores in the system (populated during initialization, includes the BSP and cores that...
static Core * executing_core()
Gets the core that is currently executing.
static void write_msr(uint32_t msr, uint64_t value)
Writes the specified value to the specified MSR.
static Core * panic_core
The core that triggered the panic.
static void stack_trace(size_t)
Prints a stack trace up to the specified level.
static common::Spinlock panic_lock
Lock to prevent multiple panics at once.
static bool check_nx()
Checks if the No Execute page flag is supported.
Represents a CPU core in the system.
void wake_up(CPU *cpu)
Wakes up the core by sending the appropriate IPIs. (see core_loader.s for startup code)
void init_tss()
Initialises the task state segment for this core.
uint64_t m_stack
The stack pointer for this core.
bool m_bsp
Whether this core is the bootstrap processor.
void init_sse()
Initialises the SSE instructions.
GlobalDescriptorTable * gdt
The GDT for this core.
Core(hardwarecommunication::madt_processor_apic_t *madt_item)
Constructs a new Core object from the MADT entry.
void init()
Initialises the core by setting up the GDT, IDT, TSS, SSE and APIC.
uint8_t id
The ID of this core.
bool active
Whether this core is active.
hardwarecommunication::LocalAPIC * local_apic
The local APIC for this core.
uint8_t m_apic_id
The ID of the apic for this core.
bool xsave_enabled
Whether XSAVE is enabled.
bool m_enabled
Whether the core is enabled.
bool avx_enabled
Whether AVX is enabled.
bool m_can_enable
Whether the core can be enabled.
hardwarecommunication::madt_processor_apic_t * m_madt
The MADT entry for this core.
tss_t tss
The Task State Segment for this core.
Sets up the GDT in the CPU.
Parses and provides access to Multiboot 2 information.
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.
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...
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.
CPU_FEATURE_EDX
CPU features indicated by the EDX register after calling CPUID with EAX = 1.
uint8_t core_boot_info[]
The boot info structure for the core being started.
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.
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.
@ WRITE
Memory in this page is writable.
Defines a GlobalScheduler and Scheduler for managing processes and threads.
class MaxOS::String string
Typedef for String.
An item in the MADT table.
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.
Defines the VESABootConsole driver for handling console output during boot using an VESA framebuffer.