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