summaryrefslogtreecommitdiff
path: root/kernel/src/arch/x86_64/x86_64.cpp
blob: 7653346cdfcff966a89168f041e5e2a38eb41d2b (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
120
121
122
123
124
125
126

#include <cstdint>
#include <generic/arch.hpp>
#include <generic/bootloader/bootloader.hpp>
#include <arch/x86_64/drivers/hpet.hpp>
#include <arch/x86_64/cpu_local.hpp>
#include <arch/x86_64/drivers/tsc.hpp>
#include <arch/x86_64/cpu/gdt.hpp>
#include <arch/x86_64/cpu/idt.hpp>
#include <arch/x86_64/cpu/lapic.hpp>
#include <arch/x86_64/panic.hpp>
#include <arch/x86_64/irq.hpp>
#include <klibc/stdio.hpp>
#include <arch/x86_64/drivers/ioapic.hpp>
#include <arch/x86_64/schedule_timer.hpp>
#include <utils/gobject.hpp>
#include <arch/x86_64/cpu/sse.hpp>
#include <arch/x86_64/drivers/pvclock.hpp>
#include <utils/assert.hpp>

namespace arch {
    [[gnu::weak]] void disable_interrupts() {
        asm volatile("cli");
    }

    [[gnu::weak]] void enable_interrupts() {
        asm volatile("sti");
    }

    [[gnu::weak]] void wait_for_interrupt() {
        asm volatile("hlt");
    }

    [[gnu::weak]] void hcf() {
        disable_interrupts();
        while(true) {
            wait_for_interrupt();
        }
    }

    [[gnu::weak]] void pause() {
        asm volatile("pause");
    }

    [[gnu::weak]] std::uint64_t current_root() {
        std::uint64_t cr3;
        asm volatile("mov %%cr3, %0" : "=r"(cr3) : : "memory");
        return cr3;
    }

    [[gnu::weak]] void tlb_flush(std::uintptr_t hint, std::uintptr_t len) {
        if (len / PAGE_SIZE > 256 || len == 0) {
            std::uint64_t cr3 = 0;
            asm volatile("mov %%cr3, %0" : "=r"(cr3) : : "memory");
            asm volatile("mov %0, %%cr3" : : "r"(cr3) : "memory");
        } else {
            for (std::uintptr_t i = 0; i < len; i += PAGE_SIZE) {
                asm volatile("invlpg (%0)" : : "b"(hint + i) : "memory");
            }
        }
    }

    [[gnu::weak]] const char* name() {
        return "x86_64";
    }

    [[gnu::weak]] int level_paging() {
        return bootloader::bootloader->is_5_level_paging() ? 5 : 4;
    }

    [[gnu::weak]] void init(int stage) {
        switch(stage) {
        case ARCH_INIT_EARLY:
            x86_64::init_cpu_data();
            drivers::hpet::init();
            drivers::tsc::init();
            drivers::pvclock::bsp_init();
            assert(time::timer != nullptr, "can't init orange without timer !");
            x86_64::gdt::init();
            x86_64::idt::init();
            x86_64::lapic::init(1500);
            drivers::ioapic::init();
            x86_64::schedule_timer::init();
            x86_64::sse::init();
            x86_64::sse::print_sse_features();
            return;
        case ARCH_INIT_MP:
            enable_paging(gobject::kernel_root);
            x86_64::init_cpu_data();
            drivers::tsc::init();
            drivers::pvclock::init();
            x86_64::gdt::init();
            x86_64::idt::init();
            x86_64::lapic::init(1500);
            x86_64::schedule_timer::init();
            x86_64::sse::init();
            return;
        case ARCH_INIT_COMMON:
            return;
        }
    }

    [[gnu::weak]] void panic(char* msg) {
        klibc::printf("Panic with message \"%s\"\r\n",msg);
        arch::hcf();
    }

    [[gnu::weak]] void memory_barrier() {
        asm volatile("lfence" ::: "memory");
    }

    [[gnu::weak]] int register_handler(int irq, int type, std::uint64_t flags, void (*func)(void* arg), void* arg) {
        return x86_64::irq::create(irq,type,func,arg,flags);
    }

    [[gnu::weak]] bool test_interrupts() {
        uint64_t rflags;
        __asm__ __volatile__ (
            "pushfq\n\t"
            "pop %0" : "=rm" (rflags): : "memory"
        );
        return (rflags & (1 << 9)) != 0;
    }


}