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