More work on APIC.

alentours-dev
q3k 2012-10-29 14:57:48 +01:00
parent 05b3631004
commit 54a5e96722
6 changed files with 167 additions and 37 deletions

View File

@ -115,7 +115,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 --no-kvm -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

@ -132,31 +132,31 @@ CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
u32 Value = ConfigRead(0, i);
((u32 *)&m_Header)[i/4] = Value;
}
kprintf(" VID: %h, PID: %h\n", m_Header.VendorID, m_Header.ProductID);
kprintf(" Type: ");
switch (m_Header.HeaderType)
{
case 0x00:
kprintf("Generic Device\n");
break;
case 0x01:
kprintf("PCI-PCI Bridge\n");
break;
case 0x02:
kprintf("CardBus Bridge\n");
break;
default:
kprintf("Unknown.\n");
break;
}
// kprintf(" VID: %h, PID: %h\n", m_Header.VendorID, m_Header.ProductID);
// kprintf(" Type: ");
// switch (m_Header.HeaderType)
// {
// case 0x00:
// kprintf("Generic Device\n");
// break;
// case 0x01:
// kprintf("PCI-PCI Bridge\n");
// break;
// case 0x02:
// kprintf("CardBus Bridge\n");
// break;
// default:
// kprintf("Unknown.\n");
// break;
// }
kprintf(" Info: ");
const s8 *VendorName, *ProductName, *ProductDescription;
if (CPCIManager::DBGetVendor(m_Header.VendorID, &VendorName))
kprintf("%s", VendorName);
if (CPCIManager::DBGetProduct(m_Header.VendorID, m_Header.ProductID, &ProductName, &ProductDescription))
kprintf(" %s %s", ProductName, ProductDescription);
kprintf("\n");
// kprintf(" Info: ");
// const s8 *VendorName, *ProductName, *ProductDescription;
// if (CPCIManager::DBGetVendor(m_Header.VendorID, &VendorName))
// kprintf("%s", VendorName);
// if (CPCIManager::DBGetProduct(m_Header.VendorID, m_Header.ProductID, &ProductName, &ProductDescription))
// kprintf(" %s %s", ProductName, ProductDescription);
// kprintf("\n");
switch (m_Header.HeaderType)
{
@ -173,11 +173,11 @@ CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
if (Value == 0)
continue;
kprintf(" BAR%i: ", i);
// kprintf(" BAR%i: ", i);
if (Value & 1)
{
kprintf("I/O ");
kprintf("Value: %x\n", Value);
// kprintf("I/O ");
// kprintf("Value: %x\n", Value);
}
else
{
@ -186,13 +186,13 @@ CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
kprintf(" non 32-bit, ignoring.\n");
continue;
}
kprintf("Memory ");
kprintf("Value: %x ", Value);
// kprintf("Memory ");
// kprintf("Value: %x ", Value);
ConfigWrite(0, 0x10 + (i * 4), 0xFFFFFFFF);
u32 NewValue = ConfigRead(0, 0x10 + (i * 4));
// u32 NewValue = ConfigRead(0, 0x10 + (i * 4));
ConfigWrite(0, 0x10 + (i * 4), Value);
u32 Size = ~(NewValue & ~(0b1111)) + 1;
kprintf("Size: %x (%ik)\n", Size, Size/1024);
// u32 Size = ~(NewValue & ~(0b1111)) + 1;
// kprintf("Size: %x (%ik)\n", Size, Size/1024);
}
}
break;

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)