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;
}
};
};
|