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