Merge branch 'vendor/LIBPCAP'
[dragonfly.git] / sys / cpu / i386 / include / cpufunc.h
1 /*-
2  * Copyright (c) 1993 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.96.2.3 2002/04/28 22:50:54 dwmalone Exp $
34  */
35
36 /*
37  * Functions to provide access to special i386 instructions.
38  */
39
40 #ifndef _CPU_CPUFUNC_H_
41 #define _CPU_CPUFUNC_H_
42
43 #ifndef _SYS_TYPES_H_
44 #include <sys/types.h>
45 #endif
46 #ifndef _SYS_CDEFS_H_
47 #include <sys/cdefs.h>
48 #endif
49 #include <sys/thread.h>
50 #include <machine/smp.h>
51
52 __BEGIN_DECLS
53 #define readb(va)       (*(volatile u_int8_t *) (va))
54 #define readw(va)       (*(volatile u_int16_t *) (va))
55 #define readl(va)       (*(volatile u_int32_t *) (va))
56
57 #define writeb(va, d)   (*(volatile u_int8_t *) (va) = (d))
58 #define writew(va, d)   (*(volatile u_int16_t *) (va) = (d))
59 #define writel(va, d)   (*(volatile u_int32_t *) (va) = (d))
60
61 #ifdef  __GNUC__
62
63 #include <machine/lock.h>               /* XXX */
64
65 #ifdef SWTCH_OPTIM_STATS
66 extern  int     tlb_flush_count;        /* XXX */
67 #endif
68
69 static __inline void
70 breakpoint(void)
71 {
72         __asm __volatile("int $3");
73 }
74
75 static __inline void
76 cpu_pause(void)
77 {
78         __asm __volatile("pause":::"memory");
79 }
80
81 /*
82  * Find the first 1 in mask, starting with bit 0 and return the
83  * bit number.  If mask is 0 the result is undefined.
84  */
85 static __inline u_int
86 bsfl(u_int mask)
87 {
88         u_int   result;
89
90         __asm __volatile("bsfl %0,%0" : "=r" (result) : "0" (mask));
91         return (result);
92 }
93
94 static __inline u_int
95 bsflong(u_long mask)
96 {
97         u_long  result;
98
99         __asm __volatile("bsfl %0,%0" : "=r" (result) : "0" (mask));
100         return (result);
101 }
102
103 /*
104  * Find the last 1 in mask, starting with bit 31 and return the
105  * bit number.  If mask is 0 the result is undefined.
106  */
107 static __inline u_int
108 bsrl(u_int mask)
109 {
110         u_int   result;
111
112         __asm __volatile("bsrl %0,%0" : "=r" (result) : "0" (mask));
113         return (result);
114 }
115
116 /*
117  * Test and set the specified bit (1 << bit) in the integer.  The
118  * previous value of the bit is returned (0 or 1).
119  */
120 static __inline int
121 btsl(u_int *mask, int bit)
122 {
123         int result;
124
125         __asm __volatile("btsl %2,%1; movl $0,%0; adcl $0,%0" :
126                     "=r"(result), "=m"(*mask) : "r" (bit));
127         return(result);
128 }
129
130 /*
131  * Test and clear the specified bit (1 << bit) in the integer.  The
132  * previous value of the bit is returned (0 or 1).
133  */
134 static __inline int
135 btrl(u_int *mask, int bit)
136 {
137         int result;
138
139         __asm __volatile("btrl %2,%1; movl $0,%0; adcl $0,%0" :
140                     "=r"(result), "=m"(*mask) : "r" (bit));
141         return(result);
142 }
143
144 static __inline void
145 clflush(u_long addr)
146 {
147         __asm __volatile("clflush %0" : : "m" (*(char *) addr));
148 }
149
150 static __inline void
151 do_cpuid(u_int ax, u_int *p)
152 {
153         __asm __volatile("cpuid"
154                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
155                          :  "0" (ax));
156 }
157
158 static __inline void
159 cpuid_count(u_int ax, u_int cx, u_int *p)
160 {
161         __asm __volatile("cpuid"
162                         : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
163                         :  "0" (ax), "c" (cx));
164 }
165
166 #ifndef _CPU_DISABLE_INTR_DEFINED
167
168 static __inline void
169 cpu_disable_intr(void)
170 {
171         __asm __volatile("cli" : : : "memory");
172 }
173
174 #endif
175
176 #ifndef _CPU_ENABLE_INTR_DEFINED
177
178 static __inline void
179 cpu_enable_intr(void)
180 {
181         __asm __volatile("sti");
182 }
183
184 #endif
185
186 /*
187  * Cpu and compiler memory ordering fence.  mfence ensures strong read and
188  * write ordering.
189  *
190  * A serializing or fence instruction is required here.  A locked bus
191  * cycle on data for which we already own cache mastership is the most
192  * portable.
193  */
194 static __inline void
195 cpu_mfence(void)
196 {
197 #ifdef CPU_HAS_SSE2
198         __asm __volatile("mfence" : : : "memory");
199 #else
200         __asm __volatile("lock; addl $0,(%%esp)" : : : "memory");
201 #endif
202 }
203
204 /*
205  * cpu_lfence() ensures strong read ordering for reads issued prior
206  * to the instruction verses reads issued afterwords.
207  *
208  * A serializing or fence instruction is required here.  A locked bus
209  * cycle on data for which we already own cache mastership is the most
210  * portable.
211  */
212 static __inline void
213 cpu_lfence(void)
214 {
215 #ifdef CPU_HAS_SSE2
216         __asm __volatile("lfence" : : : "memory");
217 #else
218         __asm __volatile("lock; addl $0,(%%esp)" : : : "memory");
219 #endif
220 }
221
222 /*
223  * cpu_sfence() ensures strong write ordering for writes issued prior
224  * to the instruction verses writes issued afterwords.  Writes are
225  * ordered on intel cpus so we do not actually have to do anything.
226  */
227 static __inline void
228 cpu_sfence(void)
229 {
230         /*
231          * NOTE:
232          * Don't use 'sfence' here, as it will create a lot of
233          * unnecessary stalls.
234          */
235         __asm __volatile("" : : : "memory");
236 }
237
238 /*
239  * cpu_ccfence() prevents the compiler from reordering instructions, in
240  * particular stores, relative to the current cpu.  Use cpu_sfence() if
241  * you need to guarentee ordering by both the compiler and by the cpu.
242  *
243  * This also prevents the compiler from caching memory loads into local
244  * variables across the routine.
245  */
246 static __inline void
247 cpu_ccfence(void)
248 {
249         __asm __volatile("" : : : "memory");
250 }
251
252 /*
253  * This is a horrible, horrible hack that might have to be put at the
254  * end of certain procedures (on a case by case basis), just before it
255  * returns to avoid what we believe to be an unreported AMD cpu bug.
256  * Found to occur on both a Phenom II X4 820 (two of them), as well
257  * as a 48-core built around an Opteron 6168 (Id = 0x100f91  Stepping = 1).
258  * The problem does not appear to occur w/Intel cpus.
259  *
260  * The bug is likely related to either a write combining issue or the
261  * Return Address Stack (RAS) hardware cache.
262  *
263  * In particular, we had to do this for GCC's fill_sons_in_loop() routine
264  * which due to its deep recursion and stack flow appears to be able to
265  * tickle the amd cpu bug (w/ gcc-4.4.7).  Adding a single 'nop' to the
266  * end of the routine just before it returns works around the bug.
267  *
268  * The bug appears to be extremely sensitive to %rip and %rsp values, to
269  * the point where even just inserting an instruction in an unrelated
270  * procedure (shifting the entire code base being run) effects the outcome.
271  * DragonFly is probably able to more readily reproduce the bug due to
272  * the stackgap randomization code.  We would expect OpenBSD (where we got
273  * the stackgap randomization code from) to also be able to reproduce the
274  * issue.  To date we have only reproduced the issue in DragonFly.
275  */
276 #define __AMDCPUBUG_DFLY01_AVAILABLE__
277
278 static __inline void
279 cpu_amdcpubug_dfly01(void)
280 {
281         __asm __volatile("nop" : : : "memory");
282 }
283
284 #ifdef _KERNEL
285
286 #define HAVE_INLINE_FFS
287
288 static __inline int
289 ffs(int mask)
290 {
291         /*
292          * Note that gcc-2's builtin ffs would be used if we didn't declare
293          * this inline or turn off the builtin.  The builtin is faster but
294          * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
295          * versions.
296          */
297          return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
298 }
299
300 #define HAVE_INLINE_FLS
301
302 static __inline int
303 fls(int mask)
304 {
305         return (mask == 0 ? mask : (int) bsrl((u_int)mask) + 1);
306 }
307
308 #endif /* _KERNEL */
309
310 /*
311  * The following complications are to get around gcc not having a
312  * constraint letter for the range 0..255.  We still put "d" in the
313  * constraint because "i" isn't a valid constraint when the port
314  * isn't constant.  This only matters for -O0 because otherwise
315  * the non-working version gets optimized away.
316  * 
317  * Use an expression-statement instead of a conditional expression
318  * because gcc-2.6.0 would promote the operands of the conditional
319  * and produce poor code for "if ((inb(var) & const1) == const2)".
320  *
321  * The unnecessary test `(port) < 0x10000' is to generate a warning if
322  * the `port' has type u_short or smaller.  Such types are pessimal.
323  * This actually only works for signed types.  The range check is
324  * careful to avoid generating warnings.
325  */
326 #define inb(port) __extension__ ({                                      \
327         u_char  _data;                                                  \
328         if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100     \
329             && (port) < 0x10000)                                        \
330                 _data = inbc(port);                                     \
331         else                                                            \
332                 _data = inbv(port);                                     \
333         _data; })
334
335 #define outb(port, data) (                                              \
336         __builtin_constant_p(port) && ((port) & 0xffff) < 0x100         \
337         && (port) < 0x10000                                             \
338         ? outbc(port, data) : outbv(port, data))
339
340 static __inline u_char
341 inbc(u_int port)
342 {
343         u_char  data;
344
345         __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
346         return (data);
347 }
348
349 static __inline void
350 outbc(u_int port, u_char data)
351 {
352         __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
353 }
354
355 static __inline u_char
356 inbv(u_int port)
357 {
358         u_char  data;
359         /*
360          * We use %%dx and not %1 here because i/o is done at %dx and not at
361          * %edx, while gcc generates inferior code (movw instead of movl)
362          * if we tell it to load (u_short) port.
363          */
364         __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
365         return (data);
366 }
367
368 static __inline u_int
369 inl(u_int port)
370 {
371         u_int   data;
372
373         __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
374         return (data);
375 }
376
377 static __inline void
378 insb(u_int port, void *addr, size_t cnt)
379 {
380         __asm __volatile("cld; rep; insb"
381                          : "=D" (addr), "=c" (cnt)
382                          :  "0" (addr),  "1" (cnt), "d" (port)
383                          : "memory");
384 }
385
386 static __inline void
387 insw(u_int port, void *addr, size_t cnt)
388 {
389         __asm __volatile("cld; rep; insw"
390                          : "=D" (addr), "=c" (cnt)
391                          :  "0" (addr),  "1" (cnt), "d" (port)
392                          : "memory");
393 }
394
395 static __inline void
396 insl(u_int port, void *addr, size_t cnt)
397 {
398         __asm __volatile("cld; rep; insl"
399                          : "=D" (addr), "=c" (cnt)
400                          :  "0" (addr),  "1" (cnt), "d" (port)
401                          : "memory");
402 }
403
404 static __inline void
405 invd(void)
406 {
407         __asm __volatile("invd");
408 }
409
410 #if defined(_KERNEL)
411
412 void smp_invltlb(void);
413 void smp_invltlb_intr(void);
414
415 #ifndef _CPU_INVLPG_DEFINED
416
417 /*
418  * Invalidate a patricular VA on this cpu only
419  */
420 static __inline void
421 cpu_invlpg(void *addr)
422 {
423         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
424 }
425
426 #endif
427
428 #ifndef _CPU_INVLTLB_DEFINED
429
430 /*
431  * Invalidate the TLB on this cpu only
432  */
433 static __inline void
434 cpu_invltlb(void)
435 {
436         u_int   temp;
437         /*
438          * This should be implemented as load_cr3(rcr3()) when load_cr3()
439          * is inlined.
440          */
441         __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
442                          : : "memory");
443 #if defined(SWTCH_OPTIM_STATS)
444         ++tlb_flush_count;
445 #endif
446 }
447
448 #endif
449
450 static __inline void
451 cpu_nop(void)
452 {
453         __asm __volatile("rep; nop");
454 }
455
456 #endif  /* _KERNEL */
457
458 static __inline u_short
459 inw(u_int port)
460 {
461         u_short data;
462
463         __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
464         return (data);
465 }
466
467 static __inline u_int
468 loadandclear(volatile u_int *addr)
469 {
470         u_int   result;
471
472         __asm __volatile("xorl %0,%0; xchgl %1,%0"
473                          : "=&r" (result) : "m" (*addr));
474         return (result);
475 }
476
477 static __inline void
478 outbv(u_int port, u_char data)
479 {
480         u_char  al;
481         /*
482          * Use an unnecessary assignment to help gcc's register allocator.
483          * This make a large difference for gcc-1.40 and a tiny difference
484          * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
485          * best results.  gcc-2.6.0 can't handle this.
486          */
487         al = data;
488         __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
489 }
490
491 static __inline void
492 outl(u_int port, u_int data)
493 {
494         /*
495          * outl() and outw() aren't used much so we haven't looked at
496          * possible micro-optimizations such as the unnecessary
497          * assignment for them.
498          */
499         __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
500 }
501
502 static __inline void
503 outsb(u_int port, const void *addr, size_t cnt)
504 {
505         __asm __volatile("cld; rep; outsb"
506                          : "=S" (addr), "=c" (cnt)
507                          :  "0" (addr),  "1" (cnt), "d" (port));
508 }
509
510 static __inline void
511 outsw(u_int port, const void *addr, size_t cnt)
512 {
513         __asm __volatile("cld; rep; outsw"
514                          : "=S" (addr), "=c" (cnt)
515                          :  "0" (addr),  "1" (cnt), "d" (port));
516 }
517
518 static __inline void
519 outsl(u_int port, const void *addr, size_t cnt)
520 {
521         __asm __volatile("cld; rep; outsl"
522                          : "=S" (addr), "=c" (cnt)
523                          :  "0" (addr),  "1" (cnt), "d" (port));
524 }
525
526 static __inline void
527 outw(u_int port, u_short data)
528 {
529         __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
530 }
531
532 static __inline u_int
533 rcr2(void)
534 {
535         u_int   data;
536
537         __asm __volatile("movl %%cr2,%0" : "=r" (data));
538         return (data);
539 }
540
541 static __inline u_int
542 read_eflags(void)
543 {
544         u_int   ef;
545
546         __asm __volatile("pushfl; popl %0" : "=r" (ef));
547         return (ef);
548 }
549
550 static __inline u_int64_t
551 rdmsr(u_int msr)
552 {
553         u_int64_t rv;
554
555         __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
556         return (rv);
557 }
558
559 static __inline u_int64_t
560 rdpmc(u_int pmc)
561 {
562         u_int64_t rv;
563
564         __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
565         return (rv);
566 }
567
568 #define _RDTSC_SUPPORTED_
569
570 static __inline u_int64_t
571 rdtsc(void)
572 {
573         u_int64_t rv;
574
575         __asm __volatile("rdtsc" : "=A" (rv));
576         return (rv);
577 }
578
579 static __inline void
580 wbinvd(void)
581 {
582         __asm __volatile("wbinvd");
583 }
584
585 #if defined(_KERNEL)
586 void cpu_wbinvd_on_all_cpus_callback(void *arg);
587
588 static __inline void
589 cpu_wbinvd_on_all_cpus(void)
590 {
591         lwkt_cpusync_simple(smp_active_mask, cpu_wbinvd_on_all_cpus_callback, NULL);
592 }
593 #endif
594
595 static __inline void
596 write_eflags(u_int ef)
597 {
598         __asm __volatile("pushl %0; popfl" : : "r" (ef));
599 }
600
601 static __inline void
602 wrmsr(u_int msr, u_int64_t newval)
603 {
604         __asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
605 }
606
607 static __inline u_short
608 rfs(void)
609 {
610         u_short sel;
611         __asm __volatile("movw %%fs,%0" : "=rm" (sel));
612         return (sel);
613 }
614
615 static __inline u_short
616 rgs(void)
617 {
618         u_short sel;
619         __asm __volatile("movw %%gs,%0" : "=rm" (sel));
620         return (sel);
621 }
622
623 static __inline void
624 load_fs(u_short sel)
625 {
626         __asm __volatile("movw %0,%%fs" : : "rm" (sel));
627 }
628
629 static __inline void
630 load_gs(u_short sel)
631 {
632         __asm __volatile("movw %0,%%gs" : : "rm" (sel));
633 }
634
635 static __inline u_int
636 rdr0(void)
637 {
638         u_int   data;
639         __asm __volatile("movl %%dr0,%0" : "=r" (data));
640         return (data);
641 }
642
643 static __inline void
644 load_dr0(u_int sel)
645 {
646         __asm __volatile("movl %0,%%dr0" : : "r" (sel));
647 }
648
649 static __inline u_int
650 rdr1(void)
651 {
652         u_int   data;
653         __asm __volatile("movl %%dr1,%0" : "=r" (data));
654         return (data);
655 }
656
657 static __inline void
658 load_dr1(u_int sel)
659 {
660         __asm __volatile("movl %0,%%dr1" : : "r" (sel));
661 }
662
663 static __inline u_int
664 rdr2(void)
665 {
666         u_int   data;
667         __asm __volatile("movl %%dr2,%0" : "=r" (data));
668         return (data);
669 }
670
671 static __inline void
672 load_dr2(u_int sel)
673 {
674         __asm __volatile("movl %0,%%dr2" : : "r" (sel));
675 }
676
677 static __inline u_int
678 rdr3(void)
679 {
680         u_int   data;
681         __asm __volatile("movl %%dr3,%0" : "=r" (data));
682         return (data);
683 }
684
685 static __inline void
686 load_dr3(u_int sel)
687 {
688         __asm __volatile("movl %0,%%dr3" : : "r" (sel));
689 }
690
691 static __inline u_int
692 rdr4(void)
693 {
694         u_int   data;
695         __asm __volatile("movl %%dr4,%0" : "=r" (data));
696         return (data);
697 }
698
699 static __inline void
700 load_dr4(u_int sel)
701 {
702         __asm __volatile("movl %0,%%dr4" : : "r" (sel));
703 }
704
705 static __inline u_int
706 rdr5(void)
707 {
708         u_int   data;
709         __asm __volatile("movl %%dr5,%0" : "=r" (data));
710         return (data);
711 }
712
713 static __inline void
714 load_dr5(u_int sel)
715 {
716         __asm __volatile("movl %0,%%dr5" : : "r" (sel));
717 }
718
719 static __inline u_int
720 rdr6(void)
721 {
722         u_int   data;
723         __asm __volatile("movl %%dr6,%0" : "=r" (data));
724         return (data);
725 }
726
727 static __inline void
728 load_dr6(u_int sel)
729 {
730         __asm __volatile("movl %0,%%dr6" : : "r" (sel));
731 }
732
733 static __inline u_int
734 rdr7(void)
735 {
736         u_int   data;
737         __asm __volatile("movl %%dr7,%0" : "=r" (data));
738         return (data);
739 }
740
741 static __inline void
742 load_dr7(u_int sel)
743 {
744         __asm __volatile("movl %0,%%dr7" : : "r" (sel));
745 }
746
747 #else /* !__GNUC__ */
748
749 int     breakpoint      (void);
750 void    cpu_pause       (void);
751 u_int   bsfl            (u_int mask);
752 u_int   bsrl            (u_int mask);
753 void    cpu_disable_intr (void);
754 void    do_cpuid        (u_int ax, u_int *p);
755 void    cpu_enable_intr (void);
756 u_char  inb             (u_int port);
757 u_int   inl             (u_int port);
758 void    insb            (u_int port, void *addr, size_t cnt);
759 void    insl            (u_int port, void *addr, size_t cnt);
760 void    insw            (u_int port, void *addr, size_t cnt);
761 void    invd            (void);
762 u_short inw             (u_int port);
763 u_int   loadandclear    (u_int *addr);
764 void    outb            (u_int port, u_char data);
765 void    outl            (u_int port, u_int data);
766 void    outsb           (u_int port, void *addr, size_t cnt);
767 void    outsl           (u_int port, void *addr, size_t cnt);
768 void    outsw           (u_int port, void *addr, size_t cnt);
769 void    outw            (u_int port, u_short data);
770 u_int   rcr2            (void);
771 u_int64_t rdmsr         (u_int msr);
772 u_int64_t rdpmc         (u_int pmc);
773 u_int64_t rdtsc         (void);
774 u_int   read_eflags     (void);
775 void    wbinvd          (void);
776 void    write_eflags    (u_int ef);
777 void    wrmsr           (u_int msr, u_int64_t newval);
778 u_short rfs             (void);
779 u_short rgs             (void);
780 void    load_fs         (u_short sel);
781 void    load_gs         (u_short sel);
782
783 #endif  /* __GNUC__ */
784
785 void    load_cr0        (u_int cr0);
786 void    load_cr3        (u_int cr3);
787 void    load_cr4        (u_int cr4);
788 void    ltr             (u_short sel);
789 u_int   rcr0            (void);
790 u_int   rcr3            (void);
791 u_int   rcr4            (void);
792 int     rdmsr_safe      (u_int msr, uint64_t *val);
793 void    reset_dbregs    (void);
794 __END_DECLS
795
796 #endif /* !_CPU_CPUFUNC_H_ */