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/smp.c | |
| parent | aa4b4c6c1918a51318709761873d1c5e248a831d (diff) | |
struggling with pic and lapic and smp...
Diffstat (limited to 'kernel/smp.c')
| -rw-r--r-- | kernel/smp.c | 119 |
1 files changed, 65 insertions, 54 deletions
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); } |
