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