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
|
#include "Msr.h"
Msr::Msr()
{
Cpuinfo cpuinfo;
cpuinfo.cpuid(Cpuinfo::VersionInfo);
msrSupport = cpuinfo.getRegs().edx & Cpuinfo::MSR;
};
bool Msr::rdmsr(MsrCommand *cmd)
{
if(!msrSupport or cmd == nullptr) return true;
uint64 rdmsrResult = 0;
uint32 regs[2];
asm(
"mov %2, %%ecx\n\t"
"rdmsr\n\t"
"mov %%eax, %0\n\t"
"mov %%edx, %1\n\t"
: "=&r"(regs[0]), "=&r"(regs[1])
: "r"(cmd->getCommand()));
MemoryOperations::copy(regs, &rdmsrResult, sizeof(uint64));
cmd->decode(rdmsrResult);
return false;
};
bool Msr::wrmsr(MsrCommand *cmd)
{
if(!msrSupport or cmd == nullptr) return true;
uint32 regs[2];
uint64 msr = cmd->getMsr();
MemoryOperations::copy(&msr, regs, sizeof(uint64));
asm(
"mov %0, %%eax\n\t"
"mov %1, %%edx\n\t"
"mov %2, %%ecx\n\t"
"wrmsr\n\t"
: "=r"(regs[0]), "=r"(regs[1])
: "r"(cmd->getCommand()));
return false;
};
Ia32ApicBase::Ia32ApicBase()
{
Cpuinfo cpuinfo;
bool cpuidAddrSzNotSupport = cpuinfo.cpuid(Cpuinfo::AddressSize);
cpuidOutputRegisters AddrSzRegs = cpuinfo.getRegs();
cpuinfo.cpuid(Cpuinfo::VersionInfo);
if(cpuinfo.getRegs().edx & Cpuinfo::PAE
and cpuidAddrSzNotSupport) maxPhyAddr = 36;
else if(cpuidAddrSzNotSupport) maxPhyAddr = 32;
else if(!cpuidAddrSzNotSupport) maxPhyAddr = (uint8)AddrSzRegs.edx;
bspFlag = enableFlag = false;
baseField = NULL;
};
uint32 Ia32ApicBase::getCommand()
{
return 0x1b;
};
void Ia32ApicBase::decode(uint64 rdmsrResult)
{
bspFlag = rdmsrResult & BSP_FLAG;
enableFlag = rdmsrResult & APIC_ENABLE_FLAG;
setBaseField(rdmsrResult);
};
uint64 Ia32ApicBase::getMsr()
{
uint64 msr = 0;
MemoryOperations::copy(&baseField, &msr, sizeof(uint64));
msr |= bspFlag << 8;
msr |= enableFlag << 11;
return msr;
};
void Ia32ApicBase::setBaseField(uint64 fieldAddr)
{
uint64 mask = BASE_FIELD_MASK_LOW |
((UINT64_HIGH<< (maxPhyAddr - 32)) ^ UINT64_HIGH);
baseField = fieldAddr & mask;
};
void Ia32ApicBase::setBspFlag(bool flag)
{
bspFlag = flag;
};
void Ia32ApicBase::setEnableFlag(bool flag)
{
enableFlag = flag;
};
|