Revert "rename amd64 architecture to x86_64"
[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 static __inline void
392 cpu_nop(void)
393 {
394         __asm __volatile("rep; nop");
395 }
396
397 #endif  /* _KERNEL */
398
399 static __inline u_short
400 inw(u_int port)
401 {
402         u_short data;
403
404         __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
405         return (data);
406 }
407
408 static __inline u_int
409 loadandclear(volatile u_int *addr)
410 {
411         u_int   result;
412
413         __asm __volatile("xorl %0,%0; xchgl %1,%0"
414                         : "=&r" (result) : "m" (*addr));
415         return (result);
416 }
417
418 static __inline void
419 outbv(u_int port, u_char data)
420 {
421         u_char  al;
422         /*
423          * Use an unnecessary assignment to help gcc's register allocator.
424          * This make a large difference for gcc-1.40 and a tiny difference
425          * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
426          * best results.  gcc-2.6.0 can't handle this.
427          */
428         al = data;
429         __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
430 }
431
432 static __inline void
433 outl(u_int port, u_int data)
434 {
435         /*
436          * outl() and outw() aren't used much so we haven't looked at
437          * possible micro-optimizations such as the unnecessary
438          * assignment for them.
439          */
440         __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
441 }
442
443 static __inline void
444 outsb(u_int port, const void *addr, size_t cnt)
445 {
446         __asm __volatile("cld; rep; outsb"
447                          : "+S" (addr), "+c" (cnt)
448                          : "d" (port));
449 }
450
451 static __inline void
452 outsw(u_int port, const void *addr, size_t cnt)
453 {
454         __asm __volatile("cld; rep; outsw"
455                          : "+S" (addr), "+c" (cnt)
456                          : "d" (port));
457 }
458
459 static __inline void
460 outsl(u_int port, const void *addr, size_t cnt)
461 {
462         __asm __volatile("cld; rep; outsl"
463                          : "+S" (addr), "+c" (cnt)
464                          : "d" (port));
465 }
466
467 static __inline void
468 outw(u_int port, u_short data)
469 {
470         __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
471 }
472
473 static __inline void
474 ia32_pause(void)
475 {
476         __asm __volatile("pause");
477 }
478
479 static __inline u_long
480 read_rflags(void)
481 {
482         u_long  rf;
483
484         __asm __volatile("pushfq; popq %0" : "=r" (rf));
485         return (rf);
486 }
487
488 static __inline u_int64_t
489 rdmsr(u_int msr)
490 {
491         u_int32_t low, high;
492
493         __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
494         return (low | ((u_int64_t)high << 32));
495 }
496
497 static __inline u_int64_t
498 rdpmc(u_int pmc)
499 {
500         u_int32_t low, high;
501
502         __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
503         return (low | ((u_int64_t)high << 32));
504 }
505
506 #define _RDTSC_SUPPORTED_
507
508 static __inline u_int64_t
509 rdtsc(void)
510 {
511         u_int32_t low, high;
512
513         __asm __volatile("rdtsc" : "=a" (low), "=d" (high));
514         return (low | ((u_int64_t)high << 32));
515 }
516
517 static __inline void
518 wbinvd(void)
519 {
520         __asm __volatile("wbinvd");
521 }
522
523 static __inline void
524 write_rflags(u_long rf)
525 {
526         __asm __volatile("pushq %0;  popfq" : : "r" (rf));
527 }
528
529 static __inline void
530 wrmsr(u_int msr, u_int64_t newval)
531 {
532         u_int32_t low, high;
533
534         low = newval;
535         high = newval >> 32;
536         __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
537 }
538
539 static __inline void
540 load_cr0(u_long data)
541 {
542
543         __asm __volatile("movq %0,%%cr0" : : "r" (data));
544 }
545
546 static __inline u_long
547 rcr0(void)
548 {
549         u_long  data;
550
551         __asm __volatile("movq %%cr0,%0" : "=r" (data));
552         return (data);
553 }
554
555 static __inline u_long
556 rcr2(void)
557 {
558         u_long  data;
559
560         __asm __volatile("movq %%cr2,%0" : "=r" (data));
561         return (data);
562 }
563
564 static __inline void
565 load_cr3(u_long data)
566 {
567
568         __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
569 }
570
571 static __inline u_long
572 rcr3(void)
573 {
574         u_long  data;
575
576         __asm __volatile("movq %%cr3,%0" : "=r" (data));
577         return (data);
578 }
579
580 static __inline void
581 load_cr4(u_long data)
582 {
583         __asm __volatile("movq %0,%%cr4" : : "r" (data));
584 }
585
586 static __inline u_long
587 rcr4(void)
588 {
589         u_long  data;
590
591         __asm __volatile("movq %%cr4,%0" : "=r" (data));
592         return (data);
593 }
594
595 /*
596  * Global TLB flush (except for thise for pages marked PG_G)
597  */
598 static __inline void
599 cpu_invltlb(void)
600 {
601
602         load_cr3(rcr3());
603 }
604
605 /*
606  * TLB flush for an individual page (even if it has PG_G).
607  * Only works on 486+ CPUs (i386 does not have PG_G).
608  */
609 static __inline void
610 invlpg(u_long addr)
611 {
612
613         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
614 }
615
616 static __inline u_int
617 rfs(void)
618 {
619         u_int sel;
620         __asm __volatile("movl %%fs,%0" : "=rm" (sel));
621         return (sel);
622 }
623
624 static __inline u_int
625 rgs(void)
626 {
627         u_int sel;
628         __asm __volatile("movl %%gs,%0" : "=rm" (sel));
629         return (sel);
630 }
631
632 static __inline void
633 load_ds(u_int sel)
634 {
635         __asm __volatile("movl %0,%%ds" : : "rm" (sel));
636 }
637
638 static __inline void
639 load_es(u_int sel)
640 {
641         __asm __volatile("movl %0,%%es" : : "rm" (sel));
642 }
643
644 #ifdef _KERNEL
645 /* This is defined in <machine/specialreg.h> but is too painful to get to */
646 #ifndef MSR_FSBASE
647 #define MSR_FSBASE      0xc0000100
648 #endif
649 static __inline void
650 load_fs(u_int sel)
651 {
652         /* Preserve the fsbase value across the selector load */
653         __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
654             : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
655 }
656
657 #ifndef MSR_GSBASE
658 #define MSR_GSBASE      0xc0000101
659 #endif
660 static __inline void
661 load_gs(u_int sel)
662 {
663         /*
664          * Preserve the gsbase value across the selector load.
665          * Note that we have to disable interrupts because the gsbase
666          * being trashed happens to be the kernel gsbase at the time.
667          */
668         __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
669             : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
670 }
671 #else
672 /* Usable by userland */
673 static __inline void
674 load_fs(u_int sel)
675 {
676         __asm __volatile("movl %0,%%fs" : : "rm" (sel));
677 }
678
679 static __inline void
680 load_gs(u_int sel)
681 {
682         __asm __volatile("movl %0,%%gs" : : "rm" (sel));
683 }
684 #endif
685
686 /* void lidt(struct region_descriptor *addr); */
687 static __inline void
688 lidt(struct region_descriptor *addr)
689 {
690         __asm __volatile("lidt (%0)" : : "r" (addr));
691 }
692
693 /* void lldt(u_short sel); */
694 static __inline void
695 lldt(u_short sel)
696 {
697         __asm __volatile("lldt %0" : : "r" (sel));
698 }
699
700 /* void ltr(u_short sel); */
701 static __inline void
702 ltr(u_short sel)
703 {
704         __asm __volatile("ltr %0" : : "r" (sel));
705 }
706
707 static __inline u_int64_t
708 rdr0(void)
709 {
710         u_int64_t data;
711         __asm __volatile("movq %%dr0,%0" : "=r" (data));
712         return (data);
713 }
714
715 static __inline void
716 load_dr0(u_int64_t dr0)
717 {
718         __asm __volatile("movq %0,%%dr0" : : "r" (dr0));
719 }
720
721 static __inline u_int64_t
722 rdr1(void)
723 {
724         u_int64_t data;
725         __asm __volatile("movq %%dr1,%0" : "=r" (data));
726         return (data);
727 }
728
729 static __inline void
730 load_dr1(u_int64_t dr1)
731 {
732         __asm __volatile("movq %0,%%dr1" : : "r" (dr1));
733 }
734
735 static __inline u_int64_t
736 rdr2(void)
737 {
738         u_int64_t data;
739         __asm __volatile("movq %%dr2,%0" : "=r" (data));
740         return (data);
741 }
742
743 static __inline void
744 load_dr2(u_int64_t dr2)
745 {
746         __asm __volatile("movq %0,%%dr2" : : "r" (dr2));
747 }
748
749 static __inline u_int64_t
750 rdr3(void)
751 {
752         u_int64_t data;
753         __asm __volatile("movq %%dr3,%0" : "=r" (data));
754         return (data);
755 }
756
757 static __inline void
758 load_dr3(u_int64_t dr3)
759 {
760         __asm __volatile("movq %0,%%dr3" : : "r" (dr3));
761 }
762
763 static __inline u_int64_t
764 rdr4(void)
765 {
766         u_int64_t data;
767         __asm __volatile("movq %%dr4,%0" : "=r" (data));
768         return (data);
769 }
770
771 static __inline void
772 load_dr4(u_int64_t dr4)
773 {
774         __asm __volatile("movq %0,%%dr4" : : "r" (dr4));
775 }
776
777 static __inline u_int64_t
778 rdr5(void)
779 {
780         u_int64_t data;
781         __asm __volatile("movq %%dr5,%0" : "=r" (data));
782         return (data);
783 }
784
785 static __inline void
786 load_dr5(u_int64_t dr5)
787 {
788         __asm __volatile("movq %0,%%dr5" : : "r" (dr5));
789 }
790
791 static __inline u_int64_t
792 rdr6(void)
793 {
794         u_int64_t data;
795         __asm __volatile("movq %%dr6,%0" : "=r" (data));
796         return (data);
797 }
798
799 static __inline void
800 load_dr6(u_int64_t dr6)
801 {
802         __asm __volatile("movq %0,%%dr6" : : "r" (dr6));
803 }
804
805 static __inline u_int64_t
806 rdr7(void)
807 {
808         u_int64_t data;
809         __asm __volatile("movq %%dr7,%0" : "=r" (data));
810         return (data);
811 }
812
813 static __inline void
814 load_dr7(u_int64_t dr7)
815 {
816         __asm __volatile("movq %0,%%dr7" : : "r" (dr7));
817 }
818
819 static __inline register_t
820 intr_disable(void)
821 {
822         register_t rflags;
823
824         rflags = read_rflags();
825         cpu_disable_intr();
826         return (rflags);
827 }
828
829 static __inline void
830 intr_restore(register_t rflags)
831 {
832         write_rflags(rflags);
833 }
834
835 #else /* !__GNUC__ */
836
837 int     breakpoint(void);
838 void    cpu_pause(void);
839 u_int   bsfl(u_int mask);
840 u_int   bsrl(u_int mask);
841 void    cpu_disable_intr(void);
842 void    cpu_enable_intr(void);
843 void    cpu_invlpg(u_long addr);
844 void    cpu_invlpg_range(u_long start, u_long end);
845 void    do_cpuid(u_int ax, u_int *p);
846 void    halt(void);
847 u_char  inb(u_int port);
848 u_int   inl(u_int port);
849 void    insb(u_int port, void *addr, size_t cnt);
850 void    insl(u_int port, void *addr, size_t cnt);
851 void    insw(u_int port, void *addr, size_t cnt);
852 void    invd(void);
853 void    invlpg(u_int addr);
854 void    invlpg_range(u_int start, u_int end);
855 void    cpu_invltlb(void);
856 u_short inw(u_int port);
857 void    load_cr0(u_int cr0);
858 void    load_cr3(u_int cr3);
859 void    load_cr4(u_int cr4);
860 void    load_fs(u_int sel);
861 void    load_gs(u_int sel);
862 struct region_descriptor;
863 void    lidt(struct region_descriptor *addr);
864 void    lldt(u_short sel);
865 void    ltr(u_short sel);
866 void    outb(u_int port, u_char data);
867 void    outl(u_int port, u_int data);
868 void    outsb(u_int port, void *addr, size_t cnt);
869 void    outsl(u_int port, void *addr, size_t cnt);
870 void    outsw(u_int port, void *addr, size_t cnt);
871 void    outw(u_int port, u_short data);
872 void    ia32_pause(void);
873 u_int   rcr0(void);
874 u_int   rcr2(void);
875 u_int   rcr3(void);
876 u_int   rcr4(void);
877 u_int   rfs(void);
878 u_int   rgs(void);
879 u_int64_t rdmsr(u_int msr);
880 u_int64_t rdpmc(u_int pmc);
881 u_int64_t rdtsc(void);
882 u_int   read_rflags(void);
883 void    wbinvd(void);
884 void    write_rflags(u_int rf);
885 void    wrmsr(u_int msr, u_int64_t newval);
886 u_int64_t       rdr0(void);
887 void    load_dr0(u_int64_t dr0);
888 u_int64_t       rdr1(void);
889 void    load_dr1(u_int64_t dr1);
890 u_int64_t       rdr2(void);
891 void    load_dr2(u_int64_t dr2);
892 u_int64_t       rdr3(void);
893 void    load_dr3(u_int64_t dr3);
894 u_int64_t       rdr4(void);
895 void    load_dr4(u_int64_t dr4);
896 u_int64_t       rdr5(void);
897 void    load_dr5(u_int64_t dr5);
898 u_int64_t       rdr6(void);
899 void    load_dr6(u_int64_t dr6);
900 u_int64_t       rdr7(void);
901 void    load_dr7(u_int64_t dr7);
902 register_t      intr_disable(void);
903 void    intr_restore(register_t rf);
904
905 #endif  /* __GNUC__ */
906
907 void    reset_dbregs(void);
908
909 __END_DECLS
910
911 #endif /* !_CPU_CPUFUNC_H_ */