66 lines
1.4 KiB
C
66 lines
1.4 KiB
C
/*
|
|
* @author xamidev <xamidev@riseup.net>
|
|
* @brief x86 MSR C wrappers
|
|
* @description
|
|
* Wrapper functions to access Model Specific Registers
|
|
*
|
|
* @license GPL-3.0-only
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <arch/x86.h>
|
|
|
|
/*
|
|
* rdmsr - Read from MSR
|
|
* @msr: model specific register number
|
|
*
|
|
* Read a 64-bit word from a Model Specific Register.
|
|
* Wrapper for the "rdmsr" instruction. It originally
|
|
* outputs to two 32-bit registers (EDX:EAX), so the
|
|
* function does the job of uniting them as a 64-bit
|
|
* value for us.
|
|
*
|
|
* Return:
|
|
* <value> - value read from MSR
|
|
*/
|
|
uint64_t rdmsr(uint32_t msr)
|
|
{
|
|
uint32_t low;
|
|
uint32_t high;
|
|
|
|
__asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
|
|
|
return ((uint64_t)high << 32) | low;
|
|
}
|
|
|
|
/*
|
|
* wrmsr - Write to MSR
|
|
* @msr: model specific register number
|
|
*
|
|
* Write a 64-bit value to a Model Specific Register.
|
|
*/
|
|
void wrmsr(uint32_t msr, uint64_t value)
|
|
{
|
|
uint32_t low = (uint32_t)(value & 0xFFFFFFFF);
|
|
uint32_t high = (uint32_t)(value >> 32);
|
|
|
|
__asm__ volatile("wrmsr" : : "c"(msr), "a"(low), "d"(high) : "memory");
|
|
}
|
|
|
|
/*
|
|
* x86_has_msr - Test for MSR support
|
|
*
|
|
* Checks if CPU supports Model Specific Registers
|
|
* using CPUID.01h:EDX[bit 5].
|
|
*
|
|
* Return:
|
|
* true - MSR are supported
|
|
* false - MSR are not supported
|
|
*/
|
|
bool x86_has_msr()
|
|
{
|
|
uint32_t eax, ebx, ecx, edx;
|
|
cpuid(1, &eax, &ebx, &ecx, &edx);
|
|
return (edx & (1 << 5)) != 0;
|
|
} |