From aa4b4c6c1918a51318709761873d1c5e248a831d Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 7 Sep 2018 03:01:28 +0200 Subject: apic timer smp --- kernel/smp.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 14 deletions(-) (limited to 'kernel/smp.c') 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 } } -- cgit v1.2.3