mirror of
https://github.com/johndoe6345789/MetalOS.git
synced 2026-04-24 13:45:02 +00:00
Complete C++ conversion - all files now use classes
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// THIS IS C++ NOW
|
||||
/*
|
||||
* MetalOS Kernel - Interrupt Handling
|
||||
*
|
||||
@@ -22,50 +21,26 @@ static inline void outb(uint16_t port, uint8_t value) {
|
||||
#define PIC2_COMMAND 0xA0
|
||||
#define PIC2_DATA 0xA1
|
||||
|
||||
// IDT entries (256 interrupts in x86_64)
|
||||
static idt_entry_t idt[256];
|
||||
static idt_ptr_t idt_ptr;
|
||||
|
||||
// External ISR handlers (defined in interrupts_asm.asm)
|
||||
extern void isr0(void);
|
||||
extern void isr1(void);
|
||||
extern void isr2(void);
|
||||
extern void isr3(void);
|
||||
extern void isr4(void);
|
||||
extern void isr5(void);
|
||||
extern void isr6(void);
|
||||
extern void isr7(void);
|
||||
extern void isr8(void);
|
||||
extern void isr9(void);
|
||||
extern void isr10(void);
|
||||
extern void isr11(void);
|
||||
extern void isr12(void);
|
||||
extern void isr13(void);
|
||||
extern void isr14(void);
|
||||
extern void isr15(void);
|
||||
extern void isr16(void);
|
||||
extern void isr17(void);
|
||||
extern void isr18(void);
|
||||
extern void isr19(void);
|
||||
extern void isr20(void);
|
||||
extern void isr21(void);
|
||||
extern void isr22(void);
|
||||
extern void isr23(void);
|
||||
extern void isr24(void);
|
||||
extern void isr25(void);
|
||||
extern void isr26(void);
|
||||
extern void isr27(void);
|
||||
extern void isr28(void);
|
||||
extern void isr29(void);
|
||||
extern void isr30(void);
|
||||
extern void isr31(void);
|
||||
extern "C" {
|
||||
void isr0(void); void isr1(void); void isr2(void); void isr3(void);
|
||||
void isr4(void); void isr5(void); void isr6(void); void isr7(void);
|
||||
void isr8(void); void isr9(void); void isr10(void); void isr11(void);
|
||||
void isr12(void); void isr13(void); void isr14(void); void isr15(void);
|
||||
void isr16(void); void isr17(void); void isr18(void); void isr19(void);
|
||||
void isr20(void); void isr21(void); void isr22(void); void isr23(void);
|
||||
void isr24(void); void isr25(void); void isr26(void); void isr27(void);
|
||||
void isr28(void); void isr29(void); void isr30(void); void isr31(void);
|
||||
void irq0(void); void irq1(void);
|
||||
}
|
||||
|
||||
// IRQ handlers
|
||||
extern void irq0(void);
|
||||
extern void irq1(void);
|
||||
// InterruptManager class implementation
|
||||
InterruptManager::InterruptManager() {
|
||||
idtPtr.limit = (sizeof(idt_entry_t) * 256) - 1;
|
||||
idtPtr.base = (uint64_t)&idt;
|
||||
}
|
||||
|
||||
// Set an IDT entry
|
||||
static void idt_set_gate(uint8_t num, uint64_t handler, uint16_t selector, uint8_t flags) {
|
||||
void InterruptManager::setGate(uint8_t num, uint64_t handler, uint16_t selector, uint8_t flags) {
|
||||
idt[num].offset_low = handler & 0xFFFF;
|
||||
idt[num].offset_mid = (handler >> 16) & 0xFFFF;
|
||||
idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF;
|
||||
@@ -75,19 +50,18 @@ static void idt_set_gate(uint8_t num, uint64_t handler, uint16_t selector, uint8
|
||||
idt[num].zero = 0;
|
||||
}
|
||||
|
||||
// Remap PIC (Programmable Interrupt Controller)
|
||||
static void pic_remap(void) {
|
||||
void InterruptManager::remapPIC() {
|
||||
// ICW1: Initialize PIC
|
||||
outb(PIC1_COMMAND, 0x11); // Master PIC
|
||||
outb(PIC2_COMMAND, 0x11); // Slave PIC
|
||||
outb(PIC1_COMMAND, 0x11);
|
||||
outb(PIC2_COMMAND, 0x11);
|
||||
|
||||
// ICW2: Set interrupt vector offsets
|
||||
outb(PIC1_DATA, 0x20); // Master offset to 0x20
|
||||
outb(PIC2_DATA, 0x28); // Slave offset to 0x28
|
||||
outb(PIC1_DATA, 0x20);
|
||||
outb(PIC2_DATA, 0x28);
|
||||
|
||||
// ICW3: Set up cascade
|
||||
outb(PIC1_DATA, 0x04); // Tell master about slave
|
||||
outb(PIC2_DATA, 0x02); // Tell slave its cascade
|
||||
outb(PIC1_DATA, 0x04);
|
||||
outb(PIC2_DATA, 0x02);
|
||||
|
||||
// ICW4: Set mode
|
||||
outb(PIC1_DATA, 0x01);
|
||||
@@ -98,74 +72,67 @@ static void pic_remap(void) {
|
||||
outb(PIC2_DATA, 0xFF);
|
||||
}
|
||||
|
||||
// Initialize IDT
|
||||
void idt_init(void) {
|
||||
idt_ptr.limit = (sizeof(idt_entry_t) * 256) - 1;
|
||||
idt_ptr.base = (uint64_t)&idt;
|
||||
|
||||
void InterruptManager::init() {
|
||||
// Clear IDT
|
||||
for (int i = 0; i < 256; i++) {
|
||||
idt_set_gate(i, 0, 0, 0);
|
||||
setGate(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Install exception handlers (ISRs 0-31)
|
||||
idt_set_gate(0, (uint64_t)isr0, 0x08, 0x8E);
|
||||
idt_set_gate(1, (uint64_t)isr1, 0x08, 0x8E);
|
||||
idt_set_gate(2, (uint64_t)isr2, 0x08, 0x8E);
|
||||
idt_set_gate(3, (uint64_t)isr3, 0x08, 0x8E);
|
||||
idt_set_gate(4, (uint64_t)isr4, 0x08, 0x8E);
|
||||
idt_set_gate(5, (uint64_t)isr5, 0x08, 0x8E);
|
||||
idt_set_gate(6, (uint64_t)isr6, 0x08, 0x8E);
|
||||
idt_set_gate(7, (uint64_t)isr7, 0x08, 0x8E);
|
||||
idt_set_gate(8, (uint64_t)isr8, 0x08, 0x8E);
|
||||
idt_set_gate(9, (uint64_t)isr9, 0x08, 0x8E);
|
||||
idt_set_gate(10, (uint64_t)isr10, 0x08, 0x8E);
|
||||
idt_set_gate(11, (uint64_t)isr11, 0x08, 0x8E);
|
||||
idt_set_gate(12, (uint64_t)isr12, 0x08, 0x8E);
|
||||
idt_set_gate(13, (uint64_t)isr13, 0x08, 0x8E);
|
||||
idt_set_gate(14, (uint64_t)isr14, 0x08, 0x8E);
|
||||
idt_set_gate(15, (uint64_t)isr15, 0x08, 0x8E);
|
||||
idt_set_gate(16, (uint64_t)isr16, 0x08, 0x8E);
|
||||
idt_set_gate(17, (uint64_t)isr17, 0x08, 0x8E);
|
||||
idt_set_gate(18, (uint64_t)isr18, 0x08, 0x8E);
|
||||
idt_set_gate(19, (uint64_t)isr19, 0x08, 0x8E);
|
||||
idt_set_gate(20, (uint64_t)isr20, 0x08, 0x8E);
|
||||
idt_set_gate(21, (uint64_t)isr21, 0x08, 0x8E);
|
||||
idt_set_gate(22, (uint64_t)isr22, 0x08, 0x8E);
|
||||
idt_set_gate(23, (uint64_t)isr23, 0x08, 0x8E);
|
||||
idt_set_gate(24, (uint64_t)isr24, 0x08, 0x8E);
|
||||
idt_set_gate(25, (uint64_t)isr25, 0x08, 0x8E);
|
||||
idt_set_gate(26, (uint64_t)isr26, 0x08, 0x8E);
|
||||
idt_set_gate(27, (uint64_t)isr27, 0x08, 0x8E);
|
||||
idt_set_gate(28, (uint64_t)isr28, 0x08, 0x8E);
|
||||
idt_set_gate(29, (uint64_t)isr29, 0x08, 0x8E);
|
||||
idt_set_gate(30, (uint64_t)isr30, 0x08, 0x8E);
|
||||
idt_set_gate(31, (uint64_t)isr31, 0x08, 0x8E);
|
||||
setGate(0, (uint64_t)isr0, 0x08, 0x8E);
|
||||
setGate(1, (uint64_t)isr1, 0x08, 0x8E);
|
||||
setGate(2, (uint64_t)isr2, 0x08, 0x8E);
|
||||
setGate(3, (uint64_t)isr3, 0x08, 0x8E);
|
||||
setGate(4, (uint64_t)isr4, 0x08, 0x8E);
|
||||
setGate(5, (uint64_t)isr5, 0x08, 0x8E);
|
||||
setGate(6, (uint64_t)isr6, 0x08, 0x8E);
|
||||
setGate(7, (uint64_t)isr7, 0x08, 0x8E);
|
||||
setGate(8, (uint64_t)isr8, 0x08, 0x8E);
|
||||
setGate(9, (uint64_t)isr9, 0x08, 0x8E);
|
||||
setGate(10, (uint64_t)isr10, 0x08, 0x8E);
|
||||
setGate(11, (uint64_t)isr11, 0x08, 0x8E);
|
||||
setGate(12, (uint64_t)isr12, 0x08, 0x8E);
|
||||
setGate(13, (uint64_t)isr13, 0x08, 0x8E);
|
||||
setGate(14, (uint64_t)isr14, 0x08, 0x8E);
|
||||
setGate(15, (uint64_t)isr15, 0x08, 0x8E);
|
||||
setGate(16, (uint64_t)isr16, 0x08, 0x8E);
|
||||
setGate(17, (uint64_t)isr17, 0x08, 0x8E);
|
||||
setGate(18, (uint64_t)isr18, 0x08, 0x8E);
|
||||
setGate(19, (uint64_t)isr19, 0x08, 0x8E);
|
||||
setGate(20, (uint64_t)isr20, 0x08, 0x8E);
|
||||
setGate(21, (uint64_t)isr21, 0x08, 0x8E);
|
||||
setGate(22, (uint64_t)isr22, 0x08, 0x8E);
|
||||
setGate(23, (uint64_t)isr23, 0x08, 0x8E);
|
||||
setGate(24, (uint64_t)isr24, 0x08, 0x8E);
|
||||
setGate(25, (uint64_t)isr25, 0x08, 0x8E);
|
||||
setGate(26, (uint64_t)isr26, 0x08, 0x8E);
|
||||
setGate(27, (uint64_t)isr27, 0x08, 0x8E);
|
||||
setGate(28, (uint64_t)isr28, 0x08, 0x8E);
|
||||
setGate(29, (uint64_t)isr29, 0x08, 0x8E);
|
||||
setGate(30, (uint64_t)isr30, 0x08, 0x8E);
|
||||
setGate(31, (uint64_t)isr31, 0x08, 0x8E);
|
||||
|
||||
// Remap PIC
|
||||
pic_remap();
|
||||
remapPIC();
|
||||
|
||||
// Install IRQ handlers (IRQs 0-15 mapped to 32-47)
|
||||
idt_set_gate(32, (uint64_t)irq0, 0x08, 0x8E); // Timer
|
||||
idt_set_gate(33, (uint64_t)irq1, 0x08, 0x8E); // Keyboard
|
||||
setGate(32, (uint64_t)irq0, 0x08, 0x8E);
|
||||
setGate(33, (uint64_t)irq1, 0x08, 0x8E);
|
||||
|
||||
// Load IDT
|
||||
__asm__ volatile("lidt %0" : : "m"(idt_ptr));
|
||||
__asm__ volatile("lidt %0" : : "m"(idtPtr));
|
||||
|
||||
// Enable interrupts
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
// Generic interrupt handler
|
||||
void interrupt_handler(registers_t* regs) {
|
||||
void InterruptManager::handleInterrupt(registers_t* regs) {
|
||||
// Handle specific interrupts
|
||||
if (regs->int_no == 32) {
|
||||
// Timer interrupt (IRQ0)
|
||||
timer_handler();
|
||||
}
|
||||
|
||||
// TODO: Handle other interrupts (keyboard, etc.)
|
||||
|
||||
// Send EOI (End of Interrupt)
|
||||
if (regs->int_no >= 32 && regs->int_no < 48) {
|
||||
// Check if we're using APIC or PIC
|
||||
@@ -175,11 +142,25 @@ void interrupt_handler(registers_t* regs) {
|
||||
} else {
|
||||
// Use legacy PIC EOI
|
||||
if (regs->int_no >= 40) {
|
||||
// Slave PIC
|
||||
outb(PIC2_COMMAND, 0x20);
|
||||
}
|
||||
// Master PIC
|
||||
outb(PIC1_COMMAND, 0x20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Global interrupt manager instance
|
||||
static InterruptManager globalInterruptManager;
|
||||
|
||||
// C-compatible wrapper functions
|
||||
extern "C" {
|
||||
|
||||
void idt_init(void) {
|
||||
globalInterruptManager.init();
|
||||
}
|
||||
|
||||
void interrupt_handler(registers_t* regs) {
|
||||
globalInterruptManager.handleInterrupt(regs);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
// THIS IS C++ NOW
|
||||
/*
|
||||
* MetalOS Kernel - Main Entry Point
|
||||
*
|
||||
* EXTREME MINIMAL kernel - only what's needed for QT6 Hello World.
|
||||
* Now with basic multicore support for better performance!
|
||||
* Just: boot -> init hardware (all cores) -> run app.
|
||||
*
|
||||
* C++ implementation: Root level function hands off to classes
|
||||
*/
|
||||
|
||||
#include "kernel/kernel.h"
|
||||
@@ -19,21 +20,21 @@
|
||||
* Kernel main entry point
|
||||
* Called by bootloader with boot information
|
||||
*
|
||||
* Initializes all hardware including multicore support.
|
||||
* Simple design: all cores initialized but only BSP runs app.
|
||||
* Future: could distribute work across cores for better performance.
|
||||
* This is the root-level function that hands off to C++ classes
|
||||
* for hardware initialization and system management.
|
||||
*/
|
||||
void kernel_main(BootInfo* boot_info) {
|
||||
// Initialize GDT (Global Descriptor Table)
|
||||
extern "C" void kernel_main(BootInfo* boot_info) {
|
||||
// Initialize GDT (Global Descriptor Table) - using GDT class
|
||||
gdt_init();
|
||||
|
||||
// Initialize IDT (Interrupt Descriptor Table)
|
||||
// Initialize IDT (Interrupt Descriptor Table) - using InterruptManager class
|
||||
idt_init();
|
||||
|
||||
// Initialize physical memory manager
|
||||
// Initialize physical memory manager - using PhysicalMemoryManager class
|
||||
pmm_init(boot_info);
|
||||
|
||||
// Initialize kernel heap (allocate 256 pages = 1MB for kernel heap)
|
||||
// Using HeapAllocator class
|
||||
void* heap_start_page = pmm_alloc_page();
|
||||
if (heap_start_page) {
|
||||
// Allocate additional pages for heap (256 pages total)
|
||||
@@ -43,13 +44,13 @@ void kernel_main(BootInfo* boot_info) {
|
||||
heap_init(heap_start_page, 256 * PAGE_SIZE); // 1MB heap
|
||||
}
|
||||
|
||||
// Initialize timer (1000 Hz = 1ms per tick)
|
||||
// Initialize timer (1000 Hz = 1ms per tick) - using Timer class
|
||||
timer_init(TIMER_FREQUENCY);
|
||||
|
||||
// Initialize PCI bus
|
||||
// Initialize PCI bus - using PCIManager class
|
||||
pci_init();
|
||||
|
||||
// Initialize SMP (Symmetric Multi-Processing)
|
||||
// Initialize SMP (Symmetric Multi-Processing) - using SMPManager class
|
||||
// This will detect and start all available CPU cores
|
||||
smp_init();
|
||||
|
||||
@@ -88,4 +89,10 @@ void kernel_main(BootInfo* boot_info) {
|
||||
* All cores available for future parallel processing.
|
||||
*
|
||||
* Total kernel size target: < 150 KB (with multicore support)
|
||||
*
|
||||
* C++ Design:
|
||||
* - Root-level kernel_main() function serves as entry point
|
||||
* - All subsystems implemented as classes (GDT, InterruptManager, Timer, etc.)
|
||||
* - Classes encapsulate state and behavior
|
||||
* - C-compatible wrappers maintain compatibility with assembly and bootloader
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// THIS IS C++ NOW
|
||||
/*
|
||||
* MetalOS Kernel - SMP (Symmetric Multi-Processing) Support
|
||||
*
|
||||
@@ -10,11 +9,6 @@
|
||||
#include "kernel/apic.h"
|
||||
#include "kernel/memory.h"
|
||||
|
||||
// CPU information array
|
||||
static cpu_info_t cpu_info[MAX_CPUS];
|
||||
static uint8_t cpu_count = 1; // Start with BSP
|
||||
static bool smp_enabled = false;
|
||||
|
||||
// Bootstrap CPU is always CPU 0
|
||||
#define BSP_CPU_ID 0
|
||||
|
||||
@@ -22,90 +16,95 @@ static bool smp_enabled = false;
|
||||
#define AP_TRAMPOLINE_ADDR 0x8000
|
||||
|
||||
// AP startup code (will be copied to low memory)
|
||||
extern void ap_trampoline_start(void);
|
||||
extern void ap_trampoline_end(void);
|
||||
extern "C" {
|
||||
void ap_trampoline_start(void);
|
||||
void ap_trampoline_end(void);
|
||||
}
|
||||
|
||||
// Get current CPU ID from APIC
|
||||
uint8_t smp_get_current_cpu(void) {
|
||||
if (!smp_enabled) {
|
||||
// SMPManager class implementation
|
||||
SMPManager::SMPManager() : cpuCount(1), smpEnabled(false) {
|
||||
// Initialize BSP
|
||||
cpuInfo[0].cpu_id = BSP_CPU_ID;
|
||||
cpuInfo[0].apic_id = 0;
|
||||
cpuInfo[0].online = false;
|
||||
cpuInfo[0].kernel_stack = 0;
|
||||
}
|
||||
|
||||
uint8_t SMPManager::getCurrentCPU() const {
|
||||
if (!smpEnabled) {
|
||||
return BSP_CPU_ID;
|
||||
}
|
||||
|
||||
uint8_t apic_id = apic_get_id();
|
||||
uint8_t apicId = apic_get_id();
|
||||
|
||||
// Find CPU by APIC ID
|
||||
for (uint8_t i = 0; i < cpu_count; i++) {
|
||||
if (cpu_info[i].apic_id == apic_id) {
|
||||
return cpu_info[i].cpu_id;
|
||||
for (uint8_t i = 0; i < cpuCount; i++) {
|
||||
if (cpuInfo[i].apic_id == apicId) {
|
||||
return cpuInfo[i].cpu_id;
|
||||
}
|
||||
}
|
||||
|
||||
return BSP_CPU_ID;
|
||||
}
|
||||
|
||||
// Initialize a CPU entry
|
||||
static void smp_init_cpu(uint8_t cpu_id, uint8_t apic_id) {
|
||||
if (cpu_id >= MAX_CPUS) return;
|
||||
void SMPManager::initCPU(uint8_t cpuId, uint8_t apicId) {
|
||||
if (cpuId >= MAX_CPUS) return;
|
||||
|
||||
cpu_info[cpu_id].cpu_id = cpu_id;
|
||||
cpu_info[cpu_id].apic_id = apic_id;
|
||||
cpu_info[cpu_id].online = false;
|
||||
cpu_info[cpu_id].kernel_stack = 0;
|
||||
cpuInfo[cpuId].cpu_id = cpuId;
|
||||
cpuInfo[cpuId].apic_id = apicId;
|
||||
cpuInfo[cpuId].online = false;
|
||||
cpuInfo[cpuId].kernel_stack = 0;
|
||||
}
|
||||
|
||||
// Mark CPU as online
|
||||
void smp_cpu_online(uint8_t cpu_id) {
|
||||
if (cpu_id < MAX_CPUS) {
|
||||
cpu_info[cpu_id].online = true;
|
||||
void SMPManager::markCPUOnline(uint8_t cpuId) {
|
||||
if (cpuId < MAX_CPUS) {
|
||||
cpuInfo[cpuId].online = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple delay for AP startup
|
||||
static void smp_delay(uint32_t microseconds) {
|
||||
void SMPManager::delay(uint32_t microseconds) {
|
||||
// Approximate delay (not precise)
|
||||
for (volatile uint32_t i = 0; i < microseconds * 100; i++) {
|
||||
__asm__ volatile("pause");
|
||||
}
|
||||
}
|
||||
|
||||
// Start an Application Processor
|
||||
static bool smp_start_ap(uint8_t apic_id) {
|
||||
bool SMPManager::startAP(uint8_t apicId) {
|
||||
// Send INIT IPI
|
||||
apic_send_ipi(apic_id, 0, APIC_IPI_INIT);
|
||||
smp_delay(10000); // 10ms
|
||||
apic_send_ipi(apicId, 0, APIC_IPI_INIT);
|
||||
delay(10000); // 10ms
|
||||
|
||||
// Send SIPI (Startup IPI) with trampoline address
|
||||
uint8_t vector = AP_TRAMPOLINE_ADDR >> 12; // Page number
|
||||
apic_send_ipi(apic_id, vector, APIC_IPI_STARTUP);
|
||||
smp_delay(200); // 200us
|
||||
apic_send_ipi(apicId, vector, APIC_IPI_STARTUP);
|
||||
delay(200); // 200us
|
||||
|
||||
// Send second SIPI (as per Intel spec)
|
||||
apic_send_ipi(apic_id, vector, APIC_IPI_STARTUP);
|
||||
smp_delay(200); // 200us
|
||||
apic_send_ipi(apicId, vector, APIC_IPI_STARTUP);
|
||||
delay(200); // 200us
|
||||
|
||||
// Wait for AP to come online (timeout after 1 second)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
// Check if AP marked itself online
|
||||
for (uint8_t cpu_id = 0; cpu_id < cpu_count; cpu_id++) {
|
||||
if (cpu_info[cpu_id].apic_id == apic_id && cpu_info[cpu_id].online) {
|
||||
for (uint8_t cpuId = 0; cpuId < cpuCount; cpuId++) {
|
||||
if (cpuInfo[cpuId].apic_id == apicId && cpuInfo[cpuId].online) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
smp_delay(10000); // 10ms
|
||||
delay(10000); // 10ms
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize SMP
|
||||
void smp_init(void) {
|
||||
void SMPManager::init() {
|
||||
// Check if APIC is available
|
||||
if (!apic_is_available()) {
|
||||
// Single core mode
|
||||
smp_init_cpu(BSP_CPU_ID, 0);
|
||||
cpu_info[BSP_CPU_ID].online = true;
|
||||
cpu_count = 1;
|
||||
smp_enabled = false;
|
||||
initCPU(BSP_CPU_ID, 0);
|
||||
cpuInfo[BSP_CPU_ID].online = true;
|
||||
cpuCount = 1;
|
||||
smpEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,48 +112,74 @@ void smp_init(void) {
|
||||
apic_init();
|
||||
|
||||
// Get BSP APIC ID
|
||||
uint8_t bsp_apic_id = apic_get_id();
|
||||
smp_init_cpu(BSP_CPU_ID, bsp_apic_id);
|
||||
cpu_info[BSP_CPU_ID].online = true;
|
||||
uint8_t bspApicId = apic_get_id();
|
||||
initCPU(BSP_CPU_ID, bspApicId);
|
||||
cpuInfo[BSP_CPU_ID].online = true;
|
||||
|
||||
// Detect additional CPUs from APIC
|
||||
// For simplicity, we'll try to start CPUs with sequential APIC IDs
|
||||
// A real implementation would parse ACPI MADT table
|
||||
uint8_t maxCPUsToTry = 12; // Try up to 12 logical processors
|
||||
|
||||
uint8_t max_cpus_to_try = 12; // Try up to 12 logical processors
|
||||
|
||||
for (uint8_t apic_id = 0; apic_id < max_cpus_to_try && cpu_count < MAX_CPUS; apic_id++) {
|
||||
for (uint8_t apicId = 0; apicId < maxCPUsToTry && cpuCount < MAX_CPUS; apicId++) {
|
||||
// Skip BSP
|
||||
if (apic_id == bsp_apic_id) {
|
||||
if (apicId == bspApicId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initialize CPU entry
|
||||
smp_init_cpu(cpu_count, apic_id);
|
||||
initCPU(cpuCount, apicId);
|
||||
|
||||
// Try to start this AP
|
||||
if (smp_start_ap(apic_id)) {
|
||||
cpu_count++;
|
||||
if (startAP(apicId)) {
|
||||
cpuCount++;
|
||||
}
|
||||
}
|
||||
|
||||
smp_enabled = (cpu_count > 1);
|
||||
smpEnabled = (cpuCount > 1);
|
||||
}
|
||||
|
||||
// Get number of CPUs
|
||||
uint8_t smp_get_cpu_count(void) {
|
||||
return cpu_count;
|
||||
uint8_t SMPManager::getCPUCount() const {
|
||||
return cpuCount;
|
||||
}
|
||||
|
||||
// Check if SMP is enabled
|
||||
bool smp_is_enabled(void) {
|
||||
return smp_enabled;
|
||||
bool SMPManager::isEnabled() const {
|
||||
return smpEnabled;
|
||||
}
|
||||
|
||||
// Get CPU info
|
||||
cpu_info_t* smp_get_cpu_info(uint8_t cpu_id) {
|
||||
if (cpu_id >= MAX_CPUS) {
|
||||
return NULL;
|
||||
cpu_info_t* SMPManager::getCPUInfo(uint8_t cpuId) {
|
||||
if (cpuId >= MAX_CPUS) {
|
||||
return nullptr;
|
||||
}
|
||||
return &cpu_info[cpu_id];
|
||||
return &cpuInfo[cpuId];
|
||||
}
|
||||
|
||||
// Global SMP manager instance
|
||||
static SMPManager globalSMP;
|
||||
|
||||
// C-compatible wrapper functions
|
||||
extern "C" {
|
||||
|
||||
void smp_init(void) {
|
||||
globalSMP.init();
|
||||
}
|
||||
|
||||
uint8_t smp_get_cpu_count(void) {
|
||||
return globalSMP.getCPUCount();
|
||||
}
|
||||
|
||||
uint8_t smp_get_current_cpu(void) {
|
||||
return globalSMP.getCurrentCPU();
|
||||
}
|
||||
|
||||
bool smp_is_enabled(void) {
|
||||
return globalSMP.isEnabled();
|
||||
}
|
||||
|
||||
cpu_info_t* smp_get_cpu_info(uint8_t cpu_id) {
|
||||
return globalSMP.getCPUInfo(cpu_id);
|
||||
}
|
||||
|
||||
void smp_cpu_online(uint8_t cpu_id) {
|
||||
globalSMP.markCPUOnline(cpu_id);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user