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