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