summaryrefslogtreecommitdiffstats
path: root/arch/x86/msr/Msr.cpp
blob: 6d21b545162c04d8a655d505d863d02ec68cd734 (plain) (blame)
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;
};