From aa4b4c6c1918a51318709761873d1c5e248a831d Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 7 Sep 2018 03:01:28 +0200 Subject: apic timer smp --- README.md | 2 +- asm/asm_int.h | 1 + asm/asm_int.s | 2 ++ asm/asm_mp.asm | 5 ++-- kernel/gdt.c | 19 ++++++++---- kernel/interrupts.c | 14 +++++++-- kernel/kernel.c | 11 ++++--- kernel/kernel.h | 3 ++ kernel/kmalloc.c | 12 +++++--- kernel/smp.c | 81 ++++++++++++++++++++++++++++++++++++++++++--------- kernel/smp.h | 2 +- userspace/foolshell.c | 2 +- 12 files changed, 116 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 565a742..efd3a29 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Discontinued Features Todos ----- -* cpuid +* cpuid (i686) check apic? * lapic / spurious . ioapic * newlib reentrant struct!! * Interrupts between BSP and APS ? diff --git a/asm/asm_int.h b/asm/asm_int.h index 4133fbf..25ab885 100644 --- a/asm/asm_int.h +++ b/asm/asm_int.h @@ -17,6 +17,7 @@ void int15(); void int128(); // syscalls void int129(); // scheduler +void int200(); // apic timer void int255(); // unhandled void exc0(); diff --git a/asm/asm_int.s b/asm/asm_int.s index 94785bc..f7107de 100644 --- a/asm/asm_int.s +++ b/asm/asm_int.s @@ -18,6 +18,7 @@ .global int128 .global int129 +.global int200 .global int255 .global exc0 @@ -157,6 +158,7 @@ int128: intx ack0 $128 interrupt_handler int129: intx ack0 $129 interrupt_handler int255: intx ack0 $255 interrupt_handler +int200: intx ack0 $200 interrupt_handler exc0: excx $0 exception_handle exc1: excx $1 exception_handle diff --git a/asm/asm_mp.asm b/asm/asm_mp.asm index a2dcee0..5e5259e 100644 --- a/asm/asm_mp.asm +++ b/asm/asm_mp.asm @@ -1,6 +1,7 @@ global smp_start global LLOCK extern smp_main +global gdt_descriptor ; master boot record for application processors smp_start: @@ -84,5 +85,5 @@ gdt_descriptor: dw gdt_end-gdt_start-1 dd gdt_start -CODE_SEG equ gdt_code - gdt_start -DATA_SEG equ gdt_data - gdt_start +;CODE_SEG equ gdt_code - gdt_start +;DATA_SEG equ gdt_data - gdt_start diff --git a/kernel/gdt.c b/kernel/gdt.c index d1ed382..c91524a 100644 --- a/kernel/gdt.c +++ b/kernel/gdt.c @@ -5,18 +5,16 @@ #include #define GDT_SIZE 6 -static uint8_t gdt_struct[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE -uint64_t gdt_descriptor; //https://wiki.osdev.org/Task_State_Segment -tss_struct sys_tss; //Define the TSS as a global structure +tss_struct sys_tss[SMP_MAX_PROC]; //Define the TSS as a global structure void install_tss(uint32_t esp0){ // now fill each value // set values necessary - sys_tss.ss0 = 0x10; //kernel data - sys_tss.esp0 = esp0; + sys_tss[0].ss0 = 0x10; //kernel data + sys_tss[0].esp0 = esp0; // now set the IO bitmap (not necessary, so set above limit) // sys_tss.iomap = ( unsigned short ) sizeof( tss_struct ); @@ -97,6 +95,8 @@ void encodeGdtEntry(uint8_t *target, GDT source) void gdt_init() { + + static int last_cpu=0; /* Pr=1 Privl 1 Exec DC RW Ac 0x9A == 1001 1010 == 1 00 1 1 0 1 0 @@ -105,6 +105,8 @@ void gdt_init() 0xF2 == 1111 0010 == 1 11 1 0 0 1 0 */ +//static uint8_t gdt_struct[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE + uint8_t *gdt_struct=kballoc(1); //[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE GDT myGDT[GDT_SIZE]; //selector 0x0 @@ -133,7 +135,7 @@ void gdt_init() myGDT[4].type=0xF2; //TSS 0x28 - myGDT[5].base=&sys_tss; //tss start + myGDT[5].base=&sys_tss[last_cpu++]; //tss start myGDT[5].limit=sizeof(tss_struct); //tss end myGDT[5].type=0x89; @@ -144,5 +146,10 @@ void gdt_init() // update tss entry install_tss(0); + setup_gdt(gdt_struct); + +} +void setup_gdt(uint8_t *gdt_struct) +{ asm_setup_gdt(&gdt_struct[0],8*GDT_SIZE); } diff --git a/kernel/interrupts.c b/kernel/interrupts.c index 4eb2a35..f93de9e 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -6,7 +6,7 @@ #include "asm_x86.h" /** The size of our interrupts table */ -#define INT_MAX 255 +#define INT_MAX 256 // 0-255 /** The interrupt descriptor table */ static struct int_desc @@ -83,6 +83,10 @@ 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==255)kpanic("Unhandled Interrupt!"); return esp; @@ -107,8 +111,8 @@ void show_selector_error(uint32_t err) { klog("Selector Error Details:"); klog("External Event: %x",err&0b1); - klog("Location: %x",err&0b110); - klog("Selector: %x",err&0b1111111111111000); + klog("Location: 0x%x (0-GDT/1-IDT/2-LDT/3-IDT)",err&0b110); + klog("Selector: 0x%x",err&0b1111111111111000); } void show_page_fault_error(uint32_t error_code) @@ -242,9 +246,13 @@ void interrupts_init(uint16_t sel) // System Calls / they can be called from ring3 (0b11) int_install_ir(0x80, 0b11101110, 0x08,&int128); + // Wake Scheduler int_install_ir(0x81, 0b11101110, 0x08,&int129); + // APIC Timer + int_install_ir(200, 0b11101110, 0x08,&int200); + // install IVT int_install(); } diff --git a/kernel/kernel.c b/kernel/kernel.c index 493fb93..30949f8 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -42,11 +42,6 @@ void kernel_main(uint32_t eax,uint32_t ebx) multiboot_information *info; info=get_multiboot(eax, ebx); - klog("Symmetrical Multi Processing (SMP) init ... "); - smp_processors procdata; -// if(!acpi_find(&procdata)&&!mp_find(&procdata))kpanic("No ACPI or MP found!"); - if(!acpi_find(&procdata))("No ACPI found!"); - klog("Memory init ... "); uint32_t kernel_blocks=mem_init(info); @@ -56,9 +51,13 @@ void kernel_main(uint32_t eax,uint32_t ebx) 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!"); + // Start the other Processors (before paging because apic addr etc..?) //TODO: remap apic !!! Check commented out sleep ()!!! - // https://wiki.osdev.org/Symmetric_Multiprocessing klog("Symmetric Multi Processing (SMP) start ... "); smp_log_procdata(&procdata); smp_start_aps(&procdata); diff --git a/kernel/kernel.h b/kernel/kernel.h index 4c480e5..e1a33d2 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -19,10 +19,13 @@ #define KMALLOC_MEM_SIZE 1024*1024*8 // 8MB for in kernel-memory #define NUMBER_SPINLOCKS 16 #define SPINLOCK_LOG 0 +#define SPINLOCK_ALLOC 1 #define S1(x) #x #define S2(x) S1(x) +#define SMP_MAX_PROC 32 + // __FUNCTION__ ? #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__) diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c index ec714c4..6a5812a 100644 --- a/kernel/kmalloc.c +++ b/kernel/kmalloc.c @@ -1,7 +1,7 @@ - #include "kmalloc.h" #include "kernel.h" +#include "spinlock.h" static uint8_t data[KMALLOC_MEM_SIZE]; // bytes @@ -32,11 +32,15 @@ static void kmallocinit() uint32_t kballoc(uint32_t size) { size*=4096; + + spinlock_spin(SPINLOCK_ALLOC); + + if(!init)kmallocinit(); - if(!init)kmallocinit(); + uint32_t old=next; + next+=size; - uint32_t old=next; - next+=size; + spinlock_release(SPINLOCK_ALLOC); if(next>=first+KMALLOC_MEM_SIZE) { diff --git a/kernel/smp.c b/kernel/smp.c index ea926ca..3709ed5 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -1,7 +1,9 @@ -#include "kernel/kernel.h" +#include "kernel.h" // http://www.intel.com/content/dam/doc/specification-update/64-architecture-x2apic-specification.pdf // http://download.intel.com/design/chipsets/datashts/29056601.pdf // http://www.scs.stanford.edu/05au-cs240c/lab/ia32/IA32-3.pdf +// https://wiki.osdev.org/Symmetric_Multiprocessing +// https://wiki.osdev.org/APIC_timer #include #include "smp.h" @@ -14,6 +16,32 @@ #define FOOLOS_APIC_INT_COMMAND_HIGH 0x0310 #define FOOLOS_APIC_ID 0x020 +#define APIC_APICID 0x20 +#define APIC_APICVER 0x30 +#define APIC_TASKPRIOR 0x80 +#define APIC_EOI 0x0B0 +#define APIC_LDR 0x0D0 +#define APIC_DFR 0x0E0 +#define APIC_SPURIOUS 0x0F0 +#define APIC_ESR 0x280 +#define APIC_ICRL 0x300 +#define APIC_ICRH 0x310 +#define APIC_LVT_TMR 0x320 +#define APIC_LVT_PERF 0x340 +#define APIC_LVT_LINT0 0x350 +#define APIC_LVT_LINT1 0x360 +#define APIC_LVT_ERR 0x370 +#define APIC_TMRINITCNT 0x380 +#define APIC_TMRCURRCNT 0x390 +#define APIC_TMRDIV 0x3E0 +#define APIC_LAST 0x38F +#define APIC_DISABLE 0x10000 +#define APIC_SW_ENABLE 0x100 +#define APIC_CPUFOCUS 0x200 +#define APIC_NMI (4<<8) +#define TMR_PERIODIC 0x20000 +#define TMR_BASEDIV (1<<20) + // some multiprocessor shit that should move away TODO uint32_t c1,c2,c3; volatile uint8_t proc; @@ -24,35 +52,58 @@ 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) +{ + uint32_t *reg; + reg=local_apic_addr+offset; + *reg=value; +} + +uint32_t readAPIC(uint32_t offset) +{ + uint32_t *reg; + reg=local_apic_addr+offset; + uint32_t value=*reg; + return value; +} + void kernel_ap() { - LLOCK=0; uint32_t *reg; reg=local_apic_addr+FOOLOS_APIC_ID; - klog("smp local apic id: %d",(*reg)); + klog("smp local apic id: 0x%08X",(*reg)); - // // // *reg=local_apic_addr+FOOLOS_APIC_SPUR_INT; - // // // *reg|=0x100;//0xffffffff; // all bits 1 and interrupt 255 -// *reg=0;//xffffffff; // all bits 1 and interrupt 255 + reg=local_apic_addr+FOOLOS_APIC_SPUR_INT; + klog("svr value: 0x%08X",(*reg)); + *reg|=0x100; // enable APIC int_install(); + gdt_init(); + + uint32_t countdown=0x0fffffff; + 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... - while(1){ - klog("%d",*reg); - for(int i=0;i<1000000000;i++); - } + while(1) + { + asm("hlt"); + klog("tack: 0x%08X: 0x%08X",readAPIC(FOOLOS_APIC_ID), readAPIC(APIC_TMRCURRCNT)); + } // switch_to_user_mode(); -// int x=1/0; /* while(1); @@ -95,8 +146,10 @@ void smp_log_procdata(smp_processors *procdata) } // this will start all our application processors! -void smp_start_aps(smp_processors *pros,char *path) +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; //bsp (boot processor) enables its local apic @@ -105,7 +158,7 @@ void smp_start_aps(smp_processors *pros,char *path) // *reg=0; uint32_t *reg=local_apic_addr+FOOLOS_APIC_ID; - klog("local apic id: 0x%08X",(*reg)); + klog("bsp local apic id: 0x%08X",(*reg)); for(int i=0;iprocessors;i++) { @@ -125,7 +178,7 @@ void smp_start_aps(smp_processors *pros,char *path) // todo: use some real sleep (not implemented yet :( ) //sleep(30); - // start proc 0x7 = 0x7000; + // start proc 0x7 = at addr 0x7000; *reg=(6<<8)|(1<<14)|0x7; // 110 SIPI } } diff --git a/kernel/smp.h b/kernel/smp.h index 256d451..61058fc 100644 --- a/kernel/smp.h +++ b/kernel/smp.h @@ -1,7 +1,7 @@ #ifndef SMP_H #define SMP_H -#define SMP_MAX_PROC 32 +#include "kernel.h" typedef struct { diff --git a/userspace/foolshell.c b/userspace/foolshell.c index 86c083c..09d6d32 100644 --- a/userspace/foolshell.c +++ b/userspace/foolshell.c @@ -96,7 +96,7 @@ int main(int argc, char **argv) //fgets(buf,255,stdin); //buf[strlen(buf)-1]=0; // remove \n - printf("[%s]",buf); + //printf("[%s]",buf); process(buf); } -- cgit v1.2.3