Complete C++ conversion - all files now use classes

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-12-28 21:45:50 +00:00
parent 7bf2b3a059
commit a0683c0722
3 changed files with 191 additions and 178 deletions

View File

@@ -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"

View File

@@ -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
*/

View File

@@ -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"