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

#include <cstdint>

#pragma once

#include <generic/paging.hpp>
#include <generic/time.hpp>
#include <generic/hhdm.hpp>
#include <utils/gobject.hpp>
#include <arch/x86_64/assembly.hpp>
#include <klibc/stdio.hpp>

namespace x86_64 {

        inline int is_lapic_init = 0;

        class lapic {

                static inline std::uint64_t base() {
                    return (std::uint64_t)((assembly::rdmsr(0x1B) & 0xFFFFF000) + etc::hhdm());
                }

                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) {
                    assembly::wrmsr(0x1B,assembly::rdmsr(0x1B));
                    paging::map_range(gobject::kernel_root,assembly::rdmsr(0x1B) & 0xFFFFF000,(assembly::rdmsr(0x1B) & 0xFFFFF000) + etc::hhdm(),PAGE_SIZE, PAGING_PRESENT | PAGING_RW);
                    write(0xf0,0xff | 0x100);
                    write(0x3e0,1);
                    write(0x320,32 | (1 << 16));
                    write(0x380,0xFFFFFFFF);
                    time::timer->sleep(us);
                    std::uint64_t ticks = 0xFFFFFFFF - read(0x390);
                    write(0x320, 32 | (1 << 17));
                    write(0x3e0,1);
                    write(0x380,0);

                    if(!is_lapic_init) {
                        klibc::printf("LAPIC: Calibration time is %lli, ticks %lli\r\n",us,ticks);
                        is_lapic_init = 1;
                    }

                    return ticks;
                }
            };
};