APIC init
authorJack Miller <jack@codezen.org>
Sat, 19 Mar 2016 18:53:58 +0000 (13:53 -0500)
committerJack Miller <jack@codezen.org>
Sat, 19 Mar 2016 19:02:48 +0000 (14:02 -0500)
include/apic.h [new file with mode: 0644]
include/cpuid.h
kernel/apic.c [new file with mode: 0644]
kernel/main.c

diff --git a/include/apic.h b/include/apic.h
new file mode 100644 (file)
index 0000000..a4f2571
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+
+struct apic {
+    void (*init) (void);
+    void (*eoi) (void);
+};
+
+int apic_init(void);
+
+struct apic *apic;
index 2e3fc66..33922b3 100644 (file)
@@ -1,3 +1,5 @@
 #pragma once
 
+#include <asm/misc.h>
+
 int cpuid_init(void);
diff --git a/kernel/apic.c b/kernel/apic.c
new file mode 100644 (file)
index 0000000..3e0dba2
--- /dev/null
@@ -0,0 +1,116 @@
+/* vim: set ts=4 sw=4 sts=4 noet : */
+
+#include <console.h>
+#include <cpuid.h>
+#include <memmap.h>
+#include <vmalloc.h>
+#include <map.h>
+#include <apic.h>
+#include <mmio.h>
+
+#define CPUID_X2APIC   (1 << 21)
+#define CPUID_LAPIC            (1 << 9)
+
+#define MSR_IA32_APIC_BASE     0x1B
+
+#define MSR_X2APIC_BASE                                0x800
+#define MSR_X2APIC_VERSION                     (MSR_X2APIC_BASE | 0x3)
+
+#define MSR_X2APIC_LVT_TIMER           (MSR_X2APIC_BASE | 0x32)
+#define                LVT_TIMER_PERIODIC              (1 << 17)
+#define                LVT_TIMER_VECTOR(x)             (x & 0xff)
+#define                LVT_MASKED                              (1 << 16)
+
+#define MSR_X2APIC_TIMER_INIT_CT       (MSR_X2APIC_BASE | 0x38)
+#define MSR_X2APIC_TIMER_CUR_CT                (MSR_X2APIC_BASE | 0x39)
+#define MSR_X2APIC_TIMER_DIVIDE                (MSR_X2APIC_BASE | 0x3e)
+
+#define XAPIC_ENABLE           (1 << 11)
+#define XAPIC_EXTD                     (1 << 10)
+
+static void xapic_init(void)
+{
+       volatile u64 *mmio_mem;
+       u64 msr;
+       u32 lvt;
+
+       msr = rdmsr(MSR_IA32_APIC_BASE);
+       wrmsr(MSR_IA32_APIC_BASE, msr | XAPIC_ENABLE);
+
+       mmio_mem = vmalloc("APIC", VMALLOC_HEAP_VIRTUAL, PAGE_SIZE);
+
+       map_page_nocache((u64) mmio_mem, msr & ~(0xFFFUL));
+
+       mmio_write(mmio_mem, 0x3e0, 0x11);
+       mmio_write(mmio_mem, 0x380, 0x1000);
+
+       lvt = mmio_read(mmio_mem, 0x320);
+
+       lvt &= ~LVT_MASKED;
+       lvt |= LVT_TIMER_VECTOR(32) | LVT_TIMER_PERIODIC;
+
+       mmio_write(mmio_mem, 0x320, lvt);
+}
+
+static void xapic_eoi(void)
+{
+
+}
+
+struct apic xapic = {
+       .init = xapic_init,
+       .eoi = xapic_eoi,
+};
+
+static void x2apic_init(void)
+{
+       u64 msr = rdmsr(MSR_IA32_APIC_BASE);
+
+       wrmsr(MSR_IA32_APIC_BASE, msr | XAPIC_ENABLE | XAPIC_EXTD);
+
+       wrmsr(MSR_X2APIC_TIMER_DIVIDE, 0x11); // divide by 1
+
+       wrmsr(MSR_X2APIC_TIMER_INIT_CT, 0x1000);
+
+       msr = rdmsr(MSR_X2APIC_LVT_TIMER);
+
+       msr &= ~LVT_MASKED;
+
+       wrmsr(MSR_X2APIC_LVT_TIMER, msr | LVT_TIMER_PERIODIC | LVT_TIMER_VECTOR(32));
+
+       msr = rdmsr(MSR_X2APIC_LVT_TIMER);
+
+       printk("timer reg: %x\n", msr);
+}
+
+static void x2apic_eoi(void)
+{
+
+}
+
+struct apic x2apic = {
+       .init = x2apic_init,
+       .eoi = x2apic_eoi,
+};
+
+int apic_init(void)
+{
+       u32 regs[4];
+
+       cpuid(0x1, regs);
+
+       if(regs[2] & CPUID_X2APIC) {
+               printk("x2apic detected\n");
+               apic = &x2apic;
+       } else if (regs[3] & CPUID_LAPIC) {
+               printk("xapic detected\n");
+               apic = &xapic;
+       } else {
+               printk("no APIC detected\n");
+               return -1;
+       }
+
+       apic->init();
+
+    return 0;
+}
index ee508c4..0d44df8 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <page_alloc.h>
 #include <console.h>
+#include <asm/misc.h>
+#include <apic.h>
 #include <cpuid.h>
 #include <vga.h>
 
@@ -13,9 +15,15 @@ void main (void *info_phys, unsigned long end_structures)
 
        console_init();
 
+       disable_pic();
+
+       asm ("sti" : : );
+
        printk("Viridis %d.%d-g%s\n", __MAJOR_VERSION__,__MINOR_VERSION__, __GIT_VERSION__);
 
        cpuid_init();
 
+       apic_init();
+
        asm ("hlt" : : );
 }