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