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