Files
bsb2/kernel/arch/core_msr.h
Niklas Gollenstede 174fe17e89 Handout
2025-10-31 22:37:36 +01:00

102 lines
2.9 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 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 <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 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