summaryrefslogtreecommitdiff
path: root/kernel/src/arch/x86_64/cpu/smp.cpp
blob: a06f4c52b995c9ce636d19eb1b9f05e78891b5ab (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

#include <cstdint>

#include <arch/x86_64/cpu/smp.hpp>
#include <generic/time.hpp>

#include <arch/x86_64/cpu/data.hpp>

#include <arch/x86_64/cpu/gdt.hpp>
#include <arch/x86_64/cpu/lapic.hpp>
#include <arch/x86_64/interrupts/idt.hpp>
#include <generic/mm/paging.hpp>

#include <generic/locks/spinlock.hpp>
#include <etc/bootloaderinfo.hpp>

#include <drivers/tsc.hpp>

#include <arch/x86_64/syscalls/syscalls.hpp>

#include <arch/x86_64/cpu/sse.hpp>

#include <etc/logging.hpp>

#include <etc/libc.hpp>

#include <limine.h>

#include <drivers/io.hpp>

#include <atomic>

using namespace arch::x86_64::cpu;

int balance_how_much_cpus = 1;

int how_much_cpus = 1;
std::atomic<int> temp_how_much_cpus[12];

locks::spinlock mp_lock;

void mp::sync(std::uint8_t id) {
    if(how_much_cpus != 1) {
        temp_how_much_cpus[id].fetch_add(1, std::memory_order_acq_rel);
        while (how_much_cpus != temp_how_much_cpus[id].load(std::memory_order_acquire)) {
            asm volatile("nop");
        }
        time::sleep(1000*1000); // perform 1 second sleep
        temp_how_much_cpus[id].store(0, std::memory_order_release);
    }
} 

void __mp_bootstrap(struct LIMINE_MP(info)* smp_info) {
    mp_lock.lock();
    memory::paging::enablekernel();
    arch::x86_64::interrupts::idt::load();
    arch::x86_64::cpu::gdt::init();
    drivers::tsc::init();

    arch::x86_64::cpu::data()->smp.cpu_id = balance_how_much_cpus++;

    arch::x86_64::cpu::data()->lapic_block = arch::x86_64::cpu::lapic::init(15000);
    arch::x86_64::cpu::sse::init();
    arch::x86_64::syscall::init();
    Log::Display(LEVEL_MESSAGE_OK,"Cpu %d is online \n",arch::x86_64::cpu::data()->smp.cpu_id);
    arch::x86_64::cpu::lapic::tick(arch::x86_64::cpu::data()->lapic_block);
    mp_lock.unlock();
    setwp();
    mp::sync(0);
    mp::sync(1);
    asm volatile("sti");
    while(1) {
        asm volatile("hlt");
    }
}

void mp::init() {
    struct LIMINE_MP(response)* mp_info = BootloaderInfo::AccessMP();
        
    how_much_cpus = mp_info->cpu_count;

    memset(temp_how_much_cpus,0,4*12);
    for(std::uint16_t i = 0;i < mp_info->cpu_count;i++) {
        if(mp_info->bsp_lapic_id != i) {
            mp_info->cpus[i]->goto_address = __mp_bootstrap;
        }
    }
}