diff options
| author | Miguel <m.i@gmx.at> | 2018-09-08 17:08:55 +0200 |
|---|---|---|
| committer | Miguel <m.i@gmx.at> | 2018-09-08 17:08:55 +0200 |
| commit | 9fde748acea83d775e367a64858414b674f05b13 (patch) | |
| tree | 0927b570c07c9ee469817a560b965c094c5d8145 /kernel | |
| parent | aa4b4c6c1918a51318709761873d1c5e248a831d (diff) | |
struggling with pic and lapic and smp...
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gdt.c | 11 | ||||
| -rw-r--r-- | kernel/interrupts.c | 26 | ||||
| -rw-r--r-- | kernel/kernel.c | 59 | ||||
| -rw-r--r-- | kernel/kernel.h | 2 | ||||
| -rw-r--r-- | kernel/scheduler.c | 11 | ||||
| -rw-r--r-- | kernel/smp.c | 119 | ||||
| -rw-r--r-- | kernel/vmem.c | 59 | ||||
| -rw-r--r-- | kernel/vmem.h | 3 |
8 files changed, 186 insertions, 104 deletions
diff --git a/kernel/gdt.c b/kernel/gdt.c index c91524a..0657387 100644 --- a/kernel/gdt.c +++ b/kernel/gdt.c @@ -9,12 +9,12 @@ //https://wiki.osdev.org/Task_State_Segment tss_struct sys_tss[SMP_MAX_PROC]; //Define the TSS as a global structure -void install_tss(uint32_t esp0){ +void install_tss(uint32_t cpu,uint32_t esp0){ // now fill each value // set values necessary - sys_tss[0].ss0 = 0x10; //kernel data - sys_tss[0].esp0 = esp0; + sys_tss[cpu].ss0 = 0x10; //kernel data + sys_tss[cpu].esp0 = esp0; // now set the IO bitmap (not necessary, so set above limit) // sys_tss.iomap = ( unsigned short ) sizeof( tss_struct ); @@ -135,7 +135,7 @@ void gdt_init() myGDT[4].type=0xF2; //TSS 0x28 - myGDT[5].base=&sys_tss[last_cpu++]; //tss start + myGDT[5].base=&sys_tss[last_cpu]; //tss start myGDT[5].limit=sizeof(tss_struct); //tss end myGDT[5].type=0x89; @@ -144,7 +144,8 @@ void gdt_init() encodeGdtEntry(&gdt_struct[8*i],myGDT[i]); // update tss entry - install_tss(0); + install_tss(last_cpu,0); + last_cpu++; setup_gdt(gdt_struct); diff --git a/kernel/interrupts.c b/kernel/interrupts.c index f93de9e..acf781d 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -57,12 +57,19 @@ void int_install() 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(); // mouse and kb if(irq==1 || irq==12 ){ uint32_t in=x86_inb(0x60); - if(irq=1)keyboard_handle(in); // do this in separate thread! + if(irq==1)keyboard_handle(in); // do this in separate thread! + // TODO: mouse + + // test ipi + apicIPI(2,170); // klog("0x60 in %d",in); } @@ -83,11 +90,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){ - klog("tick"); - writeAPIC(0xB0,0); // apic EOI + if(irq==200){ // apic timer + apicEOI(); } if(irq==255)kpanic("Unhandled Interrupt!"); + if(irq==170){ +// if(apicID()!=0)apicIPI(0,170); + apicEOI(); + } return esp; } @@ -130,6 +140,7 @@ void exception_handle(uint32_t esp, uint32_t irq) { uint32_t error_code=0; + klog("EXCEPTION: apicID: 0x%08X",apicID()); klog("EXCEPTION: vector nr.: %d",irq); switch(irq){ //this interrupts push also an error_code @@ -198,10 +209,6 @@ void exception_handle(uint32_t esp, uint32_t irq) // set default handler for all interrupts for a start void interrupts_init(uint16_t sel) { - // Setup PIC - klog("setting up PIC",&idt,&idtd); - asm_pic_setup(); - klog("initializing. IDT: 0x%08x, IDTD: 0x%08X",&idt,&idtd); // Default interrupt handling @@ -250,6 +257,9 @@ void interrupts_init(uint16_t sel) // Wake Scheduler int_install_ir(0x81, 0b11101110, 0x08,&int129); + // Wake SMP Scheduler + int_install_ir(0xAA, 0b11101110, 0x08,&int170); + // APIC Timer int_install_ir(200, 0b11101110, 0x08,&int200); diff --git a/kernel/kernel.c b/kernel/kernel.c index 30949f8..17bf9b7 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -25,9 +25,13 @@ void kernel_main(uint32_t eax,uint32_t ebx) serial_init(); klog("FOOL-OS ver-%s (%s)",GIT_REVISION,__DATE__); - klog("Programmable Interval Timer (PIT) init ..."); - uint64_t unixtime=timer_init(); - klog("Unix Time = %u seconds)",unixtime); + // while(1); + + klog("Interrupt Vector Table (IVT) init ..."); + interrupts_init(0x08); + + klog("Setting up PIC"); + asm_pic_setup(); klog("Keyboard init ..."); keyboard_init(0); @@ -44,30 +48,19 @@ void kernel_main(uint32_t eax,uint32_t ebx) klog("Memory init ... "); uint32_t kernel_blocks=mem_init(info); - - klog("Ram Filesystem init ... "); - fs_mount(info); - - klog("Interrupt Vector Table (IVT) init ..."); - interrupts_init(0x08); - + klog("Symmetrical Multi Processing (SMP) init ... "); smp_processors procdata; -// if(!mp_find(&procdata))kpanic("No MP found!"); - if(!acpi_find(&procdata))kpanic("No ACPI found!"); + if(!acpi_find(&procdata)) + if(!mp_find(&procdata))kpanic("No ACPI and no MP found!"); - // Start the other Processors (before paging because apic addr etc..?) - //TODO: remap apic !!! Check commented out sleep ()!!! - klog("Symmetric Multi Processing (SMP) start ... "); - smp_log_procdata(&procdata); - smp_start_aps(&procdata); - + // searching for ACPI etc.. in physical mem has to be performed before that. klog("Vritual Memory / Paging init ... "); - pdirectory *dir=vmem_init(kernel_blocks,(uint32_t)info->framebuffer_addr); - - klog("Peripheral Component Interconnet (PCI) init ... "); - pci_init(); + pdirectory *dir=vmem_init(kernel_blocks,(uint32_t)info->framebuffer_addr,procdata.local_apic_address); + klog("Ram Filesystem init ... "); + fs_mount(info); + klog("Video Electronics Standards Association (VESA) init ... "); // TODO check if text or fb? uint32_t addr=kballoc(1); fs_content("/binfont.bin",addr,0x100); // copy font (0x100 bytes) to memory. @@ -78,6 +71,26 @@ void kernel_main(uint32_t eax,uint32_t ebx) uint32_t sstdout = syscall_open("term",0,0); // stdout 1 uint32_t sstderr = syscall_open("stderr",0,0); // stderr 2 - klog("Enable Interrupts & Start Scheduling ..."); + klog("Scheduler init ..."); scheduler_init(dir); + + klog("Symmetric Multi Processing (SMP) start ... "); + smp_start_aps(&procdata); + + klog("Programmable Interval Timer (PIT) init ..."); + uint64_t unixtime=timer_init(); + klog("Unix Time = %u seconds)",unixtime); + + klog("Setting Interrupt Flag on BSP ..."); + asm_smp_unlock(); + x86_sti(); // this will start processing hardware interrupts. + + // TODO : pray that this is reached BEFORE scheduler kicks in!? + + klog("Unlock application processors ... "); + + while(1){ // now just wait until our scheduler kicks in. +// klog("bsp"); + asm("hlt"); + } } diff --git a/kernel/kernel.h b/kernel/kernel.h index e1a33d2..c2befbd 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -30,6 +30,4 @@ #define kpanic(...) {log(__FILE__,0," \033[41;37m--PANIC--\033[37;40m " __VA_ARGS__ ); while(1);} #define klog(...) log(__FILE__ ":" S2(__LINE__), 10, __VA_ARGS__) -//#define klog(...) __asm__("nop") - #endif diff --git a/kernel/scheduler.c b/kernel/scheduler.c index 1cbd658..72165f9 100644 --- a/kernel/scheduler.c +++ b/kernel/scheduler.c @@ -159,11 +159,12 @@ volatile uint32_t my_scheduler(uint32_t oldesp,uint32_t force_pid) if(!first) task_list[current_task].esp=oldesp; first=false; // + if(force_pid>-1) { int pid=force_pid; current_task=pid; - install_tss(task_list[pid].esp0); + install_tss(0,task_list[pid].esp0); x86_set_page_directory(task_list[pid].vmem); return task_list[pid].esp; @@ -178,7 +179,7 @@ volatile uint32_t my_scheduler(uint32_t oldesp,uint32_t force_pid) //if(current_task!=pid)klog("switch from %d to %d", current_task, pid); current_task=pid; - install_tss(task_list[pid].esp0); + install_tss(0,task_list[pid].esp0); x86_set_page_directory(task_list[pid].vmem); return task_list[pid].esp; @@ -270,12 +271,6 @@ volatile void scheduler_init(void *dir) task_pusha(task_list[2].esp); // task_pusha(task_list[1].esp); task_pusha(task_list[0].esp); - - // finally enable interrrupts so the scheduler is called (by timer) - x86_sti(); - - // loop until scheduler kicks in and reschedules us... - while(1); } volatile int task_get_current_pid() diff --git a/kernel/smp.c b/kernel/smp.c index 3709ed5..da91148 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -11,11 +11,6 @@ #include "spinlock.h" #include "asm_x86.h" -#define FOOLOS_APIC_SPUR_INT 0x00f0 -#define FOOLOS_APIC_INT_COMMAND_LOW 0x0300 -#define FOOLOS_APIC_INT_COMMAND_HIGH 0x0310 -#define FOOLOS_APIC_ID 0x020 - #define APIC_APICID 0x20 #define APIC_APICVER 0x30 #define APIC_TASKPRIOR 0x80 @@ -48,16 +43,6 @@ volatile uint8_t proc; uint32_t cpu_counter[SMP_MAX_PROC]; uint32_t local_apic_addr; -extern uint32_t LLOCK; - -void smp_main() -{ - // setup stack - uint32_t ebp=kballoc(1); - asm volatile("mov %0, %%ebp"::"r"(ebp)); - asm volatile("mov %ebp, %esp"); - asm volatile("jmp kernel_ap"); -} void writeAPIC(uint32_t offset, uint32_t value) { @@ -74,33 +59,59 @@ uint32_t readAPIC(uint32_t offset) return value; } -void kernel_ap() +uint32_t apicID() { + return readAPIC(APIC_APICID); +} - uint32_t *reg; - reg=local_apic_addr+FOOLOS_APIC_ID; - klog("smp local apic id: 0x%08X",(*reg)); +void apicEOI() +{ + writeAPIC(0xB0,0); +} - reg=local_apic_addr+FOOLOS_APIC_SPUR_INT; - klog("svr value: 0x%08X",(*reg)); - *reg|=0x100; // enable APIC +void apicIPI(uint8_t dest, uint8_t number) +{ + writeAPIC(APIC_ICRH,dest<<24); // destination apic bits 24-27 + writeAPIC(APIC_ICRL,number | (1<<14)); // send ipi +} + +void apicEnable() +{ + writeAPIC(APIC_SPURIOUS,readAPIC(APIC_SPURIOUS)|0x100); + +} + +void smp_main() +{ + // setup stack + uint32_t ebp=kballoc(1); + asm volatile("mov %0, %%ebp"::"r"(ebp)); + asm volatile("mov %ebp, %esp"); + asm volatile("jmp kernel_ap"); +} + + +void kernel_ap() +{ + klog("smp local apic id: 0x%08X",apicID()); + apicEnable(); int_install(); gdt_init(); - - uint32_t countdown=0x0fffffff; + + uint32_t countdown=0x0fffffff; // TODO: calc to be constant, depending on bus speed. (use pit for measurement?) writeAPIC(APIC_TMRDIV, 0x3); writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); writeAPIC(APIC_TMRINITCNT, countdown); - x86_sti(); - LLOCK=0; // release lock, so next ap can continue... + + asm_smp_unlock(); while(1) { asm("hlt"); - klog("tack: 0x%08X: 0x%08X",readAPIC(FOOLOS_APIC_ID), readAPIC(APIC_TMRCURRCNT)); + klog("tack: 0x%08X: 0x%08X",readAPIC(APIC_APICID), readAPIC(APIC_TMRCURRCNT)); } // switch_to_user_mode(); @@ -135,30 +146,13 @@ void kernel_ap_old() } } -void smp_log_procdata(smp_processors *procdata) -{ - klog("---- smp -----"); - for(int i=0;i<procdata->processors;i++) - { - klog("cpu %d, apic_id: 0x%X, bps: %s, apic_addr:0x%08X",i,procdata->local_apic_id[i],i==procdata->boot?"yes":"no",procdata->local_apic_address); - } - -} - // this will start all our application processors! void smp_start_aps(smp_processors *pros) { - - // TODO: check if local APIC is present via CPUID (P6 (i686) and above) + // TODO: check if local APIC is present via CPUID (P6 (i686) and above) local_apic_addr=pros->local_apic_address; - //bsp (boot processor) enables its local apic -// uint32_t *reg=local_apic_addr+FOOLOS_APIC_SPUR_INT; -// *reg=0xffffffff; // all bits 1 and interrupt 255 (is this not set anyway?) -// *reg=0; - - uint32_t *reg=local_apic_addr+FOOLOS_APIC_ID; - klog("bsp local apic id: 0x%08X",(*reg)); + klog("bsp local apic id: 0x%08X",apicID()); for(int i=0;i<pros->processors;i++) { @@ -167,18 +161,35 @@ void smp_start_aps(smp_processors *pros) uint8_t dest=pros->local_apic_id[i]; klog("starting cpu %d (dest: %d) ",i,dest); - reg=local_apic_addr+FOOLOS_APIC_INT_COMMAND_HIGH; + uint32_t *reg; + + reg=local_apic_addr+APIC_ICRH; *reg=dest<<24; // destination apic. - reg=local_apic_addr+FOOLOS_APIC_INT_COMMAND_LOW; - *reg=(5<<8)|(1<<14); // 101 INIT + reg=local_apic_addr+APIC_ICRL; + *reg=(5<<8)|(1<<14); // 101 INIT IPI - // do we really neet this? - // TODO!! - // todo: use some real sleep (not implemented yet :( ) - //sleep(30); + // TODO: wait 10 milliseconds + // https://wiki.osdev.org/Symmetric_Multiprocessing - // start proc 0x7 = at addr 0x7000; *reg=(6<<8)|(1<<14)|0x7; // 110 SIPI + // TODO: poll a flag?(timeout 1ms) + // TODO retry 110 SIPI with 1s timeout + } + + apicEnable(); // bsp seems to be enabled anyway. + + writeAPIC(APIC_TMRDIV, 0x3); + writeAPIC(APIC_TMRINITCNT, 0xFFFFFFFF); + //asm_pit_sleep_1ms(); + //writeAPIC(APIC_LVT_TMR, APIC_LVT_INT_MASKED); //?? + uint32_t ticksInS = 0xFFFFFFFF - readAPIC(APIC_TMRCURRCNT); + + klog("%d MHz bus speed",ticksInS/1000); + + uint32_t countdown=0x0fffffff; // TODO: calc to be constant, depending on bus speed. (use pit for measurement?) + writeAPIC(APIC_TMRDIV, 0x3); + writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); + writeAPIC(APIC_TMRINITCNT, countdown); } diff --git a/kernel/vmem.c b/kernel/vmem.c index 1652a9e..6d34a08 100644 --- a/kernel/vmem.c +++ b/kernel/vmem.c @@ -7,6 +7,7 @@ static uint32_t kernel_pages; uint32_t fb_addr; +uint32_t apic_addr; // TODO : why is the frame not 0xfffff?? enum PAGE_PTE_FLAGS @@ -222,7 +223,7 @@ void vmem_free_dir(pdirectory *dir) // programm pages procreates new programmspace // // TODO: FIX -// KERNEL SPACE `kernel_pages` first PAGES +// KERNEL SPACE `kernel_pages` first 8 PAGES = 32megs // FRAMEBUFER WE GET ON INIT // PROGRAMM SPACE HARDCODED TO 0x8000000+2 pages and 0x8c00000+1 pages // @@ -244,6 +245,8 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) uint32_t phys_addr=0; uint32_t virt_addr=0; + kernel_pages=8; + // first pages are identity mapped for(int j=0;j<kernel_pages;j++) { @@ -346,6 +349,57 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) virt_addr+=1024*4096; } + // 2 pages for apic ( in case on boundary??) + phys_addr=apic_addr; + virt_addr=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++) @@ -478,9 +532,10 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only) return dir; } -pdirectory* vmem_init(uint32_t kernel_blocks, uint32_t frameb_addr) +pdirectory* vmem_init(uint32_t kernel_blocks, uint32_t frameb_addr, uint32_t apic_ad) { fb_addr=frameb_addr; + apic_addr=apic_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 bfd758e..3a2a8e6 100644 --- a/kernel/vmem.h +++ b/kernel/vmem.h @@ -47,7 +47,6 @@ * */ - //! i86 architecture defines 1024 entries per table--do not change #define PAGES_PER_TABLE 1024 #define PAGES_PER_DIR 1024 @@ -81,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); +pdirectory* vmem_init(uint32_t kernel_blocks,uint32_t fb_addr,uint32_t apic_addr); |
