From 515a11b818e4140845f69bb26a19d270a9e42178 Mon Sep 17 00:00:00 2001 From: Alexey Gavrilov Date: Wed, 10 Apr 2024 12:58:20 +0700 Subject: MSR + IDT + test ISRs --- arch/x86/msr/Msr.cpp | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 arch/x86/msr/Msr.cpp (limited to 'arch/x86/msr/Msr.cpp') 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; +}; -- cgit v1.2.3