diff options
| author | Miguel <m.i@gmx.at> | 2018-09-09 03:17:52 +0200 |
|---|---|---|
| committer | Miguel <m.i@gmx.at> | 2018-09-09 03:17:52 +0200 |
| commit | fc1d491479abd74a1e038ad9ff7d4d330d79e4a8 (patch) | |
| tree | 173bc4bca336fbc8a53c9bbd3468946499e161ae | |
| parent | 9dabe01545644dd78448d8d489616872f14d964b (diff) | |
ioapic works!
| -rw-r--r-- | asm/asm_pic.asm | 7 | ||||
| -rw-r--r-- | kernel/acpi.c | 8 | ||||
| -rw-r--r-- | kernel/acpi.h | 12 | ||||
| -rw-r--r-- | kernel/interrupts.c | 38 | ||||
| -rw-r--r-- | kernel/interrupts.h | 22 | ||||
| -rw-r--r-- | kernel/kernel.c | 10 | ||||
| -rw-r--r-- | kernel/smp.c | 33 | ||||
| -rw-r--r-- | kernel/smp.h | 1 | ||||
| -rw-r--r-- | kernel/vmem.c | 55 | ||||
| -rw-r--r-- | kernel/vmem.h | 2 |
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); |
