1/* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12/* 13 * Copyright 2014 Pluribus Networks Inc. 14 */ 15 16#ifndef _COMPAT_FREEBSD_AMD64_MACHINE_CPUFUNC_H_ 17#define _COMPAT_FREEBSD_AMD64_MACHINE_CPUFUNC_H_ 18 19#include <sys/types.h> 20 21static __inline u_long 22bsfq(u_long mask) 23{ 24 u_long result; 25 26 __asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask)); 27 return (result); 28} 29 30static __inline u_int 31bsrl(u_int mask) 32{ 33 u_int result; 34 35 __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask)); 36 return (result); 37} 38 39static __inline u_long 40bsrq(u_long mask) 41{ 42 u_long result; 43 44 __asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask)); 45 return (result); 46} 47 48static __inline void 49clts(void) 50{ 51 __asm __volatile("clts"); 52} 53 54static __inline void 55do_cpuid(u_int ax, u_int *p) 56{ 57 __asm __volatile("cpuid" 58 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 59 : "0" (ax)); 60} 61 62static __inline void 63cpuid_count(u_int ax, u_int cx, u_int *p) 64{ 65 __asm __volatile("cpuid" 66 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 67 : "0" (ax), "c" (cx)); 68} 69 70static __inline void 71disable_intr(void) 72{ 73 __asm __volatile("cli"); 74} 75 76static __inline void 77enable_intr(void) 78{ 79 __asm __volatile("sti"); 80} 81 82static __inline int 83ffsl(long mask) 84{ 85 return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1); 86} 87 88static __inline int 89fls(int mask) 90{ 91 return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 92} 93 94static __inline int 95flsl(long mask) 96{ 97 return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1); 98} 99 100static __inline int 101flsll(long long mask) 102{ 103 return (flsl((long)mask)); 104} 105 106static __inline u_long 107read_rflags(void) 108{ 109 u_long rf; 110 111 __asm __volatile("pushfq; popq %0" : "=r" (rf)); 112 return (rf); 113} 114 115static __inline uint64_t 116rdmsr(u_int msr) 117{ 118 uint32_t low, high; 119 120 __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); 121 return (low | ((uint64_t)high << 32)); 122} 123 124static __inline uint64_t 125rdtsc(void) 126{ 127 extern hrtime_t tsc_gethrtimeunscaled_delta(void); 128 129 /* Get the TSC reading with any needed synch offset applied */ 130 return ((uint64_t)tsc_gethrtimeunscaled_delta()); 131} 132 133static __inline void 134wrmsr(u_int msr, uint64_t newval) 135{ 136 uint32_t low, high; 137 138 low = newval; 139 high = newval >> 32; 140 __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 141} 142 143static __inline void 144load_cr0(u_long data) 145{ 146 __asm __volatile("movq %0,%%cr0" : : "r" (data)); 147} 148 149static __inline u_long 150rcr0(void) 151{ 152 u_long data; 153 154 __asm __volatile("movq %%cr0,%0" : "=r" (data)); 155 return (data); 156} 157 158static __inline u_long 159rcr3(void) 160{ 161 u_long data; 162 163 __asm __volatile("movq %%cr3,%0" : "=r" (data)); 164 return (data); 165} 166 167static __inline void 168load_cr4(u_long data) 169{ 170 __asm __volatile("movq %0,%%cr4" : : "r" (data)); 171} 172 173static __inline u_long 174rcr4(void) 175{ 176 u_long data; 177 178 __asm __volatile("movq %%cr4,%0" : "=r" (data)); 179 return (data); 180} 181 182static __inline u_long 183rxcr(u_int reg) 184{ 185 u_int low, high; 186 187 __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 188 return (low | ((uint64_t)high << 32)); 189} 190 191static __inline void 192load_xcr(u_int reg, u_long val) 193{ 194 u_int low, high; 195 196 low = val; 197 high = val >> 32; 198 __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 199} 200 201static __inline void 202write_rflags(u_long rf) 203{ 204 __asm __volatile("pushq %0; popfq" : : "r" (rf)); 205} 206 207static __inline uint64_t 208rdr0(void) 209{ 210 uint64_t data; 211 __asm __volatile("movq %%dr0,%0" : "=r" (data)); 212 return (data); 213} 214 215static __inline void 216load_dr0(uint64_t dr0) 217{ 218 __asm __volatile("movq %0,%%dr0" : : "r" (dr0)); 219} 220 221static __inline uint64_t 222rdr1(void) 223{ 224 uint64_t data; 225 __asm __volatile("movq %%dr1,%0" : "=r" (data)); 226 return (data); 227} 228 229static __inline void 230load_dr1(uint64_t dr1) 231{ 232 __asm __volatile("movq %0,%%dr1" : : "r" (dr1)); 233} 234 235static __inline uint64_t 236rdr2(void) 237{ 238 uint64_t data; 239 __asm __volatile("movq %%dr2,%0" : "=r" (data)); 240 return (data); 241} 242 243static __inline void 244load_dr2(uint64_t dr2) 245{ 246 __asm __volatile("movq %0,%%dr2" : : "r" (dr2)); 247} 248 249static __inline uint64_t 250rdr3(void) 251{ 252 uint64_t data; 253 __asm __volatile("movq %%dr3,%0" : "=r" (data)); 254 return (data); 255} 256 257static __inline void 258load_dr3(uint64_t dr3) 259{ 260 __asm __volatile("movq %0,%%dr3" : : "r" (dr3)); 261} 262 263static __inline uint64_t 264rdr6(void) 265{ 266 uint64_t data; 267 __asm __volatile("movq %%dr6,%0" : "=r" (data)); 268 return (data); 269} 270 271static __inline void 272load_dr6(uint64_t dr6) 273{ 274 __asm __volatile("movq %0,%%dr6" : : "r" (dr6)); 275} 276 277static __inline uint64_t 278rdr7(void) 279{ 280 uint64_t data; 281 __asm __volatile("movq %%dr7,%0" : "=r" (data)); 282 return (data); 283} 284 285static __inline void 286load_dr7(uint64_t dr7) 287{ 288 __asm __volatile("movq %0,%%dr7" : : "r" (dr7)); 289} 290 291#ifdef _KERNEL 292/* 293 * Including the native sys/segments.h in userspace seriously conflicts with 294 * the FreeBSD compat/contrib headers. 295 */ 296#include <sys/segments.h> 297 298static __inline void 299lldt(u_short sel) 300{ 301 wr_ldtr(sel); 302} 303 304static __inline u_short 305sldt() 306{ 307 return (rd_ldtr()); 308} 309#endif /* _KERNEL */ 310 311#endif /* _COMPAT_FREEBSD_AMD64_MACHINE_CPUFUNC_H_ */ 312