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