/*! \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 class MSRs : uint32_t { PLATFORM_INFO = 0xce, ///< Platform information including bus frequency (Intel) TSC_DEADLINE = 0x6e0, ///< Register for LAPIC::Timer Deadline mode // Fast system calls EFER = 0xC0000080, ///< Extended Feature Enable Register, see Core::MSR_EFER STAR = 0xC0000081, ///< eip (protected mode), ring 0 and 3 segment bases LSTAR = 0xC0000082, ///< rip (long mode) SFMASK = 0xC0000084, ///< lower 32 bit: flag mask, if bit is set ///< corresponding rflag is cleared through syscall // CPU local variables FS_BASE = 0xC0000100, GS_BASE = 0xC0000101, ///< Current GS base pointer 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 class MSR_EFER : uint32_t { SCE = 1 << 0, ///< System Call Extensions LME = 1 << 8, ///< Long mode enable LMA = 1 << 10, ///< Long mode active NXE = 1 << 11, ///< No-Execute Enable SVME = 1 << 12, ///< Secure Virtual Machine Enable LMSLE = 1 << 13, ///< Long Mode Segment Limit Enable FFXSR = 1 << 14, ///< Fast `FXSAVE`/`FXRSTOR` instruction 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 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 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 void write(uint64_t value) { uint64_parts p(value); asm volatile("wrmsr \n\t" : : "c"(id), "a"(p.low), "d"(p.high)); } }; } // namespace Core