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