]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/include/cpufunc.h
Merge branch 'releng/11.3' into releng-CDN/11.3
[FreeBSD/FreeBSD.git] / sys / amd64 / include / cpufunc.h
1 /*-
2  * Copyright (c) 2003 Peter Wemm.
3  * Copyright (c) 1993 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 /*
34  * Functions to provide access to special i386 instructions.
35  * This in included in sys/systm.h, and that file should be
36  * used in preference to this.
37  */
38
39 #ifndef _MACHINE_CPUFUNC_H_
40 #define _MACHINE_CPUFUNC_H_
41
42 #ifndef _SYS_CDEFS_H_
43 #error this file needs sys/cdefs.h as a prerequisite
44 #endif
45
46 struct region_descriptor;
47
48 #define readb(va)       (*(volatile uint8_t *) (va))
49 #define readw(va)       (*(volatile uint16_t *) (va))
50 #define readl(va)       (*(volatile uint32_t *) (va))
51 #define readq(va)       (*(volatile uint64_t *) (va))
52
53 #define writeb(va, d)   (*(volatile uint8_t *) (va) = (d))
54 #define writew(va, d)   (*(volatile uint16_t *) (va) = (d))
55 #define writel(va, d)   (*(volatile uint32_t *) (va) = (d))
56 #define writeq(va, d)   (*(volatile uint64_t *) (va) = (d))
57
58 #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
59
60 static __inline void
61 breakpoint(void)
62 {
63         __asm __volatile("int $3");
64 }
65
66 static __inline u_int
67 bsfl(u_int mask)
68 {
69         u_int   result;
70
71         __asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
72         return (result);
73 }
74
75 static __inline u_long
76 bsfq(u_long mask)
77 {
78         u_long  result;
79
80         __asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask));
81         return (result);
82 }
83
84 static __inline u_int
85 bsrl(u_int mask)
86 {
87         u_int   result;
88
89         __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
90         return (result);
91 }
92
93 static __inline u_long
94 bsrq(u_long mask)
95 {
96         u_long  result;
97
98         __asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask));
99         return (result);
100 }
101
102 static __inline void
103 clflush(u_long addr)
104 {
105
106         __asm __volatile("clflush %0" : : "m" (*(char *)addr));
107 }
108
109 static __inline void
110 clflushopt(u_long addr)
111 {
112
113         __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
114 }
115
116 static __inline void
117 clwb(u_long addr)
118 {
119
120         __asm __volatile("clwb %0" : : "m" (*(char *)addr));
121 }
122
123 static __inline void
124 clts(void)
125 {
126
127         __asm __volatile("clts");
128 }
129
130 static __inline void
131 disable_intr(void)
132 {
133         __asm __volatile("cli" : : : "memory");
134 }
135
136 static __inline void
137 do_cpuid(u_int ax, u_int *p)
138 {
139         __asm __volatile("cpuid"
140                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
141                          :  "0" (ax));
142 }
143
144 static __inline void
145 cpuid_count(u_int ax, u_int cx, u_int *p)
146 {
147         __asm __volatile("cpuid"
148                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
149                          :  "0" (ax), "c" (cx));
150 }
151
152 static __inline void
153 enable_intr(void)
154 {
155         __asm __volatile("sti");
156 }
157
158 #ifdef _KERNEL
159
160 #define HAVE_INLINE_FFS
161 #define        ffs(x)  __builtin_ffs(x)
162
163 #define HAVE_INLINE_FFSL
164
165 static __inline int
166 ffsl(long mask)
167 {
168         return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1);
169 }
170
171 #define HAVE_INLINE_FFSLL
172
173 static __inline int
174 ffsll(long long mask)
175 {
176         return (ffsl((long)mask));
177 }
178
179 #define HAVE_INLINE_FLS
180
181 static __inline int
182 fls(int mask)
183 {
184         return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
185 }
186
187 #define HAVE_INLINE_FLSL
188
189 static __inline int
190 flsl(long mask)
191 {
192         return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
193 }
194
195 #define HAVE_INLINE_FLSLL
196
197 static __inline int
198 flsll(long long mask)
199 {
200         return (flsl((long)mask));
201 }
202
203 #endif /* _KERNEL */
204
205 static __inline void
206 halt(void)
207 {
208         __asm __volatile("hlt");
209 }
210
211 static __inline u_char
212 inb(u_int port)
213 {
214         u_char  data;
215
216         __asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
217         return (data);
218 }
219
220 static __inline u_int
221 inl(u_int port)
222 {
223         u_int   data;
224
225         __asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
226         return (data);
227 }
228
229 static __inline void
230 insb(u_int port, void *addr, size_t count)
231 {
232         __asm __volatile("cld; rep; insb"
233                          : "+D" (addr), "+c" (count)
234                          : "d" (port)
235                          : "memory");
236 }
237
238 static __inline void
239 insw(u_int port, void *addr, size_t count)
240 {
241         __asm __volatile("cld; rep; insw"
242                          : "+D" (addr), "+c" (count)
243                          : "d" (port)
244                          : "memory");
245 }
246
247 static __inline void
248 insl(u_int port, void *addr, size_t count)
249 {
250         __asm __volatile("cld; rep; insl"
251                          : "+D" (addr), "+c" (count)
252                          : "d" (port)
253                          : "memory");
254 }
255
256 static __inline void
257 invd(void)
258 {
259         __asm __volatile("invd");
260 }
261
262 static __inline u_short
263 inw(u_int port)
264 {
265         u_short data;
266
267         __asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
268         return (data);
269 }
270
271 static __inline void
272 outb(u_int port, u_char data)
273 {
274         __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
275 }
276
277 static __inline void
278 outl(u_int port, u_int data)
279 {
280         __asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
281 }
282
283 static __inline void
284 outsb(u_int port, const void *addr, size_t count)
285 {
286         __asm __volatile("cld; rep; outsb"
287                          : "+S" (addr), "+c" (count)
288                          : "d" (port));
289 }
290
291 static __inline void
292 outsw(u_int port, const void *addr, size_t count)
293 {
294         __asm __volatile("cld; rep; outsw"
295                          : "+S" (addr), "+c" (count)
296                          : "d" (port));
297 }
298
299 static __inline void
300 outsl(u_int port, const void *addr, size_t count)
301 {
302         __asm __volatile("cld; rep; outsl"
303                          : "+S" (addr), "+c" (count)
304                          : "d" (port));
305 }
306
307 static __inline void
308 outw(u_int port, u_short data)
309 {
310         __asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
311 }
312
313 static __inline u_long
314 popcntq(u_long mask)
315 {
316         u_long result;
317
318         __asm __volatile("popcntq %1,%0" : "=r" (result) : "rm" (mask));
319         return (result);
320 }
321
322 static __inline void
323 lfence(void)
324 {
325
326         __asm __volatile("lfence" : : : "memory");
327 }
328
329 static __inline void
330 mfence(void)
331 {
332
333         __asm __volatile("mfence" : : : "memory");
334 }
335
336 static __inline void
337 sfence(void)
338 {
339
340         __asm __volatile("sfence" : : : "memory");
341 }
342
343 static __inline void
344 ia32_pause(void)
345 {
346         __asm __volatile("pause");
347 }
348
349 static __inline u_long
350 read_rflags(void)
351 {
352         u_long  rf;
353
354         __asm __volatile("pushfq; popq %0" : "=r" (rf));
355         return (rf);
356 }
357
358 static __inline uint64_t
359 rdmsr(u_int msr)
360 {
361         uint32_t low, high;
362
363         __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
364         return (low | ((uint64_t)high << 32));
365 }
366
367 static __inline uint32_t
368 rdmsr32(u_int msr)
369 {
370         uint32_t low;
371
372         __asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "rdx");
373         return (low);
374 }
375
376 static __inline uint64_t
377 rdpmc(u_int pmc)
378 {
379         uint32_t low, high;
380
381         __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
382         return (low | ((uint64_t)high << 32));
383 }
384
385 static __inline uint64_t
386 rdtsc(void)
387 {
388         uint32_t low, high;
389
390         __asm __volatile("rdtsc" : "=a" (low), "=d" (high));
391         return (low | ((uint64_t)high << 32));
392 }
393
394 static __inline uint32_t
395 rdtsc32(void)
396 {
397         uint32_t rv;
398
399         __asm __volatile("rdtsc" : "=a" (rv) : : "edx");
400         return (rv);
401 }
402
403 static __inline void
404 wbinvd(void)
405 {
406         __asm __volatile("wbinvd");
407 }
408
409 static __inline void
410 write_rflags(u_long rf)
411 {
412         __asm __volatile("pushq %0;  popfq" : : "r" (rf));
413 }
414
415 static __inline void
416 wrmsr(u_int msr, uint64_t newval)
417 {
418         uint32_t low, high;
419
420         low = newval;
421         high = newval >> 32;
422         __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
423 }
424
425 static __inline void
426 load_cr0(u_long data)
427 {
428
429         __asm __volatile("movq %0,%%cr0" : : "r" (data));
430 }
431
432 static __inline u_long
433 rcr0(void)
434 {
435         u_long  data;
436
437         __asm __volatile("movq %%cr0,%0" : "=r" (data));
438         return (data);
439 }
440
441 static __inline u_long
442 rcr2(void)
443 {
444         u_long  data;
445
446         __asm __volatile("movq %%cr2,%0" : "=r" (data));
447         return (data);
448 }
449
450 static __inline void
451 load_cr3(u_long data)
452 {
453
454         __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
455 }
456
457 static __inline u_long
458 rcr3(void)
459 {
460         u_long  data;
461
462         __asm __volatile("movq %%cr3,%0" : "=r" (data));
463         return (data);
464 }
465
466 static __inline void
467 load_cr4(u_long data)
468 {
469         __asm __volatile("movq %0,%%cr4" : : "r" (data));
470 }
471
472 static __inline u_long
473 rcr4(void)
474 {
475         u_long  data;
476
477         __asm __volatile("movq %%cr4,%0" : "=r" (data));
478         return (data);
479 }
480
481 static __inline u_long
482 rxcr(u_int reg)
483 {
484         u_int low, high;
485
486         __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
487         return (low | ((uint64_t)high << 32));
488 }
489
490 static __inline void
491 load_xcr(u_int reg, u_long val)
492 {
493         u_int low, high;
494
495         low = val;
496         high = val >> 32;
497         __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
498 }
499
500 /*
501  * Global TLB flush (except for thise for pages marked PG_G)
502  */
503 static __inline void
504 invltlb(void)
505 {
506
507         load_cr3(rcr3());
508 }
509
510 #ifndef CR4_PGE
511 #define CR4_PGE 0x00000080      /* Page global enable */
512 #endif
513
514 /*
515  * Perform the guaranteed invalidation of all TLB entries.  This
516  * includes the global entries, and entries in all PCIDs, not only the
517  * current context.  The function works both on non-PCID CPUs and CPUs
518  * with the PCID turned off or on.  See IA-32 SDM Vol. 3a 4.10.4.1
519  * Operations that Invalidate TLBs and Paging-Structure Caches.
520  */
521 static __inline void
522 invltlb_glob(void)
523 {
524         uint64_t cr4;
525
526         cr4 = rcr4();
527         load_cr4(cr4 & ~CR4_PGE);
528         /*
529          * Although preemption at this point could be detrimental to
530          * performance, it would not lead to an error.  PG_G is simply
531          * ignored if CR4.PGE is clear.  Moreover, in case this block
532          * is re-entered, the load_cr4() either above or below will
533          * modify CR4.PGE flushing the TLB.
534          */
535         load_cr4(cr4 | CR4_PGE);
536 }
537
538 /*
539  * TLB flush for an individual page (even if it has PG_G).
540  * Only works on 486+ CPUs (i386 does not have PG_G).
541  */
542 static __inline void
543 invlpg(u_long addr)
544 {
545
546         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
547 }
548
549 #define INVPCID_ADDR    0
550 #define INVPCID_CTX     1
551 #define INVPCID_CTXGLOB 2
552 #define INVPCID_ALLCTX  3
553
554 struct invpcid_descr {
555         uint64_t        pcid:12 __packed;
556         uint64_t        pad:52 __packed;
557         uint64_t        addr;
558 } __packed;
559
560 static __inline void
561 invpcid(struct invpcid_descr *d, int type)
562 {
563
564         __asm __volatile("invpcid (%0),%1"
565             : : "r" (d), "r" ((u_long)type) : "memory");
566 }
567
568 static __inline u_short
569 rfs(void)
570 {
571         u_short sel;
572         __asm __volatile("movw %%fs,%0" : "=rm" (sel));
573         return (sel);
574 }
575
576 static __inline u_short
577 rgs(void)
578 {
579         u_short sel;
580         __asm __volatile("movw %%gs,%0" : "=rm" (sel));
581         return (sel);
582 }
583
584 static __inline u_short
585 rss(void)
586 {
587         u_short sel;
588         __asm __volatile("movw %%ss,%0" : "=rm" (sel));
589         return (sel);
590 }
591
592 static __inline void
593 load_ds(u_short sel)
594 {
595         __asm __volatile("movw %0,%%ds" : : "rm" (sel));
596 }
597
598 static __inline void
599 load_es(u_short sel)
600 {
601         __asm __volatile("movw %0,%%es" : : "rm" (sel));
602 }
603
604 static __inline void
605 cpu_monitor(const void *addr, u_long extensions, u_int hints)
606 {
607
608         __asm __volatile("monitor"
609             : : "a" (addr), "c" (extensions), "d" (hints));
610 }
611
612 static __inline void
613 cpu_mwait(u_long extensions, u_int hints)
614 {
615
616         __asm __volatile("mwait" : : "a" (hints), "c" (extensions));
617 }
618
619 #ifdef _KERNEL
620 /* This is defined in <machine/specialreg.h> but is too painful to get to */
621 #ifndef MSR_FSBASE
622 #define MSR_FSBASE      0xc0000100
623 #endif
624 static __inline void
625 load_fs(u_short sel)
626 {
627         /* Preserve the fsbase value across the selector load */
628         __asm __volatile("rdmsr; movw %0,%%fs; wrmsr"
629             : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
630 }
631
632 #ifndef MSR_GSBASE
633 #define MSR_GSBASE      0xc0000101
634 #endif
635 static __inline void
636 load_gs(u_short sel)
637 {
638         /*
639          * Preserve the gsbase value across the selector load.
640          * Note that we have to disable interrupts because the gsbase
641          * being trashed happens to be the kernel gsbase at the time.
642          */
643         __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
644             : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
645 }
646 #else
647 /* Usable by userland */
648 static __inline void
649 load_fs(u_short sel)
650 {
651         __asm __volatile("movw %0,%%fs" : : "rm" (sel));
652 }
653
654 static __inline void
655 load_gs(u_short sel)
656 {
657         __asm __volatile("movw %0,%%gs" : : "rm" (sel));
658 }
659 #endif
660
661 static __inline uint64_t
662 rdfsbase(void)
663 {
664         uint64_t x;
665
666         __asm __volatile("rdfsbase %0" : "=r" (x));
667         return (x);
668 }
669
670 static __inline void
671 wrfsbase(uint64_t x)
672 {
673
674         __asm __volatile("wrfsbase %0" : : "r" (x));
675 }
676
677 static __inline uint64_t
678 rdgsbase(void)
679 {
680         uint64_t x;
681
682         __asm __volatile("rdgsbase %0" : "=r" (x));
683         return (x);
684 }
685
686 static __inline void
687 wrgsbase(uint64_t x)
688 {
689
690         __asm __volatile("wrgsbase %0" : : "r" (x));
691 }
692
693 static __inline void
694 bare_lgdt(struct region_descriptor *addr)
695 {
696         __asm __volatile("lgdt (%0)" : : "r" (addr));
697 }
698
699 static __inline void
700 sgdt(struct region_descriptor *addr)
701 {
702         char *loc;
703
704         loc = (char *)addr;
705         __asm __volatile("sgdt %0" : "=m" (*loc) : : "memory");
706 }
707
708 static __inline void
709 lidt(struct region_descriptor *addr)
710 {
711         __asm __volatile("lidt (%0)" : : "r" (addr));
712 }
713
714 static __inline void
715 sidt(struct region_descriptor *addr)
716 {
717         char *loc;
718
719         loc = (char *)addr;
720         __asm __volatile("sidt %0" : "=m" (*loc) : : "memory");
721 }
722
723 static __inline void
724 lldt(u_short sel)
725 {
726         __asm __volatile("lldt %0" : : "r" (sel));
727 }
728
729 static __inline u_short
730 sldt(void)
731 {
732         u_short sel;
733
734         __asm __volatile("sldt %0" : "=r" (sel));
735         return (sel);
736 }
737
738 static __inline void
739 ltr(u_short sel)
740 {
741         __asm __volatile("ltr %0" : : "r" (sel));
742 }
743
744 static __inline uint32_t
745 read_tr(void)
746 {
747         u_short sel;
748
749         __asm __volatile("str %0" : "=r" (sel));
750         return (sel);
751 }
752
753 static __inline uint64_t
754 rdr0(void)
755 {
756         uint64_t data;
757         __asm __volatile("movq %%dr0,%0" : "=r" (data));
758         return (data);
759 }
760
761 static __inline void
762 load_dr0(uint64_t dr0)
763 {
764         __asm __volatile("movq %0,%%dr0" : : "r" (dr0));
765 }
766
767 static __inline uint64_t
768 rdr1(void)
769 {
770         uint64_t data;
771         __asm __volatile("movq %%dr1,%0" : "=r" (data));
772         return (data);
773 }
774
775 static __inline void
776 load_dr1(uint64_t dr1)
777 {
778         __asm __volatile("movq %0,%%dr1" : : "r" (dr1));
779 }
780
781 static __inline uint64_t
782 rdr2(void)
783 {
784         uint64_t data;
785         __asm __volatile("movq %%dr2,%0" : "=r" (data));
786         return (data);
787 }
788
789 static __inline void
790 load_dr2(uint64_t dr2)
791 {
792         __asm __volatile("movq %0,%%dr2" : : "r" (dr2));
793 }
794
795 static __inline uint64_t
796 rdr3(void)
797 {
798         uint64_t data;
799         __asm __volatile("movq %%dr3,%0" : "=r" (data));
800         return (data);
801 }
802
803 static __inline void
804 load_dr3(uint64_t dr3)
805 {
806         __asm __volatile("movq %0,%%dr3" : : "r" (dr3));
807 }
808
809 static __inline uint64_t
810 rdr4(void)
811 {
812         uint64_t data;
813         __asm __volatile("movq %%dr4,%0" : "=r" (data));
814         return (data);
815 }
816
817 static __inline void
818 load_dr4(uint64_t dr4)
819 {
820         __asm __volatile("movq %0,%%dr4" : : "r" (dr4));
821 }
822
823 static __inline uint64_t
824 rdr5(void)
825 {
826         uint64_t data;
827         __asm __volatile("movq %%dr5,%0" : "=r" (data));
828         return (data);
829 }
830
831 static __inline void
832 load_dr5(uint64_t dr5)
833 {
834         __asm __volatile("movq %0,%%dr5" : : "r" (dr5));
835 }
836
837 static __inline uint64_t
838 rdr6(void)
839 {
840         uint64_t data;
841         __asm __volatile("movq %%dr6,%0" : "=r" (data));
842         return (data);
843 }
844
845 static __inline void
846 load_dr6(uint64_t dr6)
847 {
848         __asm __volatile("movq %0,%%dr6" : : "r" (dr6));
849 }
850
851 static __inline uint64_t
852 rdr7(void)
853 {
854         uint64_t data;
855         __asm __volatile("movq %%dr7,%0" : "=r" (data));
856         return (data);
857 }
858
859 static __inline void
860 load_dr7(uint64_t dr7)
861 {
862         __asm __volatile("movq %0,%%dr7" : : "r" (dr7));
863 }
864
865 static __inline register_t
866 intr_disable(void)
867 {
868         register_t rflags;
869
870         rflags = read_rflags();
871         disable_intr();
872         return (rflags);
873 }
874
875 static __inline void
876 intr_restore(register_t rflags)
877 {
878         write_rflags(rflags);
879 }
880
881 static __inline void
882 stac(void)
883 {
884
885         __asm __volatile("stac" : : : "cc");
886 }
887
888 static __inline void
889 clac(void)
890 {
891
892         __asm __volatile("clac" : : : "cc");
893 }
894
895 #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
896
897 int     breakpoint(void);
898 u_int   bsfl(u_int mask);
899 u_int   bsrl(u_int mask);
900 void    clflush(u_long addr);
901 void    clts(void);
902 void    cpuid_count(u_int ax, u_int cx, u_int *p);
903 void    disable_intr(void);
904 void    do_cpuid(u_int ax, u_int *p);
905 void    enable_intr(void);
906 void    halt(void);
907 void    ia32_pause(void);
908 u_char  inb(u_int port);
909 u_int   inl(u_int port);
910 void    insb(u_int port, void *addr, size_t count);
911 void    insl(u_int port, void *addr, size_t count);
912 void    insw(u_int port, void *addr, size_t count);
913 register_t      intr_disable(void);
914 void    intr_restore(register_t rf);
915 void    invd(void);
916 void    invlpg(u_int addr);
917 void    invltlb(void);
918 u_short inw(u_int port);
919 void    lidt(struct region_descriptor *addr);
920 void    lldt(u_short sel);
921 void    load_cr0(u_long cr0);
922 void    load_cr3(u_long cr3);
923 void    load_cr4(u_long cr4);
924 void    load_dr0(uint64_t dr0);
925 void    load_dr1(uint64_t dr1);
926 void    load_dr2(uint64_t dr2);
927 void    load_dr3(uint64_t dr3);
928 void    load_dr4(uint64_t dr4);
929 void    load_dr5(uint64_t dr5);
930 void    load_dr6(uint64_t dr6);
931 void    load_dr7(uint64_t dr7);
932 void    load_fs(u_short sel);
933 void    load_gs(u_short sel);
934 void    ltr(u_short sel);
935 void    outb(u_int port, u_char data);
936 void    outl(u_int port, u_int data);
937 void    outsb(u_int port, const void *addr, size_t count);
938 void    outsl(u_int port, const void *addr, size_t count);
939 void    outsw(u_int port, const void *addr, size_t count);
940 void    outw(u_int port, u_short data);
941 u_long  rcr0(void);
942 u_long  rcr2(void);
943 u_long  rcr3(void);
944 u_long  rcr4(void);
945 uint64_t rdmsr(u_int msr);
946 uint32_t rdmsr32(u_int msr);
947 uint64_t rdpmc(u_int pmc);
948 uint64_t rdr0(void);
949 uint64_t rdr1(void);
950 uint64_t rdr2(void);
951 uint64_t rdr3(void);
952 uint64_t rdr4(void);
953 uint64_t rdr5(void);
954 uint64_t rdr6(void);
955 uint64_t rdr7(void);
956 uint64_t rdtsc(void);
957 u_long  read_rflags(void);
958 u_int   rfs(void);
959 u_int   rgs(void);
960 void    wbinvd(void);
961 void    write_rflags(u_int rf);
962 void    wrmsr(u_int msr, uint64_t newval);
963
964 #endif  /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
965
966 void    reset_dbregs(void);
967
968 #ifdef _KERNEL
969 int     rdmsr_safe(u_int msr, uint64_t *val);
970 int     wrmsr_safe(u_int msr, uint64_t newval);
971 #endif
972
973 #endif /* !_MACHINE_CPUFUNC_H_ */