1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2014 by Delphix. All rights reserved.
  26  * Copyright 2018 Joyent, Inc.
  27  */
  28 
  29 /*
  30  *  Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
  31  *  Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
  32  *    All Rights Reserved
  33  */
  34 
  35 /*
  36  * Copyright (c) 2009, Intel Corporation.
  37  * All rights reserved.
  38  */
  39 
  40 /*
  41  * General assembly language routines.
  42  * It is the intent of this file to contain routines that are
  43  * independent of the specific kernel architecture, and those that are
  44  * common across kernel architectures.
  45  * As architectures diverge, and implementations of specific
  46  * architecture-dependent routines change, the routines should be moved
  47  * from this file into the respective ../`arch -k`/subr.s file.
  48  */
  49 
  50 #include <sys/asm_linkage.h>
  51 #include <sys/asm_misc.h>
  52 #include <sys/panic.h>
  53 #include <sys/ontrap.h>
  54 #include <sys/regset.h>
  55 #include <sys/privregs.h>
  56 #include <sys/reboot.h>
  57 #include <sys/psw.h>
  58 #include <sys/x86_archext.h>
  59 
  60 #if defined(__lint)
  61 #include <sys/types.h>
  62 #include <sys/systm.h>
  63 #include <sys/thread.h>
  64 #include <sys/archsystm.h>
  65 #include <sys/byteorder.h>
  66 #include <sys/dtrace.h>
  67 #include <sys/ftrace.h>
  68 #else   /* __lint */
  69 #include "assym.h"
  70 #endif  /* __lint */
  71 #include <sys/dditypes.h>
  72 
  73 /*
  74  * on_fault()
  75  *
  76  * Catch lofault faults. Like setjmp except it returns one
  77  * if code following causes uncorrectable fault. Turned off
  78  * by calling no_fault(). Note that while under on_fault(),
  79  * SMAP is disabled. For more information see
  80  * uts/intel/ia32/ml/copy.s.
  81  */
  82 
  83 #if defined(__lint)
  84 
  85 /* ARGSUSED */
  86 int
  87 on_fault(label_t *ljb)
  88 { return (0); }
  89 
  90 void
  91 no_fault(void)
  92 {}
  93 
  94 #else   /* __lint */
  95 
  96 #if defined(__amd64)
  97 
  98         ENTRY(on_fault)
  99         movq    %gs:CPU_THREAD, %rsi
 100         leaq    catch_fault(%rip), %rdx
 101         movq    %rdi, T_ONFAULT(%rsi)           /* jumpbuf in t_onfault */
 102         movq    %rdx, T_LOFAULT(%rsi)           /* catch_fault in t_lofault */
 103         call    smap_disable                    /* allow user accesses */
 104         jmp     setjmp                          /* let setjmp do the rest */
 105 
 106 catch_fault:
 107         movq    %gs:CPU_THREAD, %rsi
 108         movq    T_ONFAULT(%rsi), %rdi           /* address of save area */
 109         xorl    %eax, %eax
 110         movq    %rax, T_ONFAULT(%rsi)           /* turn off onfault */
 111         movq    %rax, T_LOFAULT(%rsi)           /* turn off lofault */
 112         call    smap_enable                     /* disallow user accesses */
 113         jmp     longjmp                         /* let longjmp do the rest */
 114         SET_SIZE(on_fault)
 115 
 116         ENTRY(no_fault)
 117         movq    %gs:CPU_THREAD, %rsi
 118         xorl    %eax, %eax
 119         movq    %rax, T_ONFAULT(%rsi)           /* turn off onfault */
 120         movq    %rax, T_LOFAULT(%rsi)           /* turn off lofault */
 121         call    smap_enable                     /* disallow user accesses */
 122         ret
 123         SET_SIZE(no_fault)
 124 
 125 #elif defined(__i386)
 126 
 127         ENTRY(on_fault)
 128         movl    %gs:CPU_THREAD, %edx
 129         movl    4(%esp), %eax                   /* jumpbuf address */
 130         leal    catch_fault, %ecx
 131         movl    %eax, T_ONFAULT(%edx)           /* jumpbuf in t_onfault */
 132         movl    %ecx, T_LOFAULT(%edx)           /* catch_fault in t_lofault */
 133         jmp     setjmp                          /* let setjmp do the rest */
 134 
 135 catch_fault:
 136         movl    %gs:CPU_THREAD, %edx
 137         xorl    %eax, %eax
 138         movl    T_ONFAULT(%edx), %ecx           /* address of save area */
 139         movl    %eax, T_ONFAULT(%edx)           /* turn off onfault */
 140         movl    %eax, T_LOFAULT(%edx)           /* turn off lofault */
 141         pushl   %ecx
 142         call    longjmp                         /* let longjmp do the rest */
 143         SET_SIZE(on_fault)
 144 
 145         ENTRY(no_fault)
 146         movl    %gs:CPU_THREAD, %edx
 147         xorl    %eax, %eax
 148         movl    %eax, T_ONFAULT(%edx)           /* turn off onfault */
 149         movl    %eax, T_LOFAULT(%edx)           /* turn off lofault */
 150         ret
 151         SET_SIZE(no_fault)
 152 
 153 #endif  /* __i386 */
 154 #endif  /* __lint */
 155 
 156 /*
 157  * Default trampoline code for on_trap() (see <sys/ontrap.h>).  We just
 158  * do a longjmp(&curthread->t_ontrap->ot_jmpbuf) if this is ever called.
 159  */
 160 
 161 #if defined(lint)
 162 
 163 void
 164 on_trap_trampoline(void)
 165 {}
 166 
 167 #else   /* __lint */
 168 
 169 #if defined(__amd64)
 170 
 171         ENTRY(on_trap_trampoline)
 172         movq    %gs:CPU_THREAD, %rsi
 173         movq    T_ONTRAP(%rsi), %rdi
 174         addq    $OT_JMPBUF, %rdi
 175         jmp     longjmp
 176         SET_SIZE(on_trap_trampoline)
 177 
 178 #elif defined(__i386)
 179 
 180         ENTRY(on_trap_trampoline)
 181         movl    %gs:CPU_THREAD, %eax
 182         movl    T_ONTRAP(%eax), %eax
 183         addl    $OT_JMPBUF, %eax
 184         pushl   %eax
 185         call    longjmp
 186         SET_SIZE(on_trap_trampoline)
 187 
 188 #endif  /* __i386 */
 189 #endif  /* __lint */
 190 
 191 /*
 192  * Push a new element on to the t_ontrap stack.  Refer to <sys/ontrap.h> for
 193  * more information about the on_trap() mechanism.  If the on_trap_data is the
 194  * same as the topmost stack element, we just modify that element.
 195  */
 196 #if defined(lint)
 197 
 198 /*ARGSUSED*/
 199 int
 200 on_trap(on_trap_data_t *otp, uint_t prot)
 201 { return (0); }
 202 
 203 #else   /* __lint */
 204 
 205 #if defined(__amd64)
 206 
 207         ENTRY(on_trap)
 208         movw    %si, OT_PROT(%rdi)              /* ot_prot = prot */
 209         movw    $0, OT_TRAP(%rdi)               /* ot_trap = 0 */
 210         leaq    on_trap_trampoline(%rip), %rdx  /* rdx = &on_trap_trampoline */
 211         movq    %rdx, OT_TRAMPOLINE(%rdi)       /* ot_trampoline = rdx */
 212         xorl    %ecx, %ecx
 213         movq    %rcx, OT_HANDLE(%rdi)           /* ot_handle = NULL */
 214         movq    %rcx, OT_PAD1(%rdi)             /* ot_pad1 = NULL */
 215         movq    %gs:CPU_THREAD, %rdx            /* rdx = curthread */
 216         movq    T_ONTRAP(%rdx), %rcx            /* rcx = curthread->t_ontrap */
 217         cmpq    %rdi, %rcx                      /* if (otp == %rcx)     */
 218         je      0f                              /*      don't modify t_ontrap */
 219 
 220         movq    %rcx, OT_PREV(%rdi)             /* ot_prev = t_ontrap */
 221         movq    %rdi, T_ONTRAP(%rdx)            /* curthread->t_ontrap = otp */
 222 
 223 0:      addq    $OT_JMPBUF, %rdi                /* &ot_jmpbuf */
 224         jmp     setjmp
 225         SET_SIZE(on_trap)
 226 
 227 #elif defined(__i386)
 228 
 229         ENTRY(on_trap)
 230         movl    4(%esp), %eax                   /* %eax = otp */
 231         movl    8(%esp), %edx                   /* %edx = prot */
 232 
 233         movw    %dx, OT_PROT(%eax)              /* ot_prot = prot */
 234         movw    $0, OT_TRAP(%eax)               /* ot_trap = 0 */
 235         leal    on_trap_trampoline, %edx        /* %edx = &on_trap_trampoline */
 236         movl    %edx, OT_TRAMPOLINE(%eax)       /* ot_trampoline = %edx */
 237         movl    $0, OT_HANDLE(%eax)             /* ot_handle = NULL */
 238         movl    $0, OT_PAD1(%eax)               /* ot_pad1 = NULL */
 239         movl    %gs:CPU_THREAD, %edx            /* %edx = curthread */
 240         movl    T_ONTRAP(%edx), %ecx            /* %ecx = curthread->t_ontrap */
 241         cmpl    %eax, %ecx                      /* if (otp == %ecx) */
 242         je      0f                              /*    don't modify t_ontrap */
 243 
 244         movl    %ecx, OT_PREV(%eax)             /* ot_prev = t_ontrap */
 245         movl    %eax, T_ONTRAP(%edx)            /* curthread->t_ontrap = otp */
 246 
 247 0:      addl    $OT_JMPBUF, %eax                /* %eax = &ot_jmpbuf */
 248         movl    %eax, 4(%esp)                   /* put %eax back on the stack */
 249         jmp     setjmp                          /* let setjmp do the rest */
 250         SET_SIZE(on_trap)
 251 
 252 #endif  /* __i386 */
 253 #endif  /* __lint */
 254 
 255 /*
 256  * Setjmp and longjmp implement non-local gotos using state vectors
 257  * type label_t.
 258  */
 259 
 260 #if defined(__lint)
 261 
 262 /* ARGSUSED */
 263 int
 264 setjmp(label_t *lp)
 265 { return (0); }
 266 
 267 /* ARGSUSED */
 268 void
 269 longjmp(label_t *lp)
 270 {}
 271 
 272 #else   /* __lint */
 273 
 274 #if LABEL_PC != 0
 275 #error LABEL_PC MUST be defined as 0 for setjmp/longjmp to work as coded
 276 #endif  /* LABEL_PC != 0 */
 277 
 278 #if defined(__amd64)
 279 
 280         ENTRY(setjmp)
 281         movq    %rsp, LABEL_SP(%rdi)
 282         movq    %rbp, LABEL_RBP(%rdi)
 283         movq    %rbx, LABEL_RBX(%rdi)
 284         movq    %r12, LABEL_R12(%rdi)
 285         movq    %r13, LABEL_R13(%rdi)
 286         movq    %r14, LABEL_R14(%rdi)
 287         movq    %r15, LABEL_R15(%rdi)
 288         movq    (%rsp), %rdx            /* return address */
 289         movq    %rdx, (%rdi)            /* LABEL_PC is 0 */
 290         xorl    %eax, %eax              /* return 0 */
 291         ret
 292         SET_SIZE(setjmp)
 293 
 294         ENTRY(longjmp)
 295         movq    LABEL_SP(%rdi), %rsp
 296         movq    LABEL_RBP(%rdi), %rbp
 297         movq    LABEL_RBX(%rdi), %rbx
 298         movq    LABEL_R12(%rdi), %r12
 299         movq    LABEL_R13(%rdi), %r13
 300         movq    LABEL_R14(%rdi), %r14
 301         movq    LABEL_R15(%rdi), %r15
 302         movq    (%rdi), %rdx            /* return address; LABEL_PC is 0 */
 303         movq    %rdx, (%rsp)
 304         xorl    %eax, %eax
 305         incl    %eax                    /* return 1 */
 306         ret
 307         SET_SIZE(longjmp)
 308 
 309 #elif defined(__i386)
 310 
 311         ENTRY(setjmp)
 312         movl    4(%esp), %edx           /* address of save area */
 313         movl    %ebp, LABEL_EBP(%edx)
 314         movl    %ebx, LABEL_EBX(%edx)
 315         movl    %esi, LABEL_ESI(%edx)
 316         movl    %edi, LABEL_EDI(%edx)
 317         movl    %esp, 4(%edx)
 318         movl    (%esp), %ecx            /* %eip (return address) */
 319         movl    %ecx, (%edx)            /* LABEL_PC is 0 */
 320         subl    %eax, %eax              /* return 0 */
 321         ret
 322         SET_SIZE(setjmp)
 323 
 324         ENTRY(longjmp)
 325         movl    4(%esp), %edx           /* address of save area */
 326         movl    LABEL_EBP(%edx), %ebp
 327         movl    LABEL_EBX(%edx), %ebx
 328         movl    LABEL_ESI(%edx), %esi
 329         movl    LABEL_EDI(%edx), %edi
 330         movl    4(%edx), %esp
 331         movl    (%edx), %ecx            /* %eip (return addr); LABEL_PC is 0 */
 332         movl    $1, %eax
 333         addl    $4, %esp                /* pop ret adr */
 334         jmp     *%ecx                   /* indirect */
 335         SET_SIZE(longjmp)
 336 
 337 #endif  /* __i386 */
 338 #endif  /* __lint */
 339 
 340 /*
 341  * if a() calls b() calls caller(),
 342  * caller() returns return address in a().
 343  * (Note: We assume a() and b() are C routines which do the normal entry/exit
 344  *  sequence.)
 345  */
 346 
 347 #if defined(__lint)
 348 
 349 caddr_t
 350 caller(void)
 351 { return (0); }
 352 
 353 #else   /* __lint */
 354 
 355 #if defined(__amd64)
 356 
 357         ENTRY(caller)
 358         movq    8(%rbp), %rax           /* b()'s return pc, in a() */
 359         ret
 360         SET_SIZE(caller)
 361 
 362 #elif defined(__i386)
 363 
 364         ENTRY(caller)
 365         movl    4(%ebp), %eax           /* b()'s return pc, in a() */
 366         ret
 367         SET_SIZE(caller)
 368 
 369 #endif  /* __i386 */
 370 #endif  /* __lint */
 371 
 372 /*
 373  * if a() calls callee(), callee() returns the
 374  * return address in a();
 375  */
 376 
 377 #if defined(__lint)
 378 
 379 caddr_t
 380 callee(void)
 381 { return (0); }
 382 
 383 #else   /* __lint */
 384 
 385 #if defined(__amd64)
 386 
 387         ENTRY(callee)
 388         movq    (%rsp), %rax            /* callee()'s return pc, in a() */
 389         ret
 390         SET_SIZE(callee)
 391 
 392 #elif defined(__i386)
 393 
 394         ENTRY(callee)
 395         movl    (%esp), %eax            /* callee()'s return pc, in a() */
 396         ret
 397         SET_SIZE(callee)
 398 
 399 #endif  /* __i386 */
 400 #endif  /* __lint */
 401 
 402 /*
 403  * return the current frame pointer
 404  */
 405 
 406 #if defined(__lint)
 407 
 408 greg_t
 409 getfp(void)
 410 { return (0); }
 411 
 412 #else   /* __lint */
 413 
 414 #if defined(__amd64)
 415 
 416         ENTRY(getfp)
 417         movq    %rbp, %rax
 418         ret
 419         SET_SIZE(getfp)
 420 
 421 #elif defined(__i386)
 422 
 423         ENTRY(getfp)
 424         movl    %ebp, %eax
 425         ret
 426         SET_SIZE(getfp)
 427 
 428 #endif  /* __i386 */
 429 #endif  /* __lint */
 430 
 431 /*
 432  * Invalidate a single page table entry in the TLB
 433  */
 434 
 435 #if defined(__lint)
 436 
 437 /* ARGSUSED */
 438 void
 439 mmu_invlpg(caddr_t m)
 440 {}
 441 
 442 #else   /* __lint */
 443 
 444         ENTRY(mmu_invlpg)
 445         invlpg  (%rdi)
 446         ret
 447         SET_SIZE(mmu_invlpg)
 448 
 449 #endif  /* __lint */
 450 
 451 
 452 /*
 453  * Get/Set the value of various control registers
 454  */
 455 
 456 #if defined(__lint)
 457 
 458 ulong_t
 459 getcr0(void)
 460 { return (0); }
 461 
 462 /* ARGSUSED */
 463 void
 464 setcr0(ulong_t value)
 465 {}
 466 
 467 ulong_t
 468 getcr2(void)
 469 { return (0); }
 470 
 471 ulong_t
 472 getcr3(void)
 473 { return (0); }
 474 
 475 #if !defined(__xpv)
 476 /* ARGSUSED */
 477 void
 478 setcr3(ulong_t val)
 479 {}
 480 
 481 void
 482 reload_cr3(void)
 483 {}
 484 #endif
 485 
 486 ulong_t
 487 getcr4(void)
 488 { return (0); }
 489 
 490 /* ARGSUSED */
 491 void
 492 setcr4(ulong_t val)
 493 {}
 494 
 495 #if defined(__amd64)
 496 
 497 ulong_t
 498 getcr8(void)
 499 { return (0); }
 500 
 501 /* ARGSUSED */
 502 void
 503 setcr8(ulong_t val)
 504 {}
 505 
 506 #endif  /* __amd64 */
 507 
 508 #else   /* __lint */
 509 
 510 #if defined(__amd64)
 511 
 512         ENTRY(getcr0)
 513         movq    %cr0, %rax
 514         ret
 515         SET_SIZE(getcr0)
 516 
 517         ENTRY(setcr0)
 518         movq    %rdi, %cr0
 519         ret
 520         SET_SIZE(setcr0)
 521 
 522         ENTRY(getcr2)
 523 #if defined(__xpv)
 524         movq    %gs:CPU_VCPU_INFO, %rax
 525         movq    VCPU_INFO_ARCH_CR2(%rax), %rax
 526 #else
 527         movq    %cr2, %rax
 528 #endif
 529         ret
 530         SET_SIZE(getcr2)
 531 
 532         ENTRY(getcr3)
 533         movq    %cr3, %rax
 534         ret
 535         SET_SIZE(getcr3)
 536 
 537 #if !defined(__xpv)
 538 
 539         ENTRY(setcr3)
 540         movq    %rdi, %cr3
 541         ret
 542         SET_SIZE(setcr3)
 543 
 544         ENTRY(reload_cr3)
 545         movq    %cr3, %rdi
 546         movq    %rdi, %cr3
 547         ret
 548         SET_SIZE(reload_cr3)
 549 
 550 #endif  /* __xpv */
 551 
 552         ENTRY(getcr4)
 553         movq    %cr4, %rax
 554         ret
 555         SET_SIZE(getcr4)
 556 
 557         ENTRY(setcr4)
 558         movq    %rdi, %cr4
 559         ret
 560         SET_SIZE(setcr4)
 561 
 562         ENTRY(getcr8)
 563         movq    %cr8, %rax
 564         ret
 565         SET_SIZE(getcr8)
 566 
 567         ENTRY(setcr8)
 568         movq    %rdi, %cr8
 569         ret
 570         SET_SIZE(setcr8)
 571 
 572 #elif defined(__i386)
 573 
 574         ENTRY(getcr0)
 575         movl    %cr0, %eax
 576         ret
 577         SET_SIZE(getcr0)
 578 
 579         ENTRY(setcr0)
 580         movl    4(%esp), %eax
 581         movl    %eax, %cr0
 582         ret
 583         SET_SIZE(setcr0)
 584 
 585         /*
 586          * "lock mov %cr0" is used on processors which indicate it is
 587          * supported via CPUID. Normally the 32 bit TPR is accessed via
 588          * the local APIC.
 589          */
 590         ENTRY(getcr8)
 591         lock
 592         movl    %cr0, %eax
 593         ret
 594         SET_SIZE(getcr8)
 595 
 596         ENTRY(setcr8)
 597         movl    4(%esp), %eax
 598         lock
 599         movl    %eax, %cr0
 600         ret
 601         SET_SIZE(setcr8)
 602 
 603         ENTRY(getcr2)
 604 #if defined(__xpv)
 605         movl    %gs:CPU_VCPU_INFO, %eax
 606         movl    VCPU_INFO_ARCH_CR2(%eax), %eax
 607 #else
 608         movl    %cr2, %eax
 609 #endif
 610         ret
 611         SET_SIZE(getcr2)
 612 
 613         ENTRY(getcr3)
 614         movl    %cr3, %eax
 615         ret
 616         SET_SIZE(getcr3)
 617 
 618 #if !defined(__xpv)
 619 
 620         ENTRY(setcr3)
 621         movl    4(%esp), %eax
 622         movl    %eax, %cr3
 623         ret
 624         SET_SIZE(setcr3)
 625 
 626         ENTRY(reload_cr3)
 627         movl    %cr3, %eax
 628         movl    %eax, %cr3
 629         ret
 630         SET_SIZE(reload_cr3)
 631 
 632 #endif  /* __xpv */
 633 
 634         ENTRY(getcr4)
 635         movl    %cr4, %eax
 636         ret
 637         SET_SIZE(getcr4)
 638 
 639         ENTRY(setcr4)
 640         movl    4(%esp), %eax
 641         movl    %eax, %cr4
 642         ret
 643         SET_SIZE(setcr4)
 644 
 645 #endif  /* __i386 */
 646 #endif  /* __lint */
 647 
 648 #if defined(__lint)
 649 
 650 /*ARGSUSED*/
 651 uint32_t
 652 __cpuid_insn(struct cpuid_regs *regs)
 653 { return (0); }
 654 
 655 #else   /* __lint */
 656 
 657 #if defined(__amd64)
 658 
 659         ENTRY(__cpuid_insn)
 660         movq    %rbx, %r8
 661         movq    %rcx, %r9
 662         movq    %rdx, %r11
 663         movl    (%rdi), %eax            /* %eax = regs->cp_eax */
 664         movl    0x4(%rdi), %ebx         /* %ebx = regs->cp_ebx */
 665         movl    0x8(%rdi), %ecx         /* %ecx = regs->cp_ecx */
 666         movl    0xc(%rdi), %edx         /* %edx = regs->cp_edx */
 667         cpuid
 668         movl    %eax, (%rdi)            /* regs->cp_eax = %eax */
 669         movl    %ebx, 0x4(%rdi)         /* regs->cp_ebx = %ebx */
 670         movl    %ecx, 0x8(%rdi)         /* regs->cp_ecx = %ecx */
 671         movl    %edx, 0xc(%rdi)         /* regs->cp_edx = %edx */
 672         movq    %r8, %rbx
 673         movq    %r9, %rcx
 674         movq    %r11, %rdx
 675         ret
 676         SET_SIZE(__cpuid_insn)
 677 
 678 #elif defined(__i386)
 679 
 680         ENTRY(__cpuid_insn)
 681         pushl   %ebp
 682         movl    0x8(%esp), %ebp         /* %ebp = regs */
 683         pushl   %ebx
 684         pushl   %ecx
 685         pushl   %edx
 686         movl    (%ebp), %eax            /* %eax = regs->cp_eax */
 687         movl    0x4(%ebp), %ebx         /* %ebx = regs->cp_ebx */
 688         movl    0x8(%ebp), %ecx         /* %ecx = regs->cp_ecx */
 689         movl    0xc(%ebp), %edx         /* %edx = regs->cp_edx */
 690         cpuid
 691         movl    %eax, (%ebp)            /* regs->cp_eax = %eax */
 692         movl    %ebx, 0x4(%ebp)         /* regs->cp_ebx = %ebx */
 693         movl    %ecx, 0x8(%ebp)         /* regs->cp_ecx = %ecx */
 694         movl    %edx, 0xc(%ebp)         /* regs->cp_edx = %edx */
 695         popl    %edx
 696         popl    %ecx
 697         popl    %ebx
 698         popl    %ebp
 699         ret
 700         SET_SIZE(__cpuid_insn)
 701 
 702 #endif  /* __i386 */
 703 #endif  /* __lint */
 704 
 705 #if defined(__lint)
 706 
 707 /*ARGSUSED*/
 708 void
 709 i86_monitor(volatile uint32_t *addr, uint32_t extensions, uint32_t hints)
 710 {}
 711 
 712 #else   /* __lint */
 713 
 714 #if defined(__amd64)
 715 
 716         ENTRY_NP(i86_monitor)
 717         pushq   %rbp
 718         movq    %rsp, %rbp
 719         movq    %rdi, %rax              /* addr */
 720         movq    %rsi, %rcx              /* extensions */
 721         /* rdx contains input arg3: hints */
 722         clflush (%rax)
 723         .byte   0x0f, 0x01, 0xc8        /* monitor */
 724         leave
 725         ret
 726         SET_SIZE(i86_monitor)
 727 
 728 #elif defined(__i386)
 729 
 730 ENTRY_NP(i86_monitor)
 731         pushl   %ebp
 732         movl    %esp, %ebp
 733         movl    0x8(%ebp),%eax          /* addr */
 734         movl    0xc(%ebp),%ecx          /* extensions */
 735         movl    0x10(%ebp),%edx         /* hints */
 736         clflush (%eax)
 737         .byte   0x0f, 0x01, 0xc8        /* monitor */
 738         leave
 739         ret
 740         SET_SIZE(i86_monitor)
 741 
 742 #endif  /* __i386 */
 743 #endif  /* __lint */
 744 
 745 #if defined(__lint)
 746 
 747 /*ARGSUSED*/
 748 void
 749 i86_mwait(uint32_t data, uint32_t extensions)
 750 {}
 751 
 752 #else   /* __lint */
 753 
 754 #if defined(__amd64)
 755 
 756         ENTRY_NP(i86_mwait)
 757         pushq   %rbp
 758         movq    %rsp, %rbp
 759         movq    %rdi, %rax              /* data */
 760         movq    %rsi, %rcx              /* extensions */
 761         .byte   0x0f, 0x01, 0xc9        /* mwait */
 762         leave
 763         ret
 764         SET_SIZE(i86_mwait)
 765 
 766 #elif defined(__i386)
 767 
 768         ENTRY_NP(i86_mwait)
 769         pushl   %ebp
 770         movl    %esp, %ebp
 771         movl    0x8(%ebp),%eax          /* data */
 772         movl    0xc(%ebp),%ecx          /* extensions */
 773         .byte   0x0f, 0x01, 0xc9        /* mwait */
 774         leave
 775         ret
 776         SET_SIZE(i86_mwait)
 777 
 778 #endif  /* __i386 */
 779 #endif  /* __lint */
 780 
 781 #if defined(__xpv)
 782         /*
 783          * Defined in C
 784          */
 785 #else
 786 
 787 #if defined(__lint)
 788 
 789 hrtime_t
 790 tsc_read(void)
 791 {
 792         return (0);
 793 }
 794 
 795 #else   /* __lint */
 796 
 797 #if defined(__amd64)
 798 
 799         ENTRY_NP(tsc_read)
 800         movq    %rbx, %r11
 801         movl    $0, %eax
 802         cpuid
 803         rdtsc
 804         movq    %r11, %rbx
 805         shlq    $32, %rdx
 806         orq     %rdx, %rax
 807         ret
 808         .globl _tsc_mfence_start
 809 _tsc_mfence_start:
 810         mfence
 811         rdtsc
 812         shlq    $32, %rdx
 813         orq     %rdx, %rax
 814         ret
 815         .globl _tsc_mfence_end
 816 _tsc_mfence_end:
 817         .globl _tscp_start
 818 _tscp_start:
 819         .byte   0x0f, 0x01, 0xf9        /* rdtscp instruction */
 820         shlq    $32, %rdx
 821         orq     %rdx, %rax
 822         ret
 823         .globl _tscp_end
 824 _tscp_end:
 825         .globl _no_rdtsc_start
 826 _no_rdtsc_start:
 827         xorl    %edx, %edx
 828         xorl    %eax, %eax
 829         ret
 830         .globl _no_rdtsc_end
 831 _no_rdtsc_end:
 832         .globl _tsc_lfence_start
 833 _tsc_lfence_start:
 834         lfence
 835         rdtsc
 836         shlq    $32, %rdx
 837         orq     %rdx, %rax
 838         ret
 839         .globl _tsc_lfence_end
 840 _tsc_lfence_end:
 841         SET_SIZE(tsc_read)
 842 
 843 #else /* __i386 */
 844 
 845         ENTRY_NP(tsc_read)
 846         pushl   %ebx
 847         movl    $0, %eax
 848         cpuid
 849         rdtsc
 850         popl    %ebx
 851         ret
 852         .globl _tsc_mfence_start
 853 _tsc_mfence_start:
 854         mfence
 855         rdtsc
 856         ret
 857         .globl _tsc_mfence_end
 858 _tsc_mfence_end:
 859         .globl  _tscp_start
 860 _tscp_start:
 861         .byte   0x0f, 0x01, 0xf9        /* rdtscp instruction */
 862         ret
 863         .globl _tscp_end
 864 _tscp_end:
 865         .globl _no_rdtsc_start
 866 _no_rdtsc_start:
 867         xorl    %edx, %edx
 868         xorl    %eax, %eax
 869         ret
 870         .globl _no_rdtsc_end
 871 _no_rdtsc_end:
 872         .globl _tsc_lfence_start
 873 _tsc_lfence_start:
 874         lfence
 875         rdtsc
 876         ret
 877         .globl _tsc_lfence_end
 878 _tsc_lfence_end:
 879         SET_SIZE(tsc_read)
 880 
 881 #endif  /* __i386 */
 882 
 883 #endif  /* __lint */
 884 
 885 
 886 #endif  /* __xpv */
 887 
 888 #ifdef __lint
 889 /*
 890  * Do not use this function for obtaining clock tick.  This
 891  * is called by callers who do not need to have a guarenteed
 892  * correct tick value.  The proper routine to use is tsc_read().
 893  */
 894 u_longlong_t
 895 randtick(void)
 896 {
 897         return (0);
 898 }
 899 #else
 900 #if defined(__amd64)
 901         ENTRY_NP(randtick)
 902         rdtsc
 903         shlq    $32, %rdx
 904         orq     %rdx, %rax
 905         ret
 906         SET_SIZE(randtick)
 907 #else
 908         ENTRY_NP(randtick)
 909         rdtsc
 910         ret
 911         SET_SIZE(randtick)
 912 #endif /* __i386 */
 913 #endif /* __lint */
 914 /*
 915  * Insert entryp after predp in a doubly linked list.
 916  */
 917 
 918 #if defined(__lint)
 919 
 920 /*ARGSUSED*/
 921 void
 922 _insque(caddr_t entryp, caddr_t predp)
 923 {}
 924 
 925 #else   /* __lint */
 926 
 927 #if defined(__amd64)
 928 
 929         ENTRY(_insque)
 930         movq    (%rsi), %rax            /* predp->forw                       */
 931         movq    %rsi, CPTRSIZE(%rdi)    /* entryp->back = predp              */
 932         movq    %rax, (%rdi)            /* entryp->forw = predp->forw     */
 933         movq    %rdi, (%rsi)            /* predp->forw = entryp              */
 934         movq    %rdi, CPTRSIZE(%rax)    /* predp->forw->back = entryp     */
 935         ret
 936         SET_SIZE(_insque)
 937 
 938 #elif defined(__i386)
 939 
 940         ENTRY(_insque)
 941         movl    8(%esp), %edx
 942         movl    4(%esp), %ecx
 943         movl    (%edx), %eax            /* predp->forw                       */
 944         movl    %edx, CPTRSIZE(%ecx)    /* entryp->back = predp              */
 945         movl    %eax, (%ecx)            /* entryp->forw = predp->forw     */
 946         movl    %ecx, (%edx)            /* predp->forw = entryp              */
 947         movl    %ecx, CPTRSIZE(%eax)    /* predp->forw->back = entryp     */
 948         ret
 949         SET_SIZE(_insque)
 950 
 951 #endif  /* __i386 */
 952 #endif  /* __lint */
 953 
 954 /*
 955  * Remove entryp from a doubly linked list
 956  */
 957 
 958 #if defined(__lint)
 959 
 960 /*ARGSUSED*/
 961 void
 962 _remque(caddr_t entryp)
 963 {}
 964 
 965 #else   /* __lint */
 966 
 967 #if defined(__amd64)
 968 
 969         ENTRY(_remque)
 970         movq    (%rdi), %rax            /* entry->forw */
 971         movq    CPTRSIZE(%rdi), %rdx    /* entry->back */
 972         movq    %rax, (%rdx)            /* entry->back->forw = entry->forw */
 973         movq    %rdx, CPTRSIZE(%rax)    /* entry->forw->back = entry->back */
 974         ret
 975         SET_SIZE(_remque)
 976 
 977 #elif defined(__i386)
 978 
 979         ENTRY(_remque)
 980         movl    4(%esp), %ecx
 981         movl    (%ecx), %eax            /* entry->forw */
 982         movl    CPTRSIZE(%ecx), %edx    /* entry->back */
 983         movl    %eax, (%edx)            /* entry->back->forw = entry->forw */
 984         movl    %edx, CPTRSIZE(%eax)    /* entry->forw->back = entry->back */
 985         ret
 986         SET_SIZE(_remque)
 987 
 988 #endif  /* __i386 */
 989 #endif  /* __lint */
 990 
 991 /*
 992  * Returns the number of
 993  * non-NULL bytes in string argument.
 994  */
 995 
 996 #if defined(__lint)
 997 
 998 /* ARGSUSED */
 999 size_t
