diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index 19c2f37..8597e2a 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -30,6 +30,8 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) cpu_init(); + __asm__("sti"); + debug_info("Boot complete\n"); @@ -39,7 +41,7 @@ void kmain(uint64_t multiboot_magic, void *multiboot_data) start_scheduler(); PANIC("End of kernel function!"); - + debug_info("Broke out of panic"); for(;;); } \ No newline at end of file diff --git a/src/kernel/cpu/apic.c b/src/kernel/cpu/apic.c new file mode 100644 index 0000000..8462d71 --- /dev/null +++ b/src/kernel/cpu/apic.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include + +#define APIC_BASE 0xFEE00000 + +#define APIC_MSR_ENABLE (1<<11) + +#define APIC_REG(r) (((uint32_t *)P2V(APIC_BASE + (r)))[0]) + +union ioapic_redirection{ + uint64_t val; + struct { + uint32_t l; + uint32_t h; + }__attribute__((packed)); + struct { + uint8_t vector; + uint8_t flags; + uint8_t mask; + uint32_t reserved; + uint8_t target; + }__attribute__((packed)); +}; + +static uint32_t ioapic_read(int reg) +{ + uint32_t volatile *ioregsel = P2V(ioapic.addr); + uint32_t volatile *iowin = P2V(ioapic.addr + 0x10); + *ioregsel = reg; + return *iowin; +} +static void ioapic_write(int reg, uint32_t value) +{ + uint32_t volatile *ioregsel = P2V(ioapic.addr); + uint32_t volatile *iowin = P2V(ioapic.addr + 0x10); + *ioregsel = reg; + *iowin = value; +} + +static uint64_t ioapic_read_redirection(int irq) +{ + union ioapic_redirection retval; + retval.l = ioapic_read(0x10 + 2*irq); + retval.h = ioapic_read(0x11 + 2*irq); + return retval.val; +} +static void ioapic_write_redirection(int irq, uint64_t val) +{ + union ioapic_redirection value; + value.val = val; + ioapic_write(0x10 + 2*irq, value.l); + ioapic_write(0x11 + 2*irq, value.h); +} + +void ioapic_init() +{ + vmm_set_page(kernel_P4, (uintptr_t)P2V(ioapic.addr), ioapic.addr, PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL); + + union ioapic_redirection red; + for(int i = 0; i < 24; i++) + { + red.val = ioapic_read_redirection(i); + red.vector = IRQ_BASE+i; + red.flags = 0x0; + if(i == 1) // Mask the timer interrupt + red.mask &= ~0x1; + else // but unmask all others for testing + red.mask |= 0x1; + red.target = 0x0; + ioapic_write_redirection(i, red.val); + } +} + +void apic_init() +{ + // Enable local APIC + write_msr(MSR_APIC_BASE, read_msr(MSR_APIC_BASE) | APIC_MSR_ENABLE); + + // Map apic offset into kernel memory + vmm_set_page(kernel_P4, (uintptr_t)P2V(APIC_BASE), APIC_BASE, PAGE_PRESENT | PAGE_WRITE | PAGE_GLOBAL); + + APIC_REG(0xF0) = APIC_REG(0xF0) | (1<<8); + APIC_REG(0xB0) = 0; +} \ No newline at end of file diff --git a/src/kernel/cpu/cpu.c b/src/kernel/cpu/cpu.c index 03e7f7b..905aea4 100644 --- a/src/kernel/cpu/cpu.c +++ b/src/kernel/cpu/cpu.c @@ -7,6 +7,26 @@ struct ioapic ioapic = {0,0,0}; uint8_t irq_redirects[MAX_IRQS] = \ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}; +#define PIC1_ADDR 0x20 +#define PIC2_ADDR 0xA0 +#define PIC_INITIALIZE 0x10 +#define PIC_SINGLE 0x02 +static void pic_disable() +{ + // Absolute minimum work to initialize and disable legacy PIC. + // Both the primary and secondary PIC will think they are alone + // in a MCS-80 arch computer but that doesn't matter since all + // interrupts will be masked anyway :) + // Ref: Intel 8259A Datasheet + outb(PIC1_ADDR, PIC_INITIALIZE | PIC_SINGLE); + outb(PIC2_ADDR, PIC_INITIALIZE | PIC_SINGLE); + outb(PIC1_ADDR | 1, 0); + outb(PIC2_ADDR | 1, 0); + // Mask all interrupts + outb(PIC1_ADDR | 1, 0xFF); + outb(PIC2_ADDR | 1, 0xFF); +} + void early_cpu_init() { interrupt_init(); @@ -15,4 +35,7 @@ void early_cpu_init() void cpu_init() { acpi_parse(); + pic_disable(); + apic_init(); + ioapic_init(); } \ No newline at end of file diff --git a/src/kernel/include/cpu.h b/src/kernel/include/cpu.h index f51e8f4..5d4c96c 100644 --- a/src/kernel/include/cpu.h +++ b/src/kernel/include/cpu.h @@ -1,8 +1,11 @@ #pragma once #include +#define MSR_APIC_BASE 0x0000001B + #define MAX_CPUS 16 #define MAX_IRQS 24 +#define IRQ_BASE 0x20 struct cpu { uint8_t id; @@ -30,4 +33,8 @@ uint64_t read_msr(uint32_t); uint64_t write_msr(uint32_t msr, uint64_t value); // cpu/acpi.c -void acpi_parse(); \ No newline at end of file +void acpi_parse(); + +// cpu/apic.c +void apic_init(); +void ioapic_init(); \ No newline at end of file