summaryrefslogtreecommitdiff
path: root/kernel/smp.c
blob: 01230cf1bd451ee48e5a29be7e5a977978289022 (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
#include "kernel.h"
#include "log.h"
#include "smp.h"

#include <stdint.h>
#include "gdt.h"
#include "mem.h"
#include "vmem.h"
#include "interrupts.h"
#include "kmalloc.h"
#include "spinlock.h"
#include "asm_x86.h"
#include "asm_pit.h"
#include "asm_smp.h"
#include "apic.h"
#include "vesa.h"
#include "syscalls.h"

// set cpu private value
void smp_set(uint32_t offset, uint32_t value)
{
    uint32_t *cpu_mem=VMEM_CPU_PRIVATE; 
    cpu_mem[offset]=value;
}

// get cpu private value
uint32_t smp_get(uint32_t offset)
{
    uint32_t *cpu_mem=VMEM_CPU_PRIVATE; 
    return cpu_mem[offset];
}

void smp_main_generic(bool bsp)
{
    if(!bsp) // for the bsp this was already done beforehand
    {
	klog("Install Interrupt Vector Table (IVT) on CPU with lapic_id=0x%x ...",apic_id());
	interrupts_install();

	klog("Install Global Descriptor Table (GDT) on CPU with lapic_id=0x%x ...",apic_id());
	gdt_init();

	klog("Setup Paging on CPU with lapic_id=0x%x ...",apic_id());
	struct pdirectory_struct *dir=vmem_kernel_dir();
	x86_set_page_directory(dir);
	x86_paging_enable();
    }

    // setup stack and jump to kernel_ap();
    uint32_t ebp=VMEM_CPU_STACK_TOP;
    asm volatile("mov %0, %%ebp"::"r"(ebp));
    asm volatile("mov %ebp, %esp");
    asm volatile("jmp run_smp");
}

void run_smp()
{
    apic_enable();
    
    klog("Setup the LAPIC Timer on CPU with lapic_id=0x%x ...",apic_id());
    apic_init_timer(3);// freq x HZ

    klog("Enable Interrupts on CPU with lapic_id=0x%x ...",apic_id());
    asm_smp_unlock();

    smp_set(SMP_APIC_ID,apic_id());
    smp_set(1000,'a'+apic_id());
    smp_set(SMP_SCHEDULER_INIT,1);

    if(apic_id()==0)
    {
//        apic_sipi(1,0x7);
//        apic_sipi(2,0x7);
//        apic_sipi(3,0x7);
    }

    x86_sti();

    while(1)asm("hlt"); // wait for scheduler to kick in
}

void smp_main()
{
    smp_main_generic(false);
}

void smp_bsp()
{
    smp_main_generic(true);
}