From 31fed61a7694716025b0e5b314ec8c151b003955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergiusz=20Baza=C5=84ski?= Date: Mon, 29 Oct 2012 14:57:48 +0100 Subject: [PATCH] More work on APIC. Conflicts: Kernel/src/Alentours/PCI.cpp --- Kernel/Makefile | 2 +- Kernel/include/preprocessor_hacks.h | 19 +++++++ Kernel/src/Tier0/apic.c | 79 +++++++++++++++++++++++++++-- Kernel/src/Tier0/exceptions.c | 3 ++ Kernel/src/Tier0/interrupts.c | 37 ++++++++++++++ 5 files changed, 135 insertions(+), 5 deletions(-) diff --git a/Kernel/Makefile b/Kernel/Makefile index c83a697..98d5718 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -91,7 +91,7 @@ hdd.img: kernel.bin emulate-nohdd-debug: kernel.bin @echo "[i] Starting GDB..." - @echo -e "target remote localhost:1234\n" > gdbcommands + @echo -e "file kernel.bin\ntarget remote localhost:1234\n" > gdbcommands @terminal -x /bin/bash -c "sleep 1 && gdb -x gdbcommands && rm gdbcommands" & @echo "[i] Starting QEmu..." @qemu-system-x86_64 -S -gdb tcp::1234 -d int -smp 4 -kernel ../Loader/loader.bin -initrd kernel.bin diff --git a/Kernel/include/preprocessor_hacks.h b/Kernel/include/preprocessor_hacks.h index a963236..808149e 100644 --- a/Kernel/include/preprocessor_hacks.h +++ b/Kernel/include/preprocessor_hacks.h @@ -16,6 +16,25 @@ x(7); \ x(8); \ x(9); \ +//Do something 10 times +#define PPHAX_DO16(x) \ +x(0); \ +x(1); \ +x(2); \ +x(3); \ +x(4); \ +x(5); \ +x(6); \ +x(7); \ +x(8); \ +x(9); \ +x(10); \ +x(11); \ +x(12); \ +x(13); \ +x(14); \ +x(15); \ + //Do something 256 times #define PPHAX_DO256(x) \ x(0); \ diff --git a/Kernel/src/Tier0/apic.c b/Kernel/src/Tier0/apic.c index 93bef65..cd76ec1 100755 --- a/Kernel/src/Tier0/apic.c +++ b/Kernel/src/Tier0/apic.c @@ -2,11 +2,33 @@ #include "Tier0/system.h" #include "Tier0/kstdio.h" #include "Tier0/paging.h" +#include "Tier0/interrupts.h" +#include "Tier0/panic.h" + +#define APIC_SET32(field, value) do { *((u32 *)(g_APIC.LAPIC + field)) = (value);} while(0) +#define APIC_GET32(field) (*((u32*)(g_APIC.LAPIC + field))) +#define APIC_SET32A(field, value) do { APIC_SET32(field, value); ASSERT(APIC_GET32(field) == (value));} while(0) struct { - T_APIC_LAPIC *APIC; + void *LAPIC; } g_APIC; +void apic_eoi(void) +{ + APIC_SET32(APIC_EOI, 0xFFFFFFFF); +} + +void apic_spurious_interrupt(T_ISR_REGISTERS Registers) +{ + +} + +void apic_timer_interrupt(T_ISR_REGISTERS Registers) +{ + kprintf("ohai\n"); +} + + void apic_enable_lapic(void) { u64 APICMSR = system_msr_get(0x1B); @@ -16,13 +38,62 @@ void apic_enable_lapic(void) else { kprintf("[i] APIC enable flag not set in APIC MSR. Trying to set it...\n"); - APICMSR |= (1 << 22); + APICMSR |= (1 << 11); system_msr_set(0x1B, APICMSR); } u64 Virtual = paging_minivmm_allocate(); kprintf("[i] LAPIC will be @0x%x.\n", Virtual); paging_map_page(Virtual, 0xFEE00000); - - g_APIC.APIC = (T_APIC_LAPIC *)Virtual; + + g_APIC.LAPIC = (void *)Virtual; + + // reset APIC to a kinda known state + APIC_SET32A(APIC_DFR, 0xFFFFFFFF); + APIC_SET32(APIC_LDR, (APIC_GET32(APIC_LDR)&0x00FFFFFF)|1); + APIC_SET32A(APIC_LVTTimer, 0x10000); // mask bit + APIC_SET32A(APIC_LVTPerformanceCounter, 4 << 8); // NMI bit + APIC_SET32A(APIC_LVTLINT0, 0x10000); // mask bit + APIC_SET32A(APIC_LVTLINT1, 0x10000); // mask bit + APIC_SET32A(APIC_TPR, 0); // task priority = 0 (accept all) + + // prepare interrupts .. + interrupts_setup_isr(39, (void *)apic_spurious_interrupt, E_INTERRUPTS_RING0); + interrupts_setup_isr(32, (void *)apic_timer_interrupt, E_INTERRUPTS_RING0); + + APIC_SET32A(APIC_SVR, 39 | 0x100); // spurious interrupt + sw enable bit + APIC_SET32A(APIC_LVTTimer, 32); // apic timer interrupt + APIC_SET32A(APIC_TimerDCR, 0x03); // timer divider = bus speed / 16 + + kprintf("[i] LAPIC ready to calibrate timer.\n"); + + // calibration time! let's use the PIT + koutb(0x61, kinb(0x61) | 0xFD); // disable speaker + koutb(0x43, 0xB2); // one shot, channel 2 + + // to setup a 100Hz loop, wee need a divider of... + // 1193180 / 100 Hz = 11931 = 0x2e9b + koutb(0x42, 0x9b); // write low byte + kinb(0x60); // wait a bit + koutb(0x42, 0x2e); // write high bte + + // now we are ready to fire the PIT timer + kprintf("[i] Firing PIT for calibration...\n"); + u8 Temporary = kinb(0x61) & 0xFE; + koutb(0x61, Temporary); // gate low + koutb(0x61, Temporary | 1); // gate high + // don't forget to actually fire the APIC timer at the same time... + APIC_SET32(APIC_TimerICR, 0xFFFFFFFF); + // for(;;) + // { + // kprintf("APIC: %x\n", APIC_GET32(APIC_TimerICR)); + // } + + // wait for the PIT counter to reach zero... + while (!(kinb(0x61) & 0x020)); + // disable APIC timer + APIC_SET32(APIC_LVTTimer, 0x10000); // mask bit + kprintf("[i] Timer reached zero, APIC Timer @%x.\n", APIC_GET32(APIC_TimerICR)); } + +#undef APIC_SET \ No newline at end of file diff --git a/Kernel/src/Tier0/exceptions.c b/Kernel/src/Tier0/exceptions.c index 413e9d8..def4d68 100644 --- a/Kernel/src/Tier0/exceptions.c +++ b/Kernel/src/Tier0/exceptions.c @@ -46,6 +46,9 @@ void exceptions_floating_point_isr(T_ISR_REGISTERS Registers) void exceptions_general_protection_isr(T_ISR_REGISTERS_ERR Registers) { T_ISR_REGISTERS NoErr; + kprintf("general protection fault %x.\n", Registers.Error); + __asm__ __volatile__("cli;"); + for (;;) RERR_TO_R(Registers, NoErr); PANIC_EX("General protection fault in kernel task.", NoErr); } diff --git a/Kernel/src/Tier0/interrupts.c b/Kernel/src/Tier0/interrupts.c index ff82c95..4f1021f 100644 --- a/Kernel/src/Tier0/interrupts.c +++ b/Kernel/src/Tier0/interrupts.c @@ -2,6 +2,7 @@ #include "Tier0/paging.h" #include "Tier0/kstdio.h" #include "Tier0/pic.h" +#include "preprocessor_hacks.h" struct { // IDT @@ -113,10 +114,46 @@ void interrupts_setup_isr(u8 Interrupt, void *Handler, \ *((u32*)&g_idt_entries[Interrupt]) = 0; } */ + +void interrupts_remap_pic(void) +{ + // remap the PIC IRQ's to 0x20-0x27 and 0x28-0x2F + + // save masks + u8 MaskMaster = kinb(0x21); + u8 MaskSlave = kinb(0xA1); + + koutb(0x20, 0x11); // start initialization sequence + koutb(0xA0, 0x11); // - " - + + koutb(0x21, 0x20); // master from 0x20 + koutb(0xA1, 0x28); // slave from 0x28 + koutb(0x21, 0x04); // slave PIC at IRQ2 + koutb(0xA1, 0x02); // cascade + koutb(0x21, 0x01); // 8086 mode + koutb(0xA1, 0x01); // 8086 mode + + // restore masks + koutb(0x21, MaskMaster); + koutb(0xA1, MaskSlave); +} + +#define GENERIC_IRQ_DEF(i) void interrupts_irq##i##_isr(void) { kprintf("[w] OOPS: Unhandled IRQ"#i"\n"); } +#define GENERIC_IRQ_BIND(i) interrupts_setup_isr(0x20 + i, (void *)interrupts_irq##i##_isr, E_INTERRUPTS_RING0) +PPHAX_DO16(GENERIC_IRQ_DEF); + void interrupts_init_simple(void) { interrupts_init_idt(); interrupts_lidt(); + interrupts_remap_pic(); + + // generic IRQ handlers + PPHAX_DO16(GENERIC_IRQ_BIND); + + // enable hardware interrupts + __asm__ __volatile__("sti;"); + kprintf("[i] Hardware interrupts enabled.\n"); } /* void interrupts_irq_finish(u8 IRQ)