summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm/asm_pic.asm7
-rw-r--r--kernel/acpi.c8
-rw-r--r--kernel/acpi.h12
-rw-r--r--kernel/interrupts.c38
-rw-r--r--kernel/interrupts.h22
-rw-r--r--kernel/kernel.c10
-rw-r--r--kernel/smp.c33
-rw-r--r--kernel/smp.h1
-rw-r--r--kernel/vmem.c55
-rw-r--r--kernel/vmem.h2
10 files changed, 151 insertions, 37 deletions
diff --git a/asm/asm_pic.asm b/asm/asm_pic.asm
index 8a90fdf..a665221 100644
--- a/asm/asm_pic.asm
+++ b/asm/asm_pic.asm
@@ -78,11 +78,12 @@ in al, 0xA1 ; read in the primary PIC Interrupt Mask Register (IMR)
and al, 0x00 ; 0xEF => 11101111b. This sets the IRQ4 bit (Bit 5) in AL
out 0xA1, al ; write the value back into IMR
+;ret
;disable
-;mov al, 0xff
-;out 0xa1, al
-;out 0x21, al
+mov al, 0xff
+out 0xa1, al
+out 0x21, al
ret
diff --git a/kernel/acpi.c b/kernel/acpi.c
index f5c18ca..5192c37 100644
--- a/kernel/acpi.c
+++ b/kernel/acpi.c
@@ -1,9 +1,4 @@
-#include "kernel/kernel.h"
-// Advanced Configuration and Power Interface
-// http://wiki.xomb.org/index.php?title=ACPI_Tables
-// https://wiki.osdev.org/MADT#Entry_Type_1_:_I.2FO_APIC
-
-
+#include "kernel.h"
#include <stdint.h>
#include <stdbool.h>
#include "smp.h"
@@ -79,6 +74,7 @@ uint8_t *apci_get_next_entry(uint8_t *addr,smp_processors *procdata)
else if(*addr==1)
{
klog("Type 1: IO APIC (id=%d) (addr=0x%08X) (base=%d)",addr[2], *((uint32_t*)&addr[4]),*((uint32_t*)&addr[8]));
+ procdata->io_apic_address=*((uint32_t*)&addr[4]);
}
else if(*addr==2){
klog("Type 2: Interrupt Source Override (bus src=%d) (irq src=%d) (global=%d) (flags=%d)",addr[2],addr[3],*((uint32_t*)&addr[4]),*((uint16_t*)&addr[8]));
diff --git a/kernel/acpi.h b/kernel/acpi.h
index b7c7342..ce8d710 100644
--- a/kernel/acpi.h
+++ b/kernel/acpi.h
@@ -1,2 +1,14 @@
+/**
+ * @file
+ *
+ * Advanced Configuration and Power Interface
+ * ==========================================
+ *
+ * Ref
+ * ---
+ * http://wiki.xomb.org/index.php?title=ACPI_Tables
+ * https://wiki.osdev.org/MADT#Entry_Type_1_:_I.2FO_APIC
+ */
+
#include "smp.h"
bool acpi_find(smp_processors *procdata);
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index 30d8994..992889f 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -60,7 +60,9 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
// DO NOT WRITE INSIDE INTERRUPTS!! COZ IT ACQUIRES LOCK AND WE WILL DEADLOCK
//klog("int: %d on 0x%x",irq,apicID());
- if(irq==0)asm_pit_tick();
+ if(irq==0){
+ asm_pit_tick();
+ }
// mouse and kb
if(irq==1 || irq==12 ){
@@ -69,7 +71,7 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
// TODO: mouse
// test ipi
- apicIPI(2,170);
+// apicIPI(2,170);
// klog("0x60 in %d",in);
}
@@ -90,15 +92,14 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
if(irq==0 || irq==129)esp=my_scheduler(esp,-1); // autoschedule
- if(irq==200){ // apic timer
- apicEOI();
- }
- if(irq==255)kpanic("Unhandled Interrupt!");
+ if(irq==200){} // apic timer
if(irq==170){
// if(apicID()!=0)apicIPI(0,170);
- apicEOI();
}
+ //if(irq==255)kpanic("Unhandled Interrupt!");
+
+ if(irq!=0x81 && irq!=0x80)apicEOI();
return esp;
}
@@ -238,30 +239,25 @@ void interrupts_init(uint16_t sel)
int_install_ir(17, 0b10001110, 0x08,&exc17);
int_install_ir(18, 0b10001110, 0x08,&exc18);
+ // PIT
+ int_install_ir(0x90, 0b10001110, 0x08,&int0);
- // Custom interrupts (hardcoded)
- // remember that we shifted all interrupts with the pic by 32
-
- // PIT interrupt handler (irq 0 => 32)
- int_install_ir(32, 0b10001110, 0x08,&int0);
-
- // Keyboard interrupt handler (irq 1 => 33)
- int_install_ir(33, 0b10001110, 0x08,&int1);
+ // Keyboard
+ int_install_ir(0x91, 0b10001110, 0x08,&int1);
- // Mouse interrupt handler (irq 12 => 34)
- int_install_ir(44, 0b10001110, 0x08,&int12);
+ // Mouse
+ int_install_ir(0x92, 0b10001110, 0x08,&int12);
// System Calls / they can be called from ring3 (0b11)
int_install_ir(0x80, 0b11101110, 0x08,&int128);
- // Wake Scheduler
+ // IPI
int_install_ir(0x81, 0b11101110, 0x08,&int129);
- // Wake SMP Scheduler
- int_install_ir(0xAA, 0b11101110, 0x08,&int170);
+ int_install_ir(170, 0b11101110, 0x08,&int170);
// APIC Timer
- int_install_ir(200, 0b11101110, 0x08,&int200);
+ int_install_ir(0x8C, 0b11101110, 0x08,&int200);
// install IVT
int_install();
diff --git a/kernel/interrupts.h b/kernel/interrupts.h
index 637fcfd..ab76092 100644
--- a/kernel/interrupts.h
+++ b/kernel/interrupts.h
@@ -2,6 +2,28 @@
#define INTERRUPTS_H
#include <stdint.h>
+/**
+ * @file
+ *
+ * Interrupts
+ * ==========
+ * 0x00-0x12 Exceptions
+ * 0x20-0x27 disabled pic
+ * 0x28-0x36 disabled pic
+ *
+ * Hardware
+ * --------
+ * 0x0 PIT Timer -> 0x90
+ * 0x1 Keyboard -> 0x91
+ * 0xC Mouse -> 0x92
+ *
+ * 0x8C APIC Timer
+ *
+ * Software
+ * ========
+ * 0x80 System Call
+ * 0x81 IPI
+ */
void interrupts_init(uint16_t sel);
#endif
diff --git a/kernel/kernel.c b/kernel/kernel.c
index e20d2e1..bdb34d9 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -31,7 +31,7 @@ void kernel_main(uint32_t eax,uint32_t ebx)
klog("Interrupt Vector Table (IVT) init ...");
interrupts_init(0x08);
- klog("Remapping & (not yet Disabling) PIC ...");
+ klog("Remapping & Disabling PIC ...");
asm_pic_setup();
klog("Keyboard init ...");
@@ -59,7 +59,7 @@ void kernel_main(uint32_t eax,uint32_t ebx)
uint32_t kernel_blocks=mem_init(info);
klog("Vritual Memory / Paging init ... ");
- pdirectory *dir=vmem_init(kernel_blocks,(uint32_t)info->framebuffer_addr,procdata.local_apic_address);
+ pdirectory *dir=vmem_init(kernel_blocks,(uint32_t)info->framebuffer_addr,procdata.local_apic_address,procdata.io_apic_address);
//
klog("Ram Filesystem init ... ");
@@ -85,10 +85,10 @@ void kernel_main(uint32_t eax,uint32_t ebx)
uint64_t unixtime=timer_init();
klog("Unix Time = %u seconds)",unixtime);
- klog("Enable Interrupts & Unlock application processors ... ");
+ klog("Unlock application processors ... ");
asm_smp_unlock();
- // TODO : bsp sti needs to happen before ap sti? seriously? why? is this guaranteed now?
- // TODO: switch to ioapic
+
+ klog("Enable Interrupts ... ");
x86_sti(); // this will start processing hardware interrupts
// now just wait until our scheduler kicks in.
diff --git a/kernel/smp.c b/kernel/smp.c
index b2ce6b0..0c8d2dd 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -43,8 +43,30 @@ volatile uint8_t proc;
uint32_t cpu_counter[SMP_MAX_PROC];
uint32_t local_apic_addr;
+uint32_t io_apic_addr;
+
uint32_t countdown;
+void writeIOAPIC(uint32_t offset, uint32_t value)
+{
+ uint32_t *reg=io_apic_addr;
+ reg[0]=(offset & 0xff);
+ reg[4]= value;
+}
+
+uint32_t readIOAPIC(uint32_t offset)
+{
+ uint32_t *reg=io_apic_addr;
+ reg[0]=(offset & 0xff);
+ return reg[4];
+}
+
+void irqIOAPIC(uint32_t irq, uint32_t low, uint32_t high)
+{
+ writeIOAPIC(0x10+irq*2,low);
+ writeIOAPIC(0x11+irq*2,high);
+}
+
void writeAPIC(uint32_t offset, uint32_t value)
{
uint32_t *reg;
@@ -180,6 +202,8 @@ void smp_start_aps(smp_processors *pros)
{
// TODO: check if local APIC is present via CPUID (P6 (i686) and above)
local_apic_addr=pros->local_apic_address;
+ io_apic_addr=pros->io_apic_address;
+
klog("bsp local apic id: 0x%08X",apicID());
apicEnable(); // bsp apic seems to be enabled anyway.
@@ -192,6 +216,15 @@ void smp_start_aps(smp_processors *pros)
writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); // on interrupt 200
writeAPIC(APIC_TMRINITCNT, countdown);
+ // setup IO APIC
+ // PIT irq 00 -> 02 flags 0 -> 0x90
+ // kb irq 01 -> 01 flags ? -> 0x91
+ // mouse irq 12 -> 12 flags ? -> 0x92
+
+ irqIOAPIC(2,0x90,0x0);
+ irqIOAPIC(1,0x91,0x0);
+ irqIOAPIC(12,0x92,0x0);
+
for(int i=0;i<pros->processors;i++)
{
if(pros->boot==i)continue;
diff --git a/kernel/smp.h b/kernel/smp.h
index 61058fc..ef0a660 100644
--- a/kernel/smp.h
+++ b/kernel/smp.h
@@ -12,6 +12,7 @@ typedef struct
uint8_t processors; // total number of usable processors
uint32_t local_apic_address;// same for every processor
+ uint32_t io_apic_address;
uint32_t local_apic_id[SMP_MAX_PROC]; // unique for every processor
diff --git a/kernel/vmem.c b/kernel/vmem.c
index 6d34a08..0dd896c 100644
--- a/kernel/vmem.c
+++ b/kernel/vmem.c
@@ -8,6 +8,7 @@
static uint32_t kernel_pages;
uint32_t fb_addr;
uint32_t apic_addr;
+uint32_t io_apic_addr;
// TODO : why is the frame not 0xfffff??
enum PAGE_PTE_FLAGS
@@ -400,6 +401,57 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only)
phys_addr+=1024*4096;
virt_addr+=1024*4096;
}
+ // 2 pages for ioapic ( in case on boundary??)
+ phys_addr=io_apic_addr;
+ virt_addr=io_apic_addr;
+
+ for(int j=0;j<2;j++)
+ {
+
+ // this is the table for our page directory. It maps 1024*4096 bytes
+ ptable* table;
+
+ // create new tables on init
+ if(copy_dir==NULL)
+ {
+ // alloc space for our new table
+ table = (ptable*) kballoc(1);
+ if (!table)kpanic("unable to alloc table");
+
+ //! idenitity mapping
+ for (int i=0, frame=phys_addr, virt=virt_addr; i<1024; i++, frame+=4096, virt+=4096)
+ {
+ //! create a new page
+ pt_entry page=0;
+ pt_entry_add_attrib (&page, I86_PTE_PRESENT);
+ pt_entry_add_attrib (&page, I86_PTE_WRITABLE);
+ pt_entry_add_attrib (&page, I86_PTE_USER);
+ pt_entry_set_frame (&page, frame);
+
+ //! ...and add it to the page table
+ table->m_entries [PAGE_TABLE_INDEX (virt) ] = page;
+ }
+
+ pd_entry* entry = &dir->m_entries [PAGE_DIRECTORY_INDEX (virt_addr) ];
+ *entry=0;
+ pd_entry_add_attrib (entry, I86_PDE_PRESENT);
+ pd_entry_add_attrib (entry, I86_PDE_WRITABLE);
+ pt_entry_add_attrib (entry, I86_PTE_USER);
+ pd_entry_set_frame (entry, (physical_addr)table);
+
+ }
+
+ // otherwise simply take existing stuff from pdir 0
+ else
+ {
+ dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)]=
+ copy_dir->m_entries[PAGE_DIRECTORY_INDEX(virt_addr)];
+
+ }
+
+ phys_addr+=1024*4096;
+ virt_addr+=1024*4096;
+ }
// programm space
virt_addr=0x8000000;
for(int j=0;j<2;j++)
@@ -532,10 +584,11 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only)
return dir;
}
-pdirectory* vmem_init(uint32_t kernel_blocks, uint32_t frameb_addr, uint32_t apic_ad)
+pdirectory* vmem_init(uint32_t kernel_blocks, uint32_t frameb_addr, uint32_t apic_ad, uint32_t ioapic_ad)
{
fb_addr=frameb_addr;
apic_addr=apic_ad;
+ io_apic_addr=ioapic_ad;
kernel_pages=kernel_blocks/1024+1;
return vmem_new_space_dir(NULL,false);
}
diff --git a/kernel/vmem.h b/kernel/vmem.h
index 3a2a8e6..541a84a 100644
--- a/kernel/vmem.h
+++ b/kernel/vmem.h
@@ -80,4 +80,4 @@ typedef struct pdirectory_struct {
pd_entry m_entries[PAGES_PER_DIR];
}pdirectory;
-pdirectory* vmem_init(uint32_t kernel_blocks,uint32_t fb_addr,uint32_t apic_addr);
+pdirectory* vmem_init(uint32_t kernel_blocks,uint32_t fb_addr,uint32_t apic_addr, uint32_t ioapic_addr);