11817Sdg/*-
21817Sdg * Copyright (c) 1993 The Regents of the University of California.
31817Sdg * All rights reserved.
41817Sdg *
51817Sdg * Redistribution and use in source and binary forms, with or without
61817Sdg * modification, are permitted provided that the following conditions
71817Sdg * are met:
81817Sdg * 1. Redistributions of source code must retain the above copyright
91817Sdg *    notice, this list of conditions and the following disclaimer.
101817Sdg * 2. Redistributions in binary form must reproduce the above copyright
111817Sdg *    notice, this list of conditions and the following disclaimer in the
121817Sdg *    documentation and/or other materials provided with the distribution.
131817Sdg * 4. Neither the name of the University nor the names of its contributors
141817Sdg *    may be used to endorse or promote products derived from this software
151817Sdg *    without specific prior written permission.
161817Sdg *
171817Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181817Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191817Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201817Sdg * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211817Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221817Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231817Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241817Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251817Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261817Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271817Sdg * SUCH DAMAGE.
281817Sdg *
2950477Speter * $FreeBSD$
301817Sdg */
311817Sdg
324Srgrimes/*
334Srgrimes * Functions to provide access to special i386 instructions.
3491497Smarkm * This in included in sys/systm.h, and that file should be
3591497Smarkm * used in preference to this.
364Srgrimes */
374Srgrimes
38719Swollman#ifndef _MACHINE_CPUFUNC_H_
394479Sbde#define	_MACHINE_CPUFUNC_H_
40719Swollman
41143063Sjoerg#ifndef _SYS_CDEFS_H_
42143063Sjoerg#error this file needs sys/cdefs.h as a prerequisite
43143063Sjoerg#endif
44143063Sjoerg
45181775Skmacy#ifdef XEN
46181775Skmacyextern void xen_cli(void);
47181775Skmacyextern void xen_sti(void);
48184040Skmacyextern u_int xen_rcr2(void);
49181775Skmacyextern void xen_load_cr3(u_int data);
50181775Skmacyextern void xen_tlb_flush(void);
51181775Skmacyextern void xen_invlpg(u_int addr);
52197693Skmacyextern void write_eflags(u_int eflags);
53197693Skmacyextern u_int read_eflags(void);
54181775Skmacy#endif
55181775Skmacy
56103778Speterstruct region_descriptor;
5793264Sdillon
58220627Sjkim#define readb(va)	(*(volatile uint8_t *) (va))
59220627Sjkim#define readw(va)	(*(volatile uint16_t *) (va))
60220627Sjkim#define readl(va)	(*(volatile uint32_t *) (va))
6138392Sdfr
62220627Sjkim#define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
63220627Sjkim#define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
64220627Sjkim#define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
6538392Sdfr
66143063Sjoerg#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
674Srgrimes
6815122Sbdestatic __inline void
6915122Sbdebreakpoint(void)
703102Sdg{
714479Sbde	__asm __volatile("int $3");
723102Sdg}
733102Sdg
7455672Sbdestatic __inline u_int
7555672Sbdebsfl(u_int mask)
7655672Sbde{
7755672Sbde	u_int	result;
7855672Sbde
79194115Sed	__asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
8055672Sbde	return (result);
8155672Sbde}
8255672Sbde
8355672Sbdestatic __inline u_int
8455672Sbdebsrl(u_int mask)
8555672Sbde{
8655672Sbde	u_int	result;
8755672Sbde
88194115Sed	__asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
8955672Sbde	return (result);
9055672Sbde}
9155672Sbde
923102Sdgstatic __inline void
93195940Skibclflush(u_long addr)
94195940Skib{
95195940Skib
96195940Skib	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
97195940Skib}
98195940Skib
99195940Skibstatic __inline void
100239914Sjhbclts(void)
101239914Sjhb{
102239914Sjhb
103239914Sjhb	__asm __volatile("clts");
104239914Sjhb}
105239914Sjhb
106239914Sjhbstatic __inline void
1074479Sbdedisable_intr(void)
1083102Sdg{
109181775Skmacy#ifdef XEN
110181775Skmacy	xen_cli();
111181775Skmacy#else
112184040Skmacy	__asm __volatile("cli" : : : "memory");
113181775Skmacy#endif
1143102Sdg}
1153102Sdg
1163102Sdgstatic __inline void
11794386Sdwmalonedo_cpuid(u_int ax, u_int *p)
11894386Sdwmalone{
11994386Sdwmalone	__asm __volatile("cpuid"
12094386Sdwmalone			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
12194386Sdwmalone			 :  "0" (ax));
12294386Sdwmalone}
12394386Sdwmalone
12494386Sdwmalonestatic __inline void
125146170Snectarcpuid_count(u_int ax, u_int cx, u_int *p)
126146170Snectar{
127146170Snectar	__asm __volatile("cpuid"
128146170Snectar			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
129146170Snectar			 :  "0" (ax), "c" (cx));
130146170Snectar}
131146170Snectar
132146170Snectarstatic __inline void
1334479Sbdeenable_intr(void)
1343102Sdg{
135181775Skmacy#ifdef XEN
136181775Skmacy	xen_sti();
137184040Skmacy#else
13810342Sbde	__asm __volatile("sti");
139181775Skmacy#endif
1403102Sdg}
1413102Sdg
142197647Savgstatic __inline void
143223796Sjkimcpu_monitor(const void *addr, u_long extensions, u_int hints)
144178299Sjeff{
145223796Sjkim
146223796Sjkim	__asm __volatile("monitor"
147223796Sjkim	    : : "a" (addr), "c" (extensions), "d" (hints));
148178299Sjeff}
149178299Sjeff
150197647Savgstatic __inline void
151223796Sjkimcpu_mwait(u_long extensions, u_int hints)
152178299Sjeff{
153223796Sjkim
154223796Sjkim	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
155178299Sjeff}
156178299Sjeff
157195940Skibstatic __inline void
158239902Skiblfence(void)
159239902Skib{
160239902Skib
161239902Skib	__asm __volatile("lfence" : : : "memory");
162239902Skib}
163239902Skib
164239902Skibstatic __inline void
165195940Skibmfence(void)
166195940Skib{
167195940Skib
168195940Skib	__asm __volatile("mfence" : : : "memory");
169195940Skib}
170195940Skib
171126846Sbde#ifdef _KERNEL
172126846Sbde
17350054Speter#define	HAVE_INLINE_FFS
17450054Speter
17550054Speterstatic __inline int
17650054Speterffs(int mask)
17750054Speter{
17850054Speter	/*
1794479Sbde	 * Note that gcc-2's builtin ffs would be used if we didn't declare
1804479Sbde	 * this inline or turn off the builtin.  The builtin is faster but
18155672Sbde	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
18255672Sbde	 * versions.
1834479Sbde	 */
184100078Smarkm	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
18550054Speter}
18650054Speter
18717384Swollman#define	HAVE_INLINE_FLS
18817384Swollman
18917384Swollmanstatic __inline int
19017384Swollmanfls(int mask)
19117384Swollman{
192100078Smarkm	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
19317384Swollman}
19417384Swollman
195126846Sbde#endif /* _KERNEL */
196126846Sbde
197103749Smarkmstatic __inline void
198103749Smarkmhalt(void)
199103749Smarkm{
200103749Smarkm	__asm __volatile("hlt");
201103749Smarkm}
202103749Smarkm
2034479Sbdestatic __inline u_char
204190919Sedinb(u_int port)
2053102Sdg{
2064479Sbde	u_char	data;
2074479Sbde
208220629Sjkim	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
2094479Sbde	return (data);
2103102Sdg}
2113102Sdg
21237552Sbdestatic __inline u_int
2134479Sbdeinl(u_int port)
2142826Sdg{
21537552Sbde	u_int	data;
2162826Sdg
217220629Sjkim	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
2184479Sbde	return (data);
2192826Sdg}
2202826Sdg
2214479Sbdestatic __inline void
222201369Sobrieninsb(u_int port, void *addr, size_t count)
2232826Sdg{
2244479Sbde	__asm __volatile("cld; rep; insb"
225201369Sobrien			 : "+D" (addr), "+c" (count)
22688118Sjhb			 : "d" (port)
22742427Sbde			 : "memory");
2284479Sbde}
2292826Sdg
2304479Sbdestatic __inline void
231201369Sobrieninsw(u_int port, void *addr, size_t count)
2324479Sbde{
2334479Sbde	__asm __volatile("cld; rep; insw"
234201369Sobrien			 : "+D" (addr), "+c" (count)
23588118Sjhb			 : "d" (port)
23642427Sbde			 : "memory");
2372826Sdg}
2382826Sdg
2394479Sbdestatic __inline void
240201369Sobrieninsl(u_int port, void *addr, size_t count)
2412826Sdg{
2424479Sbde	__asm __volatile("cld; rep; insl"
243201369Sobrien			 : "+D" (addr), "+c" (count)
24488118Sjhb			 : "d" (port)
24542427Sbde			 : "memory");
2462826Sdg}
2472826Sdg
24818567Sbdestatic __inline void
24924112Skatoinvd(void)
25024112Skato{
25124112Skato	__asm __volatile("invd");
25224112Skato}
25324112Skato
2544479Sbdestatic __inline u_short
2554479Sbdeinw(u_int port)
2562826Sdg{
2574479Sbde	u_short	data;
2584479Sbde
259220629Sjkim	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
2604479Sbde	return (data);
2612826Sdg}
2622826Sdg
2634479Sbdestatic __inline void
264190919Sedoutb(u_int port, u_char data)
2652826Sdg{
266190919Sed	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
2672826Sdg}
2682826Sdg
2694479Sbdestatic __inline void
27037552Sbdeoutl(u_int port, u_int data)
2714Srgrimes{
272220629Sjkim	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
2734Srgrimes}
2744Srgrimes
2754479Sbdestatic __inline void
276201369Sobrienoutsb(u_int port, const void *addr, size_t count)
2774Srgrimes{
2784479Sbde	__asm __volatile("cld; rep; outsb"
279201369Sobrien			 : "+S" (addr), "+c" (count)
28088118Sjhb			 : "d" (port));
2814Srgrimes}
2824Srgrimes
2834479Sbdestatic __inline void
284201369Sobrienoutsw(u_int port, const void *addr, size_t count)
2854Srgrimes{
2864479Sbde	__asm __volatile("cld; rep; outsw"
287201369Sobrien			 : "+S" (addr), "+c" (count)
28888118Sjhb			 : "d" (port));
2894Srgrimes}
2904Srgrimes
2914479Sbdestatic __inline void
292201369Sobrienoutsl(u_int port, const void *addr, size_t count)
2934Srgrimes{
2944479Sbde	__asm __volatile("cld; rep; outsl"
295201369Sobrien			 : "+S" (addr), "+c" (count)
29688118Sjhb			 : "d" (port));
2974Srgrimes}
2984Srgrimes
2994479Sbdestatic __inline void
3004479Sbdeoutw(u_int port, u_short data)
3014Srgrimes{
302220629Sjkim	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
3034Srgrimes}
3044Srgrimes
30597114Sjhbstatic __inline void
30697139Sjhbia32_pause(void)
30797114Sjhb{
30897114Sjhb	__asm __volatile("pause");
30997114Sjhb}
31097114Sjhb
31137552Sbdestatic __inline u_int
312197693Skmacy#ifdef XEN
313197693Skmacy_read_eflags(void)
314197693Skmacy#else
3154479Sbderead_eflags(void)
316197693Skmacy#endif
3174479Sbde{
31837552Sbde	u_int	ef;
3194479Sbde
3208876Srgrimes	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3214479Sbde	return (ef);
3224479Sbde}
3234479Sbde
324171797Snjlstatic __inline uint64_t
32515122Sbderdmsr(u_int msr)
3264479Sbde{
327171797Snjl	uint64_t rv;
32815122Sbde
32969006Smarkm	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
33015122Sbde	return (rv);
3314479Sbde}
3324479Sbde
333171797Snjlstatic __inline uint64_t
33415122Sbderdpmc(u_int pmc)
33514825Swollman{
336171797Snjl	uint64_t rv;
33715122Sbde
33869006Smarkm	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
33915122Sbde	return (rv);
34014825Swollman}
34114825Swollman
342171797Snjlstatic __inline uint64_t
34314825Swollmanrdtsc(void)
34414825Swollman{
345171797Snjl	uint64_t rv;
34615122Sbde
34769006Smarkm	__asm __volatile("rdtsc" : "=A" (rv));
34815122Sbde	return (rv);
34914825Swollman}
35014825Swollman
351220631Sjkimstatic __inline uint32_t
352220631Sjkimrdtsc32(void)
353220631Sjkim{
354220631Sjkim	uint32_t rv;
355220631Sjkim
356220631Sjkim	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
357220631Sjkim	return (rv);
358220631Sjkim}
359220631Sjkim
36015122Sbdestatic __inline void
36124112Skatowbinvd(void)
36224112Skato{
36324112Skato	__asm __volatile("wbinvd");
36424112Skato}
36524112Skato
36624112Skatostatic __inline void
367197693Skmacy#ifdef XEN
368197693Skmacy_write_eflags(u_int ef)
369197693Skmacy#else
37037552Sbdewrite_eflags(u_int ef)
371197693Skmacy#endif
37214825Swollman{
37315122Sbde	__asm __volatile("pushl %0; popfl" : : "r" (ef));
37414825Swollman}
37514825Swollman
37614825Swollmanstatic __inline void
377171797Snjlwrmsr(u_int msr, uint64_t newval)
37814825Swollman{
37969006Smarkm	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
38014825Swollman}
38114825Swollman
38299862Speterstatic __inline void
38399862Speterload_cr0(u_int data)
38499862Speter{
38599862Speter
38699862Speter	__asm __volatile("movl %0,%%cr0" : : "r" (data));
38799862Speter}
38899862Speter
38946129Sluoqistatic __inline u_int
39099862Speterrcr0(void)
39199862Speter{
39299862Speter	u_int	data;
39399862Speter
39499862Speter	__asm __volatile("movl %%cr0,%0" : "=r" (data));
39599862Speter	return (data);
39699862Speter}
39799862Speter
39899862Speterstatic __inline u_int
39999862Speterrcr2(void)
40099862Speter{
40199862Speter	u_int	data;
40299862Speter
403184040Skmacy#ifdef XEN
404184040Skmacy	return (xen_rcr2());
405184040Skmacy#endif
40699862Speter	__asm __volatile("movl %%cr2,%0" : "=r" (data));
40799862Speter	return (data);
40899862Speter}
40999862Speter
41099862Speterstatic __inline void
41199862Speterload_cr3(u_int data)
41299862Speter{
413181775Skmacy#ifdef XEN
414181775Skmacy	xen_load_cr3(data);
415181775Skmacy#else
41699862Speter	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
417181775Skmacy#endif
41899862Speter}
41999862Speter
42099862Speterstatic __inline u_int
42199862Speterrcr3(void)
42299862Speter{
42399862Speter	u_int	data;
42499862Speter
42599862Speter	__asm __volatile("movl %%cr3,%0" : "=r" (data));
42699862Speter	return (data);
42799862Speter}
42899862Speter
42999862Speterstatic __inline void
43099862Speterload_cr4(u_int data)
43199862Speter{
43299862Speter	__asm __volatile("movl %0,%%cr4" : : "r" (data));
43399862Speter}
43499862Speter
43599862Speterstatic __inline u_int
43699862Speterrcr4(void)
43799862Speter{
43899862Speter	u_int	data;
43999862Speter
44099862Speter	__asm __volatile("movl %%cr4,%0" : "=r" (data));
44199862Speter	return (data);
44299862Speter}
44399862Speter
44499862Speter/*
44599862Speter * Global TLB flush (except for thise for pages marked PG_G)
44699862Speter */
44799862Speterstatic __inline void
44899862Speterinvltlb(void)
44999862Speter{
450181775Skmacy#ifdef XEN
451181775Skmacy	xen_tlb_flush();
452181775Skmacy#else
45399862Speter	load_cr3(rcr3());
454181775Skmacy#endif
45599862Speter}
45699862Speter
45799862Speter/*
45899862Speter * TLB flush for an individual page (even if it has PG_G).
45999862Speter * Only works on 486+ CPUs (i386 does not have PG_G).
46099862Speter */
46199862Speterstatic __inline void
46299862Speterinvlpg(u_int addr)
46399862Speter{
46499862Speter
465181775Skmacy#ifdef XEN
466181775Skmacy	xen_invlpg(addr);
467181775Skmacy#else
46899862Speter	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
469181775Skmacy#endif
47099862Speter}
47199862Speter
472212177Srdivackystatic __inline u_short
47346129Sluoqirfs(void)
47446129Sluoqi{
475212177Srdivacky	u_short sel;
476212177Srdivacky	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
47746129Sluoqi	return (sel);
47846129Sluoqi}
47946129Sluoqi
480171797Snjlstatic __inline uint64_t
481171797Snjlrgdt(void)
482171797Snjl{
483171797Snjl	uint64_t gdtr;
484171797Snjl	__asm __volatile("sgdt %0" : "=m" (gdtr));
485171797Snjl	return (gdtr);
486171797Snjl}
487171797Snjl
488212177Srdivackystatic __inline u_short
48946129Sluoqirgs(void)
49046129Sluoqi{
491212177Srdivacky	u_short sel;
492212177Srdivacky	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
49346129Sluoqi	return (sel);
49446129Sluoqi}
49546129Sluoqi
496171797Snjlstatic __inline uint64_t
497171797Snjlridt(void)
498171797Snjl{
499171797Snjl	uint64_t idtr;
500171797Snjl	__asm __volatile("sidt %0" : "=m" (idtr));
501171797Snjl	return (idtr);
502171797Snjl}
503171797Snjl
504171797Snjlstatic __inline u_short
505171797Snjlrldt(void)
506171797Snjl{
507171797Snjl	u_short ldtr;
508171797Snjl	__asm __volatile("sldt %0" : "=g" (ldtr));
509171797Snjl	return (ldtr);
510171797Snjl}
511171797Snjl
512212177Srdivackystatic __inline u_short
513127813Smarcelrss(void)
514127813Smarcel{
515212177Srdivacky	u_short sel;
516212177Srdivacky	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
517127813Smarcel	return (sel);
518127813Smarcel}
519127813Smarcel
520171797Snjlstatic __inline u_short
521171797Snjlrtr(void)
522171797Snjl{
523171797Snjl	u_short tr;
524171797Snjl	__asm __volatile("str %0" : "=g" (tr));
525171797Snjl	return (tr);
526171797Snjl}
527171797Snjl
52846129Sluoqistatic __inline void
529212177Srdivackyload_fs(u_short sel)
53046129Sluoqi{
531212177Srdivacky	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
53246129Sluoqi}
53346129Sluoqi
53446129Sluoqistatic __inline void
535212177Srdivackyload_gs(u_short sel)
53646129Sluoqi{
537212177Srdivacky	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
53846129Sluoqi}
53946129Sluoqi
540103778Speterstatic __inline void
541103778Speterlidt(struct region_descriptor *addr)
542103778Speter{
543103778Speter	__asm __volatile("lidt (%0)" : : "r" (addr));
544103778Speter}
545103778Speter
546103778Speterstatic __inline void
547103778Speterlldt(u_short sel)
548103778Speter{
549103778Speter	__asm __volatile("lldt %0" : : "r" (sel));
550103778Speter}
551103778Speter
552103778Speterstatic __inline void
553103778Speterltr(u_short sel)
554103778Speter{
555103778Speter	__asm __volatile("ltr %0" : : "r" (sel));
556103778Speter}
557103778Speter
55857362Sbsdstatic __inline u_int
55957362Sbsdrdr0(void)
56057362Sbsd{
56157362Sbsd	u_int	data;
56257376Sbsd	__asm __volatile("movl %%dr0,%0" : "=r" (data));
56357362Sbsd	return (data);
56457362Sbsd}
56557362Sbsd
56678903Sbsdstatic __inline void
56797115Sjhbload_dr0(u_int dr0)
56878903Sbsd{
56997115Sjhb	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
57078903Sbsd}
57178903Sbsd
57257362Sbsdstatic __inline u_int
57357362Sbsdrdr1(void)
57457362Sbsd{
57557362Sbsd	u_int	data;
57657376Sbsd	__asm __volatile("movl %%dr1,%0" : "=r" (data));
57757362Sbsd	return (data);
57857362Sbsd}
57957362Sbsd
58078903Sbsdstatic __inline void
58197115Sjhbload_dr1(u_int dr1)
58278903Sbsd{
58397115Sjhb	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
58478903Sbsd}
58578903Sbsd
58657362Sbsdstatic __inline u_int
58757362Sbsdrdr2(void)
58857362Sbsd{
58957362Sbsd	u_int	data;
59057376Sbsd	__asm __volatile("movl %%dr2,%0" : "=r" (data));
59157362Sbsd	return (data);
59257362Sbsd}
59357362Sbsd
59478903Sbsdstatic __inline void
59597115Sjhbload_dr2(u_int dr2)
59678903Sbsd{
59797115Sjhb	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
59878903Sbsd}
59978903Sbsd
60057362Sbsdstatic __inline u_int
60157362Sbsdrdr3(void)
60257362Sbsd{
60357362Sbsd	u_int	data;
60457376Sbsd	__asm __volatile("movl %%dr3,%0" : "=r" (data));
60557362Sbsd	return (data);
60657362Sbsd}
60757362Sbsd
60878903Sbsdstatic __inline void
60997115Sjhbload_dr3(u_int dr3)
61078903Sbsd{
61197115Sjhb	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
61278903Sbsd}
61378903Sbsd
61457362Sbsdstatic __inline u_int
61578903Sbsdrdr4(void)
61678903Sbsd{
61778903Sbsd	u_int	data;
61878903Sbsd	__asm __volatile("movl %%dr4,%0" : "=r" (data));
61978903Sbsd	return (data);
62078903Sbsd}
62178903Sbsd
62278903Sbsdstatic __inline void
62397115Sjhbload_dr4(u_int dr4)
62478903Sbsd{
62597115Sjhb	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
62678903Sbsd}
62778903Sbsd
62878903Sbsdstatic __inline u_int
62978903Sbsdrdr5(void)
63078903Sbsd{
63178903Sbsd	u_int	data;
63278903Sbsd	__asm __volatile("movl %%dr5,%0" : "=r" (data));
63378903Sbsd	return (data);
63478903Sbsd}
63578903Sbsd
63678903Sbsdstatic __inline void
63797115Sjhbload_dr5(u_int dr5)
63878903Sbsd{
63997115Sjhb	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
64078903Sbsd}
64178903Sbsd
64278903Sbsdstatic __inline u_int
64357362Sbsdrdr6(void)
64457362Sbsd{
64557362Sbsd	u_int	data;
64657376Sbsd	__asm __volatile("movl %%dr6,%0" : "=r" (data));
64757362Sbsd	return (data);
64857362Sbsd}
64957362Sbsd
65078903Sbsdstatic __inline void
65197115Sjhbload_dr6(u_int dr6)
65278903Sbsd{
65397115Sjhb	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
65478903Sbsd}
65578903Sbsd
65657362Sbsdstatic __inline u_int
65757362Sbsdrdr7(void)
65857362Sbsd{
65957362Sbsd	u_int	data;
66057376Sbsd	__asm __volatile("movl %%dr7,%0" : "=r" (data));
66157362Sbsd	return (data);
66257362Sbsd}
66357362Sbsd
66478903Sbsdstatic __inline void
66597115Sjhbload_dr7(u_int dr7)
66678903Sbsd{
66797115Sjhb	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
66878903Sbsd}
66978903Sbsd
670194295Sjhbstatic __inline u_char
671194295Sjhbread_cyrix_reg(u_char reg)
672194295Sjhb{
673194295Sjhb	outb(0x22, reg);
674194295Sjhb	return inb(0x23);
675194295Sjhb}
676194295Sjhb
677194295Sjhbstatic __inline void
678194295Sjhbwrite_cyrix_reg(u_char reg, u_char data)
679194295Sjhb{
680194295Sjhb	outb(0x22, reg);
681194295Sjhb	outb(0x23, data);
682194295Sjhb}
683194295Sjhb
68492860Simpstatic __inline register_t
68592860Simpintr_disable(void)
68692860Simp{
687181911Skmacy	register_t eflags;
68892860Simp
68992860Simp	eflags = read_eflags();
69092860Simp	disable_intr();
69192860Simp	return (eflags);
69292860Simp}
69392860Simp
69492860Simpstatic __inline void
69592860Simpintr_restore(register_t eflags)
69692860Simp{
69792860Simp	write_eflags(eflags);
69892860Simp}
69992860Simp
700143063Sjoerg#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
7014Srgrimes
70292819Simpint	breakpoint(void);
70392819Simpu_int	bsfl(u_int mask);
70492819Simpu_int	bsrl(u_int mask);
705239914Sjhbvoid	clflush(u_long addr);
706239914Sjhbvoid	clts(void);
707239914Sjhbvoid	cpuid_count(u_int ax, u_int cx, u_int *p);
70892819Simpvoid	disable_intr(void);
70992819Simpvoid	do_cpuid(u_int ax, u_int *p);
71092819Simpvoid	enable_intr(void);
711103749Smarkmvoid	halt(void);
712126656Sbdevoid	ia32_pause(void);
71392819Simpu_char	inb(u_int port);
71492819Simpu_int	inl(u_int port);
715201369Sobrienvoid	insb(u_int port, void *addr, size_t count);
716201369Sobrienvoid	insl(u_int port, void *addr, size_t count);
717201369Sobrienvoid	insw(u_int port, void *addr, size_t count);
718126656Sbderegister_t	intr_disable(void);
719126656Sbdevoid	intr_restore(register_t ef);
72092819Simpvoid	invd(void);
72192819Simpvoid	invlpg(u_int addr);
72292819Simpvoid	invltlb(void);
72392819Simpu_short	inw(u_int port);
724126656Sbdevoid	lidt(struct region_descriptor *addr);
725126656Sbdevoid	lldt(u_short sel);
72699862Spetervoid	load_cr0(u_int cr0);
72799862Spetervoid	load_cr3(u_int cr3);
72899862Spetervoid	load_cr4(u_int cr4);
729126656Sbdevoid	load_dr0(u_int dr0);
730126656Sbdevoid	load_dr1(u_int dr1);
731126656Sbdevoid	load_dr2(u_int dr2);
732126656Sbdevoid	load_dr3(u_int dr3);
733126656Sbdevoid	load_dr4(u_int dr4);
734126656Sbdevoid	load_dr5(u_int dr5);
735126656Sbdevoid	load_dr6(u_int dr6);
736126656Sbdevoid	load_dr7(u_int dr7);
737212177Srdivackyvoid	load_fs(u_short sel);
738212177Srdivackyvoid	load_gs(u_short sel);
739103778Spetervoid	ltr(u_short sel);
74092819Simpvoid	outb(u_int port, u_char data);
74192819Simpvoid	outl(u_int port, u_int data);
742201369Sobrienvoid	outsb(u_int port, const void *addr, size_t count);
743201369Sobrienvoid	outsl(u_int port, const void *addr, size_t count);
744201369Sobrienvoid	outsw(u_int port, const void *addr, size_t count);
74592819Simpvoid	outw(u_int port, u_short data);
74699862Speteru_int	rcr0(void);
74792819Simpu_int	rcr2(void);
74899862Speteru_int	rcr3(void);
74999862Speteru_int	rcr4(void);
750171797Snjluint64_t rdmsr(u_int msr);
751171797Snjluint64_t rdpmc(u_int pmc);
75297114Sjhbu_int	rdr0(void);
75397114Sjhbu_int	rdr1(void);
75497114Sjhbu_int	rdr2(void);
75597114Sjhbu_int	rdr3(void);
75697114Sjhbu_int	rdr4(void);
75797114Sjhbu_int	rdr5(void);
75897114Sjhbu_int	rdr6(void);
75997114Sjhbu_int	rdr7(void);
760171797Snjluint64_t rdtsc(void);
761194295Sjhbu_char	read_cyrix_reg(u_char reg);
762126656Sbdeu_int	read_eflags(void);
763126656Sbdeu_int	rfs(void);
764171797Snjluint64_t rgdt(void);
765126656Sbdeu_int	rgs(void);
766171797Snjluint64_t ridt(void);
767171797Snjlu_short	rldt(void);
768171797Snjlu_short	rtr(void);
769126656Sbdevoid	wbinvd(void);
770194295Sjhbvoid	write_cyrix_reg(u_char reg, u_char data);
771126656Sbdevoid	write_eflags(u_int ef);
772171797Snjlvoid	wrmsr(u_int msr, uint64_t newval);
7734Srgrimes
774143063Sjoerg#endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
7754Srgrimes
77692761Salfredvoid    reset_dbregs(void);
77793264Sdillon
778181430Sstas#ifdef _KERNEL
779181430Sstasint	rdmsr_safe(u_int msr, uint64_t *val);
780181430Sstasint	wrmsr_safe(u_int msr, uint64_t newval);
781181430Sstas#endif
782181430Sstas
7834479Sbde#endif /* !_MACHINE_CPUFUNC_H_ */
784