r205751 - intrin.h: Implement __readmsr, __readcr3, and __writecr3

Reid Kleckner reid at kleckner.net
Mon Apr 7 17:28:22 PDT 2014


Author: rnk
Date: Mon Apr  7 19:28:22 2014
New Revision: 205751

URL: http://llvm.org/viewvc/llvm-project?rev=205751&view=rev
Log:
intrin.h: Implement __readmsr, __readcr3, and __writecr3

Fixes PR19301.

Based on a patch from Steven Graf!

Modified:
    cfe/trunk/lib/Headers/Intrin.h

Modified: cfe/trunk/lib/Headers/Intrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/Intrin.h?rev=205751&r1=205750&r2=205751&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/Intrin.h (original)
+++ cfe/trunk/lib/Headers/Intrin.h Mon Apr  7 19:28:22 2014
@@ -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
 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





More information about the cfe-commits mailing list