You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.2 KiB
C++

/*! \file
* \brief \ref Core::MSRs "Identifiers" for \ref Core::MSR "Model-Specific
* Register"
*/
#pragma once
#include "../types.h"
namespace Core {
/*! \brief Model-Specific Register Identifiers
*
* Selection of useful identifiers.
*
* \see [ISDMv4](intel_manual_vol4.pdf)
*/
enum MSRs {
MSR_PLATFORM_INFO =
0xce, ///< Platform information including bus frequency (Intel)
MSR_TSC_DEADLINE = 0x6e0, ///< Register for \ref LAPIC::Timer Deadline mode
// Fast system calls
// XXX: Remove if we don't do fast syscalls
MSR_EFER =
0xC0000080, ///< Extended Feature Enable Register, \see Core::MSR_EFER
MSR_STAR = 0xC0000081, ///< eip (protected mode), ring 0 and 3 segment bases
MSR_LSTAR = 0xC0000082, ///< rip (long mode)
MSR_SFMASK = 0xC0000084, ///< lower 32 bit: flag mask, if bit is set
///< corresponding rflag is cleared through syscall
// CPU local variables
MSR_FS_BASE = 0xC0000100,
MSR_GS_BASE = 0xC0000101, ///< Current GS base pointer
MSR_SHADOW_GS_BASE = 0xC0000102, ///< Usually called `MSR_KERNEL_GS_BASE` but
///< this is misleading
};
/* \brief Important bits in Extended Feature Enable Register (EFER)
*
* \see [ISDMv3, 2.2.1 Extended Feature Enable
* Register](intel_manual_vol3.pdf#page=69)
* \see [AAPMv2, 3.1.7 Extended Feature Enable
* Register](amd64_manual_vol2.pdf#page=107)
*/
enum MSR_EFER {
MSR_EFER_SCE = 1 << 0, ///< System Call Extensions
MSR_EFER_LME = 1 << 8, ///< Long mode enable
MSR_EFER_LMA = 1 << 10, ///< Long mode active
MSR_EFER_NXE = 1 << 11, ///< No-Execute Enable
MSR_EFER_SVME = 1 << 12, ///< Secure Virtual Machine Enable
MSR_EFER_LMSLE = 1 << 13, ///< Long Mode Segment Limit Enable
MSR_EFER_FFXSR = 1 << 14, ///< Fast `FXSAVE`/`FXRSTOR` instruction
MSR_EFER_TCE = 1 << 15, ///< Translation Cache Extension
};
/*! \brief Access to the Model-Specific Register (MSR)
*
* \see [ISDMv3, 9.4 Model-Specific Registers
* (MSRs)](intel_manual_vol3.pdf#page=319)
* \see [ISDMv4](intel_manual_vol4.pdf)
* \tparam id ID of the Model-Specific Register to access
*/
template <enum MSRs id>
class MSR {
/*! \brief Helper to access low and high bits of a 64 bit value
* \internal
*/
union uint64_parts {
struct {
uint32_t low;
uint32_t high;
} __attribute__((packed));
uint64_t value;
explicit uint64_parts(uint64_t value = 0) : value(value) {}
};
public:
/*! \brief Read the value of the current MSR
*
* \return Value stored in the MSR
*
* \see [ISDMv2, Chapter 4. RDMSR - Read from Model Specific
* Register](intel_manual_vol2.pdf#page=1186)
*/
static inline uint64_t read() {
uint64_parts p;
asm volatile("rdmsr \n\t" : "=a"(p.low), "=d"(p.high) : "c"(id));
return p.value;
}
/*! \brief Write a value into the current MSR
*
* \param value Value to write into the MSR
*
* \see [ISDMv2, Chapter 5. WRMSR - Write to Model Specific
* Register](intel_manual_vol2.pdf#page=1912)
*/
static inline void write(uint64_t value) {
uint64_parts p(value);
asm volatile("wrmsr \n\t" : : "c"(id), "a"(p.low), "d"(p.high));
}
};
} // namespace Core