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 uint32_t 390 rdtsc32(void) 391 { 392 uint32_t rv; 393 394 __asm __volatile("rdtsc" : "=a" (rv) : : "edx"); 395 return (rv); 396 } 397 398 static __inline void 399 wbinvd(void) 400 { 401 __asm __volatile("wbinvd"); 402 } 403 404 static __inline void 405 write_rflags(u_long rf) 406 { 407 __asm __volatile("pushq %0; popfq" : : "r" (rf)); 408 } 409 410 static __inline void 411 wrmsr(u_int msr, uint64_t newval) 412 { 413 uint32_t low, high; 414 415 low = newval; 416 high = newval >> 32; 417 __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 418 } 419 420 static __inline void 421 load_cr0(u_long data) 422 { 423 424 __asm __volatile("movq %0,%%cr0" : : "r" (data)); 425 } 426 427 static __inline u_long 428 rcr0(void) 429 { 430 u_long data; 431 432 __asm __volatile("movq %%cr0,%0" : "=r" (data)); 433 return (data); 434 } 435 436 static __inline u_long 437 rcr2(void) 438 { 439 u_long data; 440 441 __asm __volatile("movq %%cr2,%0" : "=r" (data)); 442 return (data); 443 } 444 445 static __inline void 446 load_cr3(u_long data) 447 { 448 449 __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory"); 450 } 451 452 static __inline u_long 453 rcr3(void) 454 { 455 u_long data; 456 457 __asm __volatile("movq %%cr3,%0" : "=r" (data)); 458 return (data); 459 } 460 461 static __inline void 462 load_cr4(u_long data) 463 { 464 __asm __volatile("movq %0,%%cr4" : : "r" (data)); 465 } 466 467 static __inline u_long 468 rcr4(void) 469 { 470 u_long data; 471 472 __asm __volatile("movq %%cr4,%0" : "=r" (data)); 473 return (data); 474 } 475 476 static __inline u_long 477 rxcr(u_int reg) 478 { 479 u_int low, high; 480 481 __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 482 return (low | ((uint64_t)high << 32)); 483 } 484 485 static __inline void 486 load_xcr(u_int reg, u_long val) 487 { 488 u_int low, high; 489 490 low = val; 491 high = val >> 32; 492 __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 493 } 494 495 /* 496 * Global TLB flush (except for thise for pages marked PG_G) 497 */ 498 static __inline void 499 invltlb(void) 500 { 501 502 load_cr3(rcr3()); 503 } 504 505 #ifndef CR4_PGE 506 #define CR4_PGE 0x00000080 /* Page global enable */ 507 #endif 508 509 /* 510 * Perform the guaranteed invalidation of all TLB entries. This 511 * includes the global entries, and entries in all PCIDs, not only the 512 * current context. The function works both on non-PCID CPUs and CPUs 513 * with the PCID turned off or on. See IA-32 SDM Vol. 3a 4.10.4.1 514 * Operations that Invalidate TLBs and Paging-Structure Caches. 515 */ 516 static __inline void 517 invltlb_glob(void) 518 { 519 uint64_t cr4; 520 521 cr4 = rcr4(); 522 load_cr4(cr4 & ~CR4_PGE); 523 /* 524 * Although preemption at this point could be detrimental to 525 * performance, it would not lead to an error. PG_G is simply 526 * ignored if CR4.PGE is clear. Moreover, in case this block 527 * is re-entered, the load_cr4() either above or below will 528 * modify CR4.PGE flushing the TLB. 529 */ 530 load_cr4(cr4 | CR4_PGE); 531 } 532 533 /* 534 * TLB flush for an individual page (even if it has PG_G). 535 * Only works on 486+ CPUs (i386 does not have PG_G). 536 */ 537 static __inline void 538 invlpg(u_long addr) 539 { 540 541 __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 542 } 543 544 #define INVPCID_ADDR 0 545 #define INVPCID_CTX 1 546 #define INVPCID_CTXGLOB 2 547 #define INVPCID_ALLCTX 3 548 549 struct invpcid_descr { 550 uint64_t pcid:12 __packed; 551 uint64_t pad:52 __packed; 552 uint64_t addr; 553 } __packed; 554 555 static __inline void 556 invpcid(struct invpcid_descr *d, int type) 557 { 558 559 __asm __volatile("invpcid (%0),%1" 560 : : "r" (d), "r" ((u_long)type) : "memory"); 561 } 562 563 static __inline u_short 564 rfs(void) 565 { 566 u_short sel; 567 __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 568 return (sel); 569 } 570 571 static __inline u_short 572 rgs(void) 573 { 574 u_short sel; 575 __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 576 return (sel); 577 } 578 579 static __inline u_short 580 rss(void) 581 { 582 u_short sel; 583 __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 584 return (sel); 585 } 586 587 static __inline void 588 load_ds(u_short sel) 589 { 590 __asm __volatile("movw %0,%%ds" : : "rm" (sel)); 591 } 592 593 static __inline void 594 load_es(u_short sel) 595 { 596 __asm __volatile("movw %0,%%es" : : "rm" (sel)); 597 } 598 599 static __inline void 600 cpu_monitor(const void *addr, u_long extensions, u_int hints) 601 { 602 603 __asm __volatile("monitor" 604 : : "a" (addr), "c" (extensions), "d" (hints)); 605 } 606 607 static __inline void 608 cpu_mwait(u_long extensions, u_int hints) 609 { 610 611 __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); 612 } 613 614 #ifdef _KERNEL 615 /* This is defined in <machine/specialreg.h> but is too painful to get to */ 616 #ifndef MSR_FSBASE 617 #define MSR_FSBASE 0xc0000100 618 #endif 619 static __inline void 620 load_fs(u_short sel) 621 { 622 /* Preserve the fsbase value across the selector load */ 623 __asm __volatile("rdmsr; movw %0,%%fs; wrmsr" 624 : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx"); 625 } 626 627 #ifndef MSR_GSBASE 628 #define MSR_GSBASE 0xc0000101 629 #endif 630 static __inline void 631 load_gs(u_short sel) 632 { 633 /* 634 * Preserve the gsbase value across the selector load. 635 * Note that we have to disable interrupts because the gsbase 636 * being trashed happens to be the kernel gsbase at the time. 637 */ 638 __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq" 639 : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx"); 640 } 641 #else 642 /* Usable by userland */ 643 static __inline void 644 load_fs(u_short sel) 645 { 646 __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 647 } 648 649 static __inline void 650 load_gs(u_short sel) 651 { 652 __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 653 } 654 #endif 655 656 static __inline uint64_t 657 rdfsbase(void) 658 { 659 uint64_t x; 660 661 __asm __volatile("rdfsbase %0" : "=r" (x)); 662 return (x); 663 } 664 665 static __inline void 666 wrfsbase(uint64_t x) 667 { 668 669 __asm __volatile("wrfsbase %0" : : "r" (x)); 670 } 671 672 static __inline uint64_t 673 rdgsbase(void) 674 { 675 uint64_t x; 676 677 __asm __volatile("rdgsbase %0" : "=r" (x)); 678 return (x); 679 } 680 681 static __inline void 682 wrgsbase(uint64_t x) 683 { 684 685 __asm __volatile("wrgsbase %0" : : "r" (x)); 686 } 687 688 static __inline void 689 bare_lgdt(struct region_descriptor *addr) 690 { 691 __asm __volatile("lgdt (%0)" : : "r" (addr)); 692 } 693 694 static __inline void 695 sgdt(struct region_descriptor *addr) 696 { 697 char *loc; 698 699 loc = (char *)addr; 700 __asm __volatile("sgdt %0" : "=m" (*loc) : : "memory"); 701 } 702 703 static __inline void 704 lidt(struct region_descriptor *addr) 705 { 706 __asm __volatile("lidt (%0)" : : "r" (addr)); 707 } 708 709 static __inline void 710 sidt(struct region_descriptor *addr) 711 { 712 char *loc; 713 714 loc = (char *)addr; 715 __asm __volatile("sidt %0" : "=m" (*loc) : : "memory"); 716 } 717 718 static __inline void 719 lldt(u_short sel) 720 { 721 __asm __volatile("lldt %0" : : "r" (sel)); 722 } 723 724 static __inline void 725 ltr(u_short sel) 726 { 727 __asm __volatile("ltr %0" : : "r" (sel)); 728 } 729 730 static __inline uint32_t 731 read_tr(void) 732 { 733 u_short sel; 734 735 __asm __volatile("str %0" : "=r" (sel)); 736 return (sel); 737 } 738 739 static __inline uint64_t 740 rdr0(void) 741 { 742 uint64_t data; 743 __asm __volatile("movq %%dr0,%0" : "=r" (data)); 744 return (data); 745 } 746 747 static __inline void 748 load_dr0(uint64_t dr0) 749 { 750 __asm __volatile("movq %0,%%dr0" : : "r" (dr0)); 751 } 752 753 static __inline uint64_t 754 rdr1(void) 755 { 756 uint64_t data; 757 __asm __volatile("movq %%dr1,%0" : "=r" (data)); 758 return (data); 759 } 760 761 static __inline void 762 load_dr1(uint64_t dr1) 763 { 764 __asm __volatile("movq %0,%%dr1" : : "r" (dr1)); 765 } 766 767 static __inline uint64_t 768 rdr2(void) 769 { 770 uint64_t data; 771 __asm __volatile("movq %%dr2,%0" : "=r" (data)); 772 return (data); 773 } 774 775 static __inline void 776 load_dr2(uint64_t dr2) 777 { 778 __asm __volatile("movq %0,%%dr2" : : "r" (dr2)); 779 } 780 781 static __inline uint64_t 782 rdr3(void) 783 { 784 uint64_t data; 785 __asm __volatile("movq %%dr3,%0" : "=r" (data)); 786 return (data); 787 } 788 789 static __inline void 790 load_dr3(uint64_t dr3) 791 { 792 __asm __volatile("movq %0,%%dr3" : : "r" (dr3)); 793 } 794 795 static __inline uint64_t 796 rdr6(void) 797 { 798 uint64_t data; 799 __asm __volatile("movq %%dr6,%0" : "=r" (data)); 800 return (data); 801 } 802 803 static __inline void 804 load_dr6(uint64_t dr6) 805 { 806 __asm __volatile("movq %0,%%dr6" : : "r" (dr6)); 807 } 808 809 static __inline uint64_t 810 rdr7(void) 811 { 812 uint64_t data; 813 __asm __volatile("movq %%dr7,%0" : "=r" (data)); 814 return (data); 815 } 816 817 static __inline void 818 load_dr7(uint64_t dr7) 819 { 820 __asm __volatile("movq %0,%%dr7" : : "r" (dr7)); 821 } 822 823 static __inline register_t 824 intr_disable(void) 825 { 826 register_t rflags; 827 828 rflags = read_rflags(); 829 disable_intr(); 830 return (rflags); 831 } 832 833 static __inline void 834 intr_restore(register_t rflags) 835 { 836 write_rflags(rflags); 837 } 838 839 static __inline void 840 stac(void) 841 { 842 843 __asm __volatile("stac" : : : "cc"); 844 } 845 846 static __inline void 847 clac(void) 848 { 849 850 __asm __volatile("clac" : : : "cc"); 851 } 852 853 enum { 854 SGX_ECREATE = 0x0, 855 SGX_EADD = 0x1, 856 SGX_EINIT = 0x2, 857 SGX_EREMOVE = 0x3, 858 SGX_EDGBRD = 0x4, 859 SGX_EDGBWR = 0x5, 860 SGX_EEXTEND = 0x6, 861 SGX_ELDU = 0x8, 862 SGX_EBLOCK = 0x9, 863 SGX_EPA = 0xA, 864 SGX_EWB = 0xB, 865 SGX_ETRACK = 0xC, 866 }; 867 868 enum { 869 SGX_PT_SECS = 0x00, 870 SGX_PT_TCS = 0x01, 871 SGX_PT_REG = 0x02, 872 SGX_PT_VA = 0x03, 873 SGX_PT_TRIM = 0x04, 874 }; 875 876 int sgx_encls(uint32_t eax, uint64_t rbx, uint64_t rcx, uint64_t rdx); 877 878 static __inline int 879 sgx_ecreate(void *pginfo, void *secs) 880 { 881 882 return (sgx_encls(SGX_ECREATE, (uint64_t)pginfo, 883 (uint64_t)secs, 0)); 884 } 885 886 static __inline int 887 sgx_eadd(void *pginfo, void *epc) 888 { 889 890 return (sgx_encls(SGX_EADD, (uint64_t)pginfo, 891 (uint64_t)epc, 0)); 892 } 893 894 static __inline int 895 sgx_einit(void *sigstruct, void *secs, void *einittoken) 896 { 897 898 return (sgx_encls(SGX_EINIT, (uint64_t)sigstruct, 899 (uint64_t)secs, (uint64_t)einittoken)); 900 } 901 902 static __inline int 903 sgx_eextend(void *secs, void *epc) 904 { 905 906 return (sgx_encls(SGX_EEXTEND, (uint64_t)secs, 907 (uint64_t)epc, 0)); 908 } 909 910 static __inline int 911 sgx_epa(void *epc) 912 { 913 914 return (sgx_encls(SGX_EPA, SGX_PT_VA, (uint64_t)epc, 0)); 915 } 916 917 static __inline int 918 sgx_eldu(uint64_t rbx, uint64_t rcx, 919 uint64_t rdx) 920 { 921 922 return (sgx_encls(SGX_ELDU, rbx, rcx, rdx)); 923 } 924 925 static __inline int 926 sgx_eremove(void *epc) 927 { 928 929 return (sgx_encls(SGX_EREMOVE, 0, (uint64_t)epc, 0)); 930 } 931 932 #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 933 934 int breakpoint(void); 935 u_int bsfl(u_int mask); 936 u_int bsrl(u_int mask); 937 void clflush(u_long addr); 938 void clts(void); 939 void cpuid_count(u_int ax, u_int cx, u_int *p); 940 void disable_intr(void); 941 void do_cpuid(u_int ax, u_int *p); 942 void enable_intr(void); 943 void halt(void); 944 void ia32_pause(void); 945 u_char inb(u_int port); 946 u_int inl(u_int port); 947 void insb(u_int port, void *addr, size_t count); 948 void insl(u_int port, void *addr, size_t count); 949 void insw(u_int port, void *addr, size_t count); 950 register_t intr_disable(void); 951 void intr_restore(register_t rf); 952 void invd(void); 953 void invlpg(u_int addr); 954 void invltlb(void); 955 u_short inw(u_int port); 956 void lidt(struct region_descriptor *addr); 957 void lldt(u_short sel); 958 void load_cr0(u_long cr0); 959 void load_cr3(u_long cr3); 960 void load_cr4(u_long cr4); 961 void load_dr0(uint64_t dr0); 962 void load_dr1(uint64_t dr1); 963 void load_dr2(uint64_t dr2); 964 void load_dr3(uint64_t dr3); 965 void load_dr6(uint64_t dr6); 966 void load_dr7(uint64_t dr7); 967 void load_fs(u_short sel); 968 void load_gs(u_short sel); 969 void ltr(u_short sel); 970 void outb(u_int port, u_char data); 971 void outl(u_int port, u_int data); 972 void outsb(u_int port, const void *addr, size_t count); 973 void outsl(u_int port, const void *addr, size_t count); 974 void outsw(u_int port, const void *addr, size_t count); 975 void outw(u_int port, u_short data); 976 u_long rcr0(void); 977 u_long rcr2(void); 978 u_long rcr3(void); 979 u_long rcr4(void); 980 uint64_t rdmsr(u_int msr); 981 uint32_t rdmsr32(u_int msr); 982 uint64_t rdpmc(u_int pmc); 983 uint64_t rdr0(void); 984 uint64_t rdr1(void); 985 uint64_t rdr2(void); 986 uint64_t rdr3(void); 987 uint64_t rdr6(void); 988 uint64_t rdr7(void); 989 uint64_t rdtsc(void); 990 u_long read_rflags(void); 991 u_int rfs(void); 992 u_int rgs(void); 993 void wbinvd(void); 994 void write_rflags(u_int rf); 995 void wrmsr(u_int msr, uint64_t newval); 996 997 #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 998 999 void reset_dbregs(void); 1000 1001 #ifdef _KERNEL 1002 int rdmsr_safe(u_int msr, uint64_t *val); 1003 int wrmsr_safe(u_int msr, uint64_t newval); 1004 #endif 1005 1006 #endif /* !_MACHINE_CPUFUNC_H_ */ 1007