summaryrefslogtreecommitdiff
path: root/kernel/include/arch/x86_64/cpu/lapic.hpp
blob: 350edac1ab29c5b0e441764e488a0f86f9d3956f (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

#include <cstdint>

#pragma once

#include <generic/mm/paging.hpp>
#include <drivers/tsc.hpp>

#include <drivers/hpet.hpp>

#include <generic/time.hpp>

#include <etc/logging.hpp>

#include <etc/assembly.hpp>
#include <etc/etc.hpp>

extern "C" void setwp();

namespace arch {
    namespace x86_64 {
        namespace cpu {
            class lapic {

                static inline std::uint64_t base() {
                    return (std::uint64_t)Other::toVirt(__rdmsr(0x1B) & 0xFFFFF000);
                }

                static inline std::uint32_t read(std::uint32_t reg) {
                    return *(volatile std::uint32_t*)(base() + reg); 
                }

                static inline void write(std::uint32_t reg,std::uint32_t value) {
                    *(volatile std::uint32_t*)(base() + reg) = value;
                }

            public:

                static inline std::uint32_t id() {
                    return read(0x20) >> 24;
                }

                static inline void eoi() {
                    write(0xB0,0);
                }

                static inline void tick(std::uint64_t tick) {
                    write(0x380,tick);
                }

                static inline std::uint64_t init(std::uint32_t us) {
                    __wrmsr(0x1B,__rdmsr(0x1B));
                    memory::paging::kernelmap(0,__rdmsr(0x1B) & 0xFFFFF000);
                    write(0xf0,0xff | 0x100);
                    write(0x3e0,1);
                    write(0x320,32 | (1 << 16));
                    write(0x380,0xFFFFFFFF);
                    time::sleep(us);
                    std::uint64_t ticks = 0xFFFFFFFF - read(0x390);
                    write(0x320, 32 | (1 << 17));
                    write(0x3e0,1);
                    write(0x380,0);
                    return ticks;
                }
            };
        };
    };
};