1000 strlen(const char *str)
1001 { return (0); }
1002 
1003 #else   /* __lint */
1004 
1005 #if defined(__amd64)
1006 
1007 /*
1008  * This is close to a simple transliteration of a C version of this
1009  * routine.  We should either just -make- this be a C version, or
1010  * justify having it in assembler by making it significantly faster.
1011  *
1012  * size_t
1013  * strlen(const char *s)
1014  * {
1015  *      const char *s0;
1016  * #if defined(DEBUG)
1017  *      if ((uintptr_t)s < KERNELBASE)
1018  *              panic(.str_panic_msg);
1019  * #endif
1020  *      for (s0 = s; *s; s++)
1021  *              ;
1022  *      return (s - s0);
1023  * }
1024  */
1025 
1026         ENTRY(strlen)
1027 #ifdef DEBUG
1028         movq    postbootkernelbase(%rip), %rax
1029         cmpq    %rax, %rdi
1030         jae     str_valid
1031         pushq   %rbp
1032         movq    %rsp, %rbp
1033         leaq    .str_panic_msg(%rip), %rdi
1034         xorl    %eax, %eax
1035         call    panic
1036 #endif  /* DEBUG */
1037 str_valid:
1038         cmpb    $0, (%rdi)
1039         movq    %rdi, %rax
1040         je      .null_found
1041         .align  4
1042 .strlen_loop:
1043         incq    %rdi
1044         cmpb    $0, (%rdi)
1045         jne     .strlen_loop
1046 .null_found:
1047         subq    %rax, %rdi
1048         movq    %rdi, %rax
1049         ret
1050         SET_SIZE(strlen)
1051 
1052 #elif defined(__i386)
1053 
1054         ENTRY(strlen)
1055 #ifdef DEBUG
1056         movl    postbootkernelbase, %eax
1057         cmpl    %eax, 4(%esp)
1058         jae     str_valid
1059         pushl   %ebp
1060         movl    %esp, %ebp
1061         pushl   $.str_panic_msg
1062         call    panic
1063 #endif /* DEBUG */
1064 
1065 str_valid:
1066         movl    4(%esp), %eax           /* %eax = string address */
1067         testl   $3, %eax                /* if %eax not word aligned */
1068         jnz     .not_word_aligned       /* goto .not_word_aligned */
1069         .align  4
1070 .word_aligned:
1071         movl    (%eax), %edx            /* move 1 word from (%eax) to %edx */
1072         movl    $0x7f7f7f7f, %ecx
1073         andl    %edx, %ecx              /* %ecx = %edx & 0x7f7f7f7f */
1074         addl    $4, %eax                /* next word */
1075         addl    $0x7f7f7f7f, %ecx       /* %ecx += 0x7f7f7f7f */
1076         orl     %edx, %ecx              /* %ecx |= %edx */
1077         andl    $0x80808080, %ecx       /* %ecx &= 0x80808080 */
1078         cmpl    $0x80808080, %ecx       /* if no null byte in this word */
1079         je      .word_aligned           /* goto .word_aligned */
1080         subl    $4, %eax                /* post-incremented */
1081 .not_word_aligned:
1082         cmpb    $0, (%eax)              /* if a byte in (%eax) is null */
1083         je      .null_found             /* goto .null_found */
1084         incl    %eax                    /* next byte */
1085         testl   $3, %eax                /* if %eax not word aligned */
1086         jnz     .not_word_aligned       /* goto .not_word_aligned */
1087         jmp     .word_aligned           /* goto .word_aligned */
1088         .align  4
1089 .null_found:
1090         subl    4(%esp), %eax           /* %eax -= string address */
1091         ret
1092         SET_SIZE(strlen)
1093 
1094 #endif  /* __i386 */
1095 
1096 #ifdef DEBUG
1097         .text
1098 .str_panic_msg:
1099         .string "strlen: argument below kernelbase"
1100 #endif /* DEBUG */
1101 
1102 #endif  /* __lint */
1103 
1104         /*
1105          * Berkeley 4.3 introduced symbolically named interrupt levels
1106          * as a way deal with priority in a machine independent fashion.
1107          * Numbered priorities are machine specific, and should be
1108          * discouraged where possible.
1109          *
1110          * Note, for the machine specific priorities there are
1111          * examples listed for devices that use a particular priority.
1112          * It should not be construed that all devices of that
1113          * type should be at that priority.  It is currently were
1114          * the current devices fit into the priority scheme based
1115          * upon time criticalness.
1116          *
1117          * The underlying assumption of these assignments is that
1118          * IPL 10 is the highest level from which a device
1119          * routine can call wakeup.  Devices that interrupt from higher
1120          * levels are restricted in what they can do.  If they need
1121          * kernels services they should schedule a routine at a lower
1122          * level (via software interrupt) to do the required
1123          * processing.
1124          *
1125          * Examples of this higher usage:
1126          *      Level   Usage
1127          *      14      Profiling clock (and PROM uart polling clock)
1128          *      12      Serial ports
1129          *
1130          * The serial ports request lower level processing on level 6.
1131          *
1132          * Also, almost all splN routines (where N is a number or a
1133          * mnemonic) will do a RAISE(), on the assumption that they are
1134          * never used to lower our priority.
1135          * The exceptions are:
1136          *      spl8()          Because you can't be above 15 to begin with!
1137          *      splzs()         Because this is used at boot time to lower our
1138          *                      priority, to allow the PROM to poll the uart.
1139          *      spl0()          Used to lower priority to 0.
1140          */
1141 
1142 #if defined(__lint)
1143 
1144 int spl0(void)          { return (0); }
1145 int spl6(void)          { return (0); }
1146 int spl7(void)          { return (0); }
1147 int spl8(void)          { return (0); }
1148 int splhigh(void)       { return (0); }
1149 int splhi(void)         { return (0); }
1150 int splzs(void)         { return (0); }
1151 
1152 /* ARGSUSED */
1153 void
1154 splx(int level)
1155 {}
1156 
1157 #else   /* __lint */
1158 
1159 #if defined(__amd64)
1160 
1161 #define SETPRI(level) \
1162         movl    $/**/level, %edi;       /* new priority */              \
1163         jmp     do_splx                 /* redirect to do_splx */
1164 
1165 #define RAISE(level) \
1166         movl    $/**/level, %edi;       /* new priority */              \
1167         jmp     splr                    /* redirect to splr */
1168 
1169 #elif defined(__i386)
1170 
1171 #define SETPRI(level) \
1172         pushl   $/**/level;     /* new priority */                      \
1173         call    do_splx;        /* invoke common splx code */           \
1174         addl    $4, %esp;       /* unstack arg */                       \
1175         ret
1176 
1177 #define RAISE(level) \
1178         pushl   $/**/level;     /* new priority */                      \
1179         call    splr;           /* invoke common splr code */           \
1180         addl    $4, %esp;       /* unstack args */                      \
1181         ret
1182 
1183 #endif  /* __i386 */
1184 
1185         /* locks out all interrupts, including memory errors */
1186         ENTRY(spl8)
1187         SETPRI(15)
1188         SET_SIZE(spl8)
1189 
1190         /* just below the level that profiling runs */
1191         ENTRY(spl7)
1192         RAISE(13)
1193         SET_SIZE(spl7)
1194 
1195         /* sun specific - highest priority onboard serial i/o asy ports */
1196         ENTRY(splzs)
1197         SETPRI(12)      /* Can't be a RAISE, as it's used to lower us */
1198         SET_SIZE(splzs)
1199 
1200         ENTRY(splhi)
1201         ALTENTRY(splhigh)
1202         ALTENTRY(spl6)
1203         ALTENTRY(i_ddi_splhigh)
1204 
1205         RAISE(DISP_LEVEL)
1206 
1207         SET_SIZE(i_ddi_splhigh)
1208         SET_SIZE(spl6)
1209         SET_SIZE(splhigh)
1210         SET_SIZE(splhi)
1211 
1212         /* allow all interrupts */
1213         ENTRY(spl0)
1214         SETPRI(0)
1215         SET_SIZE(spl0)
1216 
1217 
1218         /* splx implementation */
1219         ENTRY(splx)
1220         jmp     do_splx         /* redirect to common splx code */
1221         SET_SIZE(splx)
1222 
1223 #endif  /* __lint */
1224 
1225 #if defined(__i386)
1226 
1227 /*
1228  * Read and write the %gs register
1229  */
1230 
1231 #if defined(__lint)
1232 
1233 /*ARGSUSED*/
1234 uint16_t
1235 getgs(void)
1236 { return (0); }
1237 
1238 /*ARGSUSED*/
1239 void
1240 setgs(uint16_t sel)
1241 {}
1242 
1243 #else   /* __lint */
1244 
1245         ENTRY(getgs)
1246         clr     %eax
1247         movw    %gs, %ax
1248         ret
1249         SET_SIZE(getgs)
1250 
1251         ENTRY(setgs)
1252         movw    4(%esp), %gs
1253         ret
1254         SET_SIZE(setgs)
1255 
1256 #endif  /* __lint */
1257 #endif  /* __i386 */
1258 
1259 #if defined(__lint)
1260 
1261 void
1262 pc_reset(void)
1263 {}
1264 
1265 void
1266 efi_reset(void)
1267 {}
1268 
1269 #else   /* __lint */
1270 
1271         ENTRY(wait_500ms)
1272 #if defined(__amd64)
1273         pushq   %rbx
1274 #elif defined(__i386)
1275         push    %ebx
1276 #endif
1277         movl    $50000, %ebx
1278 1:
1279         call    tenmicrosec
1280         decl    %ebx
1281         jnz     1b
1282 #if defined(__amd64)
1283         popq    %rbx
1284 #elif defined(__i386)
1285         pop     %ebx
1286 #endif
1287         ret     
1288         SET_SIZE(wait_500ms)
1289 
1290 #define RESET_METHOD_KBC        1
1291 #define RESET_METHOD_PORT92     2
1292 #define RESET_METHOD_PCI        4
1293 
1294         DGDEF3(pc_reset_methods, 4, 8)
1295         .long RESET_METHOD_KBC|RESET_METHOD_PORT92|RESET_METHOD_PCI;
1296 
1297         ENTRY(pc_reset)
1298 
1299 #if defined(__i386)
1300         testl   $RESET_METHOD_KBC, pc_reset_methods
1301 #elif defined(__amd64)
1302         testl   $RESET_METHOD_KBC, pc_reset_methods(%rip)
1303 #endif
1304         jz      1f
1305 
1306         /
1307         / Try the classic keyboard controller-triggered reset.
1308         /
1309         movw    $0x64, %dx
1310         movb    $0xfe, %al
1311         outb    (%dx)
1312 
1313         / Wait up to 500 milliseconds here for the keyboard controller
1314         / to pull the reset line.  On some systems where the keyboard
1315         / controller is slow to pull the reset line, the next reset method
1316         / may be executed (which may be bad if those systems hang when the
1317         / next reset method is used, e.g. Ferrari 3400 (doesn't like port 92),
1318         / and Ferrari 4000 (doesn't like the cf9 reset method))
1319 
1320         call    wait_500ms
1321 
1322 1:
1323 #if defined(__i386)
1324         testl   $RESET_METHOD_PORT92, pc_reset_methods
1325 #elif defined(__amd64)
1326         testl   $RESET_METHOD_PORT92, pc_reset_methods(%rip)
1327 #endif
1328         jz      3f
1329 
1330         /
1331         / Try port 0x92 fast reset
1332         /
1333         movw    $0x92, %dx
1334         inb     (%dx)
1335         cmpb    $0xff, %al      / If port's not there, we should get back 0xFF
1336         je      1f
1337         testb   $1, %al         / If bit 0
1338         jz      2f              / is clear, jump to perform the reset
1339         andb    $0xfe, %al      / otherwise,
1340         outb    (%dx)           / clear bit 0 first, then
1341 2:
1342         orb     $1, %al         / Set bit 0
1343         outb    (%dx)           / and reset the system
1344 1:
1345 
1346         call    wait_500ms
1347 
1348 3:
1349 #if defined(__i386)
1350         testl   $RESET_METHOD_PCI, pc_reset_methods
1351 #elif defined(__amd64)
1352         testl   $RESET_METHOD_PCI, pc_reset_methods(%rip)
1353 #endif
1354         jz      4f
1355 
1356         / Try the PCI (soft) reset vector (should work on all modern systems,
1357         / but has been shown to cause problems on 450NX systems, and some newer
1358         / systems (e.g. ATI IXP400-equipped systems))
1359         / When resetting via this method, 2 writes are required.  The first
1360         / targets bit 1 (0=hard reset without power cycle, 1=hard reset with
1361         / power cycle).
1362         / The reset occurs on the second write, during bit 2's transition from
1363         / 0->1.
1364         movw    $0xcf9, %dx
1365         movb    $0x2, %al       / Reset mode = hard, no power cycle
1366         outb    (%dx)
1367         movb    $0x6, %al
1368         outb    (%dx)
1369 
1370         call    wait_500ms
1371 
1372 4:
1373         /
1374         / port 0xcf9 failed also.  Last-ditch effort is to
1375         / triple-fault the CPU.
1376         / Also, use triple fault for EFI firmware
1377         /
1378         ENTRY(efi_reset)
1379 #if defined(__amd64)
1380         pushq   $0x0
1381         pushq   $0x0            / IDT base of 0, limit of 0 + 2 unused bytes
1382         lidt    (%rsp)
1383 #elif defined(__i386)
1384         pushl   $0x0
1385         pushl   $0x0            / IDT base of 0, limit of 0 + 2 unused bytes
1386         lidt    (%esp)
1387 #endif
1388         int     $0x0            / Trigger interrupt, generate triple-fault
1389 
1390         cli
1391         hlt                     / Wait forever
1392         /*NOTREACHED*/
1393         SET_SIZE(efi_reset)
1394         SET_SIZE(pc_reset)
1395 
1396 #endif  /* __lint */
1397 
1398 /*
1399  * C callable in and out routines
1400  */
1401 
1402 #if defined(__lint)
1403 
1404 /* ARGSUSED */
1405 void
1406 outl(int port_address, uint32_t val)
1407 {}
1408 
1409 #else   /* __lint */
1410 
1411 #if defined(__amd64)
1412 
1413         ENTRY(outl)
1414         movw    %di, %dx
1415         movl    %esi, %eax
1416         outl    (%dx)
1417         ret
1418         SET_SIZE(outl)
1419 
1420 #elif defined(__i386)
1421 
1422         .set    PORT, 4
1423         .set    VAL, 8
1424 
1425         ENTRY(outl)
1426         movw    PORT(%esp), %dx
1427         movl    VAL(%esp), %eax
1428         outl    (%dx)
1429         ret
1430         SET_SIZE(outl)
1431 
1432 #endif  /* __i386 */
1433 #endif  /* __lint */
1434 
1435 #if defined(__lint)
1436 
1437 /* ARGSUSED */
1438 void
1439 outw(int port_address, uint16_t val)
1440 {}
1441 
1442 #else   /* __lint */
1443 
1444 #if defined(__amd64)
1445 
1446         ENTRY(outw)
1447         movw    %di, %dx
1448         movw    %si, %ax
1449         D16 outl (%dx)          /* XX64 why not outw? */
1450         ret
1451         SET_SIZE(outw)
1452 
1453 #elif defined(__i386)
1454 
1455         ENTRY(outw)
1456         movw    PORT(%esp), %dx
1457         movw    VAL(%esp), %ax
1458         D16 outl (%dx)
1459         ret
1460         SET_SIZE(outw)
1461 
1462 #endif  /* __i386 */
1463 #endif  /* __lint */
1464 
1465 #if defined(__lint)
1466 
1467 /* ARGSUSED */
1468 void
1469 outb(int port_address, uint8_t val)
1470 {}
1471 
1472 #else   /* __lint */
1473 
1474 #if defined(__amd64)
1475 
1476         ENTRY(outb)
1477         movw    %di, %dx
1478         movb    %sil, %al
1479         outb    (%dx)
1480         ret
1481         SET_SIZE(outb)
1482 
1483 #elif defined(__i386)
1484 
1485         ENTRY(outb)
1486         movw    PORT(%esp), %dx
1487         movb    VAL(%esp), %al
1488         outb    (%dx)
1489         ret
1490         SET_SIZE(outb)
1491 
1492 #endif  /* __i386 */
1493 #endif  /* __lint */
1494 
1495 #if defined(__lint)
1496 
1497 /* ARGSUSED */
1498 uint32_t
1499 inl(int port_address)
1500 { return (0); }
1501 
1502 #else   /* __lint */
1503 
1504 #if defined(__amd64)
1505 
1506         ENTRY(inl)
1507         xorl    %eax, %eax
1508         movw    %di, %dx
1509         inl     (%dx)
1510         ret
1511         SET_SIZE(inl)
1512 
1513 #elif defined(__i386)
1514 
1515         ENTRY(inl)
1516         movw    PORT(%esp), %dx
1517         inl     (%dx)
1518         ret
1519         SET_SIZE(inl)
1520 
1521 #endif  /* __i386 */
1522 #endif  /* __lint */
1523 
1524 #if defined(__lint)
1525 
1526 /* ARGSUSED */
1527 uint16_t
1528 inw(int port_address)
1529 { return (0); }
1530 
1531 #else   /* __lint */
1532 
1533 #if defined(__amd64)
1534 
1535         ENTRY(inw)
1536         xorl    %eax, %eax
1537         movw    %di, %dx
1538         D16 inl (%dx)
1539         ret
1540         SET_SIZE(inw)
1541 
1542 #elif defined(__i386)
1543 
1544         ENTRY(inw)
1545         subl    %eax, %eax
1546         movw    PORT(%esp), %dx
1547         D16 inl (%dx)
1548         ret
1549         SET_SIZE(inw)
1550 
1551 #endif  /* __i386 */
1552 #endif  /* __lint */
1553 
1554 
1555 #if defined(__lint)
1556 
1557 /* ARGSUSED */
1558 uint8_t
1559 inb(int port_address)
1560 { return (0); }
1561 
1562 #else   /* __lint */
1563 
1564 #if defined(__amd64)
1565 
1566         ENTRY(inb)
1567         xorl    %eax, %eax
1568         movw    %di, %dx
1569         inb     (%dx)
1570         ret
1571         SET_SIZE(inb)
1572 
1573 #elif defined(__i386)
1574 
1575         ENTRY(inb)
1576         subl    %eax, %eax
1577         movw    PORT(%esp), %dx
1578         inb     (%dx)
1579         ret
1580         SET_SIZE(inb)
1581 
1582 #endif  /* __i386 */
1583 #endif  /* __lint */
1584 
1585 
1586 #if defined(__lint)
1587 
1588 /* ARGSUSED */
1589 void
1590 repoutsw(int port, uint16_t *addr, int cnt)
1591 {}
1592 
1593 #else   /* __lint */
1594 
1595 #if defined(__amd64)
1596 
1597         ENTRY(repoutsw)
1598         movl    %edx, %ecx
1599         movw    %di, %dx
1600         rep
1601           D16 outsl
1602         ret
1603         SET_SIZE(repoutsw)
1604 
1605 #elif defined(__i386)
1606 
1607         /*
1608          * The arguments and saved registers are on the stack in the
1609          *  following order:
1610          *      |  cnt  |  +16
1611          *      | *addr |  +12
1612          *      | port  |  +8
1613          *      |  eip  |  +4
1614          *      |  esi  |  <-- %esp
1615          * If additional values are pushed onto the stack, make sure
1616          * to adjust the following constants accordingly.
1617          */
1618         .set    PORT, 8
1619         .set    ADDR, 12
1620         .set    COUNT, 16
1621 
1622         ENTRY(repoutsw)
1623         pushl   %esi
1624         movl    PORT(%esp), %edx
1625         movl    ADDR(%esp), %esi
1626         movl    COUNT(%esp), %ecx
1627         rep
1628           D16 outsl
1629         popl    %esi
1630         ret
1631         SET_SIZE(repoutsw)
1632 
1633 #endif  /* __i386 */
1634 #endif  /* __lint */
1635 
1636 
1637 #if defined(__lint)
1638 
1639 /* ARGSUSED */
1640 void
1641 repinsw(int port_addr, uint16_t *addr, int cnt)
1642 {}
1643 
1644 #else   /* __lint */
1645 
1646 #if defined(__amd64)
1647 
1648         ENTRY(repinsw)
1649         movl    %edx, %ecx
1650         movw    %di, %dx
1651         rep
1652           D16 insl
1653         ret
1654         SET_SIZE(repinsw)
1655 
1656 #elif defined(__i386)
1657 
1658         ENTRY(repinsw)
1659         pushl   %edi
1660         movl    PORT(%esp), %edx
1661         movl    ADDR(%esp), %edi
1662         movl    COUNT(%esp), %ecx
1663         rep
1664           D16 insl
1665         popl    %edi
1666         ret
1667         SET_SIZE(repinsw)
1668 
1669 #endif  /* __i386 */
1670 #endif  /* __lint */
1671 
1672 
1673 #if defined(__lint)
1674 
1675 /* ARGSUSED */
1676 void
1677 repinsb(int port, uint8_t *addr, int count)
1678 {}
1679 
1680 #else   /* __lint */
1681 
1682 #if defined(__amd64)
1683 
1684         ENTRY(repinsb)
1685         movl    %edx, %ecx      
1686         movw    %di, %dx
1687         movq    %rsi, %rdi
1688         rep
1689           insb
1690         ret             
1691         SET_SIZE(repinsb)
1692 
1693 #elif defined(__i386)
1694         
1695         /*
1696          * The arguments and saved registers are on the stack in the
1697          *  following order:
1698          *      |  cnt  |  +16
1699          *      | *addr |  +12
1700          *      | port  |  +8
1701          *      |  eip  |  +4
1702          *      |  esi  |  <-- %esp
1703          * If additional values are pushed onto the stack, make sure
1704          * to adjust the following constants accordingly.
1705          */
1706         .set    IO_PORT, 8
1707         .set    IO_ADDR, 12
1708         .set    IO_COUNT, 16
1709 
1710         ENTRY(repinsb)
1711         pushl   %edi
1712         movl    IO_ADDR(%esp), %edi
1713         movl    IO_COUNT(%esp), %ecx
1714         movl    IO_PORT(%esp), %edx
1715         rep
1716           insb
1717         popl    %edi
1718         ret
1719         SET_SIZE(repinsb)
1720 
1721 #endif  /* __i386 */
1722 #endif  /* __lint */
1723 
1724 
1725 /*
1726  * Input a stream of 32-bit words.
1727  * NOTE: count is a DWORD count.
1728  */
1729 #if defined(__lint)
1730 
1731 /* ARGSUSED */
1732 void
1733 repinsd(int port, uint32_t *addr, int count)
1734 {}
1735 
1736 #else   /* __lint */
1737 
1738 #if defined(__amd64)
1739         
1740         ENTRY(repinsd)
1741         movl    %edx, %ecx
1742         movw    %di, %dx
1743         movq    %rsi, %rdi
1744         rep
1745           insl
1746         ret
1747         SET_SIZE(repinsd)
1748 
1749 #elif defined(__i386)
1750 
1751         ENTRY(repinsd)
1752         pushl   %edi
1753         movl    IO_ADDR(%esp), %edi
1754         movl    IO_COUNT(%esp), %ecx
1755         movl    IO_PORT(%esp), %edx
1756         rep
1757           insl
1758         popl    %edi
1759         ret
1760         SET_SIZE(repinsd)
1761 
1762 #endif  /* __i386 */
1763 #endif  /* __lint */
1764 
1765 /*
1766  * Output a stream of bytes
1767  * NOTE: count is a byte count
1768  */
1769 #if defined(__lint)
1770 
1771 /* ARGSUSED */
1772 void
1773 repoutsb(int port, uint8_t *addr, int count)
1774 {}
1775 
1776 #else   /* __lint */
1777 
1778 #if defined(__amd64)
1779 
1780         ENTRY(repoutsb)
1781         movl    %edx, %ecx
1782         movw    %di, %dx
1783         rep
1784           outsb
1785         ret     
1786         SET_SIZE(repoutsb)
1787 
1788 #elif defined(__i386)
1789 
1790         ENTRY(repoutsb)
1791         pushl   %esi
1792         movl    IO_ADDR(%esp), %esi
1793         movl    IO_COUNT(%esp), %ecx
1794         movl    IO_PORT(%esp), %edx
1795         rep
1796           outsb
1797         popl    %esi
1798         ret
1799         SET_SIZE(repoutsb)
1800 
1801 #endif  /* __i386 */    
1802 #endif  /* __lint */
1803 
1804 /*
1805  * Output a stream of 32-bit words
1806  * NOTE: count is a DWORD count
1807  */
1808 #if defined(__lint)
1809 
1810 /* ARGSUSED */
1811 void
1812 repoutsd(int port, uint32_t *addr, int count)
1813 {}
1814 
1815 #else   /* __lint */
1816 
1817 #if defined(__amd64)
1818 
1819         ENTRY(repoutsd)
1820         movl    %edx, %ecx
1821         movw    %di, %dx
1822         rep
1823           outsl
1824         ret     
1825         SET_SIZE(repoutsd)
1826 
1827 #elif defined(__i386)
1828 
1829         ENTRY(repoutsd)
1830         pushl   %esi
1831         movl    IO_ADDR(%esp), %esi
1832         movl    IO_COUNT(%esp), %ecx
1833         movl    IO_PORT(%esp), %edx
1834         rep
1835           outsl
1836         popl    %esi
1837         ret
1838         SET_SIZE(repoutsd)
1839 
1840 #endif  /* __i386 */
1841 #endif  /* __lint */
1842 
1843 /*
1844  * void int3(void)
1845  * void int18(void)
1846  * void int20(void)
1847  * void int_cmci(void)
1848  */
1849 
1850 #if defined(__lint)
1851 
1852 void
1853 int3(void)
1854 {}
1855 
1856 void
1857 int18(void)
1858 {}
1859 
1860 void
1861 int20(void)
1862 {}
1863 
1864 void
1865 int_cmci(void)
1866 {}
1867 
1868 #else   /* __lint */
1869 
1870         ENTRY(int3)
1871         int     $T_BPTFLT
1872         ret
1873         SET_SIZE(int3)
1874 
1875         ENTRY(int18)
1876         int     $T_MCE
1877         ret
1878         SET_SIZE(int18)
1879 
1880         ENTRY(int20)
1881         movl    boothowto, %eax
1882         andl    $RB_DEBUG, %eax
1883         jz      1f
1884 
1885         int     $T_DBGENTR
1886 1:
1887         rep;    ret     /* use 2 byte return instruction when branch target */
1888                         /* AMD Software Optimization Guide - Section 6.2 */
1889         SET_SIZE(int20)
1890 
1891         ENTRY(int_cmci)
1892         int     $T_ENOEXTFLT
1893         ret
1894         SET_SIZE(int_cmci)
1895 
1896 #endif  /* __lint */
1897 
1898 #if defined(__lint)
1899 
1900 /* ARGSUSED */
1901 int
1902 scanc(size_t size, uchar_t *cp, uchar_t *table, uchar_t mask)
1903 { return (0); }
1904 
1905 #else   /* __lint */
1906 
1907 #if defined(__amd64)
1908 
1909         ENTRY(scanc)
1910                                         /* rdi == size */
1911                                         /* rsi == cp */
1912                                         /* rdx == table */
1913                                         /* rcx == mask */
1914         addq    %rsi, %rdi              /* end = &cp[size] */
1915 .scanloop:
1916         cmpq    %rdi, %rsi              /* while (cp < end */
1917         jnb     .scandone
1918         movzbq  (%rsi), %r8             /* %r8 = *cp */
1919         incq    %rsi                    /* cp++ */
1920         testb   %cl, (%r8, %rdx)
1921         jz      .scanloop               /*  && (table[*cp] & mask) == 0) */
1922         decq    %rsi                    /* (fix post-increment) */
1923 .scandone:
1924         movl    %edi, %eax
1925         subl    %esi, %eax              /* return (end - cp) */
1926         ret
1927         SET_SIZE(scanc)
1928 
1929 #elif defined(__i386)
1930 
1931         ENTRY(scanc)
1932         pushl   %edi
1933         pushl   %esi
1934         movb    24(%esp), %cl           /* mask = %cl */
1935         movl    16(%esp), %esi          /* cp = %esi */
1936         movl    20(%esp), %edx          /* table = %edx */
1937         movl    %esi, %edi
1938         addl    12(%esp), %edi          /* end = &cp[size]; */
1939 .scanloop:
1940         cmpl    %edi, %esi              /* while (cp < end */
1941         jnb     .scandone
1942         movzbl  (%esi),  %eax           /* %al = *cp */
1943         incl    %esi                    /* cp++ */
1944         movb    (%edx,  %eax), %al      /* %al = table[*cp] */
1945         testb   %al, %cl
1946         jz      .scanloop               /*   && (table[*cp] & mask) == 0) */
1947         dec     %esi                    /* post-incremented */
1948 .scandone:
1949         movl    %edi, %eax
1950         subl    %esi, %eax              /* return (end - cp) */
1951         popl    %esi
1952         popl    %edi
1953         ret
1954         SET_SIZE(scanc)
1955 
1956 #endif  /* __i386 */
1957 #endif  /* __lint */
1958 
1959 /*
1960  * Replacement functions for ones that are normally inlined.
1961  * In addition to the copy in i86.il, they are defined here just in case.
1962  */
1963 
1964 #if defined(__lint)
1965 
1966 ulong_t
1967 intr_clear(void)
1968 { return (0); }
1969 
1970 ulong_t
1971 clear_int_flag(void)
1972 { return (0); }
1973 
1974 #else   /* __lint */
1975 
1976 #if defined(__amd64)
1977 
1978         ENTRY(intr_clear)
1979         ENTRY(clear_int_flag)
1980         pushfq
1981         popq    %rax
1982 #if defined(__xpv)
1983         leaq    xpv_panicking, %rdi
1984         movl    (%rdi), %edi
1985         cmpl    $0, %edi
1986         jne     2f
1987         CLIRET(%rdi, %dl)       /* returns event mask in %dl */
1988         /*
1989          * Synthesize the PS_IE bit from the event mask bit
1990          */
1991         andq    $_BITNOT(PS_IE), %rax
1992         testb   $1, %dl
1993         jnz     1f
1994         orq     $PS_IE, %rax
1995 1:
1996         ret
1997 2:
1998 #endif
1999         CLI(%rdi)
2000         ret
2001         SET_SIZE(clear_int_flag)
2002         SET_SIZE(intr_clear)
2003 
2004 #elif defined(__i386)
2005 
2006         ENTRY(intr_clear)
2007         ENTRY(clear_int_flag)
2008         pushfl
2009         popl    %eax
2010 #if defined(__xpv)
2011         leal    xpv_panicking, %edx
2012         movl    (%edx), %edx
2013         cmpl    $0, %edx
2014         jne     2f
2015         CLIRET(%edx, %cl)       /* returns event mask in %cl */
2016         /*
2017          * Synthesize the PS_IE bit from the event mask bit
2018          */
2019         andl    $_BITNOT(PS_IE), %eax
2020         testb   $1, %cl
2021         jnz     1f
2022         orl     $PS_IE, %eax
2023 1:
2024         ret
2025 2:
2026 #endif
2027         CLI(%edx)
2028         ret
2029         SET_SIZE(clear_int_flag)
2030         SET_SIZE(intr_clear)
2031 
2032 #endif  /* __i386 */
2033 #endif  /* __lint */
2034 
2035 #if defined(__lint)
2036 
2037 struct cpu *
2038 curcpup(void)
2039 { return 0; }
2040 
2041 #else   /* __lint */
2042 
2043 #if defined(__amd64)
2044 
2045         ENTRY(curcpup)
2046         movq    %gs:CPU_SELF, %rax
2047         ret
2048         SET_SIZE(curcpup)
2049 
2050 #elif defined(__i386)
2051 
2052         ENTRY(curcpup)
2053         movl    %gs:CPU_SELF, %eax
2054         ret
2055         SET_SIZE(curcpup)
2056 
2057 #endif  /* __i386 */
2058 #endif  /* __lint */
2059 
2060 /* htonll(), ntohll(), htonl(), ntohl(), htons(), ntohs()
2061  * These functions reverse the byte order of the input parameter and returns
2062  * the result.  This is to convert the byte order from host byte order
2063  * (little endian) to network byte order (big endian), or vice versa.
2064  */
2065 
2066 #if defined(__lint)
2067 
2068 uint64_t
2069 htonll(uint64_t i)
2070 { return (i); }
2071 
2072 uint64_t
2073 ntohll(uint64_t i)
2074 { return (i); }
2075 
2076 uint32_t
2077 htonl(uint32_t i)
2078 { return (i); }
2079 
2080 uint32_t
2081 ntohl(uint32_t i)
2082 { return (i); }
2083 
2084 uint16_t
2085 htons(uint16_t i)
2086 { return (i); }
2087 
2088 uint16_t
2089 ntohs(uint16_t i)
2090 { return (i); }
2091 
2092 #else   /* __lint */
2093 
2094 #if defined(__amd64)
2095 
2096         ENTRY(htonll)
2097         ALTENTRY(ntohll)
2098         movq    %rdi, %rax
2099         bswapq  %rax
2100         ret
2101         SET_SIZE(ntohll)
2102         SET_SIZE(htonll)
2103 
2104         /* XX64 there must be shorter sequences for this */
2105         ENTRY(htonl)
2106         ALTENTRY(ntohl)
2107         movl    %edi, %eax
2108         bswap   %eax
2109         ret
2110         SET_SIZE(ntohl)
2111         SET_SIZE(htonl)
2112 
2113         /* XX64 there must be better sequences for this */
2114         ENTRY(htons)
2115         ALTENTRY(ntohs)
2116         movl    %edi, %eax
2117         bswap   %eax
2118         shrl    $16, %eax
2119         ret
2120         SET_SIZE(ntohs)
2121         SET_SIZE(htons)
2122 
2123 #elif defined(__i386)
2124 
2125         ENTRY(htonll)
2126         ALTENTRY(ntohll)
2127         movl    4(%esp), %edx
2128         movl    8(%esp), %eax
2129         bswap   %edx
2130         bswap   %eax
2131         ret
2132         SET_SIZE(ntohll)
2133         SET_SIZE(htonll)
2134 
2135         ENTRY(htonl)
2136         ALTENTRY(ntohl)
2137         movl    4(%esp), %eax
2138         bswap   %eax
2139         ret
2140         SET_SIZE(ntohl)
2141         SET_SIZE(htonl)
2142 
2143         ENTRY(htons)
2144         ALTENTRY(ntohs)
2145         movl    4(%esp), %eax
2146         bswap   %eax
2147         shrl    $16, %eax
2148         ret
2149         SET_SIZE(ntohs)
2150         SET_SIZE(htons)
2151 
2152 #endif  /* __i386 */
2153 #endif  /* __lint */
2154 
2155 
2156 #if defined(__lint)
2157 
2158 /* ARGSUSED */
2159 void
2160 intr_restore(ulong_t i)
2161 { return; }
2162 
2163 /* ARGSUSED */
2164 void
2165 restore_int_flag(ulong_t i)
2166 { return; }
2167 
2168 #else   /* __lint */
2169 
2170 #if defined(__amd64)
2171 
2172         ENTRY(intr_restore)
2173         ENTRY(restore_int_flag)
2174         testq   $PS_IE, %rdi
2175         jz      1f
2176 #if defined(__xpv)
2177         leaq    xpv_panicking, %rsi
2178         movl    (%rsi), %esi
2179         cmpl    $0, %esi
2180         jne     1f
2181         /*
2182          * Since we're -really- running unprivileged, our attempt
2183          * to change the state of the IF bit will be ignored.
2184          * The virtual IF bit is tweaked by CLI and STI.
2185          */
2186         IE_TO_EVENT_MASK(%rsi, %rdi)
2187 #else
2188         sti
2189 #endif
2190 1:
2191         ret
2192         SET_SIZE(restore_int_flag)
2193         SET_SIZE(intr_restore)
2194 
2195 #elif defined(__i386)
2196 
2197         ENTRY(intr_restore)
2198         ENTRY(restore_int_flag)
2199         testl   $PS_IE, 4(%esp)
2200         jz      1f
2201 #if defined(__xpv)
2202         leal    xpv_panicking, %edx
2203         movl    (%edx), %edx
2204         cmpl    $0, %edx
2205         jne     1f
2206         /*
2207          * Since we're -really- running unprivileged, our attempt
2208          * to change the state of the IF bit will be ignored.
2209          * The virtual IF bit is tweaked by CLI and STI.
2210          */
2211         IE_TO_EVENT_MASK(%edx, 4(%esp))
2212 #else
2213         sti
2214 #endif
2215 1:
2216         ret
2217         SET_SIZE(restore_int_flag)
2218         SET_SIZE(intr_restore)
2219 
2220 #endif  /* __i386 */
2221 #endif  /* __lint */
2222 
2223 #if defined(__lint)
2224 
2225 void
2226 sti(void)
2227 {}
2228 
2229 void
2230 cli(void)
2231 {}
2232 
2233 #else   /* __lint */
2234 
2235         ENTRY(sti)
2236         STI
2237         ret
2238         SET_SIZE(sti)
2239 
2240         ENTRY(cli)
2241 #if defined(__amd64)
2242         CLI(%rax)
2243 #elif defined(__i386)
2244         CLI(%eax)
2245 #endif  /* __i386 */
2246         ret
2247         SET_SIZE(cli)
2248 
2249 #endif  /* __lint */
2250 
2251 #if defined(__lint)
2252 
2253 dtrace_icookie_t
2254 dtrace_interrupt_disable(void)
2255 { return (0); }
2256 
2257 #else   /* __lint */
2258 
2259 #if defined(__amd64)
2260 
2261         ENTRY(dtrace_interrupt_disable)
2262         pushfq
2263         popq    %rax
2264 #if defined(__xpv)
2265         leaq    xpv_panicking, %rdi
2266         movl    (%rdi), %edi
2267         cmpl    $0, %edi
2268         jne     .dtrace_interrupt_disable_done
2269         CLIRET(%rdi, %dl)       /* returns event mask in %dl */
2270         /*
2271          * Synthesize the PS_IE bit from the event mask bit
2272          */
2273         andq    $_BITNOT(PS_IE), %rax
2274         testb   $1, %dl
2275         jnz     .dtrace_interrupt_disable_done
2276         orq     $PS_IE, %rax
2277 #else
2278         CLI(%rdx)
2279 #endif
2280 .dtrace_interrupt_disable_done:
2281         ret
2282         SET_SIZE(dtrace_interrupt_disable)
2283 
2284 #elif defined(__i386)
2285                 
2286         ENTRY(dtrace_interrupt_disable)
2287         pushfl
2288         popl    %eax
2289 #if defined(__xpv)
2290         leal    xpv_panicking, %edx
2291         movl    (%edx), %edx
2292         cmpl    $0, %edx
2293         jne     .dtrace_interrupt_disable_done
2294         CLIRET(%edx, %cl)       /* returns event mask in %cl */
2295         /*
2296          * Synthesize the PS_IE bit from the event mask bit
2297          */
2298         andl    $_BITNOT(PS_IE), %eax
2299         testb   $1, %cl
2300         jnz     .dtrace_interrupt_disable_done
2301         orl     $PS_IE, %eax
2302 #else
2303         CLI(%edx)
2304 #endif
2305 .dtrace_interrupt_disable_done:
2306         ret
2307         SET_SIZE(dtrace_interrupt_disable)
2308 
2309 #endif  /* __i386 */    
2310 #endif  /* __lint */
2311 
2312 #if defined(__lint)
2313 
2314 /*ARGSUSED*/
2315 void
2316 dtrace_interrupt_enable(dtrace_icookie_t cookie)
2317 {}
2318 
2319 #else   /* __lint */
2320 
2321 #if defined(__amd64)
2322 
2323         ENTRY(dtrace_interrupt_enable)
2324         pushq   %rdi
2325         popfq
2326 #if defined(__xpv)
2327         leaq    xpv_panicking, %rdx
2328         movl    (%rdx), %edx
2329         cmpl    $0, %edx
2330         jne     .dtrace_interrupt_enable_done
2331         /*
2332          * Since we're -really- running unprivileged, our attempt
2333          * to change the state of the IF bit will be ignored. The
2334          * virtual IF bit is tweaked by CLI and STI.
2335          */
2336         IE_TO_EVENT_MASK(%rdx, %rdi)
2337 #endif
2338 .dtrace_interrupt_enable_done:
2339         ret
2340         SET_SIZE(dtrace_interrupt_enable)
2341 
2342 #elif defined(__i386)
2343                 
2344         ENTRY(dtrace_interrupt_enable)
2345         movl    4(%esp), %eax
2346         pushl   %eax
2347         popfl
2348 #if defined(__xpv)
2349         leal    xpv_panicking, %edx
2350         movl    (%edx), %edx
2351         cmpl    $0, %edx
2352         jne     .dtrace_interrupt_enable_done
2353         /*
2354          * Since we're -really- running unprivileged, our attempt
2355          * to change the state of the IF bit will be ignored. The
2356          * virtual IF bit is tweaked by CLI and STI.
2357          */
2358         IE_TO_EVENT_MASK(%edx, %eax)
2359 #endif
2360 .dtrace_interrupt_enable_done:
2361         ret
2362         SET_SIZE(dtrace_interrupt_enable)
2363 
2364 #endif  /* __i386 */    
2365 #endif  /* __lint */
2366 
2367 
2368 #if defined(lint)
2369 
2370 void
2371 dtrace_membar_producer(void)
2372 {}
2373 
2374 void
2375 dtrace_membar_consumer(void)
2376 {}
2377 
2378 #else   /* __lint */
2379 
2380         ENTRY(dtrace_membar_producer)
2381         rep;    ret     /* use 2 byte return instruction when branch target */
2382                         /* AMD Software Optimization Guide - Section 6.2 */
2383         SET_SIZE(dtrace_membar_producer)
2384 
2385         ENTRY(dtrace_membar_consumer)
2386         rep;    ret     /* use 2 byte return instruction when branch target */
2387                         /* AMD Software Optimization Guide - Section 6.2 */
2388         SET_SIZE(dtrace_membar_consumer)
2389 
2390 #endif  /* __lint */
2391 
2392 #if defined(__lint)
2393 
2394 kthread_id_t
2395 threadp(void)
2396 { return ((kthread_id_t)0); }
2397 
2398 #else   /* __lint */
2399 
2400 #if defined(__amd64)
2401         
2402         ENTRY(threadp)
2403         movq    %gs:CPU_THREAD, %rax
2404         ret
2405         SET_SIZE(threadp)
2406 
2407 #elif defined(__i386)
2408 
2409         ENTRY(threadp)
2410         movl    %gs:CPU_THREAD, %eax
2411         ret
2412         SET_SIZE(threadp)
2413 
2414 #endif  /* __i386 */
2415 #endif  /* __lint */
2416 
2417 /*
2418  *   Checksum routine for Internet Protocol Headers
2419  */
2420 
2421 #if defined(__lint)
2422 
2423 /* ARGSUSED */
2424 unsigned int
2425 ip_ocsum(
2426         ushort_t *address,      /* ptr to 1st message buffer */
2427         int halfword_count,     /* length of data */
2428         unsigned int sum)       /* partial checksum */
2429 { 
2430         int             i;
2431         unsigned int    psum = 0;       /* partial sum */
2432 
2433         for (i = 0; i < halfword_count; i++, address++) {
2434                 psum += *address;
2435         }
2436 
2437         while ((psum >> 16) != 0) {
2438                 psum = (psum & 0xffff) + (psum >> 16);
2439         }
2440 
2441         psum += sum;
2442 
2443         while ((psum >> 16) != 0) {
2444                 psum = (psum & 0xffff) + (psum >> 16);
2445         }
2446 
2447         return (psum);
2448 }
2449 
2450 #else   /* __lint */
2451 
2452 #if defined(__amd64)
2453 
2454         ENTRY(ip_ocsum)
2455         pushq   %rbp
2456         movq    %rsp, %rbp
2457 #ifdef DEBUG
2458         movq    postbootkernelbase(%rip), %rax
2459         cmpq    %rax, %rdi
2460         jnb     1f
2461         xorl    %eax, %eax
2462         movq    %rdi, %rsi
2463         leaq    .ip_ocsum_panic_msg(%rip), %rdi
2464         call    panic
2465         /*NOTREACHED*/
2466 .ip_ocsum_panic_msg:
2467         .string "ip_ocsum: address 0x%p below kernelbase\n"
2468 1:
2469 #endif
2470         movl    %esi, %ecx      /* halfword_count */
2471         movq    %rdi, %rsi      /* address */
2472                                 /* partial sum in %edx */
2473         xorl    %eax, %eax
2474         testl   %ecx, %ecx
2475         jz      .ip_ocsum_done
2476         testq   $3, %rsi
2477         jnz     .ip_csum_notaligned
2478 .ip_csum_aligned:       /* XX64 opportunities for 8-byte operations? */
2479 .next_iter:
2480         /* XX64 opportunities for prefetch? */
2481         /* XX64 compute csum with 64 bit quantities? */
2482         subl    $32, %ecx
2483         jl      .less_than_32
2484 
2485         addl    0(%rsi), %edx
2486 .only60:
2487         adcl    4(%rsi), %eax
2488 .only56:
2489         adcl    8(%rsi), %edx
2490 .only52:
2491         adcl    12(%rsi), %eax
2492 .only48:
2493         adcl    16(%rsi), %edx
2494 .only44:
2495         adcl    20(%rsi), %eax
2496 .only40:
2497         adcl    24(%rsi), %edx
2498 .only36:
2499         adcl    28(%rsi), %eax
2500 .only32:
2501         adcl    32(%rsi), %edx
2502 .only28:
2503         adcl    36(%rsi), %eax
2504 .only24:
2505         adcl    40(%rsi), %edx
2506 .only20:
2507         adcl    44(%rsi), %eax
2508 .only16:
2509         adcl    48(%rsi), %edx
2510 .only12:
2511         adcl    52(%rsi), %eax
2512 .only8:
2513         adcl    56(%rsi), %edx
2514 .only4:
2515         adcl    60(%rsi), %eax  /* could be adding -1 and -1 with a carry */
2516 .only0:
2517         adcl    $0, %eax        /* could be adding -1 in eax with a carry */
2518         adcl    $0, %eax
2519 
2520         addq    $64, %rsi
2521         testl   %ecx, %ecx
2522         jnz     .next_iter
2523 
2524 .ip_ocsum_done:
2525         addl    %eax, %edx
2526         adcl    $0, %edx
2527         movl    %edx, %eax      /* form a 16 bit checksum by */
2528         shrl    $16, %eax       /* adding two halves of 32 bit checksum */
2529         addw    %dx, %ax
2530         adcw    $0, %ax
2531         andl    $0xffff, %eax
2532         leave
2533         ret
2534 
2535 .ip_csum_notaligned:
2536         xorl    %edi, %edi
2537         movw    (%rsi), %di
2538         addl    %edi, %edx
2539         adcl    $0, %edx
2540         addq    $2, %rsi
2541         decl    %ecx
2542         jmp     .ip_csum_aligned
2543 
2544 .less_than_32:
2545         addl    $32, %ecx
2546         testl   $1, %ecx
2547         jz      .size_aligned
2548         andl    $0xfe, %ecx
2549         movzwl  (%rsi, %rcx, 2), %edi
2550         addl    %edi, %edx
2551         adcl    $0, %edx
2552 .size_aligned:
2553         movl    %ecx, %edi
2554         shrl    $1, %ecx
2555         shl     $1, %edi
2556         subq    $64, %rdi
2557         addq    %rdi, %rsi
2558         leaq    .ip_ocsum_jmptbl(%rip), %rdi
2559         leaq    (%rdi, %rcx, 8), %rdi
2560         xorl    %ecx, %ecx
2561         clc
2562         jmp     *(%rdi)
2563 
2564         .align  8
2565 .ip_ocsum_jmptbl:
2566         .quad   .only0, .only4, .only8, .only12, .only16, .only20
2567         .quad   .only24, .only28, .only32, .only36, .only40, .only44
2568         .quad   .only48, .only52, .only56, .only60
2569         SET_SIZE(ip_ocsum)
2570 
2571 #elif defined(__i386)
2572 
2573         ENTRY(ip_ocsum)
2574         pushl   %ebp
2575         movl    %esp, %ebp
2576         pushl   %ebx
2577         pushl   %esi
2578         pushl   %edi
2579         movl    12(%ebp), %ecx  /* count of half words */
2580         movl    16(%ebp), %edx  /* partial checksum */
2581         movl    8(%ebp), %esi
2582         xorl    %eax, %eax
2583         testl   %ecx, %ecx
2584         jz      .ip_ocsum_done
2585 
2586         testl   $3, %esi
2587         jnz     .ip_csum_notaligned
2588 .ip_csum_aligned:
2589 .next_iter:
2590         subl    $32, %ecx
2591         jl      .less_than_32
2592 
2593         addl    0(%esi), %edx
2594 .only60:
2595         adcl    4(%esi), %eax
2596 .only56:
2597         adcl    8(%esi), %edx
2598 .only52:
2599         adcl    12(%esi), %eax
2600 .only48:
2601         adcl    16(%esi), %edx
2602 .only44:
2603         adcl    20(%esi), %eax
2604 .only40:
2605         adcl    24(%esi), %edx
2606 .only36:
2607         adcl    28(%esi), %eax
2608 .only32:
2609         adcl    32(%esi), %edx
2610 .only28:
2611         adcl    36(%esi), %eax
2612 .only24:
2613         adcl    40(%esi), %edx
2614 .only20:
2615         adcl    44(%esi), %eax
2616 .only16:
2617         adcl    48(%esi), %edx
2618 .only12:
2619         adcl    52(%esi), %eax
2620 .only8:
2621         adcl    56(%esi), %edx
2622 .only4:
2623         adcl    60(%esi), %eax  /* We could be adding -1 and -1 with a carry */
2624 .only0:
2625         adcl    $0, %eax        /* we could be adding -1 in eax with a carry */
2626         adcl    $0, %eax
2627 
2628         addl    $64, %esi
2629         andl    %ecx, %ecx
2630         jnz     .next_iter
2631 
2632 .ip_ocsum_done:
2633         addl    %eax, %edx
2634         adcl    $0, %edx
2635         movl    %edx, %eax      /* form a 16 bit checksum by */
2636         shrl    $16, %eax       /* adding two halves of 32 bit checksum */
2637         addw    %dx, %ax
2638         adcw    $0, %ax
2639         andl    $0xffff, %eax
2640         popl    %edi            /* restore registers */
2641         popl    %esi
2642         popl    %ebx
2643         leave
2644         ret
2645 
2646 .ip_csum_notaligned:
2647         xorl    %edi, %edi
2648         movw    (%esi), %di
2649         addl    %edi, %edx
2650         adcl    $0, %edx
2651         addl    $2, %esi
2652         decl    %ecx
2653         jmp     .ip_csum_aligned
2654 
2655 .less_than_32:
2656         addl    $32, %ecx
2657         testl   $1, %ecx
2658         jz      .size_aligned
2659         andl    $0xfe, %ecx
2660         movzwl  (%esi, %ecx, 2), %edi
2661         addl    %edi, %edx
2662         adcl    $0, %edx
2663 .size_aligned:
2664         movl    %ecx, %edi
2665         shrl    $1, %ecx
2666         shl     $1, %edi
2667         subl    $64, %edi
2668         addl    %edi, %esi
2669         movl    $.ip_ocsum_jmptbl, %edi
2670         lea     (%edi, %ecx, 4), %edi
2671         xorl    %ecx, %ecx
2672         clc
2673         jmp     *(%edi)
2674         SET_SIZE(ip_ocsum)
2675 
2676         .data
2677         .align  4
2678 
2679 .ip_ocsum_jmptbl:
2680         .long   .only0, .only4, .only8, .only12, .only16, .only20
2681         .long   .only24, .only28, .only32, .only36, .only40, .only44
2682         .long   .only48, .only52, .only56, .only60
2683 
2684         
2685 #endif  /* __i386 */            
2686 #endif  /* __lint */
2687 
2688 /*
2689  * multiply two long numbers and yield a u_longlong_t result, callable from C.
2690  * Provided to manipulate hrtime_t values.
2691  */
2692 #if defined(__lint)
2693 
2694 /* result = a * b; */
2695 
2696 /* ARGSUSED */
2697 unsigned long long
2698 mul32(uint_t a, uint_t b)
2699 { return (0); }
2700 
2701 #else   /* __lint */
2702 
2703 #if defined(__amd64)
2704 
2705         ENTRY(mul32)
2706         xorl    %edx, %edx      /* XX64 joe, paranoia? */
2707         movl    %edi, %eax
2708         mull    %esi
2709         shlq    $32, %rdx       
2710         orq     %rdx, %rax
2711         ret
2712         SET_SIZE(mul32)
2713 
2714 #elif defined(__i386)
2715 
2716         ENTRY(mul32)
2717         movl    8(%esp), %eax
2718         movl    4(%esp), %ecx
2719         mull    %ecx
2720         ret
2721         SET_SIZE(mul32)
2722 
2723 #endif  /* __i386 */
2724 #endif  /* __lint */
2725 
2726 #if defined(notused)
2727 #if defined(__lint)
2728 /* ARGSUSED */
2729 void
2730 load_pte64(uint64_t *pte, uint64_t pte_value)
2731 {}
2732 #else   /* __lint */
2733         .globl load_pte64
2734 load_pte64:
2735         movl    4(%esp), %eax
2736         movl    8(%esp), %ecx
2737         movl    12(%esp), %edx
2738         movl    %edx, 4(%eax)
2739         movl    %ecx, (%eax)
2740         ret
2741 #endif  /* __lint */
2742 #endif  /* notused */
2743 
2744 #if defined(__lint)
2745 
2746 /*ARGSUSED*/
2747 void
2748 scan_memory(caddr_t addr, size_t size)
2749 {}
2750 
2751 #else   /* __lint */
2752 
2753 #if defined(__amd64)
2754 
2755         ENTRY(scan_memory)
2756         shrq    $3, %rsi        /* convert %rsi from byte to quadword count */
2757         jz      .scanm_done
2758         movq    %rsi, %rcx      /* move count into rep control register */
2759         movq    %rdi, %rsi      /* move addr into lodsq control reg. */
2760         rep lodsq               /* scan the memory range */
2761 .scanm_done:
2762         rep;    ret     /* use 2 byte return instruction when branch target */
2763                         /* AMD Software Optimization Guide - Section 6.2 */
2764         SET_SIZE(scan_memory)
2765 
2766 #elif defined(__i386)
2767 
2768         ENTRY(scan_memory)
2769         pushl   %ecx
2770         pushl   %esi
2771         movl    16(%esp), %ecx  /* move 2nd arg into rep control register */
2772         shrl    $2, %ecx        /* convert from byte count to word count */
2773         jz      .scanm_done
2774         movl    12(%esp), %esi  /* move 1st arg into lodsw control register */
2775         .byte   0xf3            /* rep prefix.  lame assembler.  sigh. */
2776         lodsl
2777 .scanm_done:
2778         popl    %esi
2779         popl    %ecx
2780         ret
2781         SET_SIZE(scan_memory)
2782 
2783 #endif  /* __i386 */
2784 #endif  /* __lint */
2785 
2786 
2787 #if defined(__lint)
2788 
2789 /*ARGSUSED */
2790 int
2791 lowbit(ulong_t i)
2792 { return (0); }
2793 
2794 #else   /* __lint */
2795 
2796 #if defined(__amd64)
2797 
2798         ENTRY(lowbit)
2799         movl    $-1, %eax
2800         bsfq    %rdi, %rdi
2801         cmovnz  %edi, %eax
2802         incl    %eax
2803         ret
2804         SET_SIZE(lowbit)
2805 
2806 #elif defined(__i386)
2807 
2808         ENTRY(lowbit)
2809         bsfl    4(%esp), %eax
2810         jz      0f
2811         incl    %eax
2812         ret
2813 0:
2814         xorl    %eax, %eax
2815         ret
2816         SET_SIZE(lowbit)
2817 
2818 #endif  /* __i386 */
2819 #endif  /* __lint */
2820 
2821 #if defined(__lint)
2822 
2823 /*ARGSUSED*/
2824 int
2825 highbit(ulong_t i)
2826 { return (0); }
2827 
2828 /*ARGSUSED*/
2829 int
2830 highbit64(uint64_t i)
2831 { return (0); }
2832 
2833 #else   /* __lint */
2834 
2835 #if defined(__amd64)
2836 
2837         ENTRY(highbit)
2838         ALTENTRY(highbit64)
2839         movl    $-1, %eax
2840         bsrq    %rdi, %rdi
2841         cmovnz  %edi, %eax
2842         incl    %eax
2843         ret
2844         SET_SIZE(highbit64)
2845         SET_SIZE(highbit)
2846 
2847 #elif defined(__i386)
2848 
2849         ENTRY(highbit)
2850         bsrl    4(%esp), %eax
2851         jz      0f
2852         incl    %eax
2853         ret
2854 0:
2855         xorl    %eax, %eax
2856         ret    
2857         SET_SIZE(highbit)
2858 
2859         ENTRY(highbit64)
2860         bsrl    8(%esp), %eax
2861         jz      highbit
2862         addl    $33, %eax
2863         ret
2864         SET_SIZE(highbit64)
2865 
2866 #endif  /* __i386 */
2867 #endif  /* __lint */
2868 
2869 #if defined(__lint)
2870 
2871 /*ARGSUSED*/
2872 uint64_t
2873 rdmsr(uint_t r)
2874 { return (0); }
2875 
2876 /*ARGSUSED*/
2877 void
2878 wrmsr(uint_t r, const uint64_t val)
2879 {}
2880 
2881 /*ARGSUSED*/
2882 uint64_t
2883 xrdmsr(uint_t r)
2884 { return (0); }
2885 
2886 /*ARGSUSED*/
2887 void
2888 xwrmsr(uint_t r, const uint64_t val)
2889 {}
2890 
2891 void
2892 invalidate_cache(void)
2893 {}
2894 
2895 /*ARGSUSED*/
2896 uint64_t
2897 get_xcr(uint_t r)
2898 { return (0); }
2899 
2900 /*ARGSUSED*/
2901 void
2902 set_xcr(uint_t r, const uint64_t val)
2903 {}
2904 
2905 #else  /* __lint */
2906 
2907 #define XMSR_ACCESS_VAL         $0x9c5a203a
2908 
2909 #if defined(__amd64)
2910         
2911         ENTRY(rdmsr)
2912         movl    %edi, %ecx
2913         rdmsr
2914         shlq    $32, %rdx
2915         orq     %rdx, %rax
2916         ret
2917         SET_SIZE(rdmsr)
2918 
2919         ENTRY(wrmsr)
2920         movq    %rsi, %rdx
2921         shrq    $32, %rdx
2922         movl    %esi, %eax
2923         movl    %edi, %ecx
2924         wrmsr
2925         ret
2926         SET_SIZE(wrmsr)
2927 
2928         ENTRY(xrdmsr)
2929         pushq   %rbp
2930         movq    %rsp, %rbp
2931         movl    %edi, %ecx
2932         movl    XMSR_ACCESS_VAL, %edi   /* this value is needed to access MSR */
2933         rdmsr
2934         shlq    $32, %rdx
2935         orq     %rdx, %rax
2936         leave
2937         ret
2938         SET_SIZE(xrdmsr)
2939 
2940         ENTRY(xwrmsr)
2941         pushq   %rbp
2942         movq    %rsp, %rbp
2943         movl    %edi, %ecx
2944         movl    XMSR_ACCESS_VAL, %edi   /* this value is needed to access MSR */
2945         movq    %rsi, %rdx
2946         shrq    $32, %rdx
2947         movl    %esi, %eax
2948         wrmsr
2949         leave
2950         ret
2951         SET_SIZE(xwrmsr)
2952 
2953         ENTRY(get_xcr)
2954         movl    %edi, %ecx
2955         #xgetbv
2956         .byte   0x0f,0x01,0xd0
2957         shlq    $32, %rdx
2958         orq     %rdx, %rax
2959         ret
2960         SET_SIZE(get_xcr)
2961 
2962         ENTRY(set_xcr)
2963         movq    %rsi, %rdx
2964         shrq    $32, %rdx
2965         movl    %esi, %eax
2966         movl    %edi, %ecx
2967         #xsetbv
2968         .byte   0x0f,0x01,0xd1
2969         ret
2970         SET_SIZE(set_xcr)
2971 
2972 #elif defined(__i386)
2973 
2974         ENTRY(rdmsr)
2975         movl    4(%esp), %ecx
2976         rdmsr
2977         ret
2978         SET_SIZE(rdmsr)
2979 
2980         ENTRY(wrmsr)
2981         movl    4(%esp), %ecx
2982         movl    8(%esp), %eax
2983         movl    12(%esp), %edx 
2984         wrmsr
2985         ret
2986         SET_SIZE(wrmsr)
2987 
2988         ENTRY(xrdmsr)
2989         pushl   %ebp
2990         movl    %esp, %ebp
2991         movl    8(%esp), %ecx
2992         pushl   %edi
2993         movl    XMSR_ACCESS_VAL, %edi   /* this value is needed to access MSR */
2994         rdmsr
2995         popl    %edi
2996         leave
2997         ret
2998         SET_SIZE(xrdmsr)
2999 
3000         ENTRY(xwrmsr)
3001         pushl   %ebp
3002         movl    %esp, %ebp
3003         movl    8(%esp), %ecx
3004         movl    12(%esp), %eax
3005         movl    16(%esp), %edx 
3006         pushl   %edi
3007         movl    XMSR_ACCESS_VAL, %edi   /* this value is needed to access MSR */
3008         wrmsr
3009         popl    %edi
3010         leave
3011         ret
3012         SET_SIZE(xwrmsr)
3013 
3014         ENTRY(get_xcr)
3015         movl    4(%esp), %ecx
3016         #xgetbv
3017         .byte   0x0f,0x01,0xd0
3018         ret
3019         SET_SIZE(get_xcr)
3020 
3021         ENTRY(set_xcr)
3022         movl    4(%esp), %ecx
3023         movl    8(%esp), %eax
3024         movl    12(%esp), %edx
3025         #xsetbv
3026         .byte   0x0f,0x01,0xd1
3027         ret
3028         SET_SIZE(set_xcr)
3029 
3030 #endif  /* __i386 */
3031 
3032         ENTRY(invalidate_cache)
3033         wbinvd
3034         ret
3035         SET_SIZE(invalidate_cache)
3036 
3037 #endif  /* __lint */
3038 
3039 #if defined(__lint)
3040 
3041 /*ARGSUSED*/
3042 void
3043 getcregs(struct cregs *crp)
3044 {}
3045 
3046 #else   /* __lint */
3047 
3048 #if defined(__amd64)
3049 
3050         ENTRY_NP(getcregs)
3051 #if defined(__xpv)
3052         /*
3053          * Only a few of the hardware control registers or descriptor tables
3054          * are directly accessible to us, so just zero the structure.
3055          *
3056          * XXPV Perhaps it would be helpful for the hypervisor to return
3057          *      virtualized versions of these for post-mortem use.
3058          *      (Need to reevaluate - perhaps it already does!)
3059          */
3060         pushq   %rdi            /* save *crp */
3061         movq    $CREGSZ, %rsi
3062         call    bzero
3063         popq    %rdi
3064 
3065         /*
3066          * Dump what limited information we can
3067          */
3068         movq    %cr0, %rax
3069         movq    %rax, CREG_CR0(%rdi)    /* cr0 */
3070         movq    %cr2, %rax
3071         movq    %rax, CREG_CR2(%rdi)    /* cr2 */
3072         movq    %cr3, %rax
3073         movq    %rax, CREG_CR3(%rdi)    /* cr3 */
3074         movq    %cr4, %rax
3075         movq    %rax, CREG_CR4(%rdi)    /* cr4 */
3076 
3077 #else   /* __xpv */
3078 
3079 #define GETMSR(r, off, d)       \
3080         movl    $r, %ecx;       \
3081         rdmsr;                  \
3082         movl    %eax, off(d);   \
3083         movl    %edx, off+4(d)
3084 
3085         xorl    %eax, %eax
3086         movq    %rax, CREG_GDT+8(%rdi)
3087         sgdt    CREG_GDT(%rdi)          /* 10 bytes */
3088         movq    %rax, CREG_IDT+8(%rdi)
3089         sidt    CREG_IDT(%rdi)          /* 10 bytes */
3090         movq    %rax, CREG_LDT(%rdi)
3091         sldt    CREG_LDT(%rdi)          /* 2 bytes */
3092         movq    %rax, CREG_TASKR(%rdi)
3093         str     CREG_TASKR(%rdi)        /* 2 bytes */
3094         movq    %cr0, %rax
3095         movq    %rax, CREG_CR0(%rdi)    /* cr0 */
3096         movq    %cr2, %rax
3097         movq    %rax, CREG_CR2(%rdi)    /* cr2 */
3098         movq    %cr3, %rax
3099         movq    %rax, CREG_CR3(%rdi)    /* cr3 */
3100         movq    %cr4, %rax
3101         movq    %rax, CREG_CR4(%rdi)    /* cr4 */
3102         movq    %cr8, %rax
3103         movq    %rax, CREG_CR8(%rdi)    /* cr8 */
3104         GETMSR(MSR_AMD_KGSBASE, CREG_KGSBASE, %rdi)
3105         GETMSR(MSR_AMD_EFER, CREG_EFER, %rdi)
3106 #endif  /* __xpv */
3107         ret
3108         SET_SIZE(getcregs)
3109 
3110 #undef GETMSR
3111 
3112 #elif defined(__i386)
3113 
3114         ENTRY_NP(getcregs)
3115 #if defined(__xpv)
3116         /*
3117          * Only a few of the hardware control registers or descriptor tables
3118          * are directly accessible to us, so just zero the structure.
3119          *
3120          * XXPV Perhaps it would be helpful for the hypervisor to return
3121          *      virtualized versions of these for post-mortem use.
3122          *      (Need to reevaluate - perhaps it already does!)
3123          */
3124         movl    4(%esp), %edx
3125         pushl   $CREGSZ
3126         pushl   %edx
3127         call    bzero
3128         addl    $8, %esp
3129         movl    4(%esp), %edx
3130 
3131         /*
3132          * Dump what limited information we can
3133          */
3134         movl    %cr0, %eax
3135         movl    %eax, CREG_CR0(%edx)    /* cr0 */
3136         movl    %cr2, %eax
3137         movl    %eax, CREG_CR2(%edx)    /* cr2 */
3138         movl    %cr3, %eax
3139         movl    %eax, CREG_CR3(%edx)    /* cr3 */
3140         movl    %cr4, %eax
3141         movl    %eax, CREG_CR4(%edx)    /* cr4 */
3142 
3143 #else   /* __xpv */
3144 
3145         movl    4(%esp), %edx
3146         movw    $0, CREG_GDT+6(%edx)
3147         movw    $0, CREG_IDT+6(%edx)
3148         sgdt    CREG_GDT(%edx)          /* gdt */
3149         sidt    CREG_IDT(%edx)          /* idt */
3150         sldt    CREG_LDT(%edx)          /* ldt */
3151         str     CREG_TASKR(%edx)        /* task */
3152         movl    %cr0, %eax
3153         movl    %eax, CREG_CR0(%edx)    /* cr0 */
3154         movl    %cr2, %eax
3155         movl    %eax, CREG_CR2(%edx)    /* cr2 */
3156         movl    %cr3, %eax
3157         movl    %eax, CREG_CR3(%edx)    /* cr3 */
3158         bt      $X86FSET_LARGEPAGE, x86_featureset
3159         jnc     .nocr4
3160         movl    %cr4, %eax
3161         movl    %eax, CREG_CR4(%edx)    /* cr4 */
3162         jmp     .skip
3163 .nocr4:
3164         movl    $0, CREG_CR4(%edx)
3165 .skip:
3166 #endif
3167         ret
3168         SET_SIZE(getcregs)
3169 
3170 #endif  /* __i386 */
3171 #endif  /* __lint */
3172 
3173 
3174 /*
3175  * A panic trigger is a word which is updated atomically and can only be set
3176  * once.  We atomically store 0xDEFACEDD and load the old value.  If the
3177  * previous value was 0, we succeed and return 1; otherwise return 0.
3178  * This allows a partially corrupt trigger to still trigger correctly.  DTrace
3179  * has its own version of this function to allow it to panic correctly from
3180  * probe context.
3181  */
3182 #if defined(__lint)
3183 
3184 /*ARGSUSED*/
3185 int
3186 panic_trigger(int *tp)
3187 { return (0); }
3188 
3189 /*ARGSUSED*/
3190 int
3191 dtrace_panic_trigger(int *tp)
3192 { return (0); }
3193 
3194 #else   /* __lint */
3195 
3196 #if defined(__amd64)
3197 
3198         ENTRY_NP(panic_trigger)
3199         xorl    %eax, %eax
3200         movl    $0xdefacedd, %edx
3201         lock
3202           xchgl %edx, (%rdi)
3203         cmpl    $0, %edx
3204         je      0f 
3205         movl    $0, %eax
3206         ret
3207 0:      movl    $1, %eax
3208         ret
3209         SET_SIZE(panic_trigger)
3210         
3211         ENTRY_NP(dtrace_panic_trigger)
3212         xorl    %eax, %eax
3213         movl    $0xdefacedd, %edx
3214         lock
3215           xchgl %edx, (%rdi)
3216         cmpl    $0, %edx
3217         je      0f
3218         movl    $0, %eax
3219         ret
3220 0:      movl    $1, %eax
3221         ret
3222         SET_SIZE(dtrace_panic_trigger)
3223 
3224 #elif defined(__i386)
3225 
3226         ENTRY_NP(panic_trigger)
3227         movl    4(%esp), %edx           / %edx = address of trigger
3228         movl    $0xdefacedd, %eax       / %eax = 0xdefacedd
3229         lock                            / assert lock
3230         xchgl %eax, (%edx)              / exchange %eax and the trigger
3231         cmpl    $0, %eax                / if (%eax == 0x0)
3232         je      0f                      /   return (1);
3233         movl    $0, %eax                / else
3234         ret                             /   return (0);
3235 0:      movl    $1, %eax
3236         ret
3237         SET_SIZE(panic_trigger)
3238 
3239         ENTRY_NP(dtrace_panic_trigger)
3240         movl    4(%esp), %edx           / %edx = address of trigger
3241         movl    $0xdefacedd, %eax       / %eax = 0xdefacedd
3242         lock                            / assert lock
3243         xchgl %eax, (%edx)              / exchange %eax and the trigger
3244         cmpl    $0, %eax                / if (%eax == 0x0)
3245         je      0f                      /   return (1);
3246         movl    $0, %eax                / else
3247         ret                             /   return (0);
3248 0:      movl    $1, %eax
3249         ret
3250         SET_SIZE(dtrace_panic_trigger)
3251 
3252 #endif  /* __i386 */
3253 #endif  /* __lint */
3254 
3255 /*
3256  * The panic() and cmn_err() functions invoke vpanic() as a common entry point
3257  * into the panic code implemented in panicsys().  vpanic() is responsible
3258  * for passing through the format string and arguments, and constructing a
3259  * regs structure on the stack into which it saves the current register
3260  * values.  If we are not dying due to a fatal trap, these registers will
3261  * then be preserved in panicbuf as the current processor state.  Before
3262  * invoking panicsys(), vpanic() activates the first panic trigger (see
3263  * common/os/panic.c) and switches to the panic_stack if successful.  Note that
3264  * DTrace takes a slightly different panic path if it must panic from probe
3265  * context.  Instead of calling panic, it calls into dtrace_vpanic(), which
3266  * sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
3267  * branches back into vpanic().
3268  */
3269 #if defined(__lint)
3270 
3271 /*ARGSUSED*/
3272 void
3273 vpanic(const char *format, va_list alist)
3274 {}
3275 
3276 /*ARGSUSED*/
3277 void
3278 dtrace_vpanic(const char *format, va_list alist)
3279 {}
3280 
3281 #else   /* __lint */
3282 
3283 #if defined(__amd64)
3284 
3285         ENTRY_NP(vpanic)                        /* Initial stack layout: */
3286         
3287         pushq   %rbp                            /* | %rip |     0x60    */
3288         movq    %rsp, %rbp                      /* | %rbp |     0x58    */
3289         pushfq                                  /* | rfl  |     0x50    */
3290         pushq   %r11                            /* | %r11 |     0x48    */
3291         pushq   %r10                            /* | %r10 |     0x40    */
3292         pushq   %rbx                            /* | %rbx |     0x38    */
3293         pushq   %rax                            /* | %rax |     0x30    */
3294         pushq   %r9                             /* | %r9  |     0x28    */
3295         pushq   %r8                             /* | %r8  |     0x20    */
3296         pushq   %rcx                            /* | %rcx |     0x18    */
3297         pushq   %rdx                            /* | %rdx |     0x10    */
3298         pushq   %rsi                            /* | %rsi |     0x8 alist */
3299         pushq   %rdi                            /* | %rdi |     0x0 format */
3300 
3301         movq    %rsp, %rbx                      /* %rbx = current %rsp */
3302 
3303         leaq    panic_quiesce(%rip), %rdi       /* %rdi = &panic_quiesce */
3304         call    panic_trigger                   /* %eax = panic_trigger() */
3305 
3306 vpanic_common:
3307         /*
3308          * The panic_trigger result is in %eax from the call above, and
3309          * dtrace_panic places it in %eax before branching here.
3310          * The rdmsr instructions that follow below will clobber %eax so
3311          * we stash the panic_trigger result in %r11d.
3312          */
3313         movl    %eax, %r11d
3314         cmpl    $0, %r11d
3315         je      0f
3316 
3317         /*
3318          * If panic_trigger() was successful, we are the first to initiate a
3319          * panic: we now switch to the reserved panic_stack before continuing.
3320          */
3321         leaq    panic_stack(%rip), %rsp
3322         addq    $PANICSTKSIZE, %rsp
3323 0:      subq    $REGSIZE, %rsp
3324         /*
3325          * Now that we've got everything set up, store the register values as
3326          * they were when we entered vpanic() to the designated location in
3327          * the regs structure we allocated on the stack.
3328          */
3329         movq    0x0(%rbx), %rcx
3330         movq    %rcx, REGOFF_RDI(%rsp)
3331         movq    0x8(%rbx), %rcx
3332         movq    %rcx, REGOFF_RSI(%rsp)
3333         movq    0x10(%rbx), %rcx
3334         movq    %rcx, REGOFF_RDX(%rsp)
3335         movq    0x18(%rbx), %rcx
3336         movq    %rcx, REGOFF_RCX(%rsp)
3337         movq    0x20(%rbx), %rcx
3338 
3339         movq    %rcx, REGOFF_R8(%rsp)
3340         movq    0x28(%rbx), %rcx
3341         movq    %rcx, REGOFF_R9(%rsp)
3342         movq    0x30(%rbx), %rcx
3343         movq    %rcx, REGOFF_RAX(%rsp)
3344         movq    0x38(%rbx), %rcx
3345         movq    %rcx, REGOFF_RBX(%rsp)
3346         movq    0x58(%rbx), %rcx
3347 
3348         movq    %rcx, REGOFF_RBP(%rsp)
3349         movq    0x40(%rbx), %rcx
3350         movq    %rcx, REGOFF_R10(%rsp)
3351         movq    0x48(%rbx), %rcx
3352         movq    %rcx, REGOFF_R11(%rsp)
3353         movq    %r12, REGOFF_R12(%rsp)
3354 
3355         movq    %r13, REGOFF_R13(%rsp)
3356         movq    %r14, REGOFF_R14(%rsp)
3357         movq    %r15, REGOFF_R15(%rsp)
3358 
3359         xorl    %ecx, %ecx
3360         movw    %ds, %cx
3361         movq    %rcx, REGOFF_DS(%rsp)
3362         movw    %es, %cx
3363         movq    %rcx, REGOFF_ES(%rsp)
3364         movw    %fs, %cx
3365         movq    %rcx, REGOFF_FS(%rsp)
3366         movw    %gs, %cx
3367         movq    %rcx, REGOFF_GS(%rsp)
3368 
3369         movq    $0, REGOFF_TRAPNO(%rsp)
3370 
3371         movq    $0, REGOFF_ERR(%rsp)
3372         leaq    vpanic(%rip), %rcx
3373         movq    %rcx, REGOFF_RIP(%rsp)
3374         movw    %cs, %cx
3375         movzwq  %cx, %rcx
3376         movq    %rcx, REGOFF_CS(%rsp)
3377         movq    0x50(%rbx), %rcx
3378         movq    %rcx, REGOFF_RFL(%rsp)
3379         movq    %rbx, %rcx
3380         addq    $0x60, %rcx
3381         movq    %rcx, REGOFF_RSP(%rsp)
3382         movw    %ss, %cx
3383         movzwq  %cx, %rcx
3384         movq    %rcx, REGOFF_SS(%rsp)
3385 
3386         /*
3387          * panicsys(format, alist, rp, on_panic_stack) 
3388          */     
3389         movq    REGOFF_RDI(%rsp), %rdi          /* format */
3390         movq    REGOFF_RSI(%rsp), %rsi          /* alist */
3391         movq    %rsp, %rdx                      /* struct regs */
3392         movl    %r11d, %ecx                     /* on_panic_stack */
3393         call    panicsys
3394         addq    $REGSIZE, %rsp
3395         popq    %rdi
3396         popq    %rsi
3397         popq    %rdx
3398         popq    %rcx
3399         popq    %r8
3400         popq    %r9
3401         popq    %rax
3402         popq    %rbx
3403         popq    %r10
3404         popq    %r11
3405         popfq
3406         leave
3407         ret
3408         SET_SIZE(vpanic)
3409 
3410         ENTRY_NP(dtrace_vpanic)                 /* Initial stack layout: */
3411 
3412         pushq   %rbp                            /* | %rip |     0x60    */
3413         movq    %rsp, %rbp                      /* | %rbp |     0x58    */
3414         pushfq                                  /* | rfl  |     0x50    */
3415         pushq   %r11                            /* | %r11 |     0x48    */
3416         pushq   %r10                            /* | %r10 |     0x40    */
3417         pushq   %rbx                            /* | %rbx |     0x38    */
3418         pushq   %rax                            /* | %rax |     0x30    */
3419         pushq   %r9                             /* | %r9  |     0x28    */
3420         pushq   %r8                             /* | %r8  |     0x20    */
3421         pushq   %rcx                            /* | %rcx |     0x18    */
3422         pushq   %rdx                            /* | %rdx |     0x10    */
3423         pushq   %rsi                            /* | %rsi |     0x8 alist */
3424         pushq   %rdi                            /* | %rdi |     0x0 format */
3425 
3426         movq    %rsp, %rbx                      /* %rbx = current %rsp */
3427 
3428         leaq    panic_quiesce(%rip), %rdi       /* %rdi = &panic_quiesce */
3429         call    dtrace_panic_trigger    /* %eax = dtrace_panic_trigger() */
3430         jmp     vpanic_common
3431 
3432         SET_SIZE(dtrace_vpanic)
3433 
3434 #elif defined(__i386)
3435 
3436         ENTRY_NP(vpanic)                        / Initial stack layout:
3437 
3438         pushl   %ebp                            / | %eip | 20
3439         movl    %esp, %ebp                      / | %ebp | 16
3440         pushl   %eax                            / | %eax | 12
3441         pushl   %ebx                            / | %ebx |  8
3442         pushl   %ecx                            / | %ecx |  4
3443         pushl   %edx                            / | %edx |  0
3444 
3445         movl    %esp, %ebx                      / %ebx = current stack pointer
3446 
3447         lea     panic_quiesce, %eax             / %eax = &panic_quiesce
3448         pushl   %eax                            / push &panic_quiesce
3449         call    panic_trigger                   / %eax = panic_trigger()
3450         addl    $4, %esp                        / reset stack pointer
3451 
3452 vpanic_common:
3453         cmpl    $0, %eax                        / if (%eax == 0)
3454         je      0f                              /   goto 0f;
3455 
3456         /*
3457          * If panic_trigger() was successful, we are the first to initiate a
3458          * panic: we now switch to the reserved panic_stack before continuing.
3459          */
3460         lea     panic_stack, %esp               / %esp  = panic_stack
3461         addl    $PANICSTKSIZE, %esp             / %esp += PANICSTKSIZE
3462 
3463 0:      subl    $REGSIZE, %esp                  / allocate struct regs
3464 
3465         /*
3466          * Now that we've got everything set up, store the register values as
3467          * they were when we entered vpanic() to the designated location in
3468          * the regs structure we allocated on the stack. 
3469          */
3470 #if !defined(__GNUC_AS__)
3471         movw    %gs, %edx
3472         movl    %edx, REGOFF_GS(%esp)
3473         movw    %fs, %edx
3474         movl    %edx, REGOFF_FS(%esp)
3475         movw    %es, %edx
3476         movl    %edx, REGOFF_ES(%esp)
3477         movw    %ds, %edx
3478         movl    %edx, REGOFF_DS(%esp)
3479 #else   /* __GNUC_AS__ */
3480         mov     %gs, %edx
3481         mov     %edx, REGOFF_GS(%esp)
3482         mov     %fs, %edx
3483         mov     %edx, REGOFF_FS(%esp)
3484         mov     %es, %edx
3485         mov     %edx, REGOFF_ES(%esp)
3486         mov     %ds, %edx
3487         mov     %edx, REGOFF_DS(%esp)
3488 #endif  /* __GNUC_AS__ */
3489         movl    %edi, REGOFF_EDI(%esp)
3490         movl    %esi, REGOFF_ESI(%esp)
3491         movl    16(%ebx), %ecx
3492         movl    %ecx, REGOFF_EBP(%esp)
3493         movl    %ebx, %ecx
3494         addl    $20, %ecx
3495         movl    %ecx, REGOFF_ESP(%esp)
3496         movl    8(%ebx), %ecx
3497         movl    %ecx, REGOFF_EBX(%esp)
3498         movl    0(%ebx), %ecx
3499         movl    %ecx, REGOFF_EDX(%esp)
3500         movl    4(%ebx), %ecx
3501         movl    %ecx, REGOFF_ECX(%esp)
3502         movl    12(%ebx), %ecx
3503         movl    %ecx, REGOFF_EAX(%esp)
3504         movl    $0, REGOFF_TRAPNO(%esp)
3505         movl    $0, REGOFF_ERR(%esp)
3506         lea     vpanic, %ecx
3507         movl    %ecx, REGOFF_EIP(%esp)
3508 #if !defined(__GNUC_AS__)
3509         movw    %cs, %edx
3510 #else   /* __GNUC_AS__ */
3511         mov     %cs, %edx
3512 #endif  /* __GNUC_AS__ */
3513         movl    %edx, REGOFF_CS(%esp)
3514         pushfl
3515         popl    %ecx
3516 #if defined(__xpv)
3517         /*
3518          * Synthesize the PS_IE bit from the event mask bit
3519          */
3520         CURTHREAD(%edx)
3521         KPREEMPT_DISABLE(%edx)
3522         EVENT_MASK_TO_IE(%edx, %ecx)
3523         CURTHREAD(%edx)
3524         KPREEMPT_ENABLE_NOKP(%edx)
3525 #endif
3526         movl    %ecx, REGOFF_EFL(%esp)
3527         movl    $0, REGOFF_UESP(%esp)
3528 #if !defined(__GNUC_AS__)
3529         movw    %ss, %edx
3530 #else   /* __GNUC_AS__ */
3531         mov     %ss, %edx
3532 #endif  /* __GNUC_AS__ */
3533         movl    %edx, REGOFF_SS(%esp)
3534 
3535         movl    %esp, %ecx                      / %ecx = &regs
3536         pushl   %eax                            / push on_panic_stack
3537         pushl   %ecx                            / push &regs
3538         movl    12(%ebp), %ecx                  / %ecx = alist
3539         pushl   %ecx                            / push alist
3540         movl    8(%ebp), %ecx                   / %ecx = format
3541         pushl   %ecx                            / push format
3542         call    panicsys                        / panicsys();
3543         addl    $16, %esp                       / pop arguments
3544 
3545         addl    $REGSIZE, %esp
3546         popl    %edx
3547         popl    %ecx
3548         popl    %ebx
3549         popl    %eax
3550         leave
3551         ret
3552         SET_SIZE(vpanic)
3553 
3554         ENTRY_NP(dtrace_vpanic)                 / Initial stack layout:
3555 
3556         pushl   %ebp                            / | %eip | 20
3557         movl    %esp, %ebp                      / | %ebp | 16
3558         pushl   %eax                            / | %eax | 12
3559         pushl   %ebx                            / | %ebx |  8
3560         pushl   %ecx                            / | %ecx |  4
3561         pushl   %edx                            / | %edx |  0
3562 
3563         movl    %esp, %ebx                      / %ebx = current stack pointer
3564 
3565         lea     panic_quiesce, %eax             / %eax = &panic_quiesce
3566         pushl   %eax                            / push &panic_quiesce
3567         call    dtrace_panic_trigger            / %eax = dtrace_panic_trigger()
3568         addl    $4, %esp                        / reset stack pointer
3569         jmp     vpanic_common                   / jump back to common code
3570 
3571         SET_SIZE(dtrace_vpanic)
3572 
3573 #endif  /* __i386 */
3574 #endif  /* __lint */
3575 
3576 #if defined(__lint)
3577 
3578 void
3579 hres_tick(void)
3580 {}
3581 
3582 int64_t timedelta;
3583 hrtime_t hrtime_base;
3584 
3585 #else   /* __lint */
3586 
3587         DGDEF3(timedelta, 8, 8)
3588         .long   0, 0
3589 
3590         /*
3591          * initialized to a non zero value to make pc_gethrtime()
3592          * work correctly even before clock is initialized
3593          */
3594         DGDEF3(hrtime_base, 8, 8)
3595         .long   _MUL(NSEC_PER_CLOCK_TICK, 6), 0
3596 
3597         DGDEF3(adj_shift, 4, 4)
3598         .long   ADJ_SHIFT
3599 
3600 #if defined(__amd64)
3601 
3602         ENTRY_NP(hres_tick)
3603         pushq   %rbp
3604         movq    %rsp, %rbp
3605 
3606         /*
3607          * We need to call *gethrtimef before picking up CLOCK_LOCK (obviously,
3608          * hres_last_tick can only be modified while holding CLOCK_LOCK).
3609          * At worst, performing this now instead of under CLOCK_LOCK may
3610          * introduce some jitter in pc_gethrestime().
3611          */
3612         call    *gethrtimef(%rip)
3613         movq    %rax, %r8
3614 
3615         leaq    hres_lock(%rip), %rax
3616         movb    $-1, %dl
3617 .CL1:
3618         xchgb   %dl, (%rax)
3619         testb   %dl, %dl
3620         jz      .CL3                    /* got it */
3621 .CL2:
3622         cmpb    $0, (%rax)              /* possible to get lock? */
3623         pause
3624         jne     .CL2
3625         jmp     .CL1                    /* yes, try again */
3626 .CL3:
3627         /*
3628          * compute the interval since last time hres_tick was called
3629          * and adjust hrtime_base and hrestime accordingly
3630          * hrtime_base is an 8 byte value (in nsec), hrestime is
3631          * a timestruc_t (sec, nsec)
3632          */
3633         leaq    hres_last_tick(%rip), %rax
3634         movq    %r8, %r11
3635         subq    (%rax), %r8
3636         addq    %r8, hrtime_base(%rip)  /* add interval to hrtime_base */
3637         addq    %r8, hrestime+8(%rip)   /* add interval to hrestime.tv_nsec */
3638         /*
3639          * Now that we have CLOCK_LOCK, we can update hres_last_tick
3640          */     
3641         movq    %r11, (%rax)    
3642 
3643         call    __adj_hrestime
3644 
3645         /*
3646          * release the hres_lock
3647          */
3648         incl    hres_lock(%rip)
3649         leave
3650         ret
3651         SET_SIZE(hres_tick)
3652         
3653 #elif defined(__i386)
3654 
3655         ENTRY_NP(hres_tick)
3656         pushl   %ebp
3657         movl    %esp, %ebp
3658         pushl   %esi
3659         pushl   %ebx
3660 
3661         /*
3662          * We need to call *gethrtimef before picking up CLOCK_LOCK (obviously,
3663          * hres_last_tick can only be modified while holding CLOCK_LOCK).
3664          * At worst, performing this now instead of under CLOCK_LOCK may
3665          * introduce some jitter in pc_gethrestime().
3666          */
3667         call    *gethrtimef
3668         movl    %eax, %ebx
3669         movl    %edx, %esi
3670 
3671         movl    $hres_lock, %eax
3672         movl    $-1, %edx
3673 .CL1:
3674         xchgb   %dl, (%eax)
3675         testb   %dl, %dl
3676         jz      .CL3                    / got it
3677 .CL2:
3678         cmpb    $0, (%eax)              / possible to get lock?
3679         pause
3680         jne     .CL2
3681         jmp     .CL1                    / yes, try again
3682 .CL3:
3683         /*
3684          * compute the interval since last time hres_tick was called
3685          * and adjust hrtime_base and hrestime accordingly
3686          * hrtime_base is an 8 byte value (in nsec), hrestime is
3687          * timestruc_t (sec, nsec)
3688          */
3689 
3690         lea     hres_last_tick, %eax
3691 
3692         movl    %ebx, %edx
3693         movl    %esi, %ecx
3694 
3695         subl    (%eax), %edx
3696         sbbl    4(%eax), %ecx
3697 
3698         addl    %edx, hrtime_base       / add interval to hrtime_base
3699         adcl    %ecx, hrtime_base+4
3700 
3701         addl    %edx, hrestime+4        / add interval to hrestime.tv_nsec
3702 
3703         /
3704         / Now that we have CLOCK_LOCK, we can update hres_last_tick.
3705         /
3706         movl    %ebx, (%eax)
3707         movl    %esi,  4(%eax)
3708 
3709         / get hrestime at this moment. used as base for pc_gethrestime
3710         /
3711         / Apply adjustment, if any
3712         /
3713         / #define HRES_ADJ      (NSEC_PER_CLOCK_TICK >> ADJ_SHIFT)
3714         / (max_hres_adj)
3715         /
3716         / void
3717         / adj_hrestime()
3718         / {
3719         /       long long adj;
3720         /
3721         /       if (hrestime_adj == 0)
3722         /               adj = 0;
3723         /       else if (hrestime_adj > 0) {
3724         /               if (hrestime_adj < HRES_ADJ)
3725         /                       adj = hrestime_adj;
3726         /               else
3727         /                       adj = HRES_ADJ;
3728         /       }
3729         /       else {
3730         /               if (hrestime_adj < -(HRES_ADJ))
3731         /                       adj = -(HRES_ADJ);
3732         /               else
3733         /                       adj = hrestime_adj;
3734         /       }
3735         /
3736         /       timedelta -= adj;
3737         /       hrestime_adj = timedelta;
3738         /       hrestime.tv_nsec += adj;
3739         /
3740         /       while (hrestime.tv_nsec >= NANOSEC) {
3741         /               one_sec++;
3742         /               hrestime.tv_sec++;
3743         /               hrestime.tv_nsec -= NANOSEC;
3744         /       }
3745         / }
3746 __adj_hrestime:
3747         movl    hrestime_adj, %esi      / if (hrestime_adj == 0)
3748         movl    hrestime_adj+4, %edx
3749         andl    %esi, %esi
3750         jne     .CL4                    / no
3751         andl    %edx, %edx
3752         jne     .CL4                    / no
3753         subl    %ecx, %ecx              / yes, adj = 0;
3754         subl    %edx, %edx
3755         jmp     .CL5
3756 .CL4:
3757         subl    %ecx, %ecx
3758         subl    %eax, %eax
3759         subl    %esi, %ecx
3760         sbbl    %edx, %eax
3761         andl    %eax, %eax              / if (hrestime_adj > 0)
3762         jge     .CL6
3763 
3764         / In the following comments, HRES_ADJ is used, while in the code
3765         / max_hres_adj is used.
3766         /
3767         / The test for "hrestime_adj < HRES_ADJ" is complicated because
3768         / hrestime_adj is 64-bits, while HRES_ADJ is 32-bits.  We rely
3769         / on the logical equivalence of:
3770         /
3771         /       !(hrestime_adj < HRES_ADJ)
3772         /
3773         / and the two step sequence:
3774         /
3775         /       (HRES_ADJ - lsw(hrestime_adj)) generates a Borrow/Carry
3776         /
3777         / which computes whether or not the least significant 32-bits
3778         / of hrestime_adj is greater than HRES_ADJ, followed by:
3779         /
3780         /       Previous Borrow/Carry + -1 + msw(hrestime_adj) generates a Carry
3781         /
3782         / which generates a carry whenever step 1 is true or the most
3783         / significant long of the longlong hrestime_adj is non-zero.
3784 
3785         movl    max_hres_adj, %ecx      / hrestime_adj is positive
3786         subl    %esi, %ecx
3787         movl    %edx, %eax
3788         adcl    $-1, %eax
3789         jnc     .CL7
3790         movl    max_hres_adj, %ecx      / adj = HRES_ADJ;
3791         subl    %edx, %edx
3792         jmp     .CL5
3793 
3794         / The following computation is similar to the one above.
3795         /
3796         / The test for "hrestime_adj < -(HRES_ADJ)" is complicated because
3797         / hrestime_adj is 64-bits, while HRES_ADJ is 32-bits.  We rely
3798         / on the logical equivalence of:
3799         /
3800         /       (hrestime_adj > -HRES_ADJ)
3801         /
3802         / and the two step sequence:
3803         /
3804         /       (HRES_ADJ + lsw(hrestime_adj)) generates a Carry
3805         /
3806         / which means the least significant 32-bits of hrestime_adj is
3807         / greater than -HRES_ADJ, followed by:
3808         /
3809         /       Previous Carry + 0 + msw(hrestime_adj) generates a Carry
3810         /
3811         / which generates a carry only when step 1 is true and the most
3812         / significant long of the longlong hrestime_adj is -1.
3813 
3814 .CL6:                                   / hrestime_adj is negative
3815         movl    %esi, %ecx
3816         addl    max_hres_adj, %ecx
3817         movl    %edx, %eax
3818         adcl    $0, %eax
3819         jc      .CL7
3820         xor     %ecx, %ecx
3821         subl    max_hres_adj, %ecx      / adj = -(HRES_ADJ);
3822         movl    $-1, %edx
3823         jmp     .CL5
3824 .CL7:
3825         movl    %esi, %ecx              / adj = hrestime_adj;
3826 .CL5:
3827         movl    timedelta, %esi
3828         subl    %ecx, %esi
3829         movl    timedelta+4, %eax
3830         sbbl    %edx, %eax
3831         movl    %esi, timedelta
3832         movl    %eax, timedelta+4       / timedelta -= adj;
3833         movl    %esi, hrestime_adj
3834         movl    %eax, hrestime_adj+4    / hrestime_adj = timedelta;
3835         addl    hrestime+4, %ecx
3836 
3837         movl    %ecx, %eax              / eax = tv_nsec
3838 1:
3839         cmpl    $NANOSEC, %eax          / if ((unsigned long)tv_nsec >= NANOSEC)
3840         jb      .CL8                    / no
3841         incl    one_sec                 / yes,  one_sec++;
3842         incl    hrestime                / hrestime.tv_sec++;
3843         addl    $-NANOSEC, %eax         / tv_nsec -= NANOSEC
3844         jmp     1b                      / check for more seconds
3845 
3846 .CL8:
3847         movl    %eax, hrestime+4        / store final into hrestime.tv_nsec
3848         incl    hres_lock               / release the hres_lock
3849 
3850         popl    %ebx
3851         popl    %esi
3852         leave
3853         ret
3854         SET_SIZE(hres_tick)
3855 
3856 #endif  /* __i386 */
3857 #endif  /* __lint */
3858 
3859 /*
3860  * void prefetch_smap_w(void *)
3861  *
3862  * Prefetch ahead within a linear list of smap structures.
3863  * Not implemented for ia32.  Stub for compatibility.
3864  */
3865 
3866 #if defined(__lint)
3867 
3868 /*ARGSUSED*/
3869 void prefetch_smap_w(void *smp)
3870 {}
3871 
3872 #else   /* __lint */
3873 
3874         ENTRY(prefetch_smap_w)
3875         rep;    ret     /* use 2 byte return instruction when branch target */
3876                         /* AMD Software Optimization Guide - Section 6.2 */
3877         SET_SIZE(prefetch_smap_w)
3878 
3879 #endif  /* __lint */
3880 
3881 /*
3882  * prefetch_page_r(page_t *)
3883  * issue prefetch instructions for a page_t
3884  */
3885 #if defined(__lint)
3886 
3887 /*ARGSUSED*/
3888 void
3889 prefetch_page_r(void *pp)
3890 {}
3891 
3892 #else   /* __lint */
3893 
3894         ENTRY(prefetch_page_r)
3895         rep;    ret     /* use 2 byte return instruction when branch target */
3896                         /* AMD Software Optimization Guide - Section 6.2 */
3897         SET_SIZE(prefetch_page_r)
3898 
3899 #endif  /* __lint */
3900 
3901 #if defined(__lint)
3902 
3903 /*ARGSUSED*/
3904 int
3905 bcmp(const void *s1, const void *s2, size_t count)
3906 { return (0); }
3907 
3908 #else   /* __lint */
3909 
3910 #if defined(__amd64)
3911 
3912         ENTRY(bcmp)
3913         pushq   %rbp
3914         movq    %rsp, %rbp
3915 #ifdef DEBUG
3916         testq   %rdx,%rdx
3917         je      1f
3918         movq    postbootkernelbase(%rip), %r11
3919         cmpq    %r11, %rdi
3920         jb      0f
3921         cmpq    %r11, %rsi
3922         jnb     1f
3923 0:      leaq    .bcmp_panic_msg(%rip), %rdi
3924         xorl    %eax, %eax
3925         call    panic
3926 1:
3927 #endif  /* DEBUG */
3928         call    memcmp
3929         testl   %eax, %eax
3930         setne   %dl
3931         leave
3932         movzbl  %dl, %eax
3933         ret
3934         SET_SIZE(bcmp)
3935         
3936 #elif defined(__i386)
3937         
3938 #define ARG_S1          8
3939 #define ARG_S2          12
3940 #define ARG_LENGTH      16
3941 
3942         ENTRY(bcmp)
3943         pushl   %ebp
3944         movl    %esp, %ebp      / create new stack frame
3945 #ifdef DEBUG
3946         cmpl    $0, ARG_LENGTH(%ebp)
3947         je      1f
3948         movl    postbootkernelbase, %eax
3949         cmpl    %eax, ARG_S1(%ebp)
3950         jb      0f
3951         cmpl    %eax, ARG_S2(%ebp)
3952         jnb     1f
3953 0:      pushl   $.bcmp_panic_msg
3954         call    panic
3955 1:
3956 #endif  /* DEBUG */
3957 
3958         pushl   %edi            / save register variable
3959         movl    ARG_S1(%ebp), %eax      / %eax = address of string 1
3960         movl    ARG_S2(%ebp), %ecx      / %ecx = address of string 2
3961         cmpl    %eax, %ecx      / if the same string
3962         je      .equal          / goto .equal
3963         movl    ARG_LENGTH(%ebp), %edi  / %edi = length in bytes
3964         cmpl    $4, %edi        / if %edi < 4
3965         jb      .byte_check     / goto .byte_check
3966         .align  4
3967 .word_loop:
3968         movl    (%ecx), %edx    / move 1 word from (%ecx) to %edx
3969         leal    -4(%edi), %edi  / %edi -= 4
3970         cmpl    (%eax), %edx    / compare 1 word from (%eax) with %edx
3971         jne     .word_not_equal / if not equal, goto .word_not_equal
3972         leal    4(%ecx), %ecx   / %ecx += 4 (next word)
3973         leal    4(%eax), %eax   / %eax += 4 (next word)
3974         cmpl    $4, %edi        / if %edi >= 4
3975         jae     .word_loop      / goto .word_loop
3976 .byte_check:
3977         cmpl    $0, %edi        / if %edi == 0
3978         je      .equal          / goto .equal
3979         jmp     .byte_loop      / goto .byte_loop (checks in bytes)
3980 .word_not_equal:
3981         leal    4(%edi), %edi   / %edi += 4 (post-decremented)
3982         .align  4
3983 .byte_loop:
3984         movb    (%ecx), %dl     / move 1 byte from (%ecx) to %dl
3985         cmpb    %dl, (%eax)     / compare %dl with 1 byte from (%eax)
3986         jne     .not_equal      / if not equal, goto .not_equal
3987         incl    %ecx            / %ecx++ (next byte)
3988         incl    %eax            / %eax++ (next byte)
3989         decl    %edi            / %edi--
3990         jnz     .byte_loop      / if not zero, goto .byte_loop
3991 .equal:
3992         xorl    %eax, %eax      / %eax = 0
3993         popl    %edi            / restore register variable
3994         leave                   / restore old stack frame
3995         ret                     / return (NULL)
3996         .align  4
3997 .not_equal:
3998         movl    $1, %eax        / return 1
3999         popl    %edi            / restore register variable
4000         leave                   / restore old stack frame
4001         ret                     / return (NULL)
4002         SET_SIZE(bcmp)
4003 
4004 #endif  /* __i386 */
4005 
4006 #ifdef DEBUG
4007         .text
4008 .bcmp_panic_msg:
4009         .string "bcmp: arguments below kernelbase"
4010 #endif  /* DEBUG */
4011 
4012 #endif  /* __lint */
4013 
4014 #if defined(__lint)
4015 
4016 uint_t
4017 bsrw_insn(uint16_t mask)
4018 {
4019         uint_t index = sizeof (mask) * NBBY - 1;
4020 
4021         while ((mask & (1 << index)) == 0)
4022                 index--;
4023         return (index);
4024 }
4025 
4026 #else   /* __lint */
4027 
4028 #if defined(__amd64)
4029 
4030         ENTRY_NP(bsrw_insn)
4031         xorl    %eax, %eax
4032         bsrw    %di, %ax
4033         ret
4034         SET_SIZE(bsrw_insn)
4035 
4036 #elif defined(__i386)
4037 
4038         ENTRY_NP(bsrw_insn)
4039         movw    4(%esp), %cx
4040         xorl    %eax, %eax
4041         bsrw    %cx, %ax
4042         ret
4043         SET_SIZE(bsrw_insn)
4044 
4045 #endif  /* __i386 */
4046 #endif  /* __lint */
4047 
4048 #if defined(__lint)
4049 
4050 uint_t
4051 atomic_btr32(uint32_t *pending, uint_t pil)
4052 {
4053         return (*pending &= ~(1 << pil));
4054 }
4055 
4056 #else   /* __lint */
4057 
4058 #if defined(__i386)
4059 
4060         ENTRY_NP(atomic_btr32)
4061         movl    4(%esp), %ecx
4062         movl    8(%esp), %edx
4063         xorl    %eax, %eax
4064         lock
4065         btrl    %edx, (%ecx)
4066         setc    %al
4067         ret
4068         SET_SIZE(atomic_btr32)
4069 
4070 #endif  /* __i386 */
4071 #endif  /* __lint */
4072 
4073 #if defined(__lint)
4074 
4075 /*ARGSUSED*/
4076 void
4077 switch_sp_and_call(void *newsp, void (*func)(uint_t, uint_t), uint_t arg1,
4078             uint_t arg2)
4079 {}
4080 
4081 #else   /* __lint */
4082 
4083 #if defined(__amd64)
4084 
4085         ENTRY_NP(switch_sp_and_call)
4086         pushq   %rbp
4087         movq    %rsp, %rbp              /* set up stack frame */
4088         movq    %rdi, %rsp              /* switch stack pointer */
4089         movq    %rdx, %rdi              /* pass func arg 1 */
4090         movq    %rsi, %r11              /* save function to call */
4091         movq    %rcx, %rsi              /* pass func arg 2 */
4092         call    *%r11                   /* call function */
4093         leave                           /* restore stack */
4094         ret
4095         SET_SIZE(switch_sp_and_call)
4096 
4097 #elif defined(__i386)
4098 
4099         ENTRY_NP(switch_sp_and_call)
4100         pushl   %ebp
4101         mov     %esp, %ebp              /* set up stack frame */
4102         movl    8(%ebp), %esp           /* switch stack pointer */
4103         pushl   20(%ebp)                /* push func arg 2 */
4104         pushl   16(%ebp)                /* push func arg 1 */
4105         call    *12(%ebp)               /* call function */
4106         addl    $8, %esp                /* pop arguments */
4107         leave                           /* restore stack */
4108         ret
4109         SET_SIZE(switch_sp_and_call)
4110 
4111 #endif  /* __i386 */
4112 #endif  /* __lint */
4113 
4114 #if defined(__lint)
4115 
4116 void
4117 kmdb_enter(void)
4118 {}
4119 
4120 #else   /* __lint */
4121 
4122 #if defined(__amd64)
4123 
4124         ENTRY_NP(kmdb_enter)
4125         pushq   %rbp
4126         movq    %rsp, %rbp
4127 
4128         /*
4129          * Save flags, do a 'cli' then return the saved flags
4130          */
4131         call    intr_clear
4132 
4133         int     $T_DBGENTR
4134 
4135         /*
4136          * Restore the saved flags
4137          */
4138         movq    %rax, %rdi
4139         call    intr_restore
4140 
4141         leave
4142         ret     
4143         SET_SIZE(kmdb_enter)
4144 
4145 #elif defined(__i386)
4146 
4147         ENTRY_NP(kmdb_enter)
4148         pushl   %ebp
4149         movl    %esp, %ebp
4150 
4151         /*
4152          * Save flags, do a 'cli' then return the saved flags
4153          */
4154         call    intr_clear
4155 
4156         int     $T_DBGENTR
4157 
4158         /*
4159          * Restore the saved flags
4160          */
4161         pushl   %eax
4162         call    intr_restore
4163         addl    $4, %esp
4164 
4165         leave
4166         ret     
4167         SET_SIZE(kmdb_enter)
4168 
4169 #endif  /* __i386 */
4170 #endif  /* __lint */
4171 
4172 #if defined(__lint)
4173 
4174 void
4175 return_instr(void)
4176 {}
4177 
4178 #else   /* __lint */
4179 
4180         ENTRY_NP(return_instr)
4181         rep;    ret     /* use 2 byte instruction when branch target */
4182                         /* AMD Software Optimization Guide - Section 6.2 */
4183         SET_SIZE(return_instr)
4184 
4185 #endif  /* __lint */
4186 
4187 #if defined(__lint)
4188 
4189 ulong_t
4190 getflags(void)
4191 {
4192         return (0);
4193 }
4194 
4195 #else   /* __lint */
4196 
4197 #if defined(__amd64)
4198 
4199         ENTRY(getflags)
4200         pushfq
4201         popq    %rax
4202 #if defined(__xpv)
4203         CURTHREAD(%rdi)
4204         KPREEMPT_DISABLE(%rdi)
4205         /*
4206          * Synthesize the PS_IE bit from the event mask bit
4207          */
4208         CURVCPU(%r11)
4209         andq    $_BITNOT(PS_IE), %rax
4210         XEN_TEST_UPCALL_MASK(%r11)
4211         jnz     1f
4212         orq     $PS_IE, %rax
4213 1:
4214         KPREEMPT_ENABLE_NOKP(%rdi)
4215 #endif
4216         ret
4217         SET_SIZE(getflags)
4218 
4219 #elif defined(__i386)
4220 
4221         ENTRY(getflags)
4222         pushfl
4223         popl    %eax
4224 #if defined(__xpv)
4225         CURTHREAD(%ecx)
4226         KPREEMPT_DISABLE(%ecx)
4227         /*
4228          * Synthesize the PS_IE bit from the event mask bit
4229          */
4230         CURVCPU(%edx)
4231         andl    $_BITNOT(PS_IE), %eax
4232         XEN_TEST_UPCALL_MASK(%edx)
4233         jnz     1f
4234         orl     $PS_IE, %eax
4235 1:
4236         KPREEMPT_ENABLE_NOKP(%ecx)
4237 #endif
4238         ret
4239         SET_SIZE(getflags)
4240 
4241 #endif  /* __i386 */
4242 
4243 #endif  /* __lint */
4244 
4245 #if defined(__lint)
4246 
4247 ftrace_icookie_t
4248 ftrace_interrupt_disable(void)
4249 { return (0); }
4250 
4251 #else   /* __lint */
4252 
4253 #if defined(__amd64)
4254 
4255         ENTRY(ftrace_interrupt_disable)
4256         pushfq
4257         popq    %rax
4258         CLI(%rdx)
4259         ret
4260         SET_SIZE(ftrace_interrupt_disable)
4261 
4262 #elif defined(__i386)
4263                 
4264         ENTRY(ftrace_interrupt_disable)
4265         pushfl
4266         popl    %eax
4267         CLI(%edx)
4268         ret
4269         SET_SIZE(ftrace_interrupt_disable)
4270 
4271 #endif  /* __i386 */    
4272 #endif  /* __lint */
4273 
4274 #if defined(__lint)
4275 
4276 /*ARGSUSED*/
4277 void
4278 ftrace_interrupt_enable(ftrace_icookie_t cookie)
4279 {}
4280 
4281 #else   /* __lint */
4282 
4283 #if defined(__amd64)
4284 
4285         ENTRY(ftrace_interrupt_enable)
4286         pushq   %rdi
4287         popfq
4288         ret
4289         SET_SIZE(ftrace_interrupt_enable)
4290 
4291 #elif defined(__i386)
4292                 
4293         ENTRY(ftrace_interrupt_enable)
4294         movl    4(%esp), %eax
4295         pushl   %eax
4296         popfl
4297         ret
4298         SET_SIZE(ftrace_interrupt_enable)
4299 
4300 #endif  /* __i386 */
4301 #endif  /* __lint */
4302 
4303 #if defined (__lint)
4304 
4305 /*ARGSUSED*/
4306 void
4307 clflush_insn(caddr_t addr)
4308 {}
4309 
4310 #else /* __lint */
4311 
4312 #if defined (__amd64)
4313         ENTRY(clflush_insn)
4314         clflush (%rdi)
4315         ret
4316         SET_SIZE(clflush_insn)
4317 #elif defined (__i386)
4318         ENTRY(clflush_insn)
4319         movl    4(%esp), %eax
4320         clflush (%eax)
4321         ret
4322         SET_SIZE(clflush_insn)
4323 
4324 #endif /* __i386 */
4325 #endif /* __lint */
4326 
4327 #if defined (__lint)
4328 /*ARGSUSED*/
4329 void
4330 mfence_insn(void)
4331 {}
4332 
4333 #else /* __lint */
4334 
4335 #if defined (__amd64)
4336         ENTRY(mfence_insn)
4337         mfence
4338         ret
4339         SET_SIZE(mfence_insn)
4340 #elif defined (__i386)
4341         ENTRY(mfence_insn)
4342         mfence
4343         ret
4344         SET_SIZE(mfence_insn)
4345 
4346 #endif /* __i386 */
4347 #endif /* __lint */
4348 
4349 /*
4350  * VMware implements an I/O port that programs can query to detect if software
4351  * is running in a VMware hypervisor. This hypervisor port behaves differently
4352  * depending on magic values in certain registers and modifies some registers
4353  * as a side effect.
4354  *
4355  * References: http://kb.vmware.com/kb/1009458 
4356  */
4357 
4358 #if defined(__lint)
4359 
4360 /* ARGSUSED */
4361 void
4362 vmware_port(int cmd, uint32_t *regs) { return; }
4363 
4364 #else
4365 
4366 #if defined(__amd64)
4367 
4368         ENTRY(vmware_port)
4369         pushq   %rbx
4370         movl    $VMWARE_HVMAGIC, %eax
4371         movl    $0xffffffff, %ebx
4372         movl    %edi, %ecx
4373         movl    $VMWARE_HVPORT, %edx
4374         inl     (%dx)
4375         movl    %eax, (%rsi)
4376         movl    %ebx, 4(%rsi)
4377         movl    %ecx, 8(%rsi)
4378         movl    %edx, 12(%rsi)
4379         popq    %rbx
4380         ret
4381         SET_SIZE(vmware_port)
4382 
4383 #elif defined(__i386)
4384 
4385         ENTRY(vmware_port)
4386         pushl   %ebx
4387         pushl   %esi
4388         movl    $VMWARE_HVMAGIC, %eax
4389         movl    $0xffffffff, %ebx
4390         movl    12(%esp), %ecx
4391         movl    $VMWARE_HVPORT, %edx
4392         inl     (%dx)
4393         movl    16(%esp), %esi
4394         movl    %eax, (%esi)
4395         movl    %ebx, 4(%esi)
4396         movl    %ecx, 8(%esi)
4397         movl    %edx, 12(%esi)
4398         popl    %esi
4399         popl    %ebx
4400         ret
4401         SET_SIZE(vmware_port)
4402 
4403 #endif /* __i386 */
4404 #endif /* __lint */