summaryrefslogtreecommitdiffstats
path: root/arch/x86/msr
diff options
context:
space:
mode:
authorAlexey Gavrilov <rebovas@yahoo.com>2024-04-10 12:58:20 +0700
committerAlexey Gavrilov <rebovas@yahoo.com>2024-04-10 12:58:20 +0700
commit515a11b818e4140845f69bb26a19d270a9e42178 (patch)
treefd22e0d8d56a6498fb67ffcd99da0a45b97ab5f3 /arch/x86/msr
parent9ad5b9b6a1f8d641ac13f7c004afd6ea9bff50ee (diff)
MSR + IDT + test ISRs
Diffstat (limited to 'arch/x86/msr')
-rw-r--r--arch/x86/msr/Msr.cpp106
-rw-r--r--arch/x86/msr/Msr.h58
2 files changed, 164 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;
+};
diff --git a/arch/x86/msr/Msr.h b/arch/x86/msr/Msr.h
new file mode 100644
index 0000000..98c1b02
--- /dev/null
+++ b/arch/x86/msr/Msr.h
@@ -0,0 +1,58 @@
+// Tasks:
+// 1) Implement msr write and save functions
+// 2) Ia32ApicBase field
+
+#include "../cpuinfo/Cpuinfo.h"
+#include <MemoryOperations.h>
+
+#ifndef MSR_H
+#define MSR_H
+
+// defines for Ia32ApicBase
+
+#define BSP_FLAG 0x100
+#define APIC_ENABLE_FLAG 0x800
+#define BASE_FIELD_MASK_LOW 0xfffff000
+#define UINT64_HIGH 0xffffffff00000000
+
+//------------------------
+
+class MsrCommand
+{
+ public:
+ virtual uint32 getCommand() = 0;
+ virtual void decode(uint64 rdmsrResult) = 0;
+ virtual uint64 getMsr() = 0;
+};
+
+class Ia32ApicBase : public MsrCommand
+{
+ private:
+ // Get through Cpuinfo instance
+ uint8 maxPhyAddr;
+ bool bspFlag, enableFlag;
+ uint64 baseField;
+
+ public:
+ Ia32ApicBase();
+ virtual uint32 getCommand() override final;
+ virtual void decode(uint64 rdmrResult) override final;
+ virtual uint64 getMsr() override final;
+ void setBspFlag(bool flag);
+ void setEnableFlag(bool flag);
+ void setBaseField(uint64 fieldAddr);
+};
+
+class Msr
+{
+ private:
+ bool msrSupport;
+ public:
+ Msr();
+ // Return true if MSR not supported (CPUID.01H:EDX[5] = 0)
+ bool rdmsr(MsrCommand *cmd);
+ // Return value same as rdmsr method
+ bool wrmsr(MsrCommand *cmd);
+};
+
+#endif