summaryrefslogtreecommitdiff
path: root/kernel/smp.c
blob: 4aff01373a0b68776b6fe4b63b9897f28df35399 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "kernel/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

#include <stdint.h>
#include "smp.h"
#include "mem.h"
#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

// some multiprocessor shit that should move away TODO
uint32_t c1,c2,c3;
volatile uint8_t proc;
uint32_t cpu_counter[SMP_MAX_PROC];

uint32_t local_apic_addr;

void smp_main()
{

//    klog("local apic_addr:0x%08X",local_apic_addr);

    // // uint32_t *reg=local_apic_addr+FOOLOS_APIC_ID;
    //klog("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

    int_install();
    
    x86_sti();



    while(1)__asm__("hlt");

//    switch_to_user_mode();
//    int x=1/0;

    while(1);

    uint32_t ebp=pmmngr_alloc_block()+4095;

    asm volatile("mov %0, %%ebp"::"r"(ebp));
    asm volatile("mov %ebp, %esp");
    asm volatile("jmp kernel_ap");

    proc=c1=c2=c3=0;
    for(int i=0;i<SMP_MAX_PROC;i++)cpu_counter[i]=0;
}


void kernel_ap()
{
	proc++;
	uint8_t p=proc;
	while(1)
	{
	    cpu_counter[p]++;

 	    //lock_spin(0);
	    if(cpu_counter[p]%1000000==0)klog("cpu[%d] %d",p,cpu_counter[p]);
	    //lock_release(0);

	}
}

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,char *path)
{
	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("local apic id: 0x%08X",(*reg));

        for(int i=0;i<pros->processors;i++)
	{
	    if(pros->boot==i)continue;

	    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;
	    *reg=dest<<24; // destination apic.

	    reg=local_apic_addr+FOOLOS_APIC_INT_COMMAND_LOW;
	    *reg=(5<<8)|(1<<14); // 101 INIT

	    // do we really neet this?
	    // TODO!!
	    // todo: use some real sleep (not implemented yet :( )
	    //sleep(30);

	    // start proc 0x7 = 0x7000;
	    *reg=(6<<8)|(1<<14)|0x7; // 110 SIPI
	}
}