summaryrefslogtreecommitdiffstats
path: root/arch/x86/msr/Msr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/msr/Msr.cpp')
-rw-r--r--arch/x86/msr/Msr.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/arch/x86/msr/Msr.cpp b/arch/x86/msr/Msr.cpp
new file mode 100644
index 0000000..6d21b54
--- /dev/null
+++ b/arch/x86/msr/Msr.cpp
@@ -0,0 +1,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;
+};