summaryrefslogtreecommitdiff
path: root/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/smp.c')
-rw-r--r--kernel/smp.c81
1 files changed, 67 insertions, 14 deletions
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 <stdint.h>
#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;i<pros->processors;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
}
}