summaryrefslogtreecommitdiff
path: root/kernel/smp.c
diff options
context:
space:
mode:
authorMiguel <m.i@gmx.at>2018-09-08 17:08:55 +0200
committerMiguel <m.i@gmx.at>2018-09-08 17:08:55 +0200
commit9fde748acea83d775e367a64858414b674f05b13 (patch)
tree0927b570c07c9ee469817a560b965c094c5d8145 /kernel/smp.c
parentaa4b4c6c1918a51318709761873d1c5e248a831d (diff)
struggling with pic and lapic and smp...
Diffstat (limited to 'kernel/smp.c')
-rw-r--r--kernel/smp.c119
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);
}