From aa1fd66d0c18ebc4dea11a33b2d8c4bb1558e70c Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 8 Apr 2014 00:28:22 +0000 Subject: [PATCH] intrin.h: Implement __readmsr, __readcr3, and __writecr3 Fixes PR19301. Based on a patch from Steven Graf! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205751 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Headers/Intrin.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/lib/Headers/Intrin.h b/lib/Headers/Intrin.h index e365abe9a7..e18b1a6588 100644 --- a/lib/Headers/Intrin.h +++ b/lib/Headers/Intrin.h @@ -105,6 +105,7 @@ unsigned __int64 __rdtsc(void); unsigned __int64 __rdtscp(unsigned int *); unsigned long __readcr0(void); unsigned long __readcr2(void); +static __inline__ unsigned long __readcr3(void); unsigned long __readcr4(void); unsigned long __readcr8(void); @@ -119,6 +120,7 @@ unsigned __int64 __readfsqword(unsigned long); static __inline__ unsigned short __readfsword(unsigned long); #endif +static __inline__ unsigned __int64 __readmsr(unsigned long); unsigned __int64 __readpmc(unsigned long); unsigned long __segmentlimit(unsigned long); @@ -143,6 +145,7 @@ void __vmx_off(void); void __vmx_vmptrst(unsigned __int64 *); void __wbinvd(void); void __writecr0(unsigned int); +static __inline__ void __writecr3(unsigned int); void __writecr4(unsigned int); void __writecr8(unsigned int); @@ -981,6 +984,38 @@ __halt(void) { __asm__ volatile ("hlt"); } +/*----------------------------------------------------------------------------*\ +|* Privileged intrinsics +\*----------------------------------------------------------------------------*/ +static __inline__ unsigned __int64 __attribute__((__always_inline__, __nodebug__)) +__readmsr(unsigned long __register) { + // Loads the contents of a 64-bit model specific register (MSR) specified in + // the ECX register into registers EDX:EAX. The EDX register is loaded with + // the high-order 32 bits of the MSR and the EAX register is loaded with the + // low-order 32 bits. If less than 64 bits are implemented in the MSR being + // read, the values returned to EDX:EAX in unimplemented bit locations are + // undefined. + unsigned long __edx; + unsigned long __eax; + __asm__ ("rdmsr" + : "=d"(__edx), "=a"(__eax) + : "c"(__register) + : "%ecx", "%edx", "%eax"); + return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax; +} + +static __inline__ unsigned long __attribute__((always_inline, __nodebug__)) +__readcr3(void) { + unsigned long value; + __asm__ __volatile__("mov %%cr3, %0" : "=q"(value)); + return value; +} + +static __inline__ void __attribute__((always_inline, __nodebug__)) +__writecr3(unsigned int Data) { + __asm__("mov %0, %%cr3" : : "q"(Data) : "memory"); +} + #ifdef __cplusplus } #endif -- 2.40.0