2b92073beb8e4119814aec097c75ff3c544d0140
[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 #define _RDTSC_SUPPORTED_
501
502 static __inline u_int64_t
503 rdtsc(void)
504 {
505         u_int32_t low, high;
506
507         __asm __volatile("rdtsc" : "=a" (low), "=d" (high));
508         return (low | ((u_int64_t)high << 32));
509 }
510
511 static __inline void
512 wbinvd(void)
513 {
514         __asm __volatile("wbinvd");
515 }
516
517 static __inline void
518 write_rflags(u_long rf)
519 {
520         __asm __volatile("pushq %0;  popfq" : : "r" (rf));
521 }
522
523 static __inline void
524 wrmsr(u_int msr, u_int64_t newval)
525 {
526         u_int32_t low, high;
527
528         low = newval;
529         high = newval >> 32;
530         __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
531 }
532
533 static __inline void
534 load_cr0(u_long data)
535 {
536
537         __asm __volatile("movq %0,%%cr0" : : "r" (data));
538 }
539
540 static __inline u_long
541 rcr0(void)
542 {
543         u_long  data;
544
545         __asm __volatile("movq %%cr0,%0" : "=r" (data));
546         return (data);
547 }
548
549 static __inline u_long
550 rcr2(void)
551 {
552         u_long  data;
553
554         __asm __volatile("movq %%cr2,%0" : "=r" (data));
555         return (data);
556 }
557
558 static __inline void
559 load_cr3(u_long data)
560 {
561
562         __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
563 }
564
565 static __inline u_long
566 rcr3(void)
567 {
568         u_long  data;
569
570         __asm __volatile("movq %%cr3,%0" : "=r" (data));
571         return (data);
572 }
573
574 static __inline void
575 load_cr4(u_long data)
576 {
577         __asm __volatile("movq %0,%%cr4" : : "r" (data));
578 }
579
580 static __inline u_long
581 rcr4(void)
582 {
583         u_long  data;
584
585         __asm __volatile("movq %%cr4,%0" : "=r" (data));
586         return (data);
587 }
588
589 /*
590  * Global TLB flush (except for thise for pages marked PG_G)
591  */
592 static __inline void
593 cpu_invltlb(void)
594 {
595
596         load_cr3(rcr3());
597 }
598
599 /*
600  * TLB flush for an individual page (even if it has PG_G).
601  * Only works on 486+ CPUs (i386 does not have PG_G).
602  */
603 static __inline void
604 invlpg(u_long addr)
605 {
606
607         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
608 }
609
610 static __inline u_int
611 rfs(void)
612 {
613         u_int sel;
614         __asm __volatile("movl %%fs,%0" : "=rm" (sel));
615         return (sel);
616 }
617
618 static __inline u_int
619 rgs(void)
620 {
621         u_int sel;
622         __asm __volatile("movl %%gs,%0" : "=rm" (sel));
623         return (sel);
624 }
625
626 static __inline void
627 load_ds(u_int sel)
628 {
629         __asm __volatile("movl %0,%%ds" : : "rm" (sel));
630 }
631
632 static __inline void
633 load_es(u_int sel)
634 {
635         __asm __volatile("movl %0,%%es" : : "rm" (sel));
636 }
637
638 #ifdef _KERNEL
639 /* This is defined in <machine/specialreg.h> but is too painful to get to */
640 #ifndef MSR_FSBASE
641 #define MSR_FSBASE      0xc0000100
642 #endif
643 static __inline void
644 load_fs(u_int sel)
645 {
646         /* Preserve the fsbase value across the selector load */
647         __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
648             : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
649 }
650
651 #ifndef MSR_GSBASE
652 #define MSR_GSBASE      0xc0000101
653 #endif
654 static __inline void
655 load_gs(u_int sel)
656 {
657         /*
658          * Preserve the gsbase value across the selector load.
659          * Note that we have to disable interrupts because the gsbase
660          * being trashed happens to be the kernel gsbase at the time.
661          */
662         __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
663             : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
664 }
665 #else
666 /* Usable by userland */
667 static __inline void
668 load_fs(u_int sel)
669 {
670         __asm __volatile("movl %0,%%fs" : : "rm" (sel));
671 }
672
673 static __inline void
674 load_gs(u_int sel)
675 {
676         __asm __volatile("movl %0,%%gs" : : "rm" (sel));
677 }
678 #endif
679
680 /* void lidt(struct region_descriptor *addr); */
681 static __inline void
682 lidt(struct region_descriptor *addr)
683 {
684         __asm __volatile("lidt (%0)" : : "r" (addr));
685 }
686
687 /* void lldt(u_short sel); */
688 static __inline void
689 lldt(u_short sel)
690 {
691         __asm __volatile("lldt %0" : : "r" (sel));
692 }
693
694 /* void ltr(u_short sel); */
695 static __inline void
696 ltr(u_short sel)
697 {
698         __asm __volatile("ltr %0" : : "r" (sel));
699 }
700
701 static __inline u_int64_t
702 rdr0(void)
703 {
704         u_int64_t data;
705         __asm __volatile("movq %%dr0,%0" : "=r" (data));
706         return (data);
707 }
708
709 static __inline void
710 load_dr0(u_int64_t dr0)
711 {
712         __asm __volatile("movq %0,%%dr0" : : "r" (dr0));
713 }
714
715 static __inline u_int64_t
716 rdr1(void)
717 {
718         u_int64_t data;
719         __asm __volatile("movq %%dr1,%0" : "=r" (data));
720         return (data);
721 }
722
723 static __inline void
724 load_dr1(u_int64_t dr1)
725 {
726         __asm __volatile("movq %0,%%dr1" : : "r" (dr1));
727 }
728
729 static __inline u_int64_t
730 rdr2(void)
731 {
732         u_int64_t data;
733         __asm __volatile("movq %%dr2,%0" : "=r" (data));
734         return (data);
735 }
736
737 static __inline void
738 load_dr2(u_int64_t dr2)
739 {
740         __asm __volatile("movq %0,%%dr2" : : "r" (dr2));
741 }
742
743 static __inline u_int64_t
744 rdr3(void)
745 {
746         u_int64_t data;
747         __asm __volatile("movq %%dr3,%0" : "=r" (data));
748         return (data);
749 }
750
751 static __inline void
752 load_dr3(u_int64_t dr3)
753 {
754         __asm __volatile("movq %0,%%dr3" : : "r" (dr3));
755 }
756
757 static __inline u_int64_t
758 rdr4(void)
759 {
760         u_int64_t data;
761         __asm __volatile("movq %%dr4,%0" : "=r" (data));
762         return (data);
763 }
764
765 static __inline void
766 load_dr4(u_int64_t dr4)
767 {
768         __asm __volatile("movq %0,%%dr4" : : "r" (dr4));
769 }
770
771 static __inline u_int64_t
772 rdr5(void)
773 {
774         u_int64_t data;
775         __asm __volatile("movq %%dr5,%0" : "=r" (data));
776         return (data);
777 }
778
779 static __inline void
780 load_dr5(u_int64_t dr5)
781 {
782         __asm __volatile("movq %0,%%dr5" : : "r" (dr5));
783 }
784
785 static __inline u_int64_t
786 rdr6(void)
787 {
788         u_int64_t data;
789         __asm __volatile("movq %%dr6,%0" : "=r" (data));
790         return (data);
791 }
792
793 static __inline void
794 load_dr6(u_int64_t dr6)
795 {
796         __asm __volatile("movq %0,%%dr6" : : "r" (dr6));
797 }
798
799 static __inline u_int64_t
800 rdr7(void)
801 {
802         u_int64_t data;
803         __asm __volatile("movq %%dr7,%0" : "=r" (data));
804         return (data);
805 }
806
807 static __inline void
808 load_dr7(u_int64_t dr7)
809 {
810         __asm __volatile("movq %0,%%dr7" : : "r" (dr7));
811 }
812
813 static __inline register_t
814 intr_disable(void)
815 {
816         register_t rflags;
817
818         rflags = read_rflags();
819         cpu_disable_intr();
820         return (rflags);
821 }
822
823 static __inline void
824 intr_restore(register_t rflags)
825 {
826         write_rflags(rflags);
827 }
828
829 #else /* !__GNUC__ */
830
831 int     breakpoint(void);
832 void    cpu_pause(void);
833 u_int   bsfl(u_int mask);
834 u_int   bsrl(u_int mask);
835 void    cpu_disable_intr(void);
836 void    cpu_enable_intr(void);
837 void    cpu_invlpg(u_long addr);
838 void    cpu_invlpg_range(u_long start, u_long end);
839 void    do_cpuid(u_int ax, u_int *p);
840 void    halt(void);
841 u_char  inb(u_int port);
842 u_int   inl(u_int port);
843 void    insb(u_int port, void *addr, size_t cnt);
844 void    insl(u_int port, void *addr, size_t cnt);
845 void    insw(u_int port, void *addr, size_t cnt);
846 void    invd(void);
847 void    invlpg(u_int addr);
848 void    invlpg_range(u_int start, u_int end);
849 void    cpu_invltlb(void);
850 u_short inw(u_int port);
851 void    load_cr0(u_int cr0);
852 void    load_cr3(u_int cr3);
853 void    load_cr4(u_int cr4);
854 void    load_fs(u_int sel);
855 void    load_gs(u_int sel);
856 struct region_descriptor;
857 void    lidt(struct region_descriptor *addr);
858 void    lldt(u_short sel);
859 void    ltr(u_short sel);
860 void    outb(u_int port, u_char data);
861 void    outl(u_int port, u_int data);
862 void    outsb(u_int port, void *addr, size_t cnt);
863 void    outsl(u_int port, void *addr, size_t cnt);
864 void    outsw(u_int port, void *addr, size_t cnt);
865 void    outw(u_int port, u_short data);
866 void    ia32_pause(void);
867 u_int   rcr0(void);
868 u_int   rcr2(void);
869 u_int   rcr3(void);
870 u_int   rcr4(void);
871 u_int   rfs(void);
872 u_int   rgs(void);
873 u_int64_t rdmsr(u_int msr);
874 u_int64_t rdpmc(u_int pmc);
875 u_int64_t rdtsc(void);
876 u_int   read_rflags(void);
877 void    wbinvd(void);
878 void    write_rflags(u_int rf);
879 void    wrmsr(u_int msr, u_int64_t newval);
880 u_int64_t       rdr0(void);
881 void    load_dr0(u_int64_t dr0);
882 u_int64_t       rdr1(void);
883 void    load_dr1(u_int64_t dr1);
884 u_int64_t       rdr2(void);
885 void    load_dr2(u_int64_t dr2);
886 u_int64_t       rdr3(void);
887 void    load_dr3(u_int64_t dr3);
888 u_int64_t       rdr4(void);
889 void    load_dr4(u_int64_t dr4);
890 u_int64_t       rdr5(void);
891 void    load_dr5(u_int64_t dr5);
892 u_int64_t       rdr6(void);
893 void    load_dr6(u_int64_t dr6);
894 u_int64_t       rdr7(void);
895 void    load_dr7(u_int64_t dr7);
896 register_t      intr_disable(void);
897 void    intr_restore(register_t rf);
898
899 #endif  /* __GNUC__ */
900
901 void    reset_dbregs(void);
902
903 __END_DECLS
904
905 #endif /* !_CPU_CPUFUNC_H_ */