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