cpufunc.h revision 181911
1193323Sed/*-
2193323Sed * Copyright (c) 1993 The Regents of the University of California.
3193323Sed * All rights reserved.
4193323Sed *
5193323Sed * Redistribution and use in source and binary forms, with or without
6193323Sed * modification, are permitted provided that the following conditions
7193323Sed * are met:
8193323Sed * 1. Redistributions of source code must retain the above copyright
9193323Sed *    notice, this list of conditions and the following disclaimer.
10193323Sed * 2. Redistributions in binary form must reproduce the above copyright
11249423Sdim *    notice, this list of conditions and the following disclaimer in the
12193323Sed *    documentation and/or other materials provided with the distribution.
13193323Sed * 4. Neither the name of the University nor the names of its contributors
14193323Sed *    may be used to endorse or promote products derived from this software
15193323Sed *    without specific prior written permission.
16234353Sdim *
17205407Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19249423Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20193323Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26212904Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27212904Sdim * SUCH DAMAGE.
28212904Sdim *
29212904Sdim * $FreeBSD: head/sys/i386/include/cpufunc.h 181911 2008-08-20 09:16:46Z kmacy $
30212904Sdim */
31234353Sdim
32212904Sdim/*
33212904Sdim * Functions to provide access to special i386 instructions.
34212904Sdim * This in included in sys/systm.h, and that file should be
35212904Sdim * used in preference to this.
36212904Sdim */
37212904Sdim
38212904Sdim#ifndef _MACHINE_CPUFUNC_H_
39243830Sdim#define	_MACHINE_CPUFUNC_H_
40243830Sdim
41243830Sdim#ifndef _SYS_CDEFS_H_
42243830Sdim#error this file needs sys/cdefs.h as a prerequisite
43243830Sdim#endif
44243830Sdim
45243830Sdim#ifdef XEN
46243830Sdimextern void xen_cli(void);
47212904Sdimextern void xen_sti(void);
48193323Sedextern void xen_load_cr3(u_int data);
49193323Sedextern void xen_tlb_flush(void);
50193323Sedextern void xen_invlpg(u_int addr);
51193323Sedextern int xen_save_and_cli(void);
52193323Sedextern void xen_restore_flags(u_int eflags);
53193323Sed#endif
54288943Sdim
55288943Sdimstruct region_descriptor;
56193323Sed
57226633Sdim#define readb(va)	(*(volatile u_int8_t *) (va))
58226633Sdim#define readw(va)	(*(volatile u_int16_t *) (va))
59193323Sed#define readl(va)	(*(volatile u_int32_t *) (va))
60193323Sed
61193323Sed#define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
62193323Sed#define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
63193323Sed#define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
64193323Sed
65193323Sed#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
66193323Sed
67193323Sedstatic __inline void
68193323Sedbreakpoint(void)
69193323Sed{
70193323Sed	__asm __volatile("int $3");
71193323Sed}
72193323Sed
73193323Sedstatic __inline u_int
74193323Sedbsfl(u_int mask)
75198090Srdivacky{
76193323Sed	u_int	result;
77193323Sed
78193323Sed	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
79193323Sed	return (result);
80193323Sed}
81193323Sed
82193323Sedstatic __inline u_int
83223017Sdimbsrl(u_int mask)
84193323Sed{
85193323Sed	u_int	result;
86193323Sed
87198090Srdivacky	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
88198090Srdivacky	return (result);
89193323Sed}
90193323Sed
91193323Sedstatic __inline void
92193323Seddisable_intr(void)
93193323Sed{
94198090Srdivacky#ifdef XEN
95193323Sed	xen_cli();
96193323Sed#else
97193323Sed    __asm __volatile("cli" : : : "memory");
98193323Sed#endif
99193323Sed}
100193323Sed
101193323Sedstatic __inline void
102218893Sdimdo_cpuid(u_int ax, u_int *p)
103218893Sdim{
104288943Sdim	__asm __volatile("cpuid"
105288943Sdim			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
106251662Sdim			 :  "0" (ax));
107218893Sdim}
108218893Sdim
109218893Sdimstatic __inline void
110218893Sdimcpuid_count(u_int ax, u_int cx, u_int *p)
111218893Sdim{
112218893Sdim	__asm __volatile("cpuid"
113218893Sdim			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
114288943Sdim			 :  "0" (ax), "c" (cx));
115218893Sdim}
116218893Sdim
117218893Sdimstatic __inline void
118218893Sdimenable_intr(void)
119218893Sdim{
120218893Sdim#ifdef XEN
121218893Sdim	xen_sti();
122193323Sed#else
123193323Sed	__asm __volatile("sti");
124193323Sed#endif
125193323Sed}
126193323Sed
127218893Sdimstatic inline void
128218893Sdimcpu_monitor(const void *addr, int extensions, int hints)
129193323Sed{
130193323Sed	__asm __volatile("monitor;"
131193323Sed	    : :"a" (addr), "c" (extensions), "d"(hints));
132193323Sed}
133193323Sed
134193323Sedstatic inline void
135193323Sedcpu_mwait(int extensions, int hints)
136193323Sed{
137193323Sed	__asm __volatile("mwait;" : :"a" (hints), "c" (extensions));
138193323Sed}
139221345Sdim
140221345Sdim#ifdef _KERNEL
141221345Sdim
142221345Sdim#define	HAVE_INLINE_FFS
143221345Sdim
144193323Sedstatic __inline int
145193323Sedffs(int mask)
146193323Sed{
147212904Sdim	/*
148193323Sed	 * Note that gcc-2's builtin ffs would be used if we didn't declare
149193323Sed	 * this inline or turn off the builtin.  The builtin is faster but
150193323Sed	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
151193323Sed	 * versions.
152249423Sdim	 */
153212904Sdim	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
154193323Sed}
155193323Sed
156212904Sdim#define	HAVE_INLINE_FLS
157212904Sdim
158212904Sdimstatic __inline int
159212904Sdimfls(int mask)
160212904Sdim{
161212904Sdim	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
162243830Sdim}
163243830Sdim
164249423Sdim#endif /* _KERNEL */
165243830Sdim
166243830Sdimstatic __inline void
167243830Sdimhalt(void)
168243830Sdim{
169243830Sdim	__asm __volatile("hlt");
170243830Sdim}
171243830Sdim
172205407Srdivacky#if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3
173205407Srdivacky
174205407Srdivacky#define	inb(port)		inbv(port)
175205407Srdivacky#define	outb(port, data)	outbv(port, data)
176205407Srdivacky
177205407Srdivacky#else /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3 */
178205407Srdivacky
179205407Srdivacky/*
180205407Srdivacky * The following complications are to get around gcc not having a
181193323Sed * constraint letter for the range 0..255.  We still put "d" in the
182193323Sed * constraint because "i" isn't a valid constraint when the port
183193323Sed * isn't constant.  This only matters for -O0 because otherwise
184193323Sed * the non-working version gets optimized away.
185193323Sed *
186193323Sed * Use an expression-statement instead of a conditional expression
187193323Sed * because gcc-2.6.0 would promote the operands of the conditional
188193323Sed * and produce poor code for "if ((inb(var) & const1) == const2)".
189193323Sed *
190193323Sed * The unnecessary test `(port) < 0x10000' is to generate a warning if
191193323Sed * the `port' has type u_short or smaller.  Such types are pessimal.
192193323Sed * This actually only works for signed types.  The range check is
193193323Sed * careful to avoid generating warnings.
194276479Sdim */
195193323Sed#define	inb(port) __extension__ ({					\
196193323Sed	u_char	_data;							\
197193323Sed	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
198193323Sed	    && (port) < 0x10000)					\
199193323Sed		_data = inbc(port);					\
200193323Sed	else								\
201193323Sed		_data = inbv(port);					\
202193323Sed	_data; })
203193323Sed
204193323Sed#define	outb(port, data) (						\
205193323Sed	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
206193323Sed	&& (port) < 0x10000						\
207193323Sed	? outbc(port, data) : outbv(port, data))
208193323Sed
209212904Sdimstatic __inline u_char
210193323Sedinbc(u_int port)
211212904Sdim{
212193323Sed	u_char	data;
213193323Sed
214193323Sed	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
215210299Sed	return (data);
216210299Sed}
217210299Sed
218210299Sedstatic __inline void
219210299Sedoutbc(u_int port, u_char data)
220210299Sed{
221210299Sed	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
222210299Sed}
223193323Sed
224193323Sed#endif /* __GNUCLIKE_BUILTIN_CONSTANT_P  && __GNUCLIKE_ASM >= 3*/
225193323Sed
226288943Sdimstatic __inline u_char
227288943Sdiminbv(u_int port)
228193323Sed{
229193323Sed	u_char	data;
230193323Sed	/*
231193323Sed	 * We use %%dx and not %1 here because i/o is done at %dx and not at
232210299Sed	 * %edx, while gcc generates inferior code (movw instead of movl)
233210299Sed	 * if we tell it to load (u_short) port.
234193323Sed	 */
235296417Sdim	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
236296417Sdim	return (data);
237296417Sdim}
238296417Sdim
239296417Sdimstatic __inline u_int
240296417Sdiminl(u_int port)
241296417Sdim{
242296417Sdim	u_int	data;
243296417Sdim
244296417Sdim	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
245296417Sdim	return (data);
246296417Sdim}
247296417Sdim
248296417Sdimstatic __inline void
249296417Sdiminsb(u_int port, void *addr, size_t cnt)
250296417Sdim{
251296417Sdim	__asm __volatile("cld; rep; insb"
252296417Sdim			 : "+D" (addr), "+c" (cnt)
253296417Sdim			 : "d" (port)
254193323Sed			 : "memory");
255210299Sed}
256193323Sed
257296417Sdimstatic __inline void
258193323Sedinsw(u_int port, void *addr, size_t cnt)
259193323Sed{
260193323Sed	__asm __volatile("cld; rep; insw"
261193323Sed			 : "+D" (addr), "+c" (cnt)
262193323Sed			 : "d" (port)
263193323Sed			 : "memory");
264193323Sed}
265193323Sed
266193323Sedstatic __inline void
267193323Sedinsl(u_int port, void *addr, size_t cnt)
268193323Sed{
269193323Sed	__asm __volatile("cld; rep; insl"
270193323Sed			 : "+D" (addr), "+c" (cnt)
271193323Sed			 : "d" (port)
272193323Sed			 : "memory");
273193323Sed}
274193323Sed
275193323Sedstatic __inline void
276193323Sedinvd(void)
277210299Sed{
278210299Sed	__asm __volatile("invd");
279193323Sed}
280193323Sed
281212904Sdimstatic __inline u_short
282193323Sedinw(u_int port)
283193323Sed{
284193323Sed	u_short	data;
285193323Sed
286193323Sed	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
287193323Sed	return (data);
288276479Sdim}
289193323Sed
290193323Sedstatic __inline void
291212904Sdimoutbv(u_int port, u_char data)
292212904Sdim{
293212904Sdim	u_char	al;
294212904Sdim	/*
295193323Sed	 * Use an unnecessary assignment to help gcc's register allocator.
296193323Sed	 * This make a large difference for gcc-1.40 and a tiny difference
297193323Sed	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
298210299Sed	 * best results.  gcc-2.6.0 can't handle this.
299193323Sed	 */
300193323Sed	al = data;
301193323Sed	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
302193323Sed}
303193323Sed
304193323Sedstatic __inline void
305193323Sedoutl(u_int port, u_int data)
306193323Sed{
307234353Sdim	/*
308234353Sdim	 * outl() and outw() aren't used much so we haven't looked at
309193323Sed	 * possible micro-optimizations such as the unnecessary
310193323Sed	 * assignment for them.
311276479Sdim	 */
312193323Sed	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
313212904Sdim}
314193323Sed
315234353Sdimstatic __inline void
316193323Sedoutsb(u_int port, const void *addr, size_t cnt)
317212904Sdim{
318193323Sed	__asm __volatile("cld; rep; outsb"
319193323Sed			 : "+S" (addr), "+c" (cnt)
320193323Sed			 : "d" (port));
321193323Sed}
322193323Sed
323193323Sedstatic __inline void
324276479Sdimoutsw(u_int port, const void *addr, size_t cnt)
325193323Sed{
326193323Sed	__asm __volatile("cld; rep; outsw"
327193323Sed			 : "+S" (addr), "+c" (cnt)
328193323Sed			 : "d" (port));
329193323Sed}
330193323Sed
331276479Sdimstatic __inline void
332193323Sedoutsl(u_int port, const void *addr, size_t cnt)
333193323Sed{
334193323Sed	__asm __volatile("cld; rep; outsl"
335212904Sdim			 : "+S" (addr), "+c" (cnt)
336212904Sdim			 : "d" (port));
337193323Sed}
338193323Sed
339193323Sedstatic __inline void
340193323Sedoutw(u_int port, u_short data)
341193323Sed{
342193323Sed	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
343193323Sed}
344193323Sed
345193323Sedstatic __inline void
346193323Sedia32_pause(void)
347193323Sed{
348193323Sed	__asm __volatile("pause");
349276479Sdim}
350193323Sed
351193323Sedstatic __inline u_int
352193323Sedread_eflags(void)
353193323Sed{
354193323Sed	u_int	ef;
355193323Sed
356193323Sed	__asm __volatile("pushfl; popl %0" : "=r" (ef));
357193323Sed	return (ef);
358193323Sed}
359193323Sed
360193323Sedstatic __inline uint64_t
361193323Sedrdmsr(u_int msr)
362193323Sed{
363276479Sdim	uint64_t rv;
364193323Sed
365193323Sed	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
366276479Sdim	return (rv);
367193323Sed}
368193323Sed
369193323Sedstatic __inline uint64_t
370193323Sedrdpmc(u_int pmc)
371193323Sed{
372193323Sed	uint64_t rv;
373193323Sed
374193323Sed	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
375193323Sed	return (rv);
376193323Sed}
377193323Sed
378193323Sedstatic __inline uint64_t
379193323Sedrdtsc(void)
380193323Sed{
381193323Sed	uint64_t rv;
382193323Sed
383193323Sed	__asm __volatile("rdtsc" : "=A" (rv));
384193323Sed	return (rv);
385193323Sed}
386193323Sed
387193323Sedstatic __inline void
388193323Sedwbinvd(void)
389193323Sed{
390193323Sed	__asm __volatile("wbinvd");
391193323Sed}
392193323Sed
393193323Sedstatic __inline void
394193323Sedwrite_eflags(u_int ef)
395193323Sed{
396193323Sed	__asm __volatile("pushl %0; popfl" : : "r" (ef));
397193323Sed}
398193323Sed
399193323Sedstatic __inline void
400193323Sedwrmsr(u_int msr, uint64_t newval)
401193323Sed{
402212904Sdim	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
403193323Sed}
404193323Sed
405193323Sedstatic __inline void
406193323Sedload_cr0(u_int data)
407193323Sed{
408193323Sed
409193323Sed	__asm __volatile("movl %0,%%cr0" : : "r" (data));
410193323Sed}
411193323Sed
412193323Sedstatic __inline u_int
413193323Sedrcr0(void)
414193323Sed{
415193323Sed	u_int	data;
416276479Sdim
417193323Sed	__asm __volatile("movl %%cr0,%0" : "=r" (data));
418193323Sed	return (data);
419193323Sed}
420193323Sed
421193323Sedstatic __inline u_int
422193323Sedrcr2(void)
423193323Sed{
424193323Sed	u_int	data;
425193323Sed
426193323Sed	__asm __volatile("movl %%cr2,%0" : "=r" (data));
427193323Sed	return (data);
428193323Sed}
429193323Sed
430193323Sedstatic __inline void
431193323Sedload_cr3(u_int data)
432193323Sed{
433193323Sed#ifdef XEN
434193323Sed	xen_load_cr3(data);
435193323Sed#else
436276479Sdim	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
437193323Sed#endif
438193323Sed}
439193323Sed
440193323Sedstatic __inline u_int
441193323Sedrcr3(void)
442193323Sed{
443193323Sed	u_int	data;
444193323Sed
445193323Sed	__asm __volatile("movl %%cr3,%0" : "=r" (data));
446276479Sdim	return (data);
447193323Sed}
448
449static __inline void
450load_cr4(u_int data)
451{
452	__asm __volatile("movl %0,%%cr4" : : "r" (data));
453}
454
455static __inline u_int
456rcr4(void)
457{
458	u_int	data;
459
460	__asm __volatile("movl %%cr4,%0" : "=r" (data));
461	return (data);
462}
463
464/*
465 * Global TLB flush (except for thise for pages marked PG_G)
466 */
467static __inline void
468invltlb(void)
469{
470#ifdef XEN
471	xen_tlb_flush();
472#else
473	load_cr3(rcr3());
474#endif
475}
476
477/*
478 * TLB flush for an individual page (even if it has PG_G).
479 * Only works on 486+ CPUs (i386 does not have PG_G).
480 */
481static __inline void
482invlpg(u_int addr)
483{
484
485#ifdef XEN
486	xen_invlpg(addr);
487#else
488	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
489#endif
490}
491
492static __inline u_int
493rfs(void)
494{
495	u_int sel;
496	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
497	return (sel);
498}
499
500static __inline uint64_t
501rgdt(void)
502{
503	uint64_t gdtr;
504	__asm __volatile("sgdt %0" : "=m" (gdtr));
505	return (gdtr);
506}
507
508static __inline u_int
509rgs(void)
510{
511	u_int sel;
512	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
513	return (sel);
514}
515
516static __inline uint64_t
517ridt(void)
518{
519	uint64_t idtr;
520	__asm __volatile("sidt %0" : "=m" (idtr));
521	return (idtr);
522}
523
524static __inline u_short
525rldt(void)
526{
527	u_short ldtr;
528	__asm __volatile("sldt %0" : "=g" (ldtr));
529	return (ldtr);
530}
531
532static __inline u_int
533rss(void)
534{
535	u_int sel;
536	__asm __volatile("movl %%ss,%0" : "=rm" (sel));
537	return (sel);
538}
539
540static __inline u_short
541rtr(void)
542{
543	u_short tr;
544	__asm __volatile("str %0" : "=g" (tr));
545	return (tr);
546}
547
548static __inline void
549load_fs(u_int sel)
550{
551	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
552}
553
554static __inline void
555load_gs(u_int sel)
556{
557	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
558}
559
560static __inline void
561lidt(struct region_descriptor *addr)
562{
563	__asm __volatile("lidt (%0)" : : "r" (addr));
564}
565
566static __inline void
567lldt(u_short sel)
568{
569	__asm __volatile("lldt %0" : : "r" (sel));
570}
571
572static __inline void
573ltr(u_short sel)
574{
575	__asm __volatile("ltr %0" : : "r" (sel));
576}
577
578static __inline u_int
579rdr0(void)
580{
581	u_int	data;
582	__asm __volatile("movl %%dr0,%0" : "=r" (data));
583	return (data);
584}
585
586static __inline void
587load_dr0(u_int dr0)
588{
589	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
590}
591
592static __inline u_int
593rdr1(void)
594{
595	u_int	data;
596	__asm __volatile("movl %%dr1,%0" : "=r" (data));
597	return (data);
598}
599
600static __inline void
601load_dr1(u_int dr1)
602{
603	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
604}
605
606static __inline u_int
607rdr2(void)
608{
609	u_int	data;
610	__asm __volatile("movl %%dr2,%0" : "=r" (data));
611	return (data);
612}
613
614static __inline void
615load_dr2(u_int dr2)
616{
617	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
618}
619
620static __inline u_int
621rdr3(void)
622{
623	u_int	data;
624	__asm __volatile("movl %%dr3,%0" : "=r" (data));
625	return (data);
626}
627
628static __inline void
629load_dr3(u_int dr3)
630{
631	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
632}
633
634static __inline u_int
635rdr4(void)
636{
637	u_int	data;
638	__asm __volatile("movl %%dr4,%0" : "=r" (data));
639	return (data);
640}
641
642static __inline void
643load_dr4(u_int dr4)
644{
645	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
646}
647
648static __inline u_int
649rdr5(void)
650{
651	u_int	data;
652	__asm __volatile("movl %%dr5,%0" : "=r" (data));
653	return (data);
654}
655
656static __inline void
657load_dr5(u_int dr5)
658{
659	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
660}
661
662static __inline u_int
663rdr6(void)
664{
665	u_int	data;
666	__asm __volatile("movl %%dr6,%0" : "=r" (data));
667	return (data);
668}
669
670static __inline void
671load_dr6(u_int dr6)
672{
673	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
674}
675
676static __inline u_int
677rdr7(void)
678{
679	u_int	data;
680	__asm __volatile("movl %%dr7,%0" : "=r" (data));
681	return (data);
682}
683
684static __inline void
685load_dr7(u_int dr7)
686{
687	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
688}
689
690static __inline register_t
691intr_disable(void)
692{
693	register_t eflags;
694
695#ifdef XEN
696	eflags = xen_save_and_cli();
697#else
698	eflags = read_eflags();
699	disable_intr();
700#endif
701	return (eflags);
702}
703
704static __inline void
705intr_restore(register_t eflags)
706{
707#ifdef XEN
708	xen_restore_flags(eflags);
709#else
710	write_eflags(eflags);
711#endif
712}
713
714#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
715
716int	breakpoint(void);
717u_int	bsfl(u_int mask);
718u_int	bsrl(u_int mask);
719void	disable_intr(void);
720void	do_cpuid(u_int ax, u_int *p);
721void	enable_intr(void);
722void	halt(void);
723void	ia32_pause(void);
724u_char	inb(u_int port);
725u_int	inl(u_int port);
726void	insb(u_int port, void *addr, size_t cnt);
727void	insl(u_int port, void *addr, size_t cnt);
728void	insw(u_int port, void *addr, size_t cnt);
729register_t	intr_disable(void);
730void	intr_restore(register_t ef);
731void	invd(void);
732void	invlpg(u_int addr);
733void	invltlb(void);
734u_short	inw(u_int port);
735void	lidt(struct region_descriptor *addr);
736void	lldt(u_short sel);
737void	load_cr0(u_int cr0);
738void	load_cr3(u_int cr3);
739void	load_cr4(u_int cr4);
740void	load_dr0(u_int dr0);
741void	load_dr1(u_int dr1);
742void	load_dr2(u_int dr2);
743void	load_dr3(u_int dr3);
744void	load_dr4(u_int dr4);
745void	load_dr5(u_int dr5);
746void	load_dr6(u_int dr6);
747void	load_dr7(u_int dr7);
748void	load_fs(u_int sel);
749void	load_gs(u_int sel);
750void	ltr(u_short sel);
751void	outb(u_int port, u_char data);
752void	outl(u_int port, u_int data);
753void	outsb(u_int port, const void *addr, size_t cnt);
754void	outsl(u_int port, const void *addr, size_t cnt);
755void	outsw(u_int port, const void *addr, size_t cnt);
756void	outw(u_int port, u_short data);
757u_int	rcr0(void);
758u_int	rcr2(void);
759u_int	rcr3(void);
760u_int	rcr4(void);
761uint64_t rdmsr(u_int msr);
762uint64_t rdpmc(u_int pmc);
763u_int	rdr0(void);
764u_int	rdr1(void);
765u_int	rdr2(void);
766u_int	rdr3(void);
767u_int	rdr4(void);
768u_int	rdr5(void);
769u_int	rdr6(void);
770u_int	rdr7(void);
771uint64_t rdtsc(void);
772u_int	read_eflags(void);
773u_int	rfs(void);
774uint64_t rgdt(void);
775u_int	rgs(void);
776uint64_t ridt(void);
777u_short	rldt(void);
778u_short	rtr(void);
779void	wbinvd(void);
780void	write_eflags(u_int ef);
781void	wrmsr(u_int msr, uint64_t newval);
782
783#endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
784
785void    reset_dbregs(void);
786
787#ifdef _KERNEL
788int	rdmsr_safe(u_int msr, uint64_t *val);
789int	wrmsr_safe(u_int msr, uint64_t newval);
790#endif
791
792#endif /* !_MACHINE_CPUFUNC_H_ */
793