More work on APIC.

Conflicts:

	Kernel/src/Alentours/PCI.cpp
alentours-dev
q3k 2012-10-29 14:57:48 +01:00 committed by Sergiusz 'q3k' Bazański
parent faab8e3c55
commit 31fed61a76
5 changed files with 135 additions and 5 deletions

View File

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

View File

@ -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); \

View File

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

View File

@ -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);
}

View File

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