xref: /titanic_51/usr/src/boot/sys/i386/include/cpufunc.h (revision 4a5d661a82b942b6538acd26209d959ce98b593a)
1*4a5d661aSToomas Soome /*-
2*4a5d661aSToomas Soome  * Copyright (c) 1993 The Regents of the University of California.
3*4a5d661aSToomas Soome  * All rights reserved.
4*4a5d661aSToomas Soome  *
5*4a5d661aSToomas Soome  * Redistribution and use in source and binary forms, with or without
6*4a5d661aSToomas Soome  * modification, are permitted provided that the following conditions
7*4a5d661aSToomas Soome  * are met:
8*4a5d661aSToomas Soome  * 1. Redistributions of source code must retain the above copyright
9*4a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer.
10*4a5d661aSToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11*4a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12*4a5d661aSToomas Soome  *    documentation and/or other materials provided with the distribution.
13*4a5d661aSToomas Soome  * 4. Neither the name of the University nor the names of its contributors
14*4a5d661aSToomas Soome  *    may be used to endorse or promote products derived from this software
15*4a5d661aSToomas Soome  *    without specific prior written permission.
16*4a5d661aSToomas Soome  *
17*4a5d661aSToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18*4a5d661aSToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*4a5d661aSToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*4a5d661aSToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21*4a5d661aSToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*4a5d661aSToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*4a5d661aSToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*4a5d661aSToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*4a5d661aSToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*4a5d661aSToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*4a5d661aSToomas Soome  * SUCH DAMAGE.
28*4a5d661aSToomas Soome  *
29*4a5d661aSToomas Soome  * $FreeBSD$
30*4a5d661aSToomas Soome  */
31*4a5d661aSToomas Soome 
32*4a5d661aSToomas Soome /*
33*4a5d661aSToomas Soome  * Functions to provide access to special i386 instructions.
34*4a5d661aSToomas Soome  * This in included in sys/systm.h, and that file should be
35*4a5d661aSToomas Soome  * used in preference to this.
36*4a5d661aSToomas Soome  */
37*4a5d661aSToomas Soome 
38*4a5d661aSToomas Soome #ifndef _MACHINE_CPUFUNC_H_
39*4a5d661aSToomas Soome #define	_MACHINE_CPUFUNC_H_
40*4a5d661aSToomas Soome 
41*4a5d661aSToomas Soome #ifndef _SYS_CDEFS_H_
42*4a5d661aSToomas Soome #error this file needs sys/cdefs.h as a prerequisite
43*4a5d661aSToomas Soome #endif
44*4a5d661aSToomas Soome 
45*4a5d661aSToomas Soome struct region_descriptor;
46*4a5d661aSToomas Soome 
47*4a5d661aSToomas Soome #define readb(va)	(*(volatile uint8_t *) (va))
48*4a5d661aSToomas Soome #define readw(va)	(*(volatile uint16_t *) (va))
49*4a5d661aSToomas Soome #define readl(va)	(*(volatile uint32_t *) (va))
50*4a5d661aSToomas Soome 
51*4a5d661aSToomas Soome #define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
52*4a5d661aSToomas Soome #define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
53*4a5d661aSToomas Soome #define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
54*4a5d661aSToomas Soome 
55*4a5d661aSToomas Soome #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
56*4a5d661aSToomas Soome 
57*4a5d661aSToomas Soome static __inline void
58*4a5d661aSToomas Soome breakpoint(void)
59*4a5d661aSToomas Soome {
60*4a5d661aSToomas Soome 	__asm __volatile("int $3");
61*4a5d661aSToomas Soome }
62*4a5d661aSToomas Soome 
63*4a5d661aSToomas Soome static __inline u_int
64*4a5d661aSToomas Soome bsfl(u_int mask)
65*4a5d661aSToomas Soome {
66*4a5d661aSToomas Soome 	u_int	result;
67*4a5d661aSToomas Soome 
68*4a5d661aSToomas Soome 	__asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
69*4a5d661aSToomas Soome 	return (result);
70*4a5d661aSToomas Soome }
71*4a5d661aSToomas Soome 
72*4a5d661aSToomas Soome static __inline u_int
73*4a5d661aSToomas Soome bsrl(u_int mask)
74*4a5d661aSToomas Soome {
75*4a5d661aSToomas Soome 	u_int	result;
76*4a5d661aSToomas Soome 
77*4a5d661aSToomas Soome 	__asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
78*4a5d661aSToomas Soome 	return (result);
79*4a5d661aSToomas Soome }
80*4a5d661aSToomas Soome 
81*4a5d661aSToomas Soome static __inline void
82*4a5d661aSToomas Soome clflush(u_long addr)
83*4a5d661aSToomas Soome {
84*4a5d661aSToomas Soome 
85*4a5d661aSToomas Soome 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
86*4a5d661aSToomas Soome }
87*4a5d661aSToomas Soome 
88*4a5d661aSToomas Soome static __inline void
89*4a5d661aSToomas Soome clflushopt(u_long addr)
90*4a5d661aSToomas Soome {
91*4a5d661aSToomas Soome 
92*4a5d661aSToomas Soome 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
93*4a5d661aSToomas Soome }
94*4a5d661aSToomas Soome 
95*4a5d661aSToomas Soome static __inline void
96*4a5d661aSToomas Soome clts(void)
97*4a5d661aSToomas Soome {
98*4a5d661aSToomas Soome 
99*4a5d661aSToomas Soome 	__asm __volatile("clts");
100*4a5d661aSToomas Soome }
101*4a5d661aSToomas Soome 
102*4a5d661aSToomas Soome static __inline void
103*4a5d661aSToomas Soome disable_intr(void)
104*4a5d661aSToomas Soome {
105*4a5d661aSToomas Soome 
106*4a5d661aSToomas Soome 	__asm __volatile("cli" : : : "memory");
107*4a5d661aSToomas Soome }
108*4a5d661aSToomas Soome 
109*4a5d661aSToomas Soome static __inline void
110*4a5d661aSToomas Soome do_cpuid(u_int ax, u_int *p)
111*4a5d661aSToomas Soome {
112*4a5d661aSToomas Soome 	__asm __volatile("cpuid"
113*4a5d661aSToomas Soome 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
114*4a5d661aSToomas Soome 			 :  "0" (ax));
115*4a5d661aSToomas Soome }
116*4a5d661aSToomas Soome 
117*4a5d661aSToomas Soome static __inline void
118*4a5d661aSToomas Soome cpuid_count(u_int ax, u_int cx, u_int *p)
119*4a5d661aSToomas Soome {
120*4a5d661aSToomas Soome 	__asm __volatile("cpuid"
121*4a5d661aSToomas Soome 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
122*4a5d661aSToomas Soome 			 :  "0" (ax), "c" (cx));
123*4a5d661aSToomas Soome }
124*4a5d661aSToomas Soome 
125*4a5d661aSToomas Soome static __inline void
126*4a5d661aSToomas Soome enable_intr(void)
127*4a5d661aSToomas Soome {
128*4a5d661aSToomas Soome 
129*4a5d661aSToomas Soome 	__asm __volatile("sti");
130*4a5d661aSToomas Soome }
131*4a5d661aSToomas Soome 
132*4a5d661aSToomas Soome static __inline void
133*4a5d661aSToomas Soome cpu_monitor(const void *addr, u_long extensions, u_int hints)
134*4a5d661aSToomas Soome {
135*4a5d661aSToomas Soome 
136*4a5d661aSToomas Soome 	__asm __volatile("monitor"
137*4a5d661aSToomas Soome 	    : : "a" (addr), "c" (extensions), "d" (hints));
138*4a5d661aSToomas Soome }
139*4a5d661aSToomas Soome 
140*4a5d661aSToomas Soome static __inline void
141*4a5d661aSToomas Soome cpu_mwait(u_long extensions, u_int hints)
142*4a5d661aSToomas Soome {
143*4a5d661aSToomas Soome 
144*4a5d661aSToomas Soome 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
145*4a5d661aSToomas Soome }
146*4a5d661aSToomas Soome 
147*4a5d661aSToomas Soome static __inline void
148*4a5d661aSToomas Soome lfence(void)
149*4a5d661aSToomas Soome {
150*4a5d661aSToomas Soome 
151*4a5d661aSToomas Soome 	__asm __volatile("lfence" : : : "memory");
152*4a5d661aSToomas Soome }
153*4a5d661aSToomas Soome 
154*4a5d661aSToomas Soome static __inline void
155*4a5d661aSToomas Soome mfence(void)
156*4a5d661aSToomas Soome {
157*4a5d661aSToomas Soome 
158*4a5d661aSToomas Soome 	__asm __volatile("mfence" : : : "memory");
159*4a5d661aSToomas Soome }
160*4a5d661aSToomas Soome 
161*4a5d661aSToomas Soome #ifdef _KERNEL
162*4a5d661aSToomas Soome 
163*4a5d661aSToomas Soome #define	HAVE_INLINE_FFS
164*4a5d661aSToomas Soome 
165*4a5d661aSToomas Soome static __inline int
166*4a5d661aSToomas Soome ffs(int mask)
167*4a5d661aSToomas Soome {
168*4a5d661aSToomas Soome 	/*
169*4a5d661aSToomas Soome 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
170*4a5d661aSToomas Soome 	 * this inline or turn off the builtin.  The builtin is faster but
171*4a5d661aSToomas Soome 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
172*4a5d661aSToomas Soome 	 * versions.
173*4a5d661aSToomas Soome 	 */
174*4a5d661aSToomas Soome 	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
175*4a5d661aSToomas Soome }
176*4a5d661aSToomas Soome 
177*4a5d661aSToomas Soome #define	HAVE_INLINE_FFSL
178*4a5d661aSToomas Soome 
179*4a5d661aSToomas Soome static __inline int
180*4a5d661aSToomas Soome ffsl(long mask)
181*4a5d661aSToomas Soome {
182*4a5d661aSToomas Soome 	return (ffs((int)mask));
183*4a5d661aSToomas Soome }
184*4a5d661aSToomas Soome 
185*4a5d661aSToomas Soome #define	HAVE_INLINE_FLS
186*4a5d661aSToomas Soome 
187*4a5d661aSToomas Soome static __inline int
188*4a5d661aSToomas Soome fls(int mask)
189*4a5d661aSToomas Soome {
190*4a5d661aSToomas Soome 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
191*4a5d661aSToomas Soome }
192*4a5d661aSToomas Soome 
193*4a5d661aSToomas Soome #define	HAVE_INLINE_FLSL
194*4a5d661aSToomas Soome 
195*4a5d661aSToomas Soome static __inline int
196*4a5d661aSToomas Soome flsl(long mask)
197*4a5d661aSToomas Soome {
198*4a5d661aSToomas Soome 	return (fls((int)mask));
199*4a5d661aSToomas Soome }
200*4a5d661aSToomas Soome 
201*4a5d661aSToomas Soome #endif /* _KERNEL */
202*4a5d661aSToomas Soome 
203*4a5d661aSToomas Soome static __inline void
204*4a5d661aSToomas Soome halt(void)
205*4a5d661aSToomas Soome {
206*4a5d661aSToomas Soome 	__asm __volatile("hlt");
207*4a5d661aSToomas Soome }
208*4a5d661aSToomas Soome 
209*4a5d661aSToomas Soome static __inline u_char
210*4a5d661aSToomas Soome inb(u_int port)
211*4a5d661aSToomas Soome {
212*4a5d661aSToomas Soome 	u_char	data;
213*4a5d661aSToomas Soome 
214*4a5d661aSToomas Soome 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
215*4a5d661aSToomas Soome 	return (data);
216*4a5d661aSToomas Soome }
217*4a5d661aSToomas Soome 
218*4a5d661aSToomas Soome static __inline u_int
219*4a5d661aSToomas Soome inl(u_int port)
220*4a5d661aSToomas Soome {
221*4a5d661aSToomas Soome 	u_int	data;
222*4a5d661aSToomas Soome 
223*4a5d661aSToomas Soome 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
224*4a5d661aSToomas Soome 	return (data);
225*4a5d661aSToomas Soome }
226*4a5d661aSToomas Soome 
227*4a5d661aSToomas Soome static __inline void
228*4a5d661aSToomas Soome insb(u_int port, void *addr, size_t count)
229*4a5d661aSToomas Soome {
230*4a5d661aSToomas Soome 	__asm __volatile("cld; rep; insb"
231*4a5d661aSToomas Soome 			 : "+D" (addr), "+c" (count)
232*4a5d661aSToomas Soome 			 : "d" (port)
233*4a5d661aSToomas Soome 			 : "memory");
234*4a5d661aSToomas Soome }
235*4a5d661aSToomas Soome 
236*4a5d661aSToomas Soome static __inline void
237*4a5d661aSToomas Soome insw(u_int port, void *addr, size_t count)
238*4a5d661aSToomas Soome {
239*4a5d661aSToomas Soome 	__asm __volatile("cld; rep; insw"
240*4a5d661aSToomas Soome 			 : "+D" (addr), "+c" (count)
241*4a5d661aSToomas Soome 			 : "d" (port)
242*4a5d661aSToomas Soome 			 : "memory");
243*4a5d661aSToomas Soome }
244*4a5d661aSToomas Soome 
245*4a5d661aSToomas Soome static __inline void
246*4a5d661aSToomas Soome insl(u_int port, void *addr, size_t count)
247*4a5d661aSToomas Soome {
248*4a5d661aSToomas Soome 	__asm __volatile("cld; rep; insl"
249*4a5d661aSToomas Soome 			 : "+D" (addr), "+c" (count)
250*4a5d661aSToomas Soome 			 : "d" (port)
251*4a5d661aSToomas Soome 			 : "memory");
252*4a5d661aSToomas Soome }
253*4a5d661aSToomas Soome 
254*4a5d661aSToomas Soome static __inline void
255*4a5d661aSToomas Soome invd(void)
256*4a5d661aSToomas Soome {
257*4a5d661aSToomas Soome 	__asm __volatile("invd");
258*4a5d661aSToomas Soome }
259*4a5d661aSToomas Soome 
260*4a5d661aSToomas Soome static __inline u_short
261*4a5d661aSToomas Soome inw(u_int port)
262*4a5d661aSToomas Soome {
263*4a5d661aSToomas Soome 	u_short	data;
264*4a5d661aSToomas Soome 
265*4a5d661aSToomas Soome 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
266*4a5d661aSToomas Soome 	return (data);
267*4a5d661aSToomas Soome }
268*4a5d661aSToomas Soome 
269*4a5d661aSToomas Soome static __inline void
270*4a5d661aSToomas Soome outb(u_int port, u_char data)
271*4a5d661aSToomas Soome {
272*4a5d661aSToomas Soome 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
273*4a5d661aSToomas Soome }
274*4a5d661aSToomas Soome 
275*4a5d661aSToomas Soome static __inline void
276*4a5d661aSToomas Soome outl(u_int port, u_int data)
277*4a5d661aSToomas Soome {
278*4a5d661aSToomas Soome 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
279*4a5d661aSToomas Soome }
280*4a5d661aSToomas Soome 
281*4a5d661aSToomas Soome static __inline void
282*4a5d661aSToomas Soome outsb(u_int port, const void *addr, size_t count)
283*4a5d661aSToomas Soome {
284*4a5d661aSToomas Soome 	__asm __volatile("cld; rep; outsb"
285*4a5d661aSToomas Soome 			 : "+S" (addr), "+c" (count)
286*4a5d661aSToomas Soome 			 : "d" (port));
287*4a5d661aSToomas Soome }
288*4a5d661aSToomas Soome 
289*4a5d661aSToomas Soome static __inline void
290*4a5d661aSToomas Soome outsw(u_int port, const void *addr, size_t count)
291*4a5d661aSToomas Soome {
292*4a5d661aSToomas Soome 	__asm __volatile("cld; rep; outsw"
293*4a5d661aSToomas Soome 			 : "+S" (addr), "+c" (count)
294*4a5d661aSToomas Soome 			 : "d" (port));
295*4a5d661aSToomas Soome }
296*4a5d661aSToomas Soome 
297*4a5d661aSToomas Soome static __inline void
298*4a5d661aSToomas Soome outsl(u_int port, const void *addr, size_t count)
299*4a5d661aSToomas Soome {
300*4a5d661aSToomas Soome 	__asm __volatile("cld; rep; outsl"
301*4a5d661aSToomas Soome 			 : "+S" (addr), "+c" (count)
302*4a5d661aSToomas Soome 			 : "d" (port));
303*4a5d661aSToomas Soome }
304*4a5d661aSToomas Soome 
305*4a5d661aSToomas Soome static __inline void
306*4a5d661aSToomas Soome outw(u_int port, u_short data)
307*4a5d661aSToomas Soome {
308*4a5d661aSToomas Soome 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
309*4a5d661aSToomas Soome }
310*4a5d661aSToomas Soome 
311*4a5d661aSToomas Soome static __inline void
312*4a5d661aSToomas Soome ia32_pause(void)
313*4a5d661aSToomas Soome {
314*4a5d661aSToomas Soome 	__asm __volatile("pause");
315*4a5d661aSToomas Soome }
316*4a5d661aSToomas Soome 
317*4a5d661aSToomas Soome static __inline u_int
318*4a5d661aSToomas Soome read_eflags(void)
319*4a5d661aSToomas Soome {
320*4a5d661aSToomas Soome 	u_int	ef;
321*4a5d661aSToomas Soome 
322*4a5d661aSToomas Soome 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
323*4a5d661aSToomas Soome 	return (ef);
324*4a5d661aSToomas Soome }
325*4a5d661aSToomas Soome 
326*4a5d661aSToomas Soome static __inline uint64_t
327*4a5d661aSToomas Soome rdmsr(u_int msr)
328*4a5d661aSToomas Soome {
329*4a5d661aSToomas Soome 	uint64_t rv;
330*4a5d661aSToomas Soome 
331*4a5d661aSToomas Soome 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
332*4a5d661aSToomas Soome 	return (rv);
333*4a5d661aSToomas Soome }
334*4a5d661aSToomas Soome 
335*4a5d661aSToomas Soome static __inline uint32_t
336*4a5d661aSToomas Soome rdmsr32(u_int msr)
337*4a5d661aSToomas Soome {
338*4a5d661aSToomas Soome 	uint32_t low;
339*4a5d661aSToomas Soome 
340*4a5d661aSToomas Soome 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "edx");
341*4a5d661aSToomas Soome 	return (low);
342*4a5d661aSToomas Soome }
343*4a5d661aSToomas Soome 
344*4a5d661aSToomas Soome static __inline uint64_t
345*4a5d661aSToomas Soome rdpmc(u_int pmc)
346*4a5d661aSToomas Soome {
347*4a5d661aSToomas Soome 	uint64_t rv;
348*4a5d661aSToomas Soome 
349*4a5d661aSToomas Soome 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
350*4a5d661aSToomas Soome 	return (rv);
351*4a5d661aSToomas Soome }
352*4a5d661aSToomas Soome 
353*4a5d661aSToomas Soome static __inline uint64_t
354*4a5d661aSToomas Soome rdtsc(void)
355*4a5d661aSToomas Soome {
356*4a5d661aSToomas Soome 	uint64_t rv;
357*4a5d661aSToomas Soome 
358*4a5d661aSToomas Soome 	__asm __volatile("rdtsc" : "=A" (rv));
359*4a5d661aSToomas Soome 	return (rv);
360*4a5d661aSToomas Soome }
361*4a5d661aSToomas Soome 
362*4a5d661aSToomas Soome static __inline uint32_t
363*4a5d661aSToomas Soome rdtsc32(void)
364*4a5d661aSToomas Soome {
365*4a5d661aSToomas Soome 	uint32_t rv;
366*4a5d661aSToomas Soome 
367*4a5d661aSToomas Soome 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
368*4a5d661aSToomas Soome 	return (rv);
369*4a5d661aSToomas Soome }
370*4a5d661aSToomas Soome 
371*4a5d661aSToomas Soome static __inline void
372*4a5d661aSToomas Soome wbinvd(void)
373*4a5d661aSToomas Soome {
374*4a5d661aSToomas Soome 	__asm __volatile("wbinvd");
375*4a5d661aSToomas Soome }
376*4a5d661aSToomas Soome 
377*4a5d661aSToomas Soome static __inline void
378*4a5d661aSToomas Soome write_eflags(u_int ef)
379*4a5d661aSToomas Soome {
380*4a5d661aSToomas Soome 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
381*4a5d661aSToomas Soome }
382*4a5d661aSToomas Soome 
383*4a5d661aSToomas Soome static __inline void
384*4a5d661aSToomas Soome wrmsr(u_int msr, uint64_t newval)
385*4a5d661aSToomas Soome {
386*4a5d661aSToomas Soome 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
387*4a5d661aSToomas Soome }
388*4a5d661aSToomas Soome 
389*4a5d661aSToomas Soome static __inline void
390*4a5d661aSToomas Soome load_cr0(u_int data)
391*4a5d661aSToomas Soome {
392*4a5d661aSToomas Soome 
393*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%cr0" : : "r" (data));
394*4a5d661aSToomas Soome }
395*4a5d661aSToomas Soome 
396*4a5d661aSToomas Soome static __inline u_int
397*4a5d661aSToomas Soome rcr0(void)
398*4a5d661aSToomas Soome {
399*4a5d661aSToomas Soome 	u_int	data;
400*4a5d661aSToomas Soome 
401*4a5d661aSToomas Soome 	__asm __volatile("movl %%cr0,%0" : "=r" (data));
402*4a5d661aSToomas Soome 	return (data);
403*4a5d661aSToomas Soome }
404*4a5d661aSToomas Soome 
405*4a5d661aSToomas Soome static __inline u_int
406*4a5d661aSToomas Soome rcr2(void)
407*4a5d661aSToomas Soome {
408*4a5d661aSToomas Soome 	u_int	data;
409*4a5d661aSToomas Soome 
410*4a5d661aSToomas Soome 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
411*4a5d661aSToomas Soome 	return (data);
412*4a5d661aSToomas Soome }
413*4a5d661aSToomas Soome 
414*4a5d661aSToomas Soome static __inline void
415*4a5d661aSToomas Soome load_cr3(u_int data)
416*4a5d661aSToomas Soome {
417*4a5d661aSToomas Soome 
418*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
419*4a5d661aSToomas Soome }
420*4a5d661aSToomas Soome 
421*4a5d661aSToomas Soome static __inline u_int
422*4a5d661aSToomas Soome rcr3(void)
423*4a5d661aSToomas Soome {
424*4a5d661aSToomas Soome 	u_int	data;
425*4a5d661aSToomas Soome 
426*4a5d661aSToomas Soome 	__asm __volatile("movl %%cr3,%0" : "=r" (data));
427*4a5d661aSToomas Soome 	return (data);
428*4a5d661aSToomas Soome }
429*4a5d661aSToomas Soome 
430*4a5d661aSToomas Soome static __inline void
431*4a5d661aSToomas Soome load_cr4(u_int data)
432*4a5d661aSToomas Soome {
433*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%cr4" : : "r" (data));
434*4a5d661aSToomas Soome }
435*4a5d661aSToomas Soome 
436*4a5d661aSToomas Soome static __inline u_int
437*4a5d661aSToomas Soome rcr4(void)
438*4a5d661aSToomas Soome {
439*4a5d661aSToomas Soome 	u_int	data;
440*4a5d661aSToomas Soome 
441*4a5d661aSToomas Soome 	__asm __volatile("movl %%cr4,%0" : "=r" (data));
442*4a5d661aSToomas Soome 	return (data);
443*4a5d661aSToomas Soome }
444*4a5d661aSToomas Soome 
445*4a5d661aSToomas Soome static __inline uint64_t
446*4a5d661aSToomas Soome rxcr(u_int reg)
447*4a5d661aSToomas Soome {
448*4a5d661aSToomas Soome 	u_int low, high;
449*4a5d661aSToomas Soome 
450*4a5d661aSToomas Soome 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
451*4a5d661aSToomas Soome 	return (low | ((uint64_t)high << 32));
452*4a5d661aSToomas Soome }
453*4a5d661aSToomas Soome 
454*4a5d661aSToomas Soome static __inline void
455*4a5d661aSToomas Soome load_xcr(u_int reg, uint64_t val)
456*4a5d661aSToomas Soome {
457*4a5d661aSToomas Soome 	u_int low, high;
458*4a5d661aSToomas Soome 
459*4a5d661aSToomas Soome 	low = val;
460*4a5d661aSToomas Soome 	high = val >> 32;
461*4a5d661aSToomas Soome 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
462*4a5d661aSToomas Soome }
463*4a5d661aSToomas Soome 
464*4a5d661aSToomas Soome /*
465*4a5d661aSToomas Soome  * Global TLB flush (except for thise for pages marked PG_G)
466*4a5d661aSToomas Soome  */
467*4a5d661aSToomas Soome static __inline void
468*4a5d661aSToomas Soome invltlb(void)
469*4a5d661aSToomas Soome {
470*4a5d661aSToomas Soome 
471*4a5d661aSToomas Soome 	load_cr3(rcr3());
472*4a5d661aSToomas Soome }
473*4a5d661aSToomas Soome 
474*4a5d661aSToomas Soome /*
475*4a5d661aSToomas Soome  * TLB flush for an individual page (even if it has PG_G).
476*4a5d661aSToomas Soome  * Only works on 486+ CPUs (i386 does not have PG_G).
477*4a5d661aSToomas Soome  */
478*4a5d661aSToomas Soome static __inline void
479*4a5d661aSToomas Soome invlpg(u_int addr)
480*4a5d661aSToomas Soome {
481*4a5d661aSToomas Soome 
482*4a5d661aSToomas Soome 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
483*4a5d661aSToomas Soome }
484*4a5d661aSToomas Soome 
485*4a5d661aSToomas Soome static __inline u_short
486*4a5d661aSToomas Soome rfs(void)
487*4a5d661aSToomas Soome {
488*4a5d661aSToomas Soome 	u_short sel;
489*4a5d661aSToomas Soome 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
490*4a5d661aSToomas Soome 	return (sel);
491*4a5d661aSToomas Soome }
492*4a5d661aSToomas Soome 
493*4a5d661aSToomas Soome static __inline uint64_t
494*4a5d661aSToomas Soome rgdt(void)
495*4a5d661aSToomas Soome {
496*4a5d661aSToomas Soome 	uint64_t gdtr;
497*4a5d661aSToomas Soome 	__asm __volatile("sgdt %0" : "=m" (gdtr));
498*4a5d661aSToomas Soome 	return (gdtr);
499*4a5d661aSToomas Soome }
500*4a5d661aSToomas Soome 
501*4a5d661aSToomas Soome static __inline u_short
502*4a5d661aSToomas Soome rgs(void)
503*4a5d661aSToomas Soome {
504*4a5d661aSToomas Soome 	u_short sel;
505*4a5d661aSToomas Soome 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
506*4a5d661aSToomas Soome 	return (sel);
507*4a5d661aSToomas Soome }
508*4a5d661aSToomas Soome 
509*4a5d661aSToomas Soome static __inline uint64_t
510*4a5d661aSToomas Soome ridt(void)
511*4a5d661aSToomas Soome {
512*4a5d661aSToomas Soome 	uint64_t idtr;
513*4a5d661aSToomas Soome 	__asm __volatile("sidt %0" : "=m" (idtr));
514*4a5d661aSToomas Soome 	return (idtr);
515*4a5d661aSToomas Soome }
516*4a5d661aSToomas Soome 
517*4a5d661aSToomas Soome static __inline u_short
518*4a5d661aSToomas Soome rldt(void)
519*4a5d661aSToomas Soome {
520*4a5d661aSToomas Soome 	u_short ldtr;
521*4a5d661aSToomas Soome 	__asm __volatile("sldt %0" : "=g" (ldtr));
522*4a5d661aSToomas Soome 	return (ldtr);
523*4a5d661aSToomas Soome }
524*4a5d661aSToomas Soome 
525*4a5d661aSToomas Soome static __inline u_short
526*4a5d661aSToomas Soome rss(void)
527*4a5d661aSToomas Soome {
528*4a5d661aSToomas Soome 	u_short sel;
529*4a5d661aSToomas Soome 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
530*4a5d661aSToomas Soome 	return (sel);
531*4a5d661aSToomas Soome }
532*4a5d661aSToomas Soome 
533*4a5d661aSToomas Soome static __inline u_short
534*4a5d661aSToomas Soome rtr(void)
535*4a5d661aSToomas Soome {
536*4a5d661aSToomas Soome 	u_short tr;
537*4a5d661aSToomas Soome 	__asm __volatile("str %0" : "=g" (tr));
538*4a5d661aSToomas Soome 	return (tr);
539*4a5d661aSToomas Soome }
540*4a5d661aSToomas Soome 
541*4a5d661aSToomas Soome static __inline void
542*4a5d661aSToomas Soome load_fs(u_short sel)
543*4a5d661aSToomas Soome {
544*4a5d661aSToomas Soome 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
545*4a5d661aSToomas Soome }
546*4a5d661aSToomas Soome 
547*4a5d661aSToomas Soome static __inline void
548*4a5d661aSToomas Soome load_gs(u_short sel)
549*4a5d661aSToomas Soome {
550*4a5d661aSToomas Soome 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
551*4a5d661aSToomas Soome }
552*4a5d661aSToomas Soome 
553*4a5d661aSToomas Soome static __inline void
554*4a5d661aSToomas Soome lidt(struct region_descriptor *addr)
555*4a5d661aSToomas Soome {
556*4a5d661aSToomas Soome 	__asm __volatile("lidt (%0)" : : "r" (addr));
557*4a5d661aSToomas Soome }
558*4a5d661aSToomas Soome 
559*4a5d661aSToomas Soome static __inline void
560*4a5d661aSToomas Soome lldt(u_short sel)
561*4a5d661aSToomas Soome {
562*4a5d661aSToomas Soome 	__asm __volatile("lldt %0" : : "r" (sel));
563*4a5d661aSToomas Soome }
564*4a5d661aSToomas Soome 
565*4a5d661aSToomas Soome static __inline void
566*4a5d661aSToomas Soome ltr(u_short sel)
567*4a5d661aSToomas Soome {
568*4a5d661aSToomas Soome 	__asm __volatile("ltr %0" : : "r" (sel));
569*4a5d661aSToomas Soome }
570*4a5d661aSToomas Soome 
571*4a5d661aSToomas Soome static __inline u_int
572*4a5d661aSToomas Soome rdr0(void)
573*4a5d661aSToomas Soome {
574*4a5d661aSToomas Soome 	u_int	data;
575*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
576*4a5d661aSToomas Soome 	return (data);
577*4a5d661aSToomas Soome }
578*4a5d661aSToomas Soome 
579*4a5d661aSToomas Soome static __inline void
580*4a5d661aSToomas Soome load_dr0(u_int dr0)
581*4a5d661aSToomas Soome {
582*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
583*4a5d661aSToomas Soome }
584*4a5d661aSToomas Soome 
585*4a5d661aSToomas Soome static __inline u_int
586*4a5d661aSToomas Soome rdr1(void)
587*4a5d661aSToomas Soome {
588*4a5d661aSToomas Soome 	u_int	data;
589*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
590*4a5d661aSToomas Soome 	return (data);
591*4a5d661aSToomas Soome }
592*4a5d661aSToomas Soome 
593*4a5d661aSToomas Soome static __inline void
594*4a5d661aSToomas Soome load_dr1(u_int dr1)
595*4a5d661aSToomas Soome {
596*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
597*4a5d661aSToomas Soome }
598*4a5d661aSToomas Soome 
599*4a5d661aSToomas Soome static __inline u_int
600*4a5d661aSToomas Soome rdr2(void)
601*4a5d661aSToomas Soome {
602*4a5d661aSToomas Soome 	u_int	data;
603*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
604*4a5d661aSToomas Soome 	return (data);
605*4a5d661aSToomas Soome }
606*4a5d661aSToomas Soome 
607*4a5d661aSToomas Soome static __inline void
608*4a5d661aSToomas Soome load_dr2(u_int dr2)
609*4a5d661aSToomas Soome {
610*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
611*4a5d661aSToomas Soome }
612*4a5d661aSToomas Soome 
613*4a5d661aSToomas Soome static __inline u_int
614*4a5d661aSToomas Soome rdr3(void)
615*4a5d661aSToomas Soome {
616*4a5d661aSToomas Soome 	u_int	data;
617*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
618*4a5d661aSToomas Soome 	return (data);
619*4a5d661aSToomas Soome }
620*4a5d661aSToomas Soome 
621*4a5d661aSToomas Soome static __inline void
622*4a5d661aSToomas Soome load_dr3(u_int dr3)
623*4a5d661aSToomas Soome {
624*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
625*4a5d661aSToomas Soome }
626*4a5d661aSToomas Soome 
627*4a5d661aSToomas Soome static __inline u_int
628*4a5d661aSToomas Soome rdr4(void)
629*4a5d661aSToomas Soome {
630*4a5d661aSToomas Soome 	u_int	data;
631*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
632*4a5d661aSToomas Soome 	return (data);
633*4a5d661aSToomas Soome }
634*4a5d661aSToomas Soome 
635*4a5d661aSToomas Soome static __inline void
636*4a5d661aSToomas Soome load_dr4(u_int dr4)
637*4a5d661aSToomas Soome {
638*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
639*4a5d661aSToomas Soome }
640*4a5d661aSToomas Soome 
641*4a5d661aSToomas Soome static __inline u_int
642*4a5d661aSToomas Soome rdr5(void)
643*4a5d661aSToomas Soome {
644*4a5d661aSToomas Soome 	u_int	data;
645*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
646*4a5d661aSToomas Soome 	return (data);
647*4a5d661aSToomas Soome }
648*4a5d661aSToomas Soome 
649*4a5d661aSToomas Soome static __inline void
650*4a5d661aSToomas Soome load_dr5(u_int dr5)
651*4a5d661aSToomas Soome {
652*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
653*4a5d661aSToomas Soome }
654*4a5d661aSToomas Soome 
655*4a5d661aSToomas Soome static __inline u_int
656*4a5d661aSToomas Soome rdr6(void)
657*4a5d661aSToomas Soome {
658*4a5d661aSToomas Soome 	u_int	data;
659*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
660*4a5d661aSToomas Soome 	return (data);
661*4a5d661aSToomas Soome }
662*4a5d661aSToomas Soome 
663*4a5d661aSToomas Soome static __inline void
664*4a5d661aSToomas Soome load_dr6(u_int dr6)
665*4a5d661aSToomas Soome {
666*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
667*4a5d661aSToomas Soome }
668*4a5d661aSToomas Soome 
669*4a5d661aSToomas Soome static __inline u_int
670*4a5d661aSToomas Soome rdr7(void)
671*4a5d661aSToomas Soome {
672*4a5d661aSToomas Soome 	u_int	data;
673*4a5d661aSToomas Soome 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
674*4a5d661aSToomas Soome 	return (data);
675*4a5d661aSToomas Soome }
676*4a5d661aSToomas Soome 
677*4a5d661aSToomas Soome static __inline void
678*4a5d661aSToomas Soome load_dr7(u_int dr7)
679*4a5d661aSToomas Soome {
680*4a5d661aSToomas Soome 	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
681*4a5d661aSToomas Soome }
682*4a5d661aSToomas Soome 
683*4a5d661aSToomas Soome static __inline u_char
684*4a5d661aSToomas Soome read_cyrix_reg(u_char reg)
685*4a5d661aSToomas Soome {
686*4a5d661aSToomas Soome 	outb(0x22, reg);
687*4a5d661aSToomas Soome 	return inb(0x23);
688*4a5d661aSToomas Soome }
689*4a5d661aSToomas Soome 
690*4a5d661aSToomas Soome static __inline void
691*4a5d661aSToomas Soome write_cyrix_reg(u_char reg, u_char data)
692*4a5d661aSToomas Soome {
693*4a5d661aSToomas Soome 	outb(0x22, reg);
694*4a5d661aSToomas Soome 	outb(0x23, data);
695*4a5d661aSToomas Soome }
696*4a5d661aSToomas Soome 
697*4a5d661aSToomas Soome static __inline register_t
698*4a5d661aSToomas Soome intr_disable(void)
699*4a5d661aSToomas Soome {
700*4a5d661aSToomas Soome 	register_t eflags;
701*4a5d661aSToomas Soome 
702*4a5d661aSToomas Soome 	eflags = read_eflags();
703*4a5d661aSToomas Soome 	disable_intr();
704*4a5d661aSToomas Soome 	return (eflags);
705*4a5d661aSToomas Soome }
706*4a5d661aSToomas Soome 
707*4a5d661aSToomas Soome static __inline void
708*4a5d661aSToomas Soome intr_restore(register_t eflags)
709*4a5d661aSToomas Soome {
710*4a5d661aSToomas Soome 	write_eflags(eflags);
711*4a5d661aSToomas Soome }
712*4a5d661aSToomas Soome 
713*4a5d661aSToomas Soome #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
714*4a5d661aSToomas Soome 
715*4a5d661aSToomas Soome int	breakpoint(void);
716*4a5d661aSToomas Soome u_int	bsfl(u_int mask);
717*4a5d661aSToomas Soome u_int	bsrl(u_int mask);
718*4a5d661aSToomas Soome void	clflush(u_long addr);
719*4a5d661aSToomas Soome void	clts(void);
720*4a5d661aSToomas Soome void	cpuid_count(u_int ax, u_int cx, u_int *p);
721*4a5d661aSToomas Soome void	disable_intr(void);
722*4a5d661aSToomas Soome void	do_cpuid(u_int ax, u_int *p);
723*4a5d661aSToomas Soome void	enable_intr(void);
724*4a5d661aSToomas Soome void	halt(void);
725*4a5d661aSToomas Soome void	ia32_pause(void);
726*4a5d661aSToomas Soome u_char	inb(u_int port);
727*4a5d661aSToomas Soome u_int	inl(u_int port);
728*4a5d661aSToomas Soome void	insb(u_int port, void *addr, size_t count);
729*4a5d661aSToomas Soome void	insl(u_int port, void *addr, size_t count);
730*4a5d661aSToomas Soome void	insw(u_int port, void *addr, size_t count);
731*4a5d661aSToomas Soome register_t	intr_disable(void);
732*4a5d661aSToomas Soome void	intr_restore(register_t ef);
733*4a5d661aSToomas Soome void	invd(void);
734*4a5d661aSToomas Soome void	invlpg(u_int addr);
735*4a5d661aSToomas Soome void	invltlb(void);
736*4a5d661aSToomas Soome u_short	inw(u_int port);
737*4a5d661aSToomas Soome void	lidt(struct region_descriptor *addr);
738*4a5d661aSToomas Soome void	lldt(u_short sel);
739*4a5d661aSToomas Soome void	load_cr0(u_int cr0);
740*4a5d661aSToomas Soome void	load_cr3(u_int cr3);
741*4a5d661aSToomas Soome void	load_cr4(u_int cr4);
742*4a5d661aSToomas Soome void	load_dr0(u_int dr0);
743*4a5d661aSToomas Soome void	load_dr1(u_int dr1);
744*4a5d661aSToomas Soome void	load_dr2(u_int dr2);
745*4a5d661aSToomas Soome void	load_dr3(u_int dr3);
746*4a5d661aSToomas Soome void	load_dr4(u_int dr4);
747*4a5d661aSToomas Soome void	load_dr5(u_int dr5);
748*4a5d661aSToomas Soome void	load_dr6(u_int dr6);
749*4a5d661aSToomas Soome void	load_dr7(u_int dr7);
750*4a5d661aSToomas Soome void	load_fs(u_short sel);
751*4a5d661aSToomas Soome void	load_gs(u_short sel);
752*4a5d661aSToomas Soome void	ltr(u_short sel);
753*4a5d661aSToomas Soome void	outb(u_int port, u_char data);
754*4a5d661aSToomas Soome void	outl(u_int port, u_int data);
755*4a5d661aSToomas Soome void	outsb(u_int port, const void *addr, size_t count);
756*4a5d661aSToomas Soome void	outsl(u_int port, const void *addr, size_t count);
757*4a5d661aSToomas Soome void	outsw(u_int port, const void *addr, size_t count);
758*4a5d661aSToomas Soome void	outw(u_int port, u_short data);
759*4a5d661aSToomas Soome u_int	rcr0(void);
760*4a5d661aSToomas Soome u_int	rcr2(void);
761*4a5d661aSToomas Soome u_int	rcr3(void);
762*4a5d661aSToomas Soome u_int	rcr4(void);
763*4a5d661aSToomas Soome uint64_t rdmsr(u_int msr);
764*4a5d661aSToomas Soome uint64_t rdpmc(u_int pmc);
765*4a5d661aSToomas Soome u_int	rdr0(void);
766*4a5d661aSToomas Soome u_int	rdr1(void);
767*4a5d661aSToomas Soome u_int	rdr2(void);
768*4a5d661aSToomas Soome u_int	rdr3(void);
769*4a5d661aSToomas Soome u_int	rdr4(void);
770*4a5d661aSToomas Soome u_int	rdr5(void);
771*4a5d661aSToomas Soome u_int	rdr6(void);
772*4a5d661aSToomas Soome u_int	rdr7(void);
773*4a5d661aSToomas Soome uint64_t rdtsc(void);
774*4a5d661aSToomas Soome u_char	read_cyrix_reg(u_char reg);
775*4a5d661aSToomas Soome u_int	read_eflags(void);
776*4a5d661aSToomas Soome u_int	rfs(void);
777*4a5d661aSToomas Soome uint64_t rgdt(void);
778*4a5d661aSToomas Soome u_int	rgs(void);
779*4a5d661aSToomas Soome uint64_t ridt(void);
780*4a5d661aSToomas Soome u_short	rldt(void);
781*4a5d661aSToomas Soome u_short	rtr(void);
782*4a5d661aSToomas Soome void	wbinvd(void);
783*4a5d661aSToomas Soome void	write_cyrix_reg(u_char reg, u_char data);
784*4a5d661aSToomas Soome void	write_eflags(u_int ef);
785*4a5d661aSToomas Soome void	wrmsr(u_int msr, uint64_t newval);
786*4a5d661aSToomas Soome 
787*4a5d661aSToomas Soome #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
788*4a5d661aSToomas Soome 
789*4a5d661aSToomas Soome void    reset_dbregs(void);
790*4a5d661aSToomas Soome 
791*4a5d661aSToomas Soome #ifdef _KERNEL
792*4a5d661aSToomas Soome int	rdmsr_safe(u_int msr, uint64_t *val);
793*4a5d661aSToomas Soome int	wrmsr_safe(u_int msr, uint64_t newval);
794*4a5d661aSToomas Soome #endif
795*4a5d661aSToomas Soome 
796*4a5d661aSToomas Soome #endif /* !_MACHINE_CPUFUNC_H_ */
797