Merge branch 'vendor/OPENSSL'
[dragonfly.git] / sys / cpu / x86_64 / include / cpufunc.h
1 /*-
2  * Copyright (c) 2003 Peter Wemm.
3  * Copyright (c) 1993 The Regents of the University of California.
4  * Copyright (c) 2008 The DragonFly Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * $FreeBSD: src/sys/amd64/include/cpufunc.h,v 1.139 2004/01/28 23:53:04 peter Exp $
36  */
37
38 /*
39  * Functions to provide access to special i386 instructions.
40  * This in included in sys/systm.h, and that file should be
41  * used in preference to this.
42  */
43
44 #ifndef _CPU_CPUFUNC_H_
45 #define _CPU_CPUFUNC_H_
46
47 #include <sys/cdefs.h>
48 #include <machine/psl.h>
49
50 struct thread;
51 struct region_descriptor;
52
53 __BEGIN_DECLS
54 #define readb(va)       (*(volatile u_int8_t *) (va))
55 #define readw(va)       (*(volatile u_int16_t *) (va))
56 #define readl(va)       (*(volatile u_int32_t *) (va))
57 #define readq(va)       (*(volatile u_int64_t *) (va))
58
59 #define writeb(va, d)   (*(volatile u_int8_t *) (va) = (d))
60 #define writew(va, d)   (*(volatile u_int16_t *) (va) = (d))
61 #define writel(va, d)   (*(volatile u_int32_t *) (va) = (d))
62 #define writeq(va, d)   (*(volatile u_int64_t *) (va) = (d))
63
64 #ifdef  __GNUC__
65
66 #ifdef SMP
67 #include <machine/lock.h>               /* XXX */
68 #endif
69
70 static __inline void
71 breakpoint(void)
72 {
73         __asm __volatile("int $3");
74 }
75
76 static __inline void
77 cpu_pause(void)
78 {
79         __asm __volatile("pause");
80 }
81
82 static __inline u_int
83 bsfl(u_int mask)
84 {
85         u_int   result;
86
87         __asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
88         return (result);
89 }
90
91 static __inline u_long
92 bsfq(u_long mask)
93 {
94         u_long  result;
95
96         __asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask));
97         return (result);
98 }
99
100 static __inline u_int
101 bsrl(u_int mask)
102 {
103         u_int   result;
104
105         __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
106         return (result);
107 }
108
109 static __inline u_long
110 bsrq(u_long mask)
111 {
112         u_long  result;
113
114         __asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask));
115         return (result);
116 }
117
118 static __inline void
119 do_cpuid(u_int ax, u_int *p)
120 {
121         __asm __volatile("cpuid"
122                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
123                          :  "0" (ax));
124 }
125
126 static __inline void
127 cpuid_count(u_int ax, u_int cx, u_int *p)
128 {
129         __asm __volatile("cpuid"
130                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
131                          :  "0" (ax), "c" (cx));
132 }
133
134 #ifndef _CPU_DISABLE_INTR_DEFINED
135
136 static __inline void
137 cpu_disable_intr(void)
138 {
139         __asm __volatile("cli" : : : "memory");
140 }
141
142 #endif
143
144 #ifndef _CPU_ENABLE_INTR_DEFINED
145
146 static __inline void
147 cpu_enable_intr(void)
148 {
149         __asm __volatile("sti");
150 }
151
152 #endif
153
154 /*
155  * Cpu and compiler memory ordering fence.  mfence ensures strong read and
156  * write ordering.
157  *
158  * A serializing or fence instruction is required here.  A locked bus
159  * cycle on data for which we already own cache mastership is the most
160  * portable.
161  */
162 static __inline void
163 cpu_mfence(void)
164 {
165 #ifdef SMP
166         __asm __volatile("mfence" : : : "memory");
167 #else
168         __asm __volatile("" : : : "memory");
169 #endif
170 }
171
172 /*
173  * cpu_lfence() ensures strong read ordering for reads issued prior
174  * to the instruction verses reads issued afterwords.
175  *
176  * A serializing or fence instruction is required here.  A locked bus
177  * cycle on data for which we already own cache mastership is the most
178  * portable.
179  */
180 static __inline void
181 cpu_lfence(void)
182 {
183 #ifdef SMP
184         __asm __volatile("lfence" : : : "memory");
185 #else
186         __asm __volatile("" : : : "memory");
187 #endif
188 }
189
190 /*
191  * cpu_sfence() ensures strong write ordering for writes issued prior
192  * to the instruction verses writes issued afterwords.  Writes are
193  * ordered on intel cpus so we do not actually have to do anything.
194  */
195 static __inline void
196 cpu_sfence(void)
197 {
198 #ifdef SMP
199         __asm __volatile("sfence" : : : "memory");
200 #else
201         __asm __volatile("" : : : "memory");
202 #endif
203 }
204
205 /*
206  * cpu_ccfence() prevents the compiler from reordering instructions, in
207  * particular stores, relative to the current cpu.  Use cpu_sfence() if
208  * you need to guarentee ordering by both the compiler and by the cpu.
209  *
210  * This also prevents the compiler from caching memory loads into local
211  * variables across the routine.
212  */
213 static __inline void
214 cpu_ccfence(void)
215 {
216         __asm __volatile("" : : : "memory");
217 }
218
219 #ifdef _KERNEL
220
221 #define HAVE_INLINE_FFS
222
223 static __inline int
224 ffs(int mask)
225 {
226 #if 0
227         /*
228          * Note that gcc-2's builtin ffs would be used if we didn't declare
229          * this inline or turn off the builtin.  The builtin is faster but
230          * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
231          * versions.
232          */
233         return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
234 #else
235         /* Actually, the above is way out of date.  The builtins use cmov etc */
236         return (__builtin_ffs(mask));
237 #endif
238 }
239
240 #define HAVE_INLINE_FFSL
241
242 static __inline int
243 ffsl(long mask)
244 {
245         return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1);
246 }
247
248 #define HAVE_INLINE_FLS
249
250 static __inline int
251 fls(int mask)
252 {
253         return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
254 }
255
256 #define HAVE_INLINE_FLSL
257
258 static __inline int
259 flsl(long mask)
260 {
261         return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
262 }
263
264 #endif /* _KERNEL */
265
266 static __inline void
267 halt(void)
268 {
269         __asm __volatile("hlt");
270 }
271
272 /*
273  * The following complications are to get around gcc not having a
274  * constraint letter for the range 0..255.  We still put "d" in the
275  * constraint because "i" isn't a valid constraint when the port
276  * isn't constant.  This only matters for -O0 because otherwise
277  * the non-working version gets optimized away.
278  * 
279  * Use an expression-statement instead of a conditional expression
280  * because gcc-2.6.0 would promote the operands of the conditional
281  * and produce poor code for "if ((inb(var) & const1) == const2)".
282  *
283  * The unnecessary test `(port) < 0x10000' is to generate a warning if
284  * the `port' has type u_short or smaller.  Such types are pessimal.
285  * This actually only works for signed types.  The range check is
286  * careful to avoid generating warnings.
287  */
288 #define inb(port) __extension__ ({                                      \
289         u_char  _data;                                                  \
290         if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100     \
291             && (port) < 0x10000)                                        \
292                 _data = inbc(port);                                     \
293         else                                                            \
294                 _data = inbv(port);                                     \
295         _data; })
296
297 #define outb(port, data) (                                              \
298         __builtin_constant_p(port) && ((port) & 0xffff) < 0x100         \
299         && (port) < 0x10000                                             \
300         ? outbc(port, data) : outbv(port, data))
301
302 static __inline u_char
303 inbc(u_int port)
304 {
305         u_char  data;
306
307         __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
308         return (data);
309 }
310
311 static __inline void
312 outbc(u_int port, u_char data)
313 {
314         __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
315 }
316
317 static __inline u_char
318 inbv(u_int port)
319 {
320         u_char  data;
321         /*
322          * We use %%dx and not %1 here because i/o is done at %dx and not at
323          * %edx, while gcc generates inferior code (movw instead of movl)
324          * if we tell it to load (u_short) port.
325          */
326         __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
327         return (data);
328 }
329
330 static __inline u_int
331 inl(u_int port)
332 {
333         u_int   data;
334
335         __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
336         return (data);
337 }
338
339 static __inline void
340 insb(u_int port, void *addr, size_t cnt)
341 {
342         __asm __volatile("cld; rep; insb"
343                          : "+D" (addr), "+c" (cnt)
344                          : "d" (port)
345                          : "memory");
346 }
347
348 static __inline void
349 insw(u_int port, void *addr, size_t cnt)
350 {
351         __asm __volatile("cld; rep; insw"
352                          : "+D" (addr), "+c" (cnt)
353                          : "d" (port)
354                          : "memory");
355 }
356
357 static __inline void
358 insl(u_int port, void *addr, size_t cnt)
359 {
360         __asm __volatile("cld; rep; insl"
361                          : "+D" (addr), "+c" (cnt)
362                          : "d" (port)
363                          : "memory");
364 }
365
366 static __inline void
367 invd(void)
368 {
369         __asm __volatile("invd");
370 }
371
372 #if defined(_KERNEL)
373
374 /*
375  * If we are not a true-SMP box then smp_invltlb() is a NOP.  Note that this
376  * will cause the invl*() functions to be equivalent to the cpu_invl*()
377  * functions.
378  */
379 #ifdef SMP
380 void smp_invltlb(void);
381 #else
382 #define smp_invltlb()
383 #endif
384
385 #ifndef _CPU_INVLPG_DEFINED
386
387 /*
388  * Invalidate a patricular VA on this cpu only
389  */
390 static __inline void
391 cpu_invlpg(void *addr)
392 {
393         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
394 }
395
396 #endif
397
398 static __inline void
399 cpu_nop(void)
400 {
401         __asm __volatile("rep; nop");
402 }
403
404 #endif  /* _KERNEL */
405
406 static __inline u_short
407 inw(u_int port)
408 {
409         u_short data;
410
411         __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
412         return (data);
413 }
414
415 static __inline u_int
416 loadandclear(volatile u_int *addr)
417 {
418         u_int   result;
419
420         __asm __volatile("xorl %0,%0; xchgl %1,%0"
421                         : "=&r" (result) : "m" (*addr));
422         return (result);
423 }
424
425 static __inline void
426 outbv(u_int port, u_char data)
427 {
428         u_char  al;
429         /*
430          * Use an unnecessary assignment to help gcc's register allocator.
431          * This make a large difference for gcc-1.40 and a tiny difference
432          * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
433          * best results.  gcc-2.6.0 can't handle this.
434          */
435         al = data;
436         __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
437 }
438
439 static __inline void
440 outl(u_int port, u_int data)
441 {
442         /*
443          * outl() and outw() aren't used much so we haven't looked at
444          * possible micro-optimizations such as the unnecessary
445          * assignment for them.
446          */
447         __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
448 }
449
450 static __inline void
451 outsb(u_int port, const void *addr, size_t cnt)
452 {
453         __asm __volatile("cld; rep; outsb"
454                          : "+S" (addr), "+c" (cnt)
455                          : "d" (port));
456 }
457
458 static __inline void
459 outsw(u_int port, const void *addr, size_t cnt)
460 {
461         __asm __volatile("cld; rep; outsw"
462                          : "+S" (addr), "+c" (cnt)
463                          : "d" (port));
464 }
465
466 static __inline void
467 outsl(u_int port, const void *addr, size_t cnt)
468 {
469         __asm __volatile("cld; rep; outsl"
470                          : "+S" (addr), "+c" (cnt)
471                          : "d" (port));
472 }
473
474 static __inline void
475 outw(u_int port, u_short data)
476 {
477         __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
478 }
479
480 static __inline void
481 ia32_pause(void)
482 {
483         __asm __volatile("pause");
484 }
485
486 static __inline u_long
487 read_rflags(void)
488 {
489         u_long  rf;
490
491         __asm __volatile("pushfq; popq %0" : "=r" (rf));
492         return (rf);
493 }
494
495 static __inline u_int64_t
496 rdmsr(u_int msr)
497 {
498         u_int32_t low, high;
499
500         __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
501         return (low | ((u_int64_t)high << 32));
502 }
503
504 static __inline u_int64_t
505 rdpmc(u_int pmc)
506 {
507         u_int32_t low, high;
508
509         __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
510         return (low | ((u_int64_t)high << 32));
511 }
512
513 #define _RDTSC_SUPPORTED_
514
515 static __inline u_int64_t
516 rdtsc(void)
517 {
518         u_int32_t low, high;
519
520         __asm __volatile("rdtsc" : "=a" (low), "=d" (high));
521         return (low | ((u_int64_t)high << 32));
522 }
523
524 static __inline void
525 wbinvd(void)
526 {
527         __asm __volatile("wbinvd");
528 }
529
530 static __inline void
531 write_rflags(u_long rf)
532 {
533         __asm __volatile("pushq %0;  popfq" : : "r" (rf));
534 }
535
536 static __inline void
537 wrmsr(u_int msr, u_int64_t newval)
538 {
539         u_int32_t low, high;
540
541         low = newval;
542         high = newval >> 32;
543         __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
544 }
545
546 static __inline void
547 load_cr0(u_long data)
548 {
549
550         __asm __volatile("movq %0,%%cr0" : : "r" (data));
551 }
552
553 static __inline u_long
554 rcr0(void)
555 {
556         u_long  data;
557
558         __asm __volatile("movq %%cr0,%0" : "=r" (data));
559         return (data);
560 }
561
562 static __inline u_long
563 rcr2(void)
564 {
565         u_long  data;
566
567         __asm __volatile("movq %%cr2,%0" : "=r" (data));
568         return (data);
569 }
570
571 static __inline void
572 load_cr3(u_long data)
573 {
574
575         __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
576 }
577
578 static __inline u_long
579 rcr3(void)
580 {
581         u_long  data;
582
583         __asm __volatile("movq %%cr3,%0" : "=r" (data));
584         return (data);
585 }
586
587 static __inline void
588 load_cr4(u_long data)
589 {
590         __asm __volatile("movq %0,%%cr4" : : "r" (data));
591 }
592
593 static __inline u_long
594 rcr4(void)
595 {
596         u_long  data;
597
598         __asm __volatile("movq %%cr4,%0" : "=r" (data));
599         return (data);
600 }
601
602 #ifndef _CPU_INVLTLB_DEFINED
603
604 /*
605  * Invalidate the TLB on this cpu only
606  */
607 static __inline void
608 cpu_invltlb(void)
609 {
610         load_cr3(rcr3());
611 #if defined(SWTCH_OPTIM_STATS)
612         ++tlb_flush_count;
613 #endif
614 }
615
616 #endif
617
618 /*
619  * TLB flush for an individual page (even if it has PG_G).
620  * Only works on 486+ CPUs (i386 does not have PG_G).
621  */
622 static __inline void
623 invlpg(u_long addr)
624 {
625
626         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
627 }
628
629 static __inline u_int
630 rfs(void)
631 {
632         u_int sel;
633         __asm __volatile("movl %%fs,%0" : "=rm" (sel));
634         return (sel);
635 }
636
637 static __inline u_int
638 rgs(void)
639 {
640         u_int sel;
641         __asm __volatile("movl %%gs,%0" : "=rm" (sel));
642         return (sel);
643 }
644
645 static __inline void
646 load_ds(u_int sel)
647 {
648         __asm __volatile("movl %0,%%ds" : : "rm" (sel));
649 }
650
651 static __inline void
652 load_es(u_int sel)
653 {
654         __asm __volatile("movl %0,%%es" : : "rm" (sel));
655 }
656
657 #ifdef _KERNEL
658 /* This is defined in <machine/specialreg.h> but is too painful to get to */
659 #ifndef MSR_FSBASE
660 #define MSR_FSBASE      0xc0000100
661 #endif
662 static __inline void
663 load_fs(u_int sel)
664 {
665         /* Preserve the fsbase value across the selector load */
666         __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
667             : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
668 }
669
670 #ifndef MSR_GSBASE
671 #define MSR_GSBASE      0xc0000101
672 #endif
673 static __inline void
674 load_gs(u_int sel)
675 {
676         /*
677          * Preserve the gsbase value across the selector load.
678          * Note that we have to disable interrupts because the gsbase
679          * being trashed happens to be the kernel gsbase at the time.
680          */
681         __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
682             : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
683 }
684 #else
685 /* Usable by userland */
686 static __inline void
687 load_fs(u_int sel)
688 {
689         __asm __volatile("movl %0,%%fs" : : "rm" (sel));
690 }
691
692 static __inline void
693 load_gs(u_int sel)
694 {
695         __asm __volatile("movl %0,%%gs" : : "rm" (sel));
696 }
697 #endif
698
699 /* void lidt(struct region_descriptor *addr); */
700 static __inline void
701 lidt(struct region_descriptor *addr)
702 {
703         __asm __volatile("lidt (%0)" : : "r" (addr));
704 }
705
706 /* void lldt(u_short sel); */
707 static __inline void
708 lldt(u_short sel)
709 {
710         __asm __volatile("lldt %0" : : "r" (sel));
711 }
712
713 /* void ltr(u_short sel); */
714 static __inline void
715 ltr(u_short sel)
716 {
717         __asm __volatile("ltr %0" : : "r" (sel));
718 }
719
720 static __inline u_int64_t
721 rdr0(void)
722 {
723         u_int64_t data;
724         __asm __volatile("movq %%dr0,%0" : "=r" (data));
725         return (data);
726 }
727
728 static __inline void
729 load_dr0(u_int64_t dr0)
730 {
731         __asm __volatile("movq %0,%%dr0" : : "r" (dr0));
732 }
733
734 static __inline u_int64_t
735 rdr1(void)
736 {
737         u_int64_t data;
738         __asm __volatile("movq %%dr1,%0" : "=r" (data));
739         return (data);
740 }
741
742 static __inline void
743 load_dr1(u_int64_t dr1)
744 {
745         __asm __volatile("movq %0,%%dr1" : : "r" (dr1));
746 }
747
748 static __inline u_int64_t
749 rdr2(void)
750 {
751         u_int64_t data;
752         __asm __volatile("movq %%dr2,%0" : "=r" (data));
753         return (data);
754 }
755
756 static __inline void
757 load_dr2(u_int64_t dr2)
758 {
759         __asm __volatile("movq %0,%%dr2" : : "r" (dr2));
760 }
761
762 static __inline u_int64_t
763 rdr3(void)
764 {
765         u_int64_t data;
766         __asm __volatile("movq %%dr3,%0" : "=r" (data));
767         return (data);
768 }
769
770 static __inline void
771 load_dr3(u_int64_t dr3)
772 {
773         __asm __volatile("movq %0,%%dr3" : : "r" (dr3));
774 }
775
776 static __inline u_int64_t
777 rdr4(void)
778 {
779         u_int64_t data;
780         __asm __volatile("movq %%dr4,%0" : "=r" (data));
781         return (data);
782 }
783
784 static __inline void
785 load_dr4(u_int64_t dr4)
786 {
787         __asm __volatile("movq %0,%%dr4" : : "r" (dr4));
788 }
789
790 static __inline u_int64_t
791 rdr5(void)
792 {
793         u_int64_t data;
794         __asm __volatile("movq %%dr5,%0" : "=r" (data));
795         return (data);
796 }
797
798 static __inline void
799 load_dr5(u_int64_t dr5)
800 {
801         __asm __volatile("movq %0,%%dr5" : : "r" (dr5));
802 }
803
804 static __inline u_int64_t
805 rdr6(void)
806 {
807         u_int64_t data;
808         __asm __volatile("movq %%dr6,%0" : "=r" (data));
809         return (data);
810 }
811
812 static __inline void
813 load_dr6(u_int64_t dr6)
814 {
815         __asm __volatile("movq %0,%%dr6" : : "r" (dr6));
816 }
817
818 static __inline u_int64_t
819 rdr7(void)
820 {
821         u_int64_t data;
822         __asm __volatile("movq %%dr7,%0" : "=r" (data));
823         return (data);
824 }
825
826 static __inline void
827 load_dr7(u_int64_t dr7)
828 {
829         __asm __volatile("movq %0,%%dr7" : : "r" (dr7));
830 }
831
832 static __inline register_t
833 intr_disable(void)
834 {
835         register_t rflags;
836
837         rflags = read_rflags();
838         cpu_disable_intr();
839         return (rflags);
840 }
841
842 static __inline void
843 intr_restore(register_t rflags)
844 {
845         write_rflags(rflags);
846 }
847
848 #else /* !__GNUC__ */
849
850 int     breakpoint(void);
851 void    cpu_pause(void);
852 u_int   bsfl(u_int mask);
853 u_int   bsrl(u_int mask);
854 void    cpu_disable_intr(void);
855 void    cpu_enable_intr(void);
856 void    cpu_invlpg(u_long addr);
857 void    cpu_invlpg_range(u_long start, u_long end);
858 void    do_cpuid(u_int ax, u_int *p);
859 void    halt(void);
860 u_char  inb(u_int port);
861 u_int   inl(u_int port);
862 void    insb(u_int port, void *addr, size_t cnt);
863 void    insl(u_int port, void *addr, size_t cnt);
864 void    insw(u_int port, void *addr, size_t cnt);
865 void    invd(void);
866 void    invlpg(u_int addr);
867 void    invlpg_range(u_int start, u_int end);
868 void    cpu_invltlb(void);
869 u_short inw(u_int port);
870 void    load_cr0(u_int cr0);
871 void    load_cr3(u_int cr3);
872 void    load_cr4(u_int cr4);
873 void    load_fs(u_int sel);
874 void    load_gs(u_int sel);
875 struct region_descriptor;
876 void    lidt(struct region_descriptor *addr);
877 void    lldt(u_short sel);
878 void    ltr(u_short sel);
879 void    outb(u_int port, u_char data);
880 void    outl(u_int port, u_int data);
881 void    outsb(u_int port, void *addr, size_t cnt);
882 void    outsl(u_int port, void *addr, size_t cnt);
883 void    outsw(u_int port, void *addr, size_t cnt);
884 void    outw(u_int port, u_short data);
885 void    ia32_pause(void);
886 u_int   rcr0(void);
887 u_int   rcr2(void);
888 u_int   rcr3(void);
889 u_int   rcr4(void);
890 u_int   rfs(void);
891 u_int   rgs(void);
892 u_int64_t rdmsr(u_int msr);
893 u_int64_t rdpmc(u_int pmc);
894 u_int64_t rdtsc(void);
895 u_int   read_rflags(void);
896 void    wbinvd(void);
897 void    write_rflags(u_int rf);
898 void    wrmsr(u_int msr, u_int64_t newval);
899 u_int64_t       rdr0(void);
900 void    load_dr0(u_int64_t dr0);
901 u_int64_t       rdr1(void);
902 void    load_dr1(u_int64_t dr1);
903 u_int64_t       rdr2(void);
904 void    load_dr2(u_int64_t dr2);
905 u_int64_t       rdr3(void);
906 void    load_dr3(u_int64_t dr3);
907 u_int64_t       rdr4(void);
908 void    load_dr4(u_int64_t dr4);
909 u_int64_t       rdr5(void);
910 void    load_dr5(u_int64_t dr5);
911 u_int64_t       rdr6(void);
912 void    load_dr6(u_int64_t dr6);
913 u_int64_t       rdr7(void);
914 void    load_dr7(u_int64_t dr7);
915 register_t      intr_disable(void);
916 void    intr_restore(register_t rf);
917
918 #endif  /* __GNUC__ */
919
920 void    reset_dbregs(void);
921
922 __END_DECLS
923
924 #endif /* !_CPU_CPUFUNC_H_ */