1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
#ifndef _X86_CPU_H
#define _X86_CPU_H
#include <klibc/compiler.h>
#include <inttypes.h>
#include <stdbool.h>
static inline bool cpu_has_eflag(unsigned long flag)
{
unsigned long f1, f2;
asm("pushf ; "
"pushf ; "
"pop %0 ; "
"mov %0,%1 ; "
"xor %2,%1 ; "
"push %1 ; "
"popf ; "
"pushf ; "
"pop %1 ; "
"popf"
: "=r" (f1), "=r" (f2) : "ri" (flag));
return !!((f1 ^ f2) & flag);
}
static inline uint64_t rdtsc(void)
{
uint32_t eax, edx;
asm volatile("rdtsc" : "=a" (eax), "=d" (edx));
return eax + ((uint64_t)edx << 32);
}
static inline uint32_t rdtscl(void)
{
uint32_t v;
asm volatile("rdtsc" : "=a" (v) : : "edx");
return v;
}
static inline void cpuid_count(uint32_t op, uint32_t cnt,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
#if defined(__i386__) && defined(__PIC__)
asm volatile("movl %%ebx,%1 ; "
"cpuid ; "
"xchgl %1,%%ebx"
: "=a" (*eax), "=SD" (*ebx), "=c" (*ecx), "=d" (*edx)
: "a"(op), "c"(cnt));
#else
asm volatile("cpuid"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "a"(op), "c"(cnt));
#endif
}
static inline void cpuid(uint32_t op,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
cpuid_count(op, 0, eax, ebx, ecx, edx);
}
static inline __constfunc uint32_t cpuid_eax(uint32_t level)
{
uint32_t eax, ebx, ecx, edx;
cpuid_count(level, 0, &eax, &ebx, &ecx, &edx);
return eax;
}
static inline __constfunc uint32_t cpuid_ebx(uint32_t level)
{
uint32_t eax, ebx, ecx, edx;
cpuid_count(level, 0, &eax, &ebx, &ecx, &edx);
return ebx;
}
static inline __constfunc uint32_t cpuid_ecx(uint32_t level)
{
uint32_t eax, ebx, ecx, edx;
cpuid_count(level, 0, &eax, &ebx, &ecx, &edx);
return ecx;
}
static inline __constfunc uint32_t cpuid_edx(uint32_t level)
{
uint32_t eax, ebx, ecx, edx;
cpuid_count(level, 0, &eax, &ebx, &ecx, &edx);
return edx;
}
static inline uint64_t rdmsr(uint32_t msr)
{
uint32_t eax, edx;
asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (msr));
return eax + ((uint64_t)edx << 32);
}
static inline void wrmsr(uint64_t v, uint32_t msr)
{
uint32_t eax = v;
uint32_t edx = v >> 32;
asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (msr));
}
static inline unsigned long long get_cr0(void)
{
unsigned long v;
asm volatile("mov %%cr0,%0" : "=r" (v));
return v;
}
static inline void set_cr0(unsigned long v)
{
asm volatile("mov %0,%%cr0" : : "r" (v));
}
static inline unsigned long get_cr4(void)
{
unsigned long v;
asm volatile("mov %%cr4,%0" : "=r" (v));
return v;
}
static inline void set_cr4(unsigned long v)
{
asm volatile("mov %0,%%cr4" : : "r" (v));
}
static inline uint32_t get_mxcsr(void)
{
uint32_t v;
asm("stmxcsr %0" : "=m" (v));
return v;
}
static inline void set_mxcsr(uint32_t v)
{
asm volatile("ldmxcsr %0" : : "m" (v));
}
static inline void fninit(void)
{
asm volatile("fninit");
}
static inline void cpu_relax(void)
{
asm volatile("rep ; nop");
}
static inline void hlt(void)
{
asm volatile("hlt" : : : "memory");
}
static inline void cli(void)
{
asm volatile("cli" : : : "memory");
}
static inline void sti(void)
{
asm volatile("sti" : : : "memory");
}
static inline unsigned long get_eflags(void)
{
unsigned long v;
asm volatile("pushf ; pop %0" : "=rm" (v));
return v;
}
static inline void set_eflags(unsigned long v)
{
asm volatile("push %0 ; popf" : : "g" (v) : "memory");
}
typedef unsigned long irq_state_t;
static inline irq_state_t irq_state(void)
{
return get_eflags();
}
static inline irq_state_t irq_save(void)
{
irq_state_t v = irq_state();
cli();
return v;
}
static inline void irq_restore(irq_state_t v)
{
set_eflags(v);
}
#endif /* _X86_CPU_H */
|