1 #ifndef _CPU_X86_64_H
2 #define _CPU_X86_64_H
3 
4 /* x86_64 cpu.h  */
5 
rdtsc(void)6 static inline uint64_t rdtsc(void)
7 {
8     uint64_t v;
9     asm volatile("rdtsc" : "=A" (v));
10     return v;
11 }
12 
rdtscl(void)13 static inline uint32_t rdtscl(void)
14 {
15     uint32_t v;
16     asm volatile("rdtsc" : "=a" (v) : : "edx");
17     return v;
18 }
19 
native_cpuid(unsigned int * eax,unsigned int * ebx,unsigned int * ecx,unsigned int * edx)20 static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
21                                 unsigned int *ecx, unsigned int *edx)
22 {
23         /* ecx is often an input as well as an output. */
24         asm volatile("cpuid"
25             : "=a" (*eax),
26               "=b" (*ebx),
27               "=c" (*ecx),
28               "=d" (*edx)
29             : "0" (*eax), "2" (*ecx)
30             : "memory");
31 }
32 /*
33  * Generic CPUID function
34  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
35  * resulting in stale register contents being returned.
36  */
cpuid(uint32_t op,uint32_t * eax,uint32_t * ebx,uint32_t * ecx,uint32_t * edx)37 static inline void cpuid(uint32_t op,
38                          uint32_t *eax, uint32_t *ebx,
39                          uint32_t *ecx, uint32_t *edx)
40 {
41         *eax = op;
42         *ecx = 0;
43         native_cpuid(eax, ebx, ecx, edx);
44 }
45 
46 /*
47  * CPUID functions returning a single datum
48  */
cpuid_eax(uint32_t op)49 static inline uint32_t cpuid_eax(uint32_t op)
50 {
51         uint32_t eax, ebx, ecx, edx;
52 
53         cpuid(op, &eax, &ebx, &ecx, &edx);
54 
55         return eax;
56 }
57 
cpuid_ebx(uint32_t op)58 static inline uint32_t cpuid_ebx(uint32_t op)
59 {
60         uint32_t eax, ebx, ecx, edx;
61 
62         cpuid(op, &eax, &ebx, &ecx, &edx);
63 
64         return ebx;
65 }
66 
cpuid_ecx(uint32_t op)67 static inline uint32_t cpuid_ecx(uint32_t op)
68 {
69         uint32_t eax, ebx, ecx, edx;
70 
71         cpuid(op, &eax, &ebx, &ecx, &edx);
72 
73         return ecx;
74 }
75 
cpuid_edx(uint32_t op)76 static inline uint32_t cpuid_edx(uint32_t op)
77 {
78         uint32_t eax, ebx, ecx, edx;
79 
80         cpuid(op, &eax, &ebx, &ecx, &edx);
81 
82         return edx;
83 }
84 
cpuid_count(uint32_t op,uint32_t cnt,uint32_t * eax,uint32_t * ebx,uint32_t * ecx,uint32_t * edx)85 static inline void cpuid_count(uint32_t op, uint32_t cnt,
86 			       uint32_t * eax, uint32_t * ebx,
87 			       uint32_t * ecx, uint32_t * edx)
88 {
89     asm volatile("movl %%ebx,%1 ; "
90 		 "cpuid ; "
91 		 "xchgl %1,%%ebx"
92 		 : "=a" (*eax), "=SD" (*ebx), "=c" (*ecx), "=d" (*edx)
93 		 : "a"(op), "c"(cnt));
94 }
95 
rdmsr(uint32_t msr)96 static inline uint64_t rdmsr(uint32_t msr)
97 {
98     uint64_t v;
99 
100     asm volatile("rdmsr" : "=A" (v) : "c"(msr));
101     return v;
102 }
103 
wrmsr(uint64_t v,uint32_t msr)104 static inline void wrmsr(uint64_t v, uint32_t msr)
105 {
106     asm volatile("wrmsr" : : "A" (v), "c" (msr));
107 }
108 
cpu_relax(void)109 static inline void cpu_relax(void)
110 {
111     asm volatile("rep ; nop" : : : "memory");
112 }
113 
hlt(void)114 static inline void hlt(void)
115 {
116     asm volatile("hlt" : : : "memory");
117 }
118 
cli(void)119 static inline void cli(void)
120 {
121     asm volatile("cli" : : : "memory");
122 }
123 
sti(void)124 static inline void sti(void)
125 {
126     asm volatile("sti" : : : "memory");
127 }
128 #endif
129