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++
		
	
			
		
		
	
	
			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
 |