mirror of
https://github.com/johndoe6345789/MetalOS.git
synced 2026-04-24 13:45:02 +00:00
Add CMake, Ninja, and Conan support with kernel modules (GDT, interrupts)
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
79
kernel/CMakeLists.txt
Normal file
79
kernel/CMakeLists.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
# MetalOS Kernel CMakeLists
|
||||
|
||||
# Include directories
|
||||
include_directories(include)
|
||||
|
||||
# Source files
|
||||
set(KERNEL_C_SOURCES
|
||||
src/main.c
|
||||
src/gdt.c
|
||||
src/interrupts.c
|
||||
)
|
||||
|
||||
set(KERNEL_ASM_SOURCES
|
||||
src/gdt_flush.asm
|
||||
src/interrupts_asm.asm
|
||||
)
|
||||
|
||||
# Kernel-specific C compiler flags
|
||||
set(KERNEL_CFLAGS
|
||||
-mcmodel=large
|
||||
-O2
|
||||
)
|
||||
|
||||
# Create kernel C object files
|
||||
add_library(kernel_c_objs OBJECT
|
||||
${KERNEL_C_SOURCES}
|
||||
)
|
||||
|
||||
target_compile_options(kernel_c_objs PRIVATE ${KERNEL_CFLAGS})
|
||||
target_include_directories(kernel_c_objs PRIVATE include)
|
||||
|
||||
# Create kernel ASM object files separately
|
||||
# We need to avoid CMake adding C flags to NASM
|
||||
foreach(asm_file ${KERNEL_ASM_SOURCES})
|
||||
get_filename_component(asm_name ${asm_file} NAME_WE)
|
||||
set(asm_obj ${CMAKE_CURRENT_BINARY_DIR}/${asm_name}.o)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${asm_obj}
|
||||
COMMAND ${CMAKE_ASM_NASM_COMPILER}
|
||||
-f elf64
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
-o ${asm_obj}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${asm_file}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${asm_file}
|
||||
COMMENT "Assembling ${asm_file}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
list(APPEND KERNEL_ASM_OBJS ${asm_obj})
|
||||
endforeach()
|
||||
|
||||
# Custom target for ASM objects
|
||||
add_custom_target(kernel_asm_objs
|
||||
DEPENDS ${KERNEL_ASM_OBJS}
|
||||
)
|
||||
|
||||
# Link kernel binary
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
COMMAND ${CMAKE_LINKER}
|
||||
-nostdlib
|
||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld
|
||||
$<TARGET_OBJECTS:kernel_c_objs>
|
||||
${KERNEL_ASM_OBJS}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
DEPENDS kernel_c_objs kernel_asm_objs ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld
|
||||
COMMENT "Linking kernel binary"
|
||||
COMMAND_EXPAND_LISTS
|
||||
)
|
||||
|
||||
add_custom_target(kernel ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
)
|
||||
|
||||
# Install kernel binary
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
DESTINATION bin
|
||||
)
|
||||
25
kernel/include/kernel/gdt.h
Normal file
25
kernel/include/kernel/gdt.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef METALOS_KERNEL_GDT_H
|
||||
#define METALOS_KERNEL_GDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// GDT Entry structure
|
||||
typedef struct {
|
||||
uint16_t limit_low;
|
||||
uint16_t base_low;
|
||||
uint8_t base_middle;
|
||||
uint8_t access;
|
||||
uint8_t granularity;
|
||||
uint8_t base_high;
|
||||
} __attribute__((packed)) gdt_entry_t;
|
||||
|
||||
// GDT Pointer structure
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed)) gdt_ptr_t;
|
||||
|
||||
// Initialize the Global Descriptor Table
|
||||
void gdt_init(void);
|
||||
|
||||
#endif // METALOS_KERNEL_GDT_H
|
||||
37
kernel/include/kernel/interrupts.h
Normal file
37
kernel/include/kernel/interrupts.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef METALOS_KERNEL_INTERRUPTS_H
|
||||
#define METALOS_KERNEL_INTERRUPTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// IDT Entry structure
|
||||
typedef struct {
|
||||
uint16_t offset_low; // Offset bits 0-15
|
||||
uint16_t selector; // Code segment selector
|
||||
uint8_t ist; // Interrupt Stack Table offset
|
||||
uint8_t type_attr; // Type and attributes
|
||||
uint16_t offset_mid; // Offset bits 16-31
|
||||
uint32_t offset_high; // Offset bits 32-63
|
||||
uint32_t zero; // Reserved
|
||||
} __attribute__((packed)) idt_entry_t;
|
||||
|
||||
// IDT Pointer structure
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed)) idt_ptr_t;
|
||||
|
||||
// CPU registers state (for interrupt handlers)
|
||||
typedef struct {
|
||||
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
||||
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
|
||||
uint64_t int_no, err_code;
|
||||
uint64_t rip, cs, rflags, rsp, ss;
|
||||
} __attribute__((packed)) registers_t;
|
||||
|
||||
// Initialize Interrupt Descriptor Table
|
||||
void idt_init(void);
|
||||
|
||||
// Generic interrupt handler (called from assembly)
|
||||
void interrupt_handler(registers_t* regs);
|
||||
|
||||
#endif // METALOS_KERNEL_INTERRUPTS_H
|
||||
56
kernel/src/gdt.c
Normal file
56
kernel/src/gdt.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* MetalOS Kernel - Global Descriptor Table (GDT)
|
||||
*
|
||||
* Minimal GDT setup for x86_64 long mode
|
||||
* Only what's needed for our single-app OS
|
||||
*/
|
||||
|
||||
#include "kernel/gdt.h"
|
||||
|
||||
// GDT entries (minimal for x86_64)
|
||||
// In long mode, most segmentation is ignored, but we still need a valid GDT
|
||||
static gdt_entry_t gdt[5];
|
||||
static gdt_ptr_t gdt_ptr;
|
||||
|
||||
// Set a GDT entry
|
||||
static void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||
gdt[num].base_low = (base & 0xFFFF);
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = (limit >> 16) & 0x0F;
|
||||
gdt[num].granularity |= gran & 0xF0;
|
||||
gdt[num].access = access;
|
||||
}
|
||||
|
||||
// Load GDT (assembly)
|
||||
extern void gdt_flush(uint64_t);
|
||||
|
||||
// Initialize GDT
|
||||
void gdt_init(void) {
|
||||
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
|
||||
gdt_ptr.base = (uint64_t)&gdt;
|
||||
|
||||
// Null descriptor
|
||||
gdt_set_gate(0, 0, 0, 0, 0);
|
||||
|
||||
// Kernel code segment (64-bit)
|
||||
// Access: Present, Ring 0, Code, Executable, Readable
|
||||
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xA0);
|
||||
|
||||
// Kernel data segment (64-bit)
|
||||
// Access: Present, Ring 0, Data, Writable
|
||||
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xC0);
|
||||
|
||||
// User code segment (64-bit)
|
||||
// Access: Present, Ring 3, Code, Executable, Readable
|
||||
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xA0);
|
||||
|
||||
// User data segment (64-bit)
|
||||
// Access: Present, Ring 3, Data, Writable
|
||||
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xC0);
|
||||
|
||||
// Flush GDT
|
||||
gdt_flush((uint64_t)&gdt_ptr);
|
||||
}
|
||||
26
kernel/src/gdt_flush.asm
Normal file
26
kernel/src/gdt_flush.asm
Normal file
@@ -0,0 +1,26 @@
|
||||
; GDT flush assembly routine
|
||||
; Load new GDT and update segment registers
|
||||
|
||||
global gdt_flush
|
||||
extern gdt_ptr
|
||||
|
||||
section .text
|
||||
bits 64
|
||||
|
||||
gdt_flush:
|
||||
lgdt [rdi] ; Load GDT pointer (first argument in rdi)
|
||||
|
||||
; Reload segments
|
||||
mov ax, 0x10 ; Kernel data segment offset
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
; Far return to reload CS
|
||||
pop rdi ; Get return address
|
||||
mov rax, 0x08 ; Kernel code segment offset
|
||||
push rax
|
||||
push rdi
|
||||
retfq ; Far return
|
||||
160
kernel/src/interrupts.c
Normal file
160
kernel/src/interrupts.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* MetalOS Kernel - Interrupt Handling
|
||||
*
|
||||
* Minimal IDT and interrupt handlers
|
||||
* Only essential interrupts for QT6 app
|
||||
*/
|
||||
|
||||
#include "kernel/interrupts.h"
|
||||
|
||||
// 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);
|
||||
|
||||
// IRQ handlers
|
||||
extern void irq0(void);
|
||||
extern void irq1(void);
|
||||
|
||||
// Set an IDT entry
|
||||
static void idt_set_gate(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;
|
||||
idt[num].selector = selector;
|
||||
idt[num].ist = 0;
|
||||
idt[num].type_attr = flags;
|
||||
idt[num].zero = 0;
|
||||
}
|
||||
|
||||
// Remap PIC (Programmable Interrupt Controller)
|
||||
static void pic_remap(void) {
|
||||
// ICW1: Initialize PIC
|
||||
__asm__ volatile("outb %0, $0x20" : : "a"((uint8_t)0x11)); // Master PIC
|
||||
__asm__ volatile("outb %0, $0xA0" : : "a"((uint8_t)0x11)); // Slave PIC
|
||||
|
||||
// ICW2: Set interrupt vector offsets
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0x20)); // Master offset to 0x20
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0x28)); // Slave offset to 0x28
|
||||
|
||||
// ICW3: Set up cascade
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0x04)); // Tell master about slave
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0x02)); // Tell slave its cascade
|
||||
|
||||
// ICW4: Set mode
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0x01));
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0x01));
|
||||
|
||||
// Mask all interrupts initially
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0xFF));
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0xFF));
|
||||
}
|
||||
|
||||
// Initialize IDT
|
||||
void idt_init(void) {
|
||||
idt_ptr.limit = (sizeof(idt_entry_t) * 256) - 1;
|
||||
idt_ptr.base = (uint64_t)&idt;
|
||||
|
||||
// Clear IDT
|
||||
for (int i = 0; i < 256; i++) {
|
||||
idt_set_gate(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);
|
||||
|
||||
// Remap PIC
|
||||
pic_remap();
|
||||
|
||||
// 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
|
||||
|
||||
// Load IDT
|
||||
__asm__ volatile("lidt %0" : : "m"(idt_ptr));
|
||||
|
||||
// Enable interrupts
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
// Generic interrupt handler
|
||||
void interrupt_handler(registers_t* regs) {
|
||||
// Handle interrupt based on interrupt number
|
||||
(void)regs; // Suppress unused warning for now
|
||||
|
||||
// TODO: Dispatch to specific handlers based on regs->int_no
|
||||
|
||||
// Send EOI (End of Interrupt) to PIC if this was an IRQ
|
||||
if (regs->int_no >= 32 && regs->int_no < 48) {
|
||||
if (regs->int_no >= 40) {
|
||||
// Slave PIC
|
||||
__asm__ volatile("outb %0, $0xA0" : : "a"((uint8_t)0x20));
|
||||
}
|
||||
// Master PIC
|
||||
__asm__ volatile("outb %0, $0x20" : : "a"((uint8_t)0x20));
|
||||
}
|
||||
}
|
||||
120
kernel/src/interrupts_asm.asm
Normal file
120
kernel/src/interrupts_asm.asm
Normal file
@@ -0,0 +1,120 @@
|
||||
; Interrupt Service Routines (ISRs) for x86_64
|
||||
; Assembly stubs that save state and call C handler
|
||||
|
||||
global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7
|
||||
global isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15
|
||||
global isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23
|
||||
global isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31
|
||||
global irq0, irq1
|
||||
|
||||
extern interrupt_handler
|
||||
|
||||
section .text
|
||||
bits 64
|
||||
|
||||
; Macro for ISRs without error code
|
||||
%macro ISR_NOERRCODE 1
|
||||
isr%1:
|
||||
push qword 0 ; Dummy error code
|
||||
push qword %1 ; Interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; Macro for ISRs with error code
|
||||
%macro ISR_ERRCODE 1
|
||||
isr%1:
|
||||
push qword %1 ; Interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; Macro for IRQs
|
||||
%macro IRQ 2
|
||||
irq%1:
|
||||
push qword 0 ; Dummy error code
|
||||
push qword %2 ; Interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; CPU Exceptions (0-31)
|
||||
ISR_NOERRCODE 0 ; Divide by zero
|
||||
ISR_NOERRCODE 1 ; Debug
|
||||
ISR_NOERRCODE 2 ; Non-maskable interrupt
|
||||
ISR_NOERRCODE 3 ; Breakpoint
|
||||
ISR_NOERRCODE 4 ; Overflow
|
||||
ISR_NOERRCODE 5 ; Bound range exceeded
|
||||
ISR_NOERRCODE 6 ; Invalid opcode
|
||||
ISR_NOERRCODE 7 ; Device not available
|
||||
ISR_ERRCODE 8 ; Double fault
|
||||
ISR_NOERRCODE 9 ; Coprocessor segment overrun
|
||||
ISR_ERRCODE 10 ; Invalid TSS
|
||||
ISR_ERRCODE 11 ; Segment not present
|
||||
ISR_ERRCODE 12 ; Stack-segment fault
|
||||
ISR_ERRCODE 13 ; General protection fault
|
||||
ISR_ERRCODE 14 ; Page fault
|
||||
ISR_NOERRCODE 15 ; Reserved
|
||||
ISR_NOERRCODE 16 ; x87 floating-point exception
|
||||
ISR_ERRCODE 17 ; Alignment check
|
||||
ISR_NOERRCODE 18 ; Machine check
|
||||
ISR_NOERRCODE 19 ; SIMD floating-point exception
|
||||
ISR_NOERRCODE 20 ; Virtualization exception
|
||||
ISR_NOERRCODE 21 ; Reserved
|
||||
ISR_NOERRCODE 22 ; Reserved
|
||||
ISR_NOERRCODE 23 ; Reserved
|
||||
ISR_NOERRCODE 24 ; Reserved
|
||||
ISR_NOERRCODE 25 ; Reserved
|
||||
ISR_NOERRCODE 26 ; Reserved
|
||||
ISR_NOERRCODE 27 ; Reserved
|
||||
ISR_NOERRCODE 28 ; Reserved
|
||||
ISR_NOERRCODE 29 ; Reserved
|
||||
ISR_ERRCODE 30 ; Security exception
|
||||
ISR_NOERRCODE 31 ; Reserved
|
||||
|
||||
; IRQs (32-47)
|
||||
IRQ 0, 32 ; Timer
|
||||
IRQ 1, 33 ; Keyboard
|
||||
|
||||
; Common ISR stub - saves state and calls C handler
|
||||
isr_common_stub:
|
||||
; Save all general purpose registers
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
; Call C handler with pointer to register state
|
||||
mov rdi, rsp
|
||||
call interrupt_handler
|
||||
|
||||
; Restore all registers
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
; Clean up error code and interrupt number
|
||||
add rsp, 16
|
||||
|
||||
; Return from interrupt
|
||||
iretq
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
#include "kernel/kernel.h"
|
||||
#include "kernel/gdt.h"
|
||||
#include "kernel/interrupts.h"
|
||||
|
||||
/*
|
||||
* Kernel main entry point
|
||||
@@ -19,13 +21,13 @@ void kernel_main(BootInfo* boot_info) {
|
||||
// Suppress unused parameter warning
|
||||
(void)boot_info;
|
||||
|
||||
// TODO: Set up minimal page tables (identity mapped or simple offset)
|
||||
// Initialize GDT (Global Descriptor Table)
|
||||
gdt_init();
|
||||
|
||||
// TODO: Set up IDT with only interrupts we need:
|
||||
// - Keyboard/mouse (USB or PS/2)
|
||||
// - Timer (for QT event loop)
|
||||
// - GPU (if needed)
|
||||
// That's it! Maybe 5 interrupt handlers total.
|
||||
// Initialize IDT (Interrupt Descriptor Table)
|
||||
idt_init();
|
||||
|
||||
// TODO: Set up minimal page tables (identity mapped or simple offset)
|
||||
|
||||
// TODO: Simple memory allocator (bump allocator is fine)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user