diff options
| author | Alexey Gavrilov <90127298+rebovas@users.noreply.github.com> | 2024-04-10 13:12:08 +0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-10 13:12:08 +0700 |
| commit | 0a50b1758fd3da118408fd724825d0a50a9ecf17 (patch) | |
| tree | 783ed019c87c3c9624a1a13f68c7bafc4c146dfb /arch/x86/msr | |
| parent | 9ad5b9b6a1f8d641ac13f7c004afd6ea9bff50ee (diff) | |
| parent | 0c56a0300b7ffbab787a4c974bc164d9a2a57ad2 (diff) | |
Merge pull request #8 from rebovas/msr
Msr + interrupts implement + crude implementation of IDT filling
Diffstat (limited to 'arch/x86/msr')
| -rw-r--r-- | arch/x86/msr/Msr.cpp | 106 | ||||
| -rw-r--r-- | arch/x86/msr/Msr.h | 58 |
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 |
