Home | History | Annotate | Download | only in ml
      1      0   stevel /*
      2      0   stevel  * CDDL HEADER START
      3      0   stevel  *
      4      0   stevel  * The contents of this file are subject to the terms of the
      5   2006   andrei  * Common Development and Distribution License (the "License").
      6   2006   andrei  * You may not use this file except in compliance with the License.
      7      0   stevel  *
      8      0   stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0   stevel  * or http://www.opensolaris.org/os/licensing.
     10      0   stevel  * See the License for the specific language governing permissions
     11      0   stevel  * and limitations under the License.
     12      0   stevel  *
     13      0   stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0   stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0   stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0   stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0   stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0   stevel  *
     19      0   stevel  * CDDL HEADER END
     20      0   stevel  */
     21   3446      mrj 
     22      0   stevel /*
     23  10395   gerald  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24      0   stevel  * Use is subject to license terms.
     25      0   stevel  */
     26      0   stevel 
     27      0   stevel /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
     28      0   stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
     29      0   stevel /*	  All Rights Reserved					*/
     30      0   stevel 
     31      0   stevel /*	Copyright (c) 1987, 1988 Microsoft Corporation		*/
     32      0   stevel /*	  All Rights Reserved					*/
     33      0   stevel 
     34      0   stevel 
     35      0   stevel #include <sys/asm_linkage.h>
     36      0   stevel #include <sys/asm_misc.h>
     37      0   stevel #include <sys/regset.h>
     38      0   stevel #include <sys/privregs.h>
     39      0   stevel #include <sys/psw.h>
     40      0   stevel #include <sys/reboot.h>
     41      0   stevel #include <sys/x86_archext.h>
     42   2006   andrei #include <sys/machparam.h>
     43      0   stevel 
     44      0   stevel #if defined(__lint)
     45      0   stevel 
     46      0   stevel #include <sys/types.h>
     47      0   stevel #include <sys/thread.h>
     48      0   stevel #include <sys/systm.h>
     49      0   stevel #include <sys/lgrp.h>
     50      0   stevel #include <sys/regset.h>
     51      0   stevel #include <sys/link.h>
     52      0   stevel #include <sys/bootconf.h>
     53      0   stevel #include <sys/bootsvcs.h>
     54      0   stevel 
     55      0   stevel #else	/* __lint */
     56      0   stevel 
     57      0   stevel #include <sys/segments.h>
     58      0   stevel #include <sys/pcb.h>
     59      0   stevel #include <sys/trap.h>
     60      0   stevel #include <sys/ftrace.h>
     61      0   stevel #include <sys/traptrace.h>
     62      0   stevel #include <sys/clock.h>
     63      0   stevel #include <sys/cmn_err.h>
     64      0   stevel #include <sys/pit.h>
     65      0   stevel #include <sys/panic.h>
     66   5084  johnlev 
     67   5084  johnlev #if defined(__xpv)
     68   5084  johnlev #include <sys/hypervisor.h>
     69   5084  johnlev #endif
     70   3446      mrj 
     71      0   stevel #include "assym.h"
     72      0   stevel 
     73      0   stevel /*
     74      0   stevel  * Our assumptions:
     75      0   stevel  *	- We are running in protected-paged mode.
     76      0   stevel  *	- Interrupts are disabled.
     77      0   stevel  *	- The GDT and IDT are the callers; we need our copies.
     78      0   stevel  *	- The kernel's text, initialized data and bss are mapped.
     79      0   stevel  *
     80      0   stevel  * Our actions:
     81      0   stevel  *	- Save arguments
     82      0   stevel  *	- Initialize our stack pointer to the thread 0 stack (t0stack)
     83      0   stevel  *	  and leave room for a phony "struct regs".
     84      0   stevel  *	- Our GDT and IDT need to get munged.
     85      0   stevel  *	- Since we are using the boot's GDT descriptors, we need
     86      0   stevel  *	  to copy them into our GDT before we switch to ours.
     87      0   stevel  *	- We start using our GDT by loading correct values in the
     88      0   stevel  *	  selector registers (cs=KCS_SEL, ds=es=ss=KDS_SEL, fs=KFS_SEL,
     89      0   stevel  *	  gs=KGS_SEL).
     90      0   stevel  *	- The default LDT entry for syscall is set.
     91      0   stevel  *	- We load the default LDT into the hardware LDT register.
     92      0   stevel  *	- We load the default TSS into the hardware task register.
     93      0   stevel  *	- Check for cpu type, i.e. 486 vs. P5 vs. P6 etc.
     94      0   stevel  *	- mlsetup(%esp) gets called.
     95      0   stevel  *	- We change our appearance to look like the real thread 0.
     96      0   stevel  *	  (NOTE: making ourselves to be a real thread may be a noop)
     97      0   stevel  *	- main() gets called.  (NOTE: main() never returns).
     98      0   stevel  *
     99      0   stevel  * NOW, the real code!
    100      0   stevel  */
    101   3446      mrj 	/*
    102   3446      mrj 	 * The very first thing in the kernel's text segment must be a jump
    103   3446      mrj 	 * to the os/fakebop.c startup code.
    104   3446      mrj 	 */
    105   3446      mrj 	.text
    106   3446      mrj 	jmp     _start
    107      0   stevel 
    108      0   stevel 	/*
    109      0   stevel 	 * Globals:
    110      0   stevel 	 */
    111   3446      mrj 	.globl	_locore_start
    112      0   stevel 	.globl	mlsetup
    113      0   stevel 	.globl	main
    114      0   stevel 	.globl	panic
    115      0   stevel 	.globl	t0stack
    116      0   stevel 	.globl	t0
    117      0   stevel 	.globl	sysp
    118      0   stevel 	.globl	edata
    119      0   stevel 
    120      0   stevel 	/*
    121      0   stevel 	 * call back into boot - sysp (bootsvcs.h) and bootops (bootconf.h)
    122      0   stevel 	 */
    123      0   stevel 	.globl	bootops
    124      0   stevel 	.globl	bootopsp
    125      0   stevel 
    126      0   stevel 	/*
    127      0   stevel 	 * NOTE: t0stack should be the first thing in the data section so that
    128      0   stevel 	 * if it ever overflows, it will fault on the last kernel text page.
    129      0   stevel 	 */
    130      0   stevel 	.data
    131      0   stevel 	.comm	t0stack, DEFAULTSTKSZ, 32
    132      0   stevel 	.comm	t0, 4094, 32
    133      0   stevel 
    134      0   stevel #endif	/* __lint */
    135      0   stevel 
    136      0   stevel 
    137      0   stevel #if defined(__amd64)
    138      0   stevel 
    139      0   stevel #if defined(__lint)
    140      0   stevel 
    141      0   stevel /* ARGSUSED */
    142      0   stevel void
    143   3446      mrj _locore_start(struct boot_syscalls *sysp, ulong_t rsi, struct bootops *bop)
    144      0   stevel {}
    145      0   stevel 
    146      0   stevel #else	/* __lint */
    147      0   stevel 
    148   3446      mrj 	/*
    149   3446      mrj 	 * kobj_init() vectors us back to here with (note) a slightly different
    150   3446      mrj 	 * set of arguments than _start is given (see lint prototypes above).
    151   5084  johnlev 	 *
    152   5084  johnlev 	 * XXX	Make this less vile, please.
    153   3446      mrj 	 */
    154   3446      mrj 	ENTRY_NP(_locore_start)
    155      0   stevel 
    156      0   stevel 	/*
    157      0   stevel 	 * %rdi = boot services (should die someday)
    158      0   stevel 	 * %rdx = bootops
    159      0   stevel 	 * end
    160      0   stevel 	 */
    161      0   stevel 
    162      0   stevel 	leaq	edata(%rip), %rbp	/* reference edata for ksyms */
    163      0   stevel 	movq	$0, (%rbp)		/* limit stack back trace */
    164      0   stevel 
    165      0   stevel 	/*
    166      0   stevel 	 * Initialize our stack pointer to the thread 0 stack (t0stack)
    167      0   stevel 	 * and leave room for a "struct regs" for lwp0.  Note that the
    168      0   stevel 	 * stack doesn't actually align to a 16-byte boundary until just
    169      0   stevel 	 * before we call mlsetup because we want to use %rsp to point at
    170      0   stevel 	 * our regs structure.
    171      0   stevel 	 */
    172      0   stevel 	leaq	t0stack(%rip), %rsp
    173      0   stevel 	addq	$_CONST(DEFAULTSTKSZ - REGSIZE), %rsp
    174      0   stevel #if (REGSIZE & 15) == 0
    175      0   stevel 	subq	$8, %rsp
    176      0   stevel #endif
    177      0   stevel 	/*
    178      0   stevel 	 * Save call back for special x86 boot services vector
    179      0   stevel 	 */
    180      0   stevel 	movq	%rdi, sysp(%rip)
    181      0   stevel 
    182      0   stevel 	movq	%rdx, bootops(%rip)		/* save bootops */
    183      0   stevel 	movq	$bootops, bootopsp(%rip)
    184      0   stevel 
    185      0   stevel 	/*
    186      0   stevel 	 * Save arguments and flags, if only for debugging ..
    187      0   stevel 	 */
    188      0   stevel 	movq	%rdi, REGOFF_RDI(%rsp)
    189      0   stevel 	movq	%rsi, REGOFF_RSI(%rsp)
    190      0   stevel 	movq	%rdx, REGOFF_RDX(%rsp)
    191      0   stevel 	movq	%rcx, REGOFF_RCX(%rsp)
    192      0   stevel 	movq	%r8, REGOFF_R8(%rsp)
    193      0   stevel 	movq	%r9, REGOFF_R9(%rsp)
    194      0   stevel 	pushf
    195      0   stevel 	popq	%r11
    196      0   stevel 	movq	%r11, REGOFF_RFL(%rsp)
    197      0   stevel 
    198   5084  johnlev #if !defined(__xpv)
    199      0   stevel 	/*
    200      0   stevel 	 * Enable write protect and alignment check faults.
    201      0   stevel 	 */
    202      0   stevel 	movq	%cr0, %rax
    203      0   stevel 	orq	$_CONST(CR0_WP|CR0_AM), %rax
    204      0   stevel 	andq	$_BITNOT(CR0_WT|CR0_CE), %rax
    205      0   stevel 	movq	%rax, %cr0
    206   5084  johnlev #endif	/* __xpv */
    207      0   stevel 
    208      0   stevel 	/*
    209      0   stevel 	 * (We just assert this works by virtue of being here)
    210      0   stevel 	 */
    211      0   stevel 	orl	$X86_CPUID, x86_feature(%rip)
    212      0   stevel 
    213      0   stevel 	/*
    214      0   stevel 	 * mlsetup() gets called with a struct regs as argument, while
    215      0   stevel 	 * main takes no args and should never return.
    216      0   stevel 	 */
    217      0   stevel 	xorl	%ebp, %ebp
    218      0   stevel 	movq	%rsp, %rdi
    219      0   stevel 	pushq	%rbp
    220      0   stevel 	/* (stack pointer now aligned on 16-byte boundary right here) */
    221      0   stevel 	movq	%rsp, %rbp
    222      0   stevel 	call	mlsetup
    223      0   stevel 	call	main
    224      0   stevel 	/* NOTREACHED */
    225      0   stevel 	leaq	__return_from_main(%rip), %rdi
    226      0   stevel 	xorl	%eax, %eax
    227      0   stevel 	call	panic
    228   3446      mrj 	SET_SIZE(_locore_start)
    229      0   stevel 
    230      0   stevel #endif	/* __amd64 */
    231      0   stevel #endif	/* __lint */
    232      0   stevel 
    233      0   stevel #if !defined(__lint)
    234      0   stevel 
    235      0   stevel __return_from_main:
    236      0   stevel 	.string	"main() returned"
    237      0   stevel __unsupported_cpu:
    238      0   stevel 	.string	"486 style cpu detected - no longer supported!"
    239      0   stevel 
    240      0   stevel #endif	/* !__lint */
    241      0   stevel 
    242      0   stevel #if !defined(__amd64)
    243      0   stevel 
    244      0   stevel #if defined(__lint)
    245      0   stevel 
    246   3446      mrj /* ARGSUSED */
    247      0   stevel void
    248   3446      mrj _locore_start(struct boot_syscalls *sysp, struct bootops *bop)
    249      0   stevel {}
    250      0   stevel 
    251      0   stevel #else	/* __lint */
    252      0   stevel 
    253      0   stevel 	/*
    254   3446      mrj 	 * kobj_init() vectors us back to here with (note) a slightly different
    255   3446      mrj 	 * set of arguments than _start is given (see lint prototypes above).
    256   5084  johnlev 	 *
    257   5084  johnlev 	 * XXX	Make this less vile, please.
    258      0   stevel 	 */
    259   3446      mrj 	ENTRY_NP(_locore_start)
    260      0   stevel 
    261      0   stevel 	/*
    262      0   stevel 	 *	%ecx = boot services (should die someday)
    263      0   stevel 	 *	%ebx = bootops
    264    414    kchow 	 */
    265      0   stevel 	mov	$edata, %ebp		/ edata needs to be defined for ksyms
    266      0   stevel 	movl	$0, (%ebp)		/ limit stack back trace
    267      0   stevel 
    268      0   stevel 	/*
    269      0   stevel 	 * Initialize our stack pointer to the thread 0 stack (t0stack)
    270      0   stevel 	 * and leave room for a phony "struct regs".
    271      0   stevel 	 */
    272      0   stevel 	movl	$t0stack + DEFAULTSTKSZ - REGSIZE, %esp
    273      0   stevel 
    274      0   stevel 	/*
    275      0   stevel 	 * Save call back for special x86 boot services vector
    276      0   stevel 	 */
    277      0   stevel 	mov	%ecx, sysp		/ save call back for boot services
    278      0   stevel 
    279      0   stevel  	mov	%ebx, bootops		/ save bootops
    280      0   stevel 	movl	$bootops, bootopsp
    281      0   stevel 
    282   3446      mrj 
    283      0   stevel 	/*
    284      0   stevel 	 * Save all registers and flags
    285      0   stevel 	 */
    286      0   stevel 	pushal
    287      0   stevel 	pushfl
    288      0   stevel 
    289   5084  johnlev #if !defined(__xpv)
    290      0   stevel 	/*
    291      0   stevel 	 * Override bios settings and enable write protect and
    292      0   stevel 	 * alignment check faults.
    293      0   stevel 	 */
    294      0   stevel 	movl	%cr0, %eax
    295      0   stevel 
    296      0   stevel 	/*
    297      0   stevel 	 * enable WP for detecting faults, and enable alignment checking.
    298      0   stevel 	 */
    299      0   stevel 	orl	$_CONST(CR0_WP|CR0_AM), %eax
    300      0   stevel 	andl	$_BITNOT(CR0_WT|CR0_CE), %eax
    301      0   stevel 	movl	%eax, %cr0		/ set the cr0 register correctly and
    302      0   stevel 					/ override the BIOS setup
    303   3446      mrj 
    304      0   stevel 	/*
    305      0   stevel 	 * If bit 21 of eflags can be flipped, then cpuid is present
    306      0   stevel 	 * and enabled.
    307      0   stevel 	 */
    308      0   stevel 	pushfl
    309      0   stevel 	popl	%ecx
    310      0   stevel 	movl	%ecx, %eax
    311      0   stevel 	xorl	$PS_ID, %eax		/ try complemented bit
    312      0   stevel 	pushl	%eax
    313      0   stevel 	popfl
    314      0   stevel 	pushfl
    315      0   stevel 	popl    %eax
    316      0   stevel 	cmpl	%eax, %ecx
    317      0   stevel 	jne	have_cpuid
    318      0   stevel 
    319      0   stevel 	/*
    320      0   stevel 	 * cpuid may be disabled on Cyrix, try to detect Cyrix by the 5/2 test
    321      0   stevel 	 * div does not modify the cc flags on Cyrix, even though this may
    322      0   stevel 	 * also be true for other vendors, this is generally true only for
    323      0   stevel 	 * newer models from those vendors that support and do not disable
    324      0   stevel 	 * cpuid (usually because cpuid cannot be disabled)
    325      0   stevel 	 */
    326      0   stevel 
    327      0   stevel 	/*
    328      0   stevel 	 * clear cc flags
    329      0   stevel 	 */
    330      0   stevel 	xorb	%ah, %ah
    331      0   stevel 	sahf
    332      0   stevel 
    333      0   stevel 	/*
    334      0   stevel 	 * perform 5/2 test
    335      0   stevel 	 */
    336      0   stevel 	movw	$5, %ax
    337      0   stevel 	movb	$2, %bl
    338      0   stevel 	divb	%bl
    339      0   stevel 
    340      0   stevel 	lahf
    341      0   stevel 	cmpb	$2, %ah
    342      0   stevel 	jne	cpu_486
    343      0   stevel 
    344      0   stevel 	/*
    345      0   stevel 	 * div did not modify the cc flags, chances are the vendor is Cyrix
    346      0   stevel 	 * assume the vendor is Cyrix and use the CCR's to enable cpuid
    347      0   stevel 	 */
    348      0   stevel 	.set	CYRIX_CRI, 0x22		/ CR Index Register
    349      0   stevel 	.set	CYRIX_CRD, 0x23		/ CR Data Register
    350      0   stevel 
    351      0   stevel 	.set	CYRIX_CCR3, 0xc3	/ Config Control Reg 3
    352      0   stevel 	.set	CYRIX_CCR4, 0xe8	/ Config Control Reg 4
    353      0   stevel 	.set	CYRIX_DIR0, 0xfe	/ Device Identification Reg 0
    354      0   stevel 	.set	CYRIX_DIR1, 0xff	/ Device Identification Reg 1
    355      0   stevel 
    356      0   stevel 	/*
    357      0   stevel 	 * even if the cpu vendor is Cyrix and the motherboard/chipset
    358      0   stevel 	 * vendor decided to ignore lines A1-A4 for I/O addresses, I/O port
    359      0   stevel 	 * 0x21 corresponds with 0x23 and since 0x22 is still untouched,
    360      0   stevel 	 * the reads and writes of 0x21 are guaranteed to be off-chip of
    361      0   stevel 	 * the cpu
    362      0   stevel 	 */
    363      0   stevel 
    364      0   stevel 	/*
    365      0   stevel 	 * enable read of ISR at I/O port 0x20
    366      0   stevel 	 */
    367      0   stevel 	movb	$0xb, %al
    368      0   stevel 	outb	$MCMD_PORT
    369      0   stevel 
    370      0   stevel 	/*
    371      0   stevel 	 * read IMR and store in %bl
    372      0   stevel 	 */
    373      0   stevel 	inb	$MIMR_PORT
    374      0   stevel 	movb	%al, %bl
    375      0   stevel 
    376      0   stevel 	/*
    377      0   stevel 	 * mask out all interrupts so that ISR will not change
    378      0   stevel 	 */
    379      0   stevel 	movb	$0xff, %al
    380      0   stevel 	outb	$MIMR_PORT
    381      0   stevel 
    382      0   stevel 	/*
    383      0   stevel 	 * reads of I/O port 0x22 on Cyrix are always directed off-chip
    384      0   stevel 	 * make use of I/O pull-up to test for an unknown device on 0x22
    385      0   stevel 	 */
    386      0   stevel 	inb	$CYRIX_CRI
    387      0   stevel 	cmpb	$0xff, %al
    388      0   stevel 	je	port_22_free
    389      0   stevel 
    390      0   stevel 	/*
    391      0   stevel 	 * motherboard/chipset vendor may be ignoring line A1 of I/O address
    392      0   stevel 	 */
    393      0   stevel 	movb	%al, %cl
    394      0   stevel 
    395      0   stevel 	/*
    396      0   stevel 	 * if the ISR and the value read from 0x22 do not match then we have
    397      0   stevel 	 * detected some unknown device, probably a chipset, at 0x22
    398      0   stevel 	 */
    399      0   stevel 	inb	$MCMD_PORT
    400      0   stevel 	cmpb	%al, %cl
    401      0   stevel 	jne	restore_IMR
    402      0   stevel 
    403      0   stevel port_22_free:
    404      0   stevel 	/*
    405      0   stevel 	 * now test to see if some unknown device is using I/O port 0x23
    406      0   stevel 	 *
    407      0   stevel 	 * read the external I/O port at 0x23
    408      0   stevel 	 */
    409      0   stevel 	inb	$CYRIX_CRD
    410      0   stevel 
    411      0   stevel 	/*
    412      0   stevel 	 * Test for pull-up at 0x23 or if I/O address line A1 is being ignored.
    413      0   stevel 	 * IMR is 0xff so both tests are performed simultaneously.
    414      0   stevel 	 */
    415      0   stevel 	cmpb	$0xff, %al
    416      0   stevel 	jne	restore_IMR
    417      0   stevel 
    418      0   stevel 	/*
    419      0   stevel 	 * We are a Cyrix part. In case we are some model of Cx486 or a Cx586,
    420      0   stevel 	 * record the type and fix it later if not.
    421      0   stevel 	 */
    422      0   stevel 	movl	$X86_VENDOR_Cyrix, x86_vendor
    423      0   stevel 	movl	$X86_TYPE_CYRIX_486, x86_type
    424      0   stevel 
    425      0   stevel 	/*
    426      0   stevel 	 * Try to read CCR3. All Cyrix cpu's which support cpuid have CCR3.
    427      0   stevel 	 *
    428      0   stevel 	 * load CCR3 index into CCR index register
    429      0   stevel 	 */
    430      0   stevel 
    431      0   stevel 	movb	$CYRIX_CCR3, %al
    432      0   stevel 	outb	$CYRIX_CRI
    433      0   stevel 
    434      0   stevel 	/*
    435      0   stevel 	 * If we are not a Cyrix cpu, then we have performed an external I/O
    436      0   stevel 	 * cycle. If the CCR index was not valid for this Cyrix model, we may
    437      0   stevel 	 * have performed an external I/O cycle as well. In these cases and
    438      0   stevel 	 * if the motherboard/chipset vendor ignores I/O address line A1,
    439      0   stevel 	 * then the PIC will have IRQ3 set at the lowest priority as a side
    440      0   stevel 	 * effect of the above outb. We are reasonalbly confident that there
    441      0   stevel 	 * is not an unknown device on I/O port 0x22, so there should have been
    442      0   stevel 	 * no unpredictable side-effect of the above outb.
    443      0   stevel 	 */
    444      0   stevel 
    445      0   stevel 	/*
    446      0   stevel 	 * read CCR3
    447      0   stevel 	 */
    448      0   stevel 	inb	$CYRIX_CRD
    449      0   stevel 
    450      0   stevel 	/*
    451      0   stevel 	 * If we are not a Cyrix cpu the inb above produced an external I/O
    452      0   stevel 	 * cycle. If we are a Cyrix model that does not support CCR3 wex
    453      0   stevel 	 * produced an external I/O cycle. In all known Cyrix models 6x86 and
    454      0   stevel 	 * above, bit 3 of CCR3 is reserved and cannot be set to 1. In all
    455      0   stevel 	 * Cyrix models prior to the 6x86 that supported CCR3, bits 4-7 are
    456      0   stevel 	 * reserved as well. It is highly unlikely that CCR3 contains the value
    457      0   stevel 	 * 0xff. We test to see if I/O port 0x23 is pull-up or the IMR and
    458      0   stevel 	 * deduce we are not a Cyrix with support for cpuid if so.
    459      0   stevel 	 */
    460      0   stevel 	cmpb	$0xff, %al
    461      0   stevel 	je	restore_PIC
    462      0   stevel 
    463      0   stevel 	/*
    464      0   stevel 	 * There exist 486 ISA Cyrix chips that support CCR3 but do not support
    465      0   stevel 	 * DIR0 and DIR1. If we try to read DIR0, we may generate external I/O
    466      0   stevel 	 * cycles, the exact behavior is model specific and undocumented.
    467      0   stevel 	 * Unfortunately these external I/O cycles may confuse some PIC's beyond
    468      0   stevel 	 * recovery. Fortunatetly we can use the following undocumented trick:
    469      0   stevel 	 * if bit 4 of CCR3 can be toggled, then DIR0 and DIR1 are supported.
    470      0   stevel 	 * Pleasantly MAPEN contains bit 4 of CCR3, so this trick is guaranteed
    471      0   stevel 	 * to work on all Cyrix cpu's which support cpuid.
    472      0   stevel 	 */
    473      0   stevel 	movb	%al, %dl
    474      0   stevel 	xorb	$0x10, %dl
    475      0   stevel 	movb	%al, %cl
    476      0   stevel 
    477      0   stevel 	/*
    478      0   stevel 	 * write back CRR3 with toggled bit 4 to CCR3
    479      0   stevel 	 */
    480      0   stevel 	movb	$CYRIX_CCR3, %al
    481      0   stevel 	outb	$CYRIX_CRI
    482      0   stevel 
    483      0   stevel 	movb	%dl, %al
    484      0   stevel 	outb	$CYRIX_CRD
    485      0   stevel 
    486      0   stevel 	/*
    487      0   stevel 	 * read CCR3
    488      0   stevel 	 */
    489      0   stevel 	movb	$CYRIX_CCR3, %al
    490      0   stevel 	outb	$CYRIX_CRI
    491      0   stevel 	inb	$CYRIX_CRD
    492      0   stevel 	movb	%al, %dl
    493      0   stevel 
    494      0   stevel 	/*
    495      0   stevel 	 * restore CCR3
    496      0   stevel 	 */
    497      0   stevel 	movb	$CYRIX_CCR3, %al
    498      0   stevel 	outb	$CYRIX_CRI
    499      0   stevel 
    500      0   stevel 	movb	%cl, %al
    501      0   stevel 	outb	$CYRIX_CRD
    502      0   stevel 
    503      0   stevel 	/*
    504      0   stevel 	 * if bit 4 was not toggled DIR0 and DIR1 are not supported in which
    505      0   stevel 	 * case we do not have cpuid anyway
    506      0   stevel 	 */
    507      0   stevel 	andb	$0x10, %al
    508      0   stevel 	andb	$0x10, %dl
    509      0   stevel 	cmpb	%al, %dl
    510      0   stevel 	je	restore_PIC
    511      0   stevel 
    512      0   stevel 	/*
    513      0   stevel 	 * read DIR0
    514      0   stevel 	 */
    515      0   stevel 	movb	$CYRIX_DIR0, %al
    516      0   stevel 	outb	$CYRIX_CRI
    517      0   stevel 	inb	$CYRIX_CRD
    518      0   stevel 
    519      0   stevel 	/*
    520      0   stevel 	 * test for pull-up
    521      0   stevel 	 */
    522      0   stevel 	cmpb	$0xff, %al
    523      0   stevel 	je	restore_PIC
    524      0   stevel 
    525      0   stevel 	/*
    526      0   stevel 	 * Values of 0x20-0x27 in DIR0 are currently reserved by Cyrix for
    527      0   stevel 	 * future use. If Cyrix ever produces a cpu that supports cpuid with
    528      0   stevel 	 * these ids, the following test will have to change. For now we remain
    529      0   stevel 	 * pessimistic since the formats of the CRR's may be different then.
    530      0   stevel 	 *
    531      0   stevel 	 * test for at least a 6x86, to see if we support both MAPEN and CPUID
    532      0   stevel 	 */
    533      0   stevel 	cmpb	$0x30, %al
    534      0   stevel 	jb	restore_IMR
    535      0   stevel 
    536      0   stevel 	/*
    537      0   stevel 	 * enable MAPEN
    538      0   stevel 	 */
    539      0   stevel 	movb	$CYRIX_CCR3, %al
    540      0   stevel 	outb	$CYRIX_CRI
    541      0   stevel 
    542      0   stevel 	andb	$0xf, %cl
    543      0   stevel 	movb	%cl, %al
    544      0   stevel 	orb	$0x10, %al
    545      0   stevel 	outb	$CYRIX_CRD
    546      0   stevel 
    547      0   stevel 	/*
    548      0   stevel 	 * select CCR4
    549      0   stevel 	 */
    550      0   stevel 	movb	$CYRIX_CCR4, %al
    551      0   stevel 	outb	$CYRIX_CRI
    552      0   stevel 
    553      0   stevel 	/*
    554      0   stevel 	 * read CCR4
    555      0   stevel 	 */
    556      0   stevel 	inb	$CYRIX_CRD
    557      0   stevel 
    558      0   stevel 	/*
    559      0   stevel 	 * enable cpuid
    560      0   stevel 	 */
    561      0   stevel 	orb	$0x80, %al
    562      0   stevel 	movb	%al, %dl
    563      0   stevel 
    564      0   stevel 	/*
    565      0   stevel 	 * select CCR4
    566      0   stevel 	 */
    567      0   stevel 	movb	$CYRIX_CCR4, %al
    568      0   stevel 	outb	$CYRIX_CRI
    569      0   stevel 
    570      0   stevel 	/*
    571      0   stevel 	 * write CCR4
    572      0   stevel 	 */
    573      0   stevel 	movb	%dl, %al
    574      0   stevel 	outb	$CYRIX_CRD
    575      0   stevel 
    576      0   stevel 	/*
    577      0   stevel 	 * select CCR3
    578      0   stevel 	 */
    579      0   stevel 	movb	$CYRIX_CCR3, %al
    580      0   stevel 	outb	$CYRIX_CRI
    581      0   stevel 
    582      0   stevel 	/*
    583      0   stevel 	 * disable MAPEN and write CCR3
    584      0   stevel 	 */
    585      0   stevel 	movb	%cl, %al
    586      0   stevel 	outb	$CYRIX_CRD
    587      0   stevel 
    588      0   stevel 	/*
    589      0   stevel 	 * restore IMR
    590      0   stevel 	 */
    591      0   stevel 	movb	%bl, %al
    592      0   stevel 	outb	$MIMR_PORT
    593      0   stevel 
    594      0   stevel 	/*
    595      0   stevel 	 * test to see if cpuid available
    596      0   stevel 	 */
    597      0   stevel 	pushfl
    598      0   stevel 	popl	%ecx
    599      0   stevel 	movl	%ecx, %eax
    600      0   stevel 	xorl	$PS_ID, %eax		/ try complemented bit
    601      0   stevel 	pushl	%eax
    602      0   stevel 	popfl
    603      0   stevel 	pushfl
    604      0   stevel 	popl    %eax
    605      0   stevel 	cmpl	%eax, %ecx
    606      0   stevel 	jne	have_cpuid
    607      0   stevel 	jmp	cpu_486
    608      0   stevel 
    609      0   stevel restore_PIC:
    610      0   stevel 	/*
    611      0   stevel 	 * In case the motherboard/chipset vendor is ignoring line A1 of the
    612      0   stevel 	 * I/O address, we set the PIC priorities to sane values.
    613      0   stevel 	 */
    614      0   stevel 	movb	$0xc7, %al	/ irq 7 lowest priority
    615      0   stevel 	outb	$MCMD_PORT
    616      0   stevel 
    617      0   stevel restore_IMR:
    618      0   stevel 	movb	%bl, %al
    619      0   stevel 	outb	$MIMR_PORT
    620      0   stevel 	jmp	cpu_486
    621      0   stevel 
    622      0   stevel have_cpuid:
    623      0   stevel 	/*
    624      0   stevel 	 * cpuid instruction present
    625      0   stevel 	 */
    626      0   stevel 	orl	$X86_CPUID, x86_feature
    627      0   stevel 	movl	$0, %eax
    628      0   stevel 	cpuid
    629      0   stevel 
    630      0   stevel 	movl	%ebx, cpu_vendor
    631      0   stevel 	movl	%edx, cpu_vendor+4
    632      0   stevel 	movl	%ecx, cpu_vendor+8
    633      0   stevel 
    634      0   stevel 	/*
    635      0   stevel 	 * early cyrix cpus are somewhat strange and need to be
    636      0   stevel 	 * probed in curious ways to determine their identity
    637      0   stevel 	 */
    638      0   stevel 
    639      0   stevel 	leal	cpu_vendor, %esi
    640      0   stevel 	leal	CyrixInstead, %edi
    641      0   stevel 	movl	$12, %ecx
    642      0   stevel 	repz
    643      0   stevel 	  cmpsb
    644      0   stevel 	je	vendor_is_cyrix
    645      0   stevel 
    646      0   stevel 	/ let mlsetup()/cpuid_pass1() handle everything else in C
    647      0   stevel 
    648      0   stevel 	jmp	cpu_done
    649      0   stevel 
    650      0   stevel is486:
    651      0   stevel 	/*
    652      0   stevel 	 * test to see if a useful cpuid
    653      0   stevel 	 */
    654      0   stevel 	testl	%eax, %eax
    655      0   stevel 	jz	isa486
    656      0   stevel 
    657      0   stevel 	movl	$1, %eax
    658      0   stevel 	cpuid
    659      0   stevel 
    660      0   stevel 	movl	%eax, %ebx
    661      0   stevel 	andl	$0xF00, %ebx
    662      0   stevel 	cmpl	$0x400, %ebx
    663      0   stevel 	je	isa486
    664      0   stevel 
    665    545    kalai 	rep;	ret	/* use 2 byte return instruction */
    666    545    kalai 			/* AMD Software Optimization Guide - Section 6.2 */
    667      0   stevel isa486:
    668      0   stevel 	/*
    669      0   stevel 	 * lose the return address
    670      0   stevel 	 */
    671      0   stevel 	popl	%eax
    672      0   stevel 	jmp	cpu_486
    673      0   stevel 
    674      0   stevel vendor_is_cyrix:
    675      0   stevel 	call	is486
    676      0   stevel 
    677      0   stevel 	/*
    678      0   stevel 	 * Processor signature and feature flags for Cyrix are insane.
    679      0   stevel 	 * BIOS can play with semi-documented registers, so cpuid must be used
    680      0   stevel 	 * cautiously. Since we are Cyrix that has cpuid, we have DIR0 and DIR1
    681      0   stevel 	 * Keep the family in %ebx and feature flags in %edx until not needed
    682      0   stevel 	 */
    683      0   stevel 
    684      0   stevel 	/*
    685      0   stevel 	 * read DIR0
    686      0   stevel 	 */
    687      0   stevel 	movb	$CYRIX_DIR0, %al
    688      0   stevel 	outb	$CYRIX_CRI
    689      0   stevel 	inb	$CYRIX_CRD
    690      0   stevel 
    691      0   stevel 	/*
    692      0   stevel 	 * First we handle the cases where we are a 6x86 or 6x86L.
    693      0   stevel 	 * The 6x86 is basically a 486, the only reliable bit in the
    694      0   stevel 	 * feature flags is for FPU. The 6x86L is better, unfortunately
    695      0   stevel 	 * there is no really good way to distinguish between these two
    696      0   stevel 	 * cpu's. We are pessimistic and when in doubt assume 6x86.
    697      0   stevel 	 */
    698      0   stevel 
    699      0   stevel 	cmpb	$0x40, %al
    700      0   stevel 	jae	maybeGX
    701      0   stevel 
    702      0   stevel 	/*
    703      0   stevel 	 * We are an M1, either a 6x86 or 6x86L.
    704      0   stevel 	 */
    705      0   stevel 	cmpb	$0x30, %al
    706      0   stevel 	je	maybe6x86L
    707      0   stevel 	cmpb	$0x31, %al
    708      0   stevel 	je	maybe6x86L
    709      0   stevel 	cmpb	$0x34, %al
    710      0   stevel 	je	maybe6x86L
    711      0   stevel 	cmpb	$0x35, %al
    712      0   stevel 	je	maybe6x86L
    713      0   stevel 
    714      0   stevel 	/*
    715      0   stevel 	 * although it is possible that we are a 6x86L, the cpu and
    716      0   stevel 	 * documentation are so buggy, we just do not care.
    717      0   stevel 	 */
    718      0   stevel 	jmp	likely6x86
    719      0   stevel 
    720      0   stevel maybe6x86L:
    721      0   stevel 	/*
    722      0   stevel 	 *  read DIR1
    723      0   stevel 	 */
    724      0   stevel 	movb	$CYRIX_DIR1, %al
    725      0   stevel 	outb	$CYRIX_CRI
    726      0   stevel 	inb	$CYRIX_CRD
    727      0   stevel 	cmpb	$0x22, %al
    728      0   stevel 	jb	likely6x86
    729      0   stevel 
    730      0   stevel 	/*
    731      0   stevel 	 * We are a 6x86L, or at least a 6x86 with honest cpuid feature flags
    732      0   stevel 	 */
    733      0   stevel 	movl	$X86_TYPE_CYRIX_6x86L, x86_type
    734      0   stevel 	jmp	coma_bug
    735      0   stevel 
    736      0   stevel likely6x86:
    737      0   stevel 	/*
    738      0   stevel 	 * We are likely a 6x86, or a 6x86L without a way of knowing
    739      0   stevel 	 *
    740      0   stevel 	 * The 6x86 has NO Pentium or Pentium Pro compatible features even
    741      0   stevel 	 * though it claims to be a Pentium Pro compatible!
    742      0   stevel 	 *
    743      0   stevel 	 * The 6x86 core used in the 6x86 may have most of the Pentium system
    744      0   stevel 	 * registers and largely conform to the Pentium System Programming
    745      0   stevel 	 * Reference. Documentation on these parts is long gone. Treat it as
    746      0   stevel 	 * a crippled Pentium and hope for the best.
    747      0   stevel 	 */
    748      0   stevel 
    749      0   stevel 	movl	$X86_TYPE_CYRIX_6x86, x86_type
    750      0   stevel 	jmp	coma_bug
    751      0   stevel 
    752      0   stevel maybeGX:
    753      0   stevel 	/*
    754      0   stevel 	 * Now we check whether we are a MediaGX or GXm. We have particular
    755      0   stevel 	 * reason for concern here. Even though most of the GXm's
    756      0   stevel 	 * report having TSC in the cpuid feature flags, the TSC may be
    757      0   stevel 	 * horribly broken. What is worse, is that MediaGX's are basically
    758      0   stevel 	 * 486's while the good GXm's are more like Pentium Pro's!
    759      0   stevel 	 */
    760      0   stevel 
    761      0   stevel 	cmpb	$0x50, %al
    762      0   stevel 	jae	maybeM2
    763      0   stevel 
    764      0   stevel 	/*
    765      0   stevel 	 * We are either a MediaGX (sometimes called a Gx86) or GXm
    766      0   stevel 	 */
    767      0   stevel 
    768      0   stevel 	cmpb	$41, %al
    769      0   stevel 	je	maybeMediaGX
    770      0   stevel 
    771      0   stevel 	cmpb	$44, %al
    772      0   stevel 	jb	maybeGXm
    773      0   stevel 
    774      0   stevel 	cmpb	$47, %al
    775      0   stevel 	jbe	maybeMediaGX
    776      0   stevel 
    777      0   stevel 	/*
    778      0   stevel 	 * We do not honestly know what we are, so assume a MediaGX
    779      0   stevel 	 */
    780      0   stevel 	jmp	media_gx
    781      0   stevel 
    782      0   stevel maybeGXm:
    783      0   stevel 	/*
    784      0   stevel 	 * It is still possible we are either a MediaGX or GXm, trust cpuid
    785      0   stevel 	 * family should be 5 on a GXm
    786      0   stevel 	 */
    787      0   stevel 	cmpl	$0x500, %ebx
    788      0   stevel 	je	GXm
    789      0   stevel 
    790      0   stevel 	/*
    791      0   stevel 	 * BIOS/Cyrix might set family to 6 on a GXm
    792      0   stevel 	 */
    793      0   stevel 	cmpl	$0x600, %ebx
    794      0   stevel 	jne	media_gx
    795      0   stevel 
    796      0   stevel GXm:
    797      0   stevel 	movl	$X86_TYPE_CYRIX_GXm, x86_type
    798      0   stevel 	jmp	cpu_done
    799      0   stevel 
    800      0   stevel maybeMediaGX:
    801      0   stevel 	/*
    802      0   stevel 	 * read DIR1
    803      0   stevel 	 */
    804      0   stevel 	movb	$CYRIX_DIR1, %al
    805      0   stevel 	outb	$CYRIX_CRI
    806      0   stevel 	inb	$CYRIX_CRD
    807      0   stevel 
    808      0   stevel 	cmpb	$0x30, %al
    809      0   stevel 	jae	maybeGXm
    810      0   stevel 
    811      0   stevel 	/*
    812      0   stevel 	 * we are a MediaGX for which we do not trust cpuid
    813      0   stevel 	 */
    814      0   stevel media_gx:
    815      0   stevel 	movl	$X86_TYPE_CYRIX_MediaGX, x86_type
    816      0   stevel 	jmp	cpu_486
    817      0   stevel 
    818      0   stevel maybeM2:
    819      0   stevel 	/*
    820      0   stevel 	 * Now we check whether we are a 6x86MX or MII. These cpu's are
    821      0   stevel 	 * virtually identical, but we care because for the 6x86MX, we
    822      0   stevel 	 * must work around the coma bug. Also for 6x86MX prior to revision
    823      0   stevel 	 * 1.4, the TSC may have serious bugs.
    824      0   stevel 	 */
    825      0   stevel 
    826      0   stevel 	cmpb	$0x60, %al
    827      0   stevel 	jae	maybeM3
    828      0   stevel 
    829      0   stevel 	/*
    830      0   stevel 	 * family should be 6, but BIOS/Cyrix might set it to 5
    831      0   stevel 	 */
    832      0   stevel 	cmpl	$0x600, %ebx
    833      0   stevel 	ja	cpu_486
    834      0   stevel 
    835      0   stevel 	/*
    836      0   stevel 	 *  read DIR1
    837      0   stevel 	 */
    838      0   stevel 	movb	$CYRIX_DIR1, %al
    839      0   stevel 	outb	$CYRIX_CRI
    840      0   stevel 	inb	$CYRIX_CRD
    841      0   stevel 
    842      0   stevel 	cmpb	$0x8, %al
    843      0   stevel 	jb	cyrix6x86MX
    844      0   stevel 	cmpb	$0x80, %al
    845      0   stevel 	jb	MII
    846      0   stevel 
    847      0   stevel cyrix6x86MX:
    848      0   stevel 	/*
    849      0   stevel 	 * It is altogether unclear how the revision stamped on the cpu
    850      0   stevel 	 * maps to the values in DIR0 and DIR1. Just assume TSC is broken.
    851      0   stevel 	 */
    852      0   stevel 	movl	$X86_TYPE_CYRIX_6x86MX, x86_type
    853      0   stevel 	jmp	coma_bug
    854      0   stevel 
    855      0   stevel MII:
    856      0   stevel 	movl	$X86_TYPE_CYRIX_MII, x86_type
    857      0   stevel likeMII:
    858      0   stevel 	jmp	cpu_done
    859      0   stevel 
    860      0   stevel maybeM3:
    861      0   stevel 	/*
    862      0   stevel 	 * We are some chip that we cannot identify yet, an MIII perhaps.
    863      0   stevel 	 * We will be optimistic and hope that the chip is much like an MII,
    864      0   stevel 	 * and that cpuid is sane. Cyrix seemed to have gotten it right in
    865      0   stevel 	 * time for the MII, we can only hope it stayed that way.
    866      0   stevel 	 * Maybe the BIOS or Cyrix is trying to hint at something
    867      0   stevel 	 */
    868      0   stevel 	cmpl	$0x500, %ebx
    869      0   stevel 	je	GXm
    870      0   stevel 
    871      0   stevel 	cmpb	$0x80, %al
    872      0   stevel 	jae	likelyM3
    873      0   stevel 
    874      0   stevel 	/*
    875      0   stevel 	 * Just test for the features Cyrix is known for
    876      0   stevel 	 */
    877      0   stevel 
    878      0   stevel 	jmp	MII
    879      0   stevel 
    880      0   stevel likelyM3:
    881      0   stevel 	/*
    882      0   stevel 	 * DIR0 with values from 0x80 to 0x8f indicates a VIA Cyrix III, aka
    883      0   stevel 	 * the Cyrix MIII. There may be parts later that use the same ranges
    884      0   stevel 	 * for DIR0 with special values in DIR1, maybe the VIA CIII, but for
    885      0   stevel 	 * now we will call anything with a DIR0 of 0x80 or higher an MIII.
    886      0   stevel 	 * The MIII is supposed to support large pages, but we will believe
    887      0   stevel 	 * it when we see it. For now we just enable and test for MII features.
    888      0   stevel 	 */
    889      0   stevel 	movl	$X86_TYPE_VIA_CYRIX_III, x86_type
    890      0   stevel 	jmp	likeMII
    891      0   stevel 
    892      0   stevel coma_bug:
    893      0   stevel 
    894      0   stevel /*
    895      0   stevel  * With NO_LOCK set to 0 in CCR1, the usual state that BIOS enforces, some
    896      0   stevel  * bus cycles are issued with LOCK# asserted. With NO_LOCK set to 1, all bus
    897      0   stevel  * cycles except page table accesses and interrupt ACK cycles do not assert
    898      0   stevel  * LOCK#. xchgl is an instruction that asserts LOCK# if NO_LOCK is set to 0.
    899      0   stevel  * Due to a bug in the cpu core involving over-optimization of branch
    900      0   stevel  * prediction, register renaming, and execution of instructions down both the
    901      0   stevel  * X and Y pipes for the xchgl instruction, short loops can be written that
    902      0   stevel  * never de-assert LOCK# from one invocation of the loop to the next, ad
    903      0   stevel  * infinitum. The undesirable effect of this situation is that interrupts are
    904      0   stevel  * not serviced. The ideal workaround to this bug would be to set NO_LOCK to
    905      0   stevel  * 1. Unfortunately bus cycles that would otherwise have asserted LOCK# no
    906      0   stevel  * longer do, unless they are page table accesses or interrupt ACK cycles.
    907      0   stevel  * With LOCK# not asserted, these bus cycles are now cached. This can cause
    908      0   stevel  * undesirable behaviour if the ARR's are not configured correctly. Solaris
    909      0   stevel  * does not configure the ARR's, nor does it provide any useful mechanism for
    910      0   stevel  * doing so, thus the ideal workaround is not viable. Fortunately, the only
    911      0   stevel  * known exploits for this bug involve the xchgl instruction specifically.
    912      0   stevel  * There is a group of undocumented registers on Cyrix 6x86, 6x86L, and
    913      0   stevel  * 6x86MX cpu's which can be used to specify one instruction as a serializing
    914      0   stevel  * instruction. With the xchgl instruction serialized, LOCK# is still
    915      0   stevel  * asserted, but it is the sole instruction for which LOCK# is asserted.
    916      0   stevel  * There is now some added penalty for the xchgl instruction, but the usual
    917      0   stevel  * bus locking is preserved. This ingenious workaround was discovered by
    918      0   stevel  * disassembling a binary provided by Cyrix as a workaround for this bug on
    919      0   stevel  * Windows, but its not documented anywhere by Cyrix, nor is the bug actually
    920      0   stevel  * mentioned in any public errata! The only concern for this workaround is
    921      0   stevel  * that there may be similar undiscovered bugs with other instructions that
    922      0   stevel  * assert LOCK# that may be leveraged to similar ends. The fact that Cyrix
    923      0   stevel  * fixed this bug sometime late in 1997 and no other exploits other than
    924      0   stevel  * xchgl have been discovered is good indication that this workaround is
    925      0   stevel  * reasonable.
    926      0   stevel  */
    927      0   stevel 
    928      0   stevel 	.set	CYRIX_DBR0, 0x30	/ Debug Register 0
    929      0   stevel 	.set	CYRIX_DBR1, 0x31	/ Debug Register 1
    930      0   stevel 	.set	CYRIX_DBR2, 0x32	/ Debug Register 2
    931      0   stevel 	.set	CYRIX_DBR3, 0x33	/ Debug Register 3
    932      0   stevel 	.set	CYRIX_DOR, 0x3c		/ Debug Opcode Register
    933      0   stevel 
    934      0   stevel 	/*
    935      0   stevel  	 * What is known about DBR1, DBR2, DBR3, and DOR is that for normal
    936      0   stevel 	 * cpu execution DBR1, DBR2, and DBR3 are set to 0. To obtain opcode
    937      0   stevel 	 * serialization, DBR1, DBR2, and DBR3 are loaded with 0xb8, 0x7f,
    938      0   stevel 	 * and 0xff. Then, DOR is loaded with the one byte opcode.
    939      0   stevel 	 */
    940      0   stevel 
    941      0   stevel 	/*
    942      0   stevel 	 * select CCR3
    943      0   stevel 	 */
    944      0   stevel 	movb	$CYRIX_CCR3, %al
    945      0   stevel 	outb	$CYRIX_CRI
    946      0   stevel 
    947      0   stevel 	/*
    948      0   stevel 	 * read CCR3 and mask out MAPEN
    949      0   stevel 	 */
    950      0   stevel 	inb	$CYRIX_CRD
    951      0   stevel 	andb	$0xf, %al
    952      0   stevel 
    953      0   stevel 	/*
    954      0   stevel 	 * save masked CCR3 in %ah
    955      0   stevel 	 */
    956      0   stevel 	movb	%al, %ah
    957      0   stevel 
    958      0   stevel 	/*
    959      0   stevel 	 * select CCR3
    960      0   stevel 	 */
    961      0   stevel 	movb	$CYRIX_CCR3, %al
    962      0   stevel 	outb	$CYRIX_CRI
    963      0   stevel 
    964      0   stevel 	/*
    965      0   stevel 	 * enable MAPEN
    966      0   stevel 	 */
    967      0   stevel 	movb	%ah, %al
    968      0   stevel 	orb	$0x10, %al
    969      0   stevel 	outb	$CYRIX_CRD
    970      0   stevel 
    971      0   stevel 	/*
    972      0   stevel 	 * read DBR0
    973      0   stevel 	 */
    974      0   stevel 	movb	$CYRIX_DBR0, %al
    975      0   stevel 	outb	$CYRIX_CRI
    976      0   stevel 	inb	$CYRIX_CRD
    977      0   stevel 
    978      0   stevel 	/*
    979      0   stevel 	 * disable MATCH and save in %bh
    980      0   stevel 	 */
    981      0   stevel 	orb	$0x80, %al
    982      0   stevel 	movb	%al, %bh
    983      0   stevel 
    984      0   stevel 	/*
    985      0   stevel 	 * write DBR0
    986      0   stevel 	 */
    987      0   stevel 	movb	$CYRIX_DBR0, %al
    988      0   stevel 	outb	$CYRIX_CRI
    989      0   stevel 	movb	%bh, %al
    990      0   stevel 	outb	$CYRIX_CRD
    991      0   stevel 
    992      0   stevel 	/*
    993      0   stevel 	 * write DBR1
    994      0   stevel 	 */
    995      0   stevel 	movb	$CYRIX_DBR1, %al
    996      0   stevel 	outb	$CYRIX_CRI
    997      0   stevel 	movb	$0xf8, %al
    998      0   stevel 	outb	$CYRIX_CRD
    999      0   stevel 
   1000      0   stevel 	/*
   1001      0   stevel 	 * write DBR2
   1002      0   stevel 	 */
   1003      0   stevel 	movb	$CYRIX_DBR2, %al
   1004      0   stevel 	outb	$CYRIX_CRI
   1005      0   stevel 	movb	$0x7f, %al
   1006      0   stevel 	outb	$CYRIX_CRD
   1007      0   stevel 
   1008      0   stevel 	/*
   1009      0   stevel 	 * write DBR3
   1010      0   stevel 	 */
   1011      0   stevel 	movb	$CYRIX_DBR3, %al
   1012      0   stevel 	outb	$CYRIX_CRI
   1013      0   stevel 	xorb	%al, %al
   1014      0   stevel 	outb	$CYRIX_CRD
   1015      0   stevel 
   1016      0   stevel 	/*
   1017      0   stevel 	 * write DOR
   1018      0   stevel 	 */
   1019      0   stevel 	movb	$CYRIX_DOR, %al
   1020      0   stevel 	outb	$CYRIX_CRI
   1021      0   stevel 	movb	$0x87, %al
   1022      0   stevel 	outb	$CYRIX_CRD
   1023      0   stevel 
   1024      0   stevel 	/*
   1025      0   stevel 	 * enable MATCH
   1026      0   stevel 	 */
   1027      0   stevel 	movb	$CYRIX_DBR0, %al
   1028      0   stevel 	outb	$CYRIX_CRI
   1029      0   stevel 	movb	%bh, %al
   1030      0   stevel 	andb	$0x7f, %al
   1031      0   stevel 	outb	$CYRIX_CRD
   1032      0   stevel 
   1033      0   stevel 	/*
   1034      0   stevel 	 * disable MAPEN
   1035      0   stevel 	 */
   1036      0   stevel 	movb	$0xc3, %al
   1037      0   stevel 	outb	$CYRIX_CRI
   1038      0   stevel 	movb	%ah, %al
   1039      0   stevel 	outb	$CYRIX_CRD
   1040      0   stevel 
   1041      0   stevel 	jmp	cpu_done
   1042      0   stevel 
   1043      0   stevel cpu_done:
   1044   3446      mrj 
   1045      0   stevel 	popfl					/* Restore original FLAGS */
   1046      0   stevel 	popal					/* Restore all registers */
   1047      0   stevel 
   1048   5084  johnlev #endif	/* !__xpv */
   1049   5084  johnlev 
   1050      0   stevel 	/*
   1051      0   stevel 	 *  mlsetup(%esp) gets called.
   1052      0   stevel 	 */
   1053      0   stevel 	pushl	%esp
   1054      0   stevel 	call	mlsetup
   1055      0   stevel 	addl	$4, %esp
   1056      0   stevel 
   1057      0   stevel 	/*
   1058      0   stevel 	 * We change our appearance to look like the real thread 0.
   1059      0   stevel 	 * (NOTE: making ourselves to be a real thread may be a noop)
   1060      0   stevel 	 * main() gets called.  (NOTE: main() never returns).
   1061      0   stevel 	 */
   1062      0   stevel 	call	main
   1063      0   stevel 	/* NOTREACHED */
   1064      0   stevel 	pushl	$__return_from_main
   1065      0   stevel 	call	panic
   1066      0   stevel 
   1067      0   stevel 	/* NOTREACHED */
   1068      0   stevel cpu_486:
   1069      0   stevel 	pushl	$__unsupported_cpu
   1070      0   stevel 	call	panic
   1071   3446      mrj 	SET_SIZE(_locore_start)
   1072      0   stevel 
   1073      0   stevel #endif	/* __lint */
   1074      0   stevel #endif	/* !__amd64 */
   1075      0   stevel 
   1076      0   stevel 
   1077      0   stevel /*
   1078   3446      mrj  *  For stack layout, see privregs.h
   1079      0   stevel  *  When cmntrap gets called, the error code and trap number have been pushed.
   1080   3446      mrj  *  When cmntrap_pushed gets called, the entire struct regs has been pushed.
   1081      0   stevel  */
   1082      0   stevel 
   1083      0   stevel #if defined(__lint)
   1084      0   stevel 
   1085      0   stevel /* ARGSUSED */
   1086      0   stevel void
   1087      0   stevel cmntrap()
   1088      0   stevel {}
   1089      0   stevel 
   1090      0   stevel #else	/* __lint */
   1091      0   stevel 
   1092      0   stevel 	.globl	trap		/* C handler called below */
   1093      0   stevel 
   1094      0   stevel #if defined(__amd64)
   1095      0   stevel 
   1096      0   stevel 	ENTRY_NP2(cmntrap, _cmntrap)
   1097      0   stevel 
   1098   3446      mrj 	INTR_PUSH
   1099   5084  johnlev 
   1100   3446      mrj 	ALTENTRY(cmntrap_pushed)
   1101   3446      mrj 
   1102   3446      mrj 	movq	%rsp, %rbp
   1103   3446      mrj 
   1104   3446      mrj 	/*
   1105   3446      mrj 	 * - if this is a #pf i.e. T_PGFLT, %r15 is live
   1106   3446      mrj 	 *   and contains the faulting address i.e. a copy of %cr2
   1107   3446      mrj 	 *
   1108   3446      mrj 	 * - if this is a #db i.e. T_SGLSTP, %r15 is live
   1109   3446      mrj 	 *   and contains the value of %db6
   1110   3446      mrj 	 */
   1111   3446      mrj 
   1112   3446      mrj 	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */
   1113   3446      mrj 	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
   1114   3446      mrj 	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
   1115      0   stevel 
   1116      0   stevel 	/*
   1117      0   stevel 	 * We must first check if DTrace has set its NOFAULT bit.  This
   1118   3446      mrj 	 * regrettably must happen before the trap stack is recorded, because
   1119   3446      mrj 	 * this requires a call to getpcstack() and may induce recursion if an
   1120   3446      mrj 	 * fbt::getpcstack: enabling is inducing the bad load.
   1121      0   stevel 	 */
   1122      0   stevel 	movl	%gs:CPU_ID, %eax
   1123      0   stevel 	shlq	$CPU_CORE_SHIFT, %rax
   1124      0   stevel 	leaq	cpu_core(%rip), %r8
   1125      0   stevel 	addq	%r8, %rax
   1126      0   stevel 	movw	CPUC_DTRACE_FLAGS(%rax), %cx
   1127    191      ahl 	testw	$CPU_DTRACE_NOFAULT, %cx
   1128      0   stevel 	jnz	.dtrace_induced
   1129      0   stevel 
   1130   3446      mrj 	TRACE_STACK(%rdi)
   1131   3446      mrj 
   1132   3446      mrj 	movq	%rbp, %rdi
   1133   3446      mrj 	movq	%r15, %rsi
   1134   3446      mrj 	movl	%gs:CPU_ID, %edx
   1135      0   stevel 
   1136      0   stevel 	/*
   1137   3446      mrj 	 * We know that this isn't a DTrace non-faulting load; we can now safely
   1138   3446      mrj 	 * reenable interrupts.  (In the case of pagefaults, we enter through an
   1139   3446      mrj 	 * interrupt gate.)
   1140      0   stevel 	 */
   1141      0   stevel 	ENABLE_INTR_FLAGS
   1142      0   stevel 
   1143      0   stevel 	call	trap		/* trap(rp, addr, cpuid) handles all traps */
   1144   3446      mrj 	jmp	_sys_rtt
   1145      0   stevel 
   1146      0   stevel .dtrace_induced:
   1147   3446      mrj 	cmpw	$KCS_SEL, REGOFF_CS(%rbp)	/* test CS for user-mode trap */
   1148   3446      mrj 	jne	2f				/* if from user, panic */
   1149      0   stevel 
   1150      0   stevel 	cmpl	$T_PGFLT, REGOFF_TRAPNO(%rbp)
   1151   3446      mrj 	je	0f
   1152      0   stevel 
   1153      0   stevel 	cmpl	$T_GPFLT, REGOFF_TRAPNO(%rbp)
   1154   3446      mrj 	jne	3f				/* if not PF or GP, panic */
   1155      0   stevel 
   1156      0   stevel 	/*
   1157      0   stevel 	 * If we've taken a GPF, we don't (unfortunately) have the address that
   1158      0   stevel 	 * induced the fault.  So instead of setting the fault to BADADDR,
   1159      0   stevel 	 * we'll set the fault to ILLOP.
   1160      0   stevel 	 */
   1161      0   stevel 	orw	$CPU_DTRACE_ILLOP, %cx
   1162      0   stevel 	movw	%cx, CPUC_DTRACE_FLAGS(%rax)
   1163      0   stevel 	jmp	1f
   1164      0   stevel 0:
   1165      0   stevel 	orw	$CPU_DTRACE_BADADDR, %cx
   1166      0   stevel 	movw	%cx, CPUC_DTRACE_FLAGS(%rax)	/* set fault to bad addr */
   1167   3446      mrj 	movq	%r15, CPUC_DTRACE_ILLVAL(%rax)
   1168      0   stevel 					    /* fault addr is illegal value */
   1169      0   stevel 1:
   1170      0   stevel 	movq	REGOFF_RIP(%rbp), %rdi
   1171      0   stevel 	movq	%rdi, %r12
   1172      0   stevel 	call	dtrace_instr_size
   1173      0   stevel 	addq	%rax, %r12
   1174      0   stevel 	movq	%r12, REGOFF_RIP(%rbp)
   1175      0   stevel 	INTR_POP
   1176   3446      mrj 	IRET
   1177   3446      mrj 	/*NOTREACHED*/
   1178      0   stevel 2:
   1179      0   stevel 	leaq	dtrace_badflags(%rip), %rdi
   1180      0   stevel 	xorl	%eax, %eax
   1181      0   stevel 	call	panic
   1182      0   stevel 3:
   1183      0   stevel 	leaq	dtrace_badtrap(%rip), %rdi
   1184      0   stevel 	xorl	%eax, %eax
   1185      0   stevel 	call	panic
   1186      0   stevel 	SET_SIZE(cmntrap)
   1187      0   stevel 	SET_SIZE(_cmntrap)
   1188      0   stevel 
   1189      0   stevel #elif defined(__i386)
   1190      0   stevel 
   1191   3446      mrj 
   1192      0   stevel 	ENTRY_NP2(cmntrap, _cmntrap)
   1193      0   stevel 
   1194      0   stevel 	INTR_PUSH
   1195   3446      mrj 
   1196   3446      mrj 	ALTENTRY(cmntrap_pushed)
   1197   3446      mrj 
   1198   3446      mrj 	movl	%esp, %ebp
   1199   3446      mrj 
   1200   3446      mrj 	/*
   1201   3446      mrj 	 * - if this is a #pf i.e. T_PGFLT, %esi is live
   1202   3446      mrj 	 *   and contains the faulting address i.e. a copy of %cr2
   1203   3446      mrj 	 *
   1204   3446      mrj 	 * - if this is a #db i.e. T_SGLSTP, %esi is live
   1205   3446      mrj 	 *   and contains the value of %db6
   1206   3446      mrj 	 */
   1207      0   stevel 
   1208      0   stevel 	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */
   1209      0   stevel 	TRACE_REGS(%edi, %esp, %ebx, %ecx)	/* Uses label 9 */
   1210      0   stevel 	TRACE_STAMP(%edi)		/* Clobbers %eax, %edx, uses 9 */
   1211      0   stevel 
   1212      0   stevel 	/*
   1213   3446      mrj 	 * We must first check if DTrace has set its NOFAULT bit.  This
   1214   3446      mrj 	 * regrettably must happen before the trap stack is recorded, because
   1215   3446      mrj 	 * this requires a call to getpcstack() and may induce recursion if an
   1216   3446      mrj 	 * fbt::getpcstack: enabling is inducing the bad load.
   1217      0   stevel 	 */
   1218      0   stevel 	movl	%gs:CPU_ID, %eax
   1219      0   stevel 	shll	$CPU_CORE_SHIFT, %eax
   1220      0   stevel 	addl	$cpu_core, %eax
   1221      0   stevel 	movw	CPUC_DTRACE_FLAGS(%eax), %cx
   1222    191      ahl 	testw	$CPU_DTRACE_NOFAULT, %cx
   1223   3446      mrj 	jnz	.dtrace_induced
   1224   3446      mrj 
   1225   3446      mrj 	TRACE_STACK(%edi)
   1226   3446      mrj 
   1227   3446      mrj 	pushl	%gs:CPU_ID
   1228   3446      mrj 	pushl	%esi		/* fault address for PGFLTs */
   1229   3446      mrj 	pushl	%ebp		/* &regs */
   1230      0   stevel 
   1231      0   stevel 	/*
   1232      0   stevel 	 * We know that this isn't a DTrace non-faulting load; we can now safely
   1233      0   stevel 	 * reenable interrupts.  (In the case of pagefaults, we enter through an
   1234      0   stevel 	 * interrupt gate.)
   1235      0   stevel 	 */
   1236      0   stevel 	ENABLE_INTR_FLAGS
   1237      0   stevel 
   1238      0   stevel 	call	trap		/* trap(rp, addr, cpuid) handles all traps */
   1239      0   stevel 	addl	$12, %esp	/* get argument off stack */
   1240      0   stevel 	jmp	_sys_rtt
   1241      0   stevel 
   1242   3446      mrj .dtrace_induced:
   1243   3446      mrj 	cmpw	$KCS_SEL, REGOFF_CS(%ebp)	/* test CS for user-mode trap */
   1244   3446      mrj 	jne	2f				/* if from user, panic */
   1245      0   stevel 
   1246      0   stevel 	cmpl	$T_PGFLT, REGOFF_TRAPNO(%ebp)
   1247   3446      mrj 	je	0f
   1248      0   stevel 
   1249      0   stevel 	cmpl	$T_GPFLT, REGOFF_TRAPNO(%ebp)
   1250   3446      mrj 	jne	3f				/* if not PF or GP, panic */
   1251      0   stevel 
   1252      0   stevel 	/*
   1253      0   stevel 	 * If we've taken a GPF, we don't (unfortunately) have the address that
   1254      0   stevel 	 * induced the fault.  So instead of setting the fault to BADADDR,
   1255      0   stevel 	 * we'll set the fault to ILLOP.
   1256      0   stevel 	 */
   1257      0   stevel 	orw	$CPU_DTRACE_ILLOP, %cx
   1258      0   stevel 	movw	%cx, CPUC_DTRACE_FLAGS(%eax)
   1259      0   stevel 	jmp	1f
   1260      0   stevel 0:
   1261      0   stevel 	orw	$CPU_DTRACE_BADADDR, %cx
   1262      0   stevel 	movw	%cx, CPUC_DTRACE_FLAGS(%eax)	/* set fault to bad addr */
   1263   3446      mrj 	movl	%esi, CPUC_DTRACE_ILLVAL(%eax)
   1264      0   stevel 					    /* fault addr is illegal value */
   1265      0   stevel 1:
   1266      0   stevel 	pushl	REGOFF_EIP(%ebp)
   1267      0   stevel 	call	dtrace_instr_size
   1268   3446      mrj 	addl	$4, %esp
   1269      0   stevel 	movl	REGOFF_EIP(%ebp), %ecx
   1270      0   stevel 	addl	%eax, %ecx
   1271      0   stevel 	movl	%ecx, REGOFF_EIP(%ebp)
   1272      0   stevel 	INTR_POP_KERNEL
   1273   3446      mrj 	IRET
   1274   5084  johnlev 	/*NOTREACHED*/
   1275      0   stevel 2:
   1276      0   stevel 	pushl	$dtrace_badflags
   1277      0   stevel 	call	panic
   1278      0   stevel 3:
   1279      0   stevel 	pushl	$dtrace_badtrap
   1280      0   stevel 	call	panic
   1281      0   stevel 	SET_SIZE(cmntrap)
   1282      0   stevel 	SET_SIZE(_cmntrap)
   1283      0   stevel 
   1284      0   stevel #endif	/* __i386 */
   1285      0   stevel 
   1286      0   stevel /*
   1287      0   stevel  * Declare a uintptr_t which has the size of _cmntrap to enable stack
   1288      0   stevel  * traceback code to know when a regs structure is on the stack.
   1289      0   stevel  */
   1290      0   stevel 	.globl	_cmntrap_size
   1291      0   stevel 	.align	CLONGSIZE
   1292      0   stevel _cmntrap_size:
   1293      0   stevel 	.NWORD	. - _cmntrap
   1294      0   stevel 	.type	_cmntrap_size, @object
   1295      0   stevel 
   1296      0   stevel dtrace_badflags:
   1297      0   stevel 	.string "bad DTrace flags"
   1298      0   stevel 
   1299      0   stevel dtrace_badtrap:
   1300      0   stevel 	.string "bad DTrace trap"
   1301      0   stevel 
   1302      0   stevel #endif	/* __lint */
   1303      0   stevel 
   1304      0   stevel #if defined(__lint)
   1305      0   stevel 
   1306      0   stevel /* ARGSUSED */
   1307      0   stevel void
   1308      0   stevel cmninttrap()
   1309      0   stevel {}
   1310      0   stevel 
   1311   5084  johnlev #if !defined(__xpv)
   1312   3446      mrj void
   1313   3446      mrj bop_trap_handler(void)
   1314   3446      mrj {}
   1315   5084  johnlev #endif
   1316   3446      mrj 
   1317      0   stevel #else	/* __lint */
   1318      0   stevel 
   1319      0   stevel 	.globl	trap		/* C handler called below */
   1320      0   stevel 
   1321      0   stevel #if defined(__amd64)
   1322      0   stevel 
   1323      0   stevel 	ENTRY_NP(cmninttrap)
   1324      0   stevel 
   1325      0   stevel 	INTR_PUSH
   1326   3446      mrj 	INTGATE_INIT_KERNEL_FLAGS
   1327      0   stevel 
   1328      0   stevel 	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */
   1329      0   stevel 	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
   1330      0   stevel 	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
   1331      0   stevel 
   1332      0   stevel 	movq	%rsp, %rbp
   1333      0   stevel 
   1334      0   stevel 	movl	%gs:CPU_ID, %edx
   1335      0   stevel 	xorl	%esi, %esi
   1336      0   stevel 	movq	%rsp, %rdi
   1337      0   stevel 	call	trap		/* trap(rp, addr, cpuid) handles all traps */
   1338      0   stevel 	jmp	_sys_rtt
   1339      0   stevel 	SET_SIZE(cmninttrap)
   1340   3446      mrj 
   1341   5084  johnlev #if !defined(__xpv)
   1342   3446      mrj 	/*
   1343   3446      mrj 	 * Handle traps early in boot. Just revectors into C quickly as
   1344   3446      mrj 	 * these are always fatal errors.
   1345  10993      Dan 	 *
   1346  10993      Dan 	 * Adjust %rsp to get same stack layout as in 32bit mode for bop_trap().
   1347   3446      mrj 	 */
   1348   3446      mrj 	ENTRY(bop_trap_handler)
   1349   3446      mrj 	movq	%rsp, %rdi
   1350  10993      Dan 	sub	$8, %rsp
   1351   3446      mrj 	call	bop_trap
   1352   3446      mrj 	SET_SIZE(bop_trap_handler)
   1353   5084  johnlev #endif
   1354      0   stevel 
   1355      0   stevel #elif defined(__i386)
   1356      0   stevel 
   1357      0   stevel 	ENTRY_NP(cmninttrap)
   1358      0   stevel 
   1359      0   stevel 	INTR_PUSH
   1360   3446      mrj 	INTGATE_INIT_KERNEL_FLAGS
   1361   3446      mrj 
   1362   3446      mrj 	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */
   1363   3446      mrj 	TRACE_REGS(%edi, %esp, %ebx, %ecx)	/* Uses label 9 */
   1364   3446      mrj 	TRACE_STAMP(%edi)		/* Clobbers %eax, %edx, uses 9 */
   1365      0   stevel 
   1366      0   stevel 	movl	%esp, %ebp
   1367      0   stevel 
   1368   3446      mrj 	TRACE_STACK(%edi)
   1369   3446      mrj 
   1370      0   stevel 	pushl	%gs:CPU_ID
   1371   3446      mrj 	pushl	$0
   1372   3446      mrj 	pushl	%ebp
   1373      0   stevel 	call	trap		/* trap(rp, addr, cpuid) handles all traps */
   1374   3446      mrj 	addl	$12, %esp
   1375      0   stevel 	jmp	_sys_rtt
   1376      0   stevel 	SET_SIZE(cmninttrap)
   1377   3446      mrj 
   1378   5084  johnlev #if !defined(__xpv)
   1379   3446      mrj 	/*
   1380   3446      mrj 	 * Handle traps early in boot. Just revectors into C quickly as
   1381   3446      mrj 	 * these are always fatal errors.
   1382   3446      mrj 	 */
   1383   3446      mrj 	ENTRY(bop_trap_handler)
   1384   3446      mrj 	movl	%esp, %eax
   1385   3446      mrj 	pushl	%eax
   1386   3446      mrj 	call	bop_trap
   1387   3446      mrj 	SET_SIZE(bop_trap_handler)
   1388   5084  johnlev #endif
   1389      0   stevel 
   1390      0   stevel #endif	/* __i386 */
   1391      0   stevel 
   1392      0   stevel #endif	/* __lint */
   1393      0   stevel 
   1394      0   stevel #if defined(__lint)
   1395      0   stevel 
   1396      0   stevel /* ARGSUSED */
   1397      0   stevel void
   1398      0   stevel dtrace_trap()
   1399      0   stevel {}
   1400      0   stevel 
   1401      0   stevel #else	/* __lint */
   1402      0   stevel 
   1403      0   stevel 	.globl	dtrace_user_probe
   1404      0   stevel 
   1405      0   stevel #if defined(__amd64)
   1406      0   stevel 
   1407      0   stevel 	ENTRY_NP(dtrace_trap)
   1408      0   stevel 
   1409      0   stevel 	INTR_PUSH
   1410      0   stevel 
   1411      0   stevel 	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */
   1412      0   stevel 	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
   1413      0   stevel 	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
   1414      0   stevel 
   1415      0   stevel 	movq	%rsp, %rbp
   1416      0   stevel 
   1417      0   stevel 	movl	%gs:CPU_ID, %edx
   1418   5084  johnlev #if defined(__xpv)
   1419   5084  johnlev 	movq	%gs:CPU_VCPU_INFO, %rsi
   1420   5084  johnlev 	movq	VCPU_INFO_ARCH_CR2(%rsi), %rsi
   1421   5084  johnlev #else
   1422      0   stevel 	movq	%cr2, %rsi
   1423   5084  johnlev #endif
   1424      0   stevel 	movq	%rsp, %rdi
   1425      0   stevel 
   1426      0   stevel 	ENABLE_INTR_FLAGS
   1427      0   stevel 
   1428      0   stevel 	call	dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */
   1429      0   stevel 	jmp	_sys_rtt
   1430      0   stevel 
   1431      0   stevel 	SET_SIZE(dtrace_trap)
   1432      0   stevel 
   1433      0   stevel #elif defined(__i386)
   1434      0   stevel 
   1435      0   stevel 	ENTRY_NP(dtrace_trap)
   1436      0   stevel 
   1437      0   stevel 	INTR_PUSH
   1438      0   stevel 
   1439      0   stevel 	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */
   1440      0   stevel 	TRACE_REGS(%edi, %esp, %ebx, %ecx)	/* Uses label 9 */
   1441      0   stevel 	TRACE_STAMP(%edi)		/* Clobbers %eax, %edx, uses 9 */
   1442      0   stevel 
   1443      0   stevel 	movl	%esp, %ebp
   1444      0   stevel 
   1445      0   stevel 	pushl	%gs:CPU_ID
   1446   5084  johnlev #if defined(__xpv)
   1447   5084  johnlev 	movl	%gs:CPU_VCPU_INFO, %eax
   1448   5084  johnlev 	movl	VCPU_INFO_ARCH_CR2(%eax), %eax
   1449   5084  johnlev #else
   1450      0   stevel 	movl	%cr2, %eax
   1451   5084  johnlev #endif
   1452      0   stevel 	pushl	%eax
   1453      0   stevel 	pushl	%ebp
   1454      0   stevel 
   1455   3446      mrj 	ENABLE_INTR_FLAGS
   1456      0   stevel 
   1457      0   stevel 	call	dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */
   1458      0   stevel 	addl	$12, %esp		/* get argument off stack */
   1459      0   stevel 
   1460      0   stevel 	jmp	_sys_rtt
   1461      0   stevel 	SET_SIZE(dtrace_trap)
   1462      0   stevel 
   1463      0   stevel #endif	/* __i386 */
   1464      0   stevel 
   1465      0   stevel #endif	/* __lint */
   1466      0   stevel 
   1467      0   stevel /*
   1468      0   stevel  * Return from _sys_trap routine.
   1469      0   stevel  */
   1470      0   stevel 
   1471      0   stevel #if defined(__lint)
   1472      0   stevel 
   1473      0   stevel void
   1474      0   stevel lwp_rtt_initial(void)
   1475      0   stevel {}
   1476      0   stevel 
   1477      0   stevel void
   1478      0   stevel lwp_rtt(void)
   1479      0   stevel {}
   1480      0   stevel 
   1481      0   stevel void
   1482      0   stevel _sys_rtt(void)
   1483      0   stevel {}
   1484      0   stevel 
   1485      0   stevel #else	/* __lint */
   1486      0   stevel 
   1487      0   stevel #if defined(__amd64)
   1488      0   stevel 
   1489      0   stevel 	ENTRY_NP(lwp_rtt_initial)
   1490      0   stevel 	movq	%gs:CPU_THREAD, %r15
   1491      0   stevel 	movq	T_STACK(%r15), %rsp	/* switch to the thread stack */
   1492   7656   Sherry 	movq	%rsp, %rbp
   1493      0   stevel 	call	__dtrace_probe___proc_start
   1494      0   stevel 	jmp	_lwp_rtt
   1495      0   stevel 
   1496      0   stevel 	ENTRY_NP(lwp_rtt)
   1497      0   stevel 
   1498      0   stevel 	/*
   1499      0   stevel 	 * r14	lwp
   1500      0   stevel 	 * rdx	lwp->lwp_procp
   1501      0   stevel 	 * r15	curthread
   1502      0   stevel 	 */
   1503      0   stevel 
   1504      0   stevel 	movq	%gs:CPU_THREAD, %r15
   1505      0   stevel 	movq	T_STACK(%r15), %rsp	/* switch to the thread stack */
   1506   7656   Sherry 	movq	%rsp, %rbp
   1507      0   stevel _lwp_rtt:
   1508      0   stevel 	call	__dtrace_probe___proc_lwp__start
   1509      0   stevel 	movq	%gs:CPU_LWP, %r14
   1510      0   stevel 	movq	LWP_PROCP(%r14), %rdx
   1511      0   stevel 
   1512      0   stevel 	/*
   1513      0   stevel 	 * XX64	Is the stack misaligned correctly at this point?
   1514      0   stevel 	 *	If not, we need to do a push before calling anything ..
   1515      0   stevel 	 */
   1516      0   stevel 
   1517      0   stevel #if defined(DEBUG)
   1518      0   stevel 	/*
   1519      0   stevel 	 * If we were to run lwp_savectx at this point -without-
   1520   4503  sudheer 	 * pcb_rupdate being set to 1, we'd end up sampling the hardware
   1521      0   stevel 	 * state left by the previous running lwp, rather than setting
   1522      0   stevel 	 * the values requested by the lwp creator.  Bad.
   1523      0   stevel 	 */
   1524   4503  sudheer 	testb	$0x1, PCB_RUPDATE(%r14)
   1525      0   stevel 	jne	1f
   1526      0   stevel 	leaq	_no_pending_updates(%rip), %rdi
   1527      0   stevel 	movl	$__LINE__, %esi
   1528      0   stevel 	movq	%r14, %rdx
   1529      0   stevel 	xorl	%eax, %eax
   1530      0   stevel 	call	panic
   1531      0   stevel _no_pending_updates:
   1532   4503  sudheer 	.string	"locore.s:%d lwp_rtt(lwp %p) but pcb_rupdate != 1"
   1533      0   stevel 1:
   1534      0   stevel #endif
   1535      0   stevel 
   1536      0   stevel 	/*
   1537      0   stevel 	 * If agent lwp, clear %fs and %gs
   1538      0   stevel 	 */
   1539      0   stevel 	cmpq	%r15, P_AGENTTP(%rdx)
   1540      0   stevel 	jne	1f
   1541      0   stevel 	xorl	%ecx, %ecx
   1542      0   stevel 	movq	%rcx, REGOFF_FS(%rsp)
   1543      0   stevel 	movq	%rcx, REGOFF_GS(%rsp)
   1544      0   stevel 	movw	%cx, LWP_PCB_FS(%r14)
   1545      0   stevel 	movw	%cx, LWP_PCB_GS(%r14)
   1546      0   stevel 1:
   1547      0   stevel 	call	dtrace_systrace_rtt
   1548      0   stevel 	movq	REGOFF_RDX(%rsp), %rsi
   1549      0   stevel 	movq	REGOFF_RAX(%rsp), %rdi
   1550      0   stevel 	call	post_syscall		/* post_syscall(rval1, rval2) */
   1551   3446      mrj 
   1552   3446      mrj 	/*
   1553   3446      mrj 	 * set up to take fault on first use of fp
   1554   3446      mrj 	 */
   1555   3446      mrj 	STTS(%rdi)
   1556   3446      mrj 
   1557   3446      mrj 	/*
   1558   3446      mrj 	 * XXX - may want a fast path that avoids sys_rtt_common in the
   1559   3446      mrj 	 * most common case.
   1560   3446      mrj 	 */
   1561      0   stevel 	ALTENTRY(_sys_rtt)
   1562   3446      mrj 	CLI(%rax)			/* disable interrupts */
   1563   5084  johnlev 	ALTENTRY(_sys_rtt_ints_disabled)
   1564   3446      mrj 	movq	%rsp, %rdi		/* pass rp to sys_rtt_common */
   1565   3446      mrj 	call	sys_rtt_common		/* do common sys_rtt tasks */
   1566   3446      mrj 	testq	%rax, %rax		/* returning to userland? */
   1567      0   stevel 	jz	sr_sup
   1568      0   stevel 
   1569      0   stevel 	/*
   1570      0   stevel 	 * Return to user
   1571      0   stevel 	 */
   1572   3446      mrj 	ASSERT_UPCALL_MASK_IS_SET
   1573      0   stevel 	cmpw	$UCS_SEL, REGOFF_CS(%rsp) /* test for native (64-bit) lwp? */
   1574      0   stevel 	je	sys_rtt_syscall
   1575      0   stevel 
   1576      0   stevel 	/*
   1577   3446      mrj 	 * Return to 32-bit userland
   1578      0   stevel 	 */
   1579      0   stevel 	ALTENTRY(sys_rtt_syscall32)
   1580   3446      mrj 	USER32_POP
   1581   3446      mrj 	IRET
   1582   3446      mrj 	/*NOTREACHED*/
   1583   5084  johnlev 
   1584   3446      mrj 	ALTENTRY(sys_rtt_syscall)
   1585      0   stevel 	/*
   1586   3446      mrj 	 * Return to 64-bit userland
   1587      0   stevel 	 */
   1588   3446      mrj 	USER_POP
   1589   5084  johnlev 	ALTENTRY(nopop_sys_rtt_syscall)
   1590   3446      mrj 	IRET
   1591      0   stevel 	/*NOTREACHED*/
   1592   5084  johnlev 	SET_SIZE(nopop_sys_rtt_syscall)
   1593      0   stevel 
   1594      0   stevel 	/*
   1595      0   stevel 	 * Return to supervisor
   1596   3446      mrj 	 * NOTE: to make the check in trap() that tests if we are executing
   1597   3446      mrj 	 * segment register fixup/restore code work properly, sr_sup MUST be
   1598   3446      mrj 	 * after _sys_rtt .
   1599      0   stevel 	 */
   1600      0   stevel 	ALTENTRY(sr_sup)
   1601      0   stevel 	/*
   1602      0   stevel 	 * Restore regs before doing iretq to kernel mode
   1603      0   stevel 	 */
   1604      0   stevel 	INTR_POP
   1605   3446      mrj 	IRET
   1606   5084  johnlev 	.globl	_sys_rtt_end
   1607   5084  johnlev _sys_rtt_end:
   1608   3446      mrj 	/*NOTREACHED*/
   1609      0   stevel 	SET_SIZE(sr_sup)
   1610   5084  johnlev 	SET_SIZE(_sys_rtt_end)
   1611      0   stevel 	SET_SIZE(lwp_rtt)
   1612      0   stevel 	SET_SIZE(lwp_rtt_initial)
   1613   5084  johnlev 	SET_SIZE(_sys_rtt_ints_disabled)
   1614      0   stevel 	SET_SIZE(_sys_rtt)
   1615      0   stevel 	SET_SIZE(sys_rtt_syscall)
   1616      0   stevel 	SET_SIZE(sys_rtt_syscall32)
   1617      0   stevel 
   1618      0   stevel #elif defined(__i386)
   1619      0   stevel 
   1620      0   stevel 	ENTRY_NP(lwp_rtt_initial)
   1621      0   stevel 	movl	%gs:CPU_THREAD, %eax
   1622      0   stevel 	movl	T_STACK(%eax), %esp	/* switch to the thread stack */
   1623   7656   Sherry 	movl	%esp, %ebp
   1624      0   stevel 	call	__dtrace_probe___proc_start
   1625      0   stevel 	jmp	_lwp_rtt
   1626      0   stevel 
   1627      0   stevel 	ENTRY_NP(lwp_rtt)
   1628      0   stevel 	movl	%gs:CPU_THREAD, %eax
   1629      0   stevel 	movl	T_STACK(%eax), %esp	/* switch to the thread stack */
   1630   7656   Sherry 	movl	%esp, %ebp
   1631      0   stevel _lwp_rtt:
   1632      0   stevel 	call	__dtrace_probe___proc_lwp__start
   1633      0   stevel 
   1634      0   stevel         /*
   1635      0   stevel          * If agent lwp, clear %fs and %gs.
   1636      0   stevel          */
   1637      0   stevel         movl    %gs:CPU_LWP, %eax
   1638      0   stevel         movl    LWP_PROCP(%eax), %edx
   1639      0   stevel 
   1640      0   stevel         cmpl    %eax, P_AGENTTP(%edx)
   1641      0   stevel         jne     1f
   1642      0   stevel         movl    $0, REGOFF_FS(%esp)
   1643      0   stevel         movl    $0, REGOFF_GS(%esp)
   1644      0   stevel 1:
   1645      0   stevel 	call	dtrace_systrace_rtt
   1646      0   stevel 	movl	REGOFF_EDX(%esp), %edx
   1647      0   stevel 	movl	REGOFF_EAX(%esp), %eax
   1648      0   stevel 	pushl	%edx
   1649      0   stevel 	pushl	%eax
   1650      0   stevel 	call	post_syscall		/* post_syscall(rval1, rval2) */
   1651      0   stevel 	addl	$8, %esp
   1652      0   stevel 
   1653   3446      mrj 	/*
   1654   3446      mrj 	 * set up to take fault on first use of fp
   1655   3446      mrj 	 */
   1656   3446      mrj 	STTS(%eax)
   1657   3446      mrj 
   1658   3446      mrj 	/*
   1659   3446      mrj 	 * XXX - may want a fast path that avoids sys_rtt_common in the
   1660   3446      mrj 	 * most common case.
   1661   3446      mrj 	 */
   1662      0   stevel 	ALTENTRY(_sys_rtt)
   1663   3446      mrj 	CLI(%eax)			/* disable interrupts */
   1664   5084  johnlev 	ALTENTRY(_sys_rtt_ints_disabled)
   1665   3446      mrj 	pushl	%esp			/* pass rp to sys_rtt_common */
   1666   3446      mrj 	call	sys_rtt_common
   1667   3446      mrj 	addl	$4, %esp		/* pop arg */
   1668   3446      mrj 	testl	%eax, %eax		/* test for return to user mode */
   1669      0   stevel 	jz	sr_sup
   1670      0   stevel 
   1671      0   stevel 	/*
   1672      0   stevel 	 * Return to User.
   1673      0   stevel 	 */
   1674      0   stevel 	ALTENTRY(sys_rtt_syscall)
   1675      0   stevel 	INTR_POP_USER
   1676   5084  johnlev 
   1677   5084  johnlev 	/*
   1678   5084  johnlev 	 * There can be no instructions between this label and IRET or
   1679   5084  johnlev 	 * we could end up breaking linux brand support. See label usage
   1680   5084  johnlev 	 * in lx_brand_int80_callback for an example.
   1681   5084  johnlev 	 */
   1682   5084  johnlev 	ALTENTRY(nopop_sys_rtt_syscall)
   1683   3446      mrj 	IRET
   1684   5084  johnlev 	/*NOTREACHED*/
   1685   5084  johnlev 	SET_SIZE(nopop_sys_rtt_syscall)
   1686   5084  johnlev 
   1687   5084  johnlev 	ALTENTRY(_sys_rtt_end)
   1688      0   stevel 
   1689      0   stevel 	/*
   1690      0   stevel 	 * Return to supervisor
   1691      0   stevel 	 */
   1692      0   stevel 	ALTENTRY(sr_sup)
   1693      0   stevel 
   1694      0   stevel 	/*
   1695      0   stevel 	 * Restore regs before doing iret to kernel mode
   1696      0   stevel 	 */
   1697   3446      mrj 	INTR_POP_KERNEL
   1698   3446      mrj 	IRET
   1699   5084  johnlev 	/*NOTREACHED*/
   1700      0   stevel 
   1701      0   stevel 	SET_SIZE(sr_sup)
   1702   5084  johnlev 	SET_SIZE(_sys_rtt_end)
   1703      0   stevel 	SET_SIZE(lwp_rtt)
   1704      0   stevel 	SET_SIZE(lwp_rtt_initial)
   1705   5084  johnlev 	SET_SIZE(_sys_rtt_ints_disabled)
   1706      0   stevel 	SET_SIZE(_sys_rtt)
   1707      0   stevel 	SET_SIZE(sys_rtt_syscall)
   1708      0   stevel 
   1709      0   stevel #endif	/* __i386 */
   1710      0   stevel 
   1711      0   stevel #endif	/* __lint */
   1712      0   stevel 
   1713      0   stevel #if defined(__lint)
   1714      0   stevel 
   1715      0   stevel /*
   1716      0   stevel  * So why do we have to deal with all this crud in the world of ia32?
   1717      0   stevel  *
   1718      0   stevel  * Basically there are four classes of ia32 implementations, those that do not
   1719      0   stevel  * have a TSC, those that have a marginal TSC that is broken to the extent
   1720      0   stevel  * that it is useless, those that have a marginal TSC that is not quite so
   1721      0   stevel  * horribly broken and can be used with some care, and those that have a
   1722      0   stevel  * reliable TSC. This crud has to be here in order to sift through all the
   1723      0   stevel  * variants.
   1724      0   stevel  */
   1725      0   stevel 
   1726      0   stevel /*ARGSUSED*/
   1727      0   stevel uint64_t
   1728      0   stevel freq_tsc(uint32_t *pit_counter)
   1729      0   stevel {
   1730      0   stevel 	return (0);
   1731      0   stevel }
   1732      0   stevel 
   1733      0   stevel #else	/* __lint */
   1734      0   stevel 
   1735      0   stevel #if defined(__amd64)
   1736      0   stevel 
   1737      0   stevel 	/*
   1738      0   stevel 	 * XX64 quick and dirty port from the i386 version. Since we
   1739      0   stevel 	 * believe the amd64 tsc is more reliable, could this code be
   1740      0   stevel 	 * simpler?
   1741      0   stevel 	 */
   1742      0   stevel 	ENTRY_NP(freq_tsc)
   1743      0   stevel 	pushq	%rbp
   1744      0   stevel 	movq	%rsp, %rbp
   1745      0   stevel 	movq	%rdi, %r9	/* save pit_counter */
   1746      0   stevel 	pushq	%rbx
   1747      0   stevel 
   1748      0   stevel / We have a TSC, but we have no way in general to know how reliable it is.
   1749      0   stevel / Usually a marginal TSC behaves appropriately unless not enough time
   1750      0   stevel / elapses between reads. A reliable TSC can be read as often and as rapidly
   1751      0   stevel / as desired. The simplistic approach of reading the TSC counter and
   1752      0   stevel / correlating to the PIT counter cannot be naively followed. Instead estimates
   1753      0   stevel / have to be taken to successively refine a guess at the speed of the cpu
   1754      0   stevel / and then the TSC and PIT counter are correlated. In practice very rarely
   1755      0   stevel / is more than one quick loop required for an estimate. Measures have to be
   1756      0   stevel / taken to prevent the PIT counter from wrapping beyond its resolution and for
   1757      0   stevel / measuring the clock rate of very fast processors.
   1758      0   stevel /
   1759      0   stevel / The following constant can be tuned. It should be such that the loop does
   1760      0   stevel / not take too many nor too few PIT counts to execute. If this value is too
   1761      0   stevel / large, then on slow machines the loop will take a long time, or the PIT
   1762      0   stevel / counter may even wrap. If this value is too small, then on fast machines
   1763      0   stevel / the PIT counter may count so few ticks that the resolution of the PIT
   1764      0   stevel / itself causes a bad guess. Because this code is used in machines with
   1765      0   stevel / marginal TSC's and/or IO, if this value is too small on those, it may
   1766      0   stevel / cause the calculated cpu frequency to vary slightly from boot to boot.
   1767      0   stevel /
   1768      0   stevel / In all cases even if this constant is set inappropriately, the algorithm
   1769      0   stevel / will still work and the caller should be able to handle variances in the
   1770      0   stevel / calculation of cpu frequency, but the calculation will be inefficient and
   1771      0   stevel / take a disproportionate amount of time relative to a well selected value.
   1772      0   stevel / As the slowest supported cpu becomes faster, this constant should be
   1773      0   stevel / carefully increased.
   1774      0   stevel 
   1775      0   stevel 	movl	$0x8000, %ecx
   1776      0   stevel 
   1777      0   stevel 	/ to make sure the instruction cache has been warmed
   1778      0   stevel 	clc
   1779      0   stevel 
   1780      0   stevel 	jmp	freq_tsc_loop
   1781      0   stevel 
   1782      0   stevel / The following block of code up to and including the latching of the PIT
   1783      0   stevel / counter after freq_tsc_perf_loop is very critical and very carefully
   1784      0   stevel / written, it should only be modified with great care. freq_tsc_loop to
   1785      0   stevel / freq_tsc_perf_loop fits exactly in 16 bytes as do the instructions in
   1786      0   stevel / freq_tsc_perf_loop up to the unlatching of the PIT counter.
   1787      0   stevel 
   1788      0   stevel 	.align	32
   1789      0   stevel freq_tsc_loop:
   1790      0   stevel 	/ save the loop count in %ebx
   1791      0   stevel 	movl	%ecx, %ebx
   1792      0   stevel 
   1793      0   stevel 	/ initialize the PIT counter and start a count down
   1794      0   stevel 	movb	$PIT_LOADMODE, %al
   1795      0   stevel 	outb	$PITCTL_PORT
   1796      0   stevel 	movb	$0xff, %al
   1797      0   stevel 	outb	$PITCTR0_PORT
   1798      0   stevel 	outb	$PITCTR0_PORT
   1799      0   stevel 
   1800      0   stevel 	/ read the TSC and store the TS in %edi:%esi
   1801      0   stevel 	rdtsc
   1802      0   stevel 	movl	%eax, %esi
   1803      0   stevel 
   1804      0   stevel freq_tsc_perf_loop:
   1805      0   stevel 	movl	%edx, %edi
   1806      0   stevel 	movl	%eax, %esi
   1807      0   stevel 	movl	%edx, %edi
   1808      0   stevel 	loop	freq_tsc_perf_loop
   1809      0   stevel 
   1810      0   stevel 	/ read the TSC and store the LSW in %ecx
   1811      0   stevel 	rdtsc
   1812      0   stevel 	movl	%eax, %ecx
   1813      0   stevel 
   1814      0   stevel 	/ latch the PIT counter and status
   1815      0   stevel 	movb	$_CONST(PIT_READBACK|PIT_READBACKC0), %al
   1816      0   stevel 	outb	$PITCTL_PORT
   1817      0   stevel 
   1818      0   stevel 	/ remember if the icache has been warmed
   1819      0   stevel 	setc	%ah
   1820      0   stevel 
   1821      0   stevel 	/ read the PIT status
   1822      0   stevel 	inb	$PITCTR0_PORT
   1823      0   stevel 	shll	$8, %eax
   1824      0   stevel 
   1825      0   stevel 	/ read PIT count
   1826      0   stevel 	inb	$PITCTR0_PORT
   1827      0   stevel 	shll	$8, %eax
   1828      0   stevel 	inb	$PITCTR0_PORT
   1829      0   stevel 	bswap	%eax
   1830      0   stevel 
   1831      0   stevel 	/ check to see if the PIT count was loaded into the CE
   1832      0   stevel 	btw	$_CONST(PITSTAT_NULLCNT+8), %ax
   1833      0   stevel 	jc	freq_tsc_increase_count
   1834      0   stevel 
   1835      0   stevel 	/ check to see if PIT counter wrapped
   1836      0   stevel 	btw	$_CONST(PITSTAT_OUTPUT+8), %ax
   1837      0   stevel 	jnc	freq_tsc_pit_did_not_wrap
   1838      0   stevel 
   1839      0   stevel 	/ halve count
   1840      0   stevel 	shrl	$1, %ebx
   1841      0   stevel 	movl	%ebx, %ecx
   1842      0   stevel 
   1843      0   stevel 	/ the instruction cache has been warmed
   1844      0   stevel 	stc
   1845      0   stevel 
   1846      0   stevel 	jmp	freq_tsc_loop
   1847      0   stevel 
   1848      0   stevel freq_tsc_increase_count:
   1849      0   stevel 	shll	$1, %ebx
   1850      0   stevel 	jc	freq_tsc_too_fast
   1851      0   stevel 
   1852      0   stevel 	movl	%ebx, %ecx
   1853      0   stevel 
   1854      0   stevel 	/ the instruction cache has been warmed
   1855      0   stevel 	stc
   1856      0   stevel 
   1857      0   stevel 	jmp	freq_tsc_loop
   1858      0   stevel 
   1859      0   stevel freq_tsc_pit_did_not_wrap:
   1860      0   stevel 	roll	$16, %eax
   1861      0   stevel 
   1862      0   stevel 	cmpw	$0x2000, %ax
   1863      0   stevel 	notw	%ax
   1864      0   stevel 	jb	freq_tsc_sufficient_duration
   1865      0   stevel 
   1866      0   stevel freq_tsc_calculate:
   1867      0   stevel 	/ in mode 0, the PIT loads the count into the CE on the first CLK pulse,
   1868      0   stevel 	/ then on the second CLK pulse the CE is decremented, therefore mode 0
   1869      0   stevel 	/ is really a (count + 1) counter, ugh
   1870      0   stevel 	xorl	%esi, %esi
   1871      0   stevel 	movw	%ax, %si
   1872      0   stevel 	incl	%esi
   1873      0   stevel 
   1874      0   stevel 	movl	$0xf000, %eax
   1875      0   stevel 	mull	%ebx
   1876      0   stevel 
   1877      0   stevel 	/ tuck away (target_pit_count * loop_count)
   1878      0   stevel 	movl	%edx, %ecx
   1879      0   stevel 	movl	%eax, %ebx
   1880      0   stevel 
   1881      0   stevel 	movl	%esi, %eax
   1882      0   stevel 	movl	$0xffffffff, %edx
   1883      0   stevel 	mull	%edx
   1884      0   stevel 
   1885      0   stevel 	addl	%esi, %eax
   1886      0   stevel 	adcl	$0, %edx
   1887      0   stevel 
   1888      0   stevel 	cmpl	%ecx, %edx
   1889      0   stevel 	ja	freq_tsc_div_safe
   1890      0   stevel 	jb	freq_tsc_too_fast
   1891      0   stevel 
   1892      0   stevel 	cmpl	%ebx, %eax
   1893      0   stevel 	jbe	freq_tsc_too_fast
   1894      0   stevel 
   1895      0   stevel freq_tsc_div_safe:
   1896      0   stevel 	movl	%ecx, %edx
   1897      0   stevel 	movl	%ebx, %eax
   1898      0   stevel 
   1899      0   stevel 	movl	%esi, %ecx
   1900      0   stevel 	divl	%ecx
   1901      0   stevel 
   1902      0   stevel 	movl	%eax, %ecx
   1903      0   stevel 
   1904      0   stevel 	/ the instruction cache has been warmed
   1905      0   stevel 	stc
   1906      0   stevel 
   1907      0   stevel 	jmp	freq_tsc_loop
   1908      0   stevel 
   1909      0   stevel freq_tsc_sufficient_duration:
   1910      0   stevel 	/ test to see if the icache has been warmed
   1911      0   stevel 	btl	$16, %eax
   1912      0   stevel 	jnc	freq_tsc_calculate
   1913      0   stevel 
   1914      0   stevel 	/ recall mode 0 is a (count + 1) counter
   1915      0   stevel 	andl	$0xffff, %eax
   1916      0   stevel 	incl	%eax
   1917      0   stevel 
   1918      0   stevel 	/ save the number of PIT counts
   1919      0   stevel 	movl	%eax, (%r9)
   1920      0   stevel 
   1921      0   stevel 	/ calculate the number of TS's that elapsed
   1922      0   stevel 	movl	%ecx, %eax
   1923      0   stevel 	subl	%esi, %eax
   1924      0   stevel 	sbbl	%edi, %edx
   1925      0   stevel 
   1926      0   stevel 	jmp	freq_tsc_end
   1927      0   stevel 
   1928      0   stevel freq_tsc_too_fast:
   1929      0   stevel 	/ return 0 as a 64 bit quantity
   1930      0   stevel 	xorl	%eax, %eax
   1931      0   stevel 	xorl	%edx, %edx
   1932      0   stevel 
   1933      0   stevel freq_tsc_end:
   1934      0   stevel 	shlq	$32, %rdx
   1935      0   stevel 	orq	%rdx, %rax
   1936      0   stevel 
   1937      0   stevel 	popq	%rbx
   1938      0   stevel 	leaveq
   1939      0   stevel 	ret
   1940      0   stevel 	SET_SIZE(freq_tsc)
   1941      0   stevel 
   1942      0   stevel #elif defined(__i386)
   1943      0   stevel 
   1944      0   stevel 	ENTRY_NP(freq_tsc)
   1945      0   stevel 	pushl	%ebp
   1946      0   stevel 	movl	%esp, %ebp
   1947      0   stevel 	pushl	%edi
   1948      0   stevel 	pushl	%esi
   1949      0   stevel 	pushl	%ebx
   1950      0   stevel 
   1951      0   stevel / We have a TSC, but we have no way in general to know how reliable it is.
   1952      0   stevel / Usually a marginal TSC behaves appropriately unless not enough time
   1953      0   stevel / elapses between reads. A reliable TSC can be read as often and as rapidly
   1954      0   stevel / as desired. The simplistic approach of reading the TSC counter and
   1955      0   stevel / correlating to the PIT counter cannot be naively followed. Instead estimates
   1956      0   stevel / have to be taken to successively refine a guess at the speed of the cpu
   1957      0   stevel / and then the TSC and PIT counter are correlated. In practice very rarely
   1958      0   stevel / is more than one quick loop required for an estimate. Measures have to be
   1959      0   stevel / taken to prevent the PIT counter from wrapping beyond its resolution and for
   1960      0   stevel / measuring the clock rate of very fast processors.
   1961      0   stevel /
   1962      0   stevel / The following constant can be tuned. It should be such that the loop does
   1963      0   stevel / not take too many nor too few PIT counts to execute. If this value is too
   1964      0   stevel / large, then on slow machines the loop will take a long time, or the PIT
   1965      0   stevel / counter may even wrap. If this value is too small, then on fast machines
   1966      0   stevel / the PIT counter may count so few ticks that the resolution of the PIT
   1967      0   stevel / itself causes a bad guess. Because this code is used in machines with
   1968      0   stevel / marginal TSC's and/or IO, if this value is too small on those, it may
   1969      0   stevel / cause the calculated cpu frequency to vary slightly from boot to boot.
   1970      0   stevel /
   1971      0   stevel / In all cases even if this constant is set inappropriately, the algorithm
   1972      0   stevel / will still work and the caller should be able to handle variances in the
   1973      0   stevel / calculation of cpu frequency, but the calculation will be inefficient and
   1974      0   stevel / take a disproportionate amount of time relative to a well selected value.
   1975      0   stevel / As the slowest supported cpu becomes faster, this constant should be
   1976      0   stevel / carefully increased.
   1977      0   stevel 
   1978      0   stevel 	movl	$0x8000, %ecx
   1979      0   stevel 
   1980      0   stevel 	/ to make sure the instruction cache has been warmed
   1981      0   stevel 	clc
   1982      0   stevel 
   1983      0   stevel 	jmp	freq_tsc_loop
   1984      0   stevel 
   1985      0   stevel / The following block of code up to and including the latching of the PIT
   1986      0   stevel / counter after freq_tsc_perf_loop is very critical and very carefully
   1987      0   stevel / written, it should only be modified with great care. freq_tsc_loop to
   1988      0   stevel / freq_tsc_perf_loop fits exactly in 16 bytes as do the instructions in
   1989      0   stevel / freq_tsc_perf_loop up to the unlatching of the PIT counter.
   1990      0   stevel 
   1991      0   stevel 	.align	32
   1992      0   stevel freq_tsc_loop:
   1993      0   stevel 	/ save the loop count in %ebx
   1994      0   stevel 	movl	%ecx, %ebx
   1995      0   stevel 
   1996      0   stevel 	/ initialize the PIT counter and start a count down
   1997      0   stevel 	movb	$PIT_LOADMODE, %al
   1998      0   stevel 	outb	$PITCTL_PORT
   1999      0   stevel 	movb	$0xff, %al
   2000      0   stevel 	outb	$PITCTR0_PORT
   2001      0   stevel 	outb	$PITCTR0_PORT
   2002      0   stevel 
   2003      0   stevel 	/ read the TSC and store the TS in %edi:%esi
   2004      0   stevel 	rdtsc
   2005      0   stevel 	movl	%eax, %esi
   2006      0   stevel 
   2007      0   stevel freq_tsc_perf_loop:
   2008      0   stevel 	movl	%edx, %edi
   2009      0   stevel 	movl	%eax, %esi
   2010      0   stevel 	movl	%edx, %edi
   2011      0   stevel 	loop	freq_tsc_perf_loop
   2012      0   stevel 
   2013      0   stevel 	/ read the TSC and store the LSW in %ecx
   2014      0   stevel 	rdtsc
   2015      0   stevel 	movl	%eax, %ecx
   2016      0   stevel 
   2017      0   stevel 	/ latch the PIT counter and status
   2018      0   stevel 	movb	$_CONST(PIT_READBACK|PIT_READBACKC0), %al
   2019      0   stevel 	outb	$PITCTL_PORT
   2020      0   stevel 
   2021      0   stevel 	/ remember if the icache has been warmed
   2022      0   stevel 	setc	%ah
   2023      0   stevel 
   2024      0   stevel 	/ read the PIT status
   2025      0   stevel 	inb	$PITCTR0_PORT
   2026      0   stevel 	shll	$8, %eax
   2027      0   stevel 
   2028      0   stevel 	/ read PIT count
   2029      0   stevel 	inb	$PITCTR0_PORT
   2030      0   stevel 	shll	$8, %eax
   2031      0   stevel 	inb	$PITCTR0_PORT
   2032      0   stevel 	bswap	%eax
   2033      0   stevel 
   2034      0   stevel 	/ check to see if the PIT count was loaded into the CE
   2035      0   stevel 	btw	$_CONST(PITSTAT_NULLCNT+8), %ax
   2036      0   stevel 	jc	freq_tsc_increase_count
   2037      0   stevel 
   2038      0   stevel 	/ check to see if PIT counter wrapped
   2039      0   stevel 	btw	$_CONST(PITSTAT_OUTPUT+8), %ax
   2040      0   stevel 	jnc	freq_tsc_pit_did_not_wrap
   2041      0   stevel 
   2042      0   stevel 	/ halve count
   2043      0   stevel 	shrl	$1, %ebx
   2044      0   stevel 	movl	%ebx, %ecx
   2045      0   stevel 
   2046      0   stevel 	/ the instruction cache has been warmed
   2047      0   stevel 	stc
   2048      0   stevel 
   2049      0   stevel 	jmp	freq_tsc_loop
   2050      0   stevel 
   2051      0   stevel freq_tsc_increase_count:
   2052      0   stevel 	shll	$1, %ebx
   2053      0   stevel 	jc	freq_tsc_too_fast
   2054      0   stevel 
   2055      0   stevel 	movl	%ebx, %ecx
   2056      0   stevel 
   2057      0   stevel 	/ the instruction cache has been warmed
   2058      0   stevel 	stc
   2059      0   stevel 
   2060      0   stevel 	jmp	freq_tsc_loop
   2061      0   stevel 
   2062      0   stevel freq_tsc_pit_did_not_wrap:
   2063      0   stevel 	roll	$16, %eax
   2064      0   stevel 
   2065      0   stevel 	cmpw	$0x2000, %ax
   2066      0   stevel 	notw	%ax
   2067      0   stevel 	jb	freq_tsc_sufficient_duration
   2068      0   stevel 
   2069      0   stevel freq_tsc_calculate:
   2070      0   stevel 	/ in mode 0, the PIT loads the count into the CE on the first CLK pulse,
   2071      0   stevel 	/ then on the second CLK pulse the CE is decremented, therefore mode 0
   2072      0   stevel 	/ is really a (count + 1) counter, ugh
   2073      0   stevel 	xorl	%esi, %esi
   2074      0   stevel 	movw	%ax, %si
   2075      0   stevel 	incl	%esi
   2076      0   stevel 
   2077      0   stevel 	movl	$0xf000, %eax
   2078      0   stevel 	mull	%ebx
   2079      0   stevel 
   2080      0   stevel 	/ tuck away (target_pit_count * loop_count)
   2081      0   stevel 	movl	%edx, %ecx
   2082      0   stevel 	movl	%eax, %ebx
   2083      0   stevel 
   2084      0   stevel 	movl	%esi, %eax
   2085      0   stevel 	movl	$0xffffffff, %edx
   2086      0   stevel 	mull	%edx
   2087      0   stevel 
   2088      0   stevel 	addl	%esi, %eax
   2089      0   stevel 	adcl	$0, %edx
   2090      0   stevel 
   2091      0   stevel 	cmpl	%ecx, %edx
   2092      0   stevel 	ja	freq_tsc_div_safe
   2093      0   stevel 	jb	freq_tsc_too_fast
   2094      0   stevel 
   2095      0   stevel 	cmpl	%ebx, %eax
   2096      0   stevel 	jbe	freq_tsc_too_fast
   2097      0   stevel 
   2098      0   stevel freq_tsc_div_safe:
   2099      0   stevel 	movl	%ecx, %edx
   2100      0   stevel 	movl	%ebx, %eax
   2101      0   stevel 
   2102      0   stevel 	movl	%esi, %ecx
   2103      0   stevel 	divl	%ecx
   2104      0   stevel 
   2105      0   stevel 	movl	%eax, %ecx
   2106      0   stevel 
   2107      0   stevel 	/ the instruction cache has been warmed
   2108      0   stevel 	stc
   2109      0   stevel 
   2110      0   stevel 	jmp	freq_tsc_loop
   2111      0   stevel 
   2112      0   stevel freq_tsc_sufficient_duration:
   2113      0   stevel 	/ test to see if the icache has been warmed
   2114      0   stevel 	btl	$16, %eax
   2115      0   stevel 	jnc	freq_tsc_calculate
   2116      0   stevel 
   2117      0   stevel 	/ recall mode 0 is a (count + 1) counter
   2118      0   stevel 	andl	$0xffff, %eax
   2119      0   stevel 	incl	%eax
   2120      0   stevel 
   2121      0   stevel 	/ save the number of PIT counts
   2122      0   stevel 	movl	8(%ebp), %ebx
   2123      0   stevel 	movl	%eax, (%ebx)
   2124      0   stevel 
   2125      0   stevel 	/ calculate the number of TS's that elapsed
   2126      0   stevel 	movl	%ecx, %eax
   2127      0   stevel 	subl	%esi, %eax
   2128      0   stevel 	sbbl	%edi, %edx
   2129      0   stevel 
   2130      0   stevel 	jmp	freq_tsc_end
   2131      0   stevel 
   2132      0   stevel freq_tsc_too_fast:
   2133      0   stevel 	/ return 0 as a 64 bit quantity
   2134      0   stevel 	xorl	%eax, %eax
   2135      0   stevel 	xorl	%edx, %edx
   2136      0   stevel 
   2137      0   stevel freq_tsc_end:
   2138      0   stevel 	popl	%ebx
   2139      0   stevel 	popl	%esi
   2140      0   stevel 	popl	%edi
   2141      0   stevel 	popl	%ebp
   2142      0   stevel 	ret
   2143      0   stevel 	SET_SIZE(freq_tsc)
   2144      0   stevel 
   2145      0   stevel #endif	/* __i386 */
   2146      0   stevel #endif	/* __lint */
   2147      0   stevel 
   2148      0   stevel #if !defined(__amd64)
   2149      0   stevel #if defined(__lint)
   2150      0   stevel 
   2151      0   stevel /*
   2152      0   stevel  * We do not have a TSC so we use a block of instructions with well known
   2153      0   stevel  * timings.
   2154      0   stevel  */
   2155      0   stevel 
   2156      0   stevel /*ARGSUSED*/
   2157      0   stevel uint64_t
   2158      0   stevel freq_notsc(uint32_t *pit_counter)
   2159      0   stevel {
   2160      0   stevel 	return (0);
   2161      0   stevel }
   2162      0   stevel 
   2163      0   stevel #else	/* __lint */
   2164      0   stevel 	ENTRY_NP(freq_notsc)
   2165      0   stevel 	pushl	%ebp
   2166      0   stevel 	movl	%esp, %ebp
   2167      0   stevel 	pushl	%edi
   2168      0   stevel 	pushl	%esi
   2169      0   stevel 	pushl	%ebx
   2170      0   stevel 
   2171      0   stevel 	/ initial count for the idivl loop
   2172      0   stevel 	movl	$0x1000, %ecx
   2173      0   stevel 
   2174      0   stevel 	/ load the divisor
   2175      0   stevel 	movl	$1, %ebx
   2176      0   stevel 
   2177      0   stevel 	jmp	freq_notsc_loop
   2178      0   stevel 
   2179      0   stevel .align	16
   2180      0   stevel freq_notsc_loop:
   2181      0   stevel 	/ set high 32 bits of dividend to zero
   2182      0   stevel 	xorl	%edx, %edx
   2183      0   stevel 
   2184      0   stevel 	/ save the loop count in %edi
   2185      0   stevel 	movl	%ecx, %edi
   2186      0   stevel 
   2187      0   stevel 	/ initialize the PIT counter and start a count down
   2188      0   stevel 	movb	$PIT_LOADMODE, %al
   2189      0   stevel 	outb	$PITCTL_PORT
   2190      0   stevel 	movb	$0xff, %al
   2191      0   stevel 	outb	$PITCTR0_PORT
   2192      0   stevel 	outb	$PITCTR0_PORT
   2193      0   stevel 
   2194      0   stevel 	/ set low 32 bits of dividend to zero
   2195      0   stevel 	xorl	%eax, %eax
   2196      0   stevel 
   2197      0   stevel / It is vital that the arguments to idivl be set appropriately because on some
   2198      0   stevel / cpu's this instruction takes more or less clock ticks depending on its
   2199      0   stevel / arguments.
   2200      0   stevel freq_notsc_perf_loop:
   2201      0   stevel 	idivl	%ebx
   2202      0   stevel 	idivl	%ebx
   2203      0   stevel 	idivl	%ebx
   2204      0   stevel 	idivl	%ebx
   2205      0   stevel 	idivl	%ebx
   2206      0   stevel 	loop	freq_notsc_perf_loop
   2207      0   stevel 
   2208      0   stevel 	/ latch the PIT counter and status
   2209      0   stevel 	movb	$_CONST(PIT_READBACK|PIT_READBACKC0), %al
   2210      0   stevel 	outb	$PITCTL_PORT
   2211      0   stevel 
   2212      0   stevel 	/ read the PIT status
   2213      0   stevel 	inb	$PITCTR0_PORT
   2214      0   stevel 	shll	$8, %eax
   2215      0   stevel 
   2216      0   stevel 	/ read PIT count
   2217      0   stevel 	inb	$PITCTR0_PORT
   2218      0   stevel 	shll	$8, %eax
   2219      0   stevel 	inb	$PITCTR0_PORT
   2220      0   stevel 	bswap	%eax
   2221      0   stevel 
   2222      0   stevel 	/ check to see if the PIT count was loaded into the CE
   2223      0   stevel 	btw	$_CONST(PITSTAT_NULLCNT+8), %ax
   2224      0   stevel 	jc	freq_notsc_increase_count
   2225      0   stevel 
   2226      0   stevel 	/ check to see if PIT counter wrapped
   2227      0   stevel 	btw	$_CONST(PITSTAT_OUTPUT+8), %ax
   2228      0   stevel 	jnc	freq_notsc_pit_did_not_wrap
   2229      0   stevel 
   2230      0   stevel 	/ halve count
   2231      0   stevel 	shrl	$1, %edi
   2232      0   stevel 	movl	%edi, %ecx
   2233      0   stevel 
   2234      0   stevel 	jmp	freq_notsc_loop
   2235      0   stevel 
   2236      0   stevel freq_notsc_increase_count:
   2237      0   stevel 	shll	$1, %edi
   2238      0   stevel 	jc	freq_notsc_too_fast
   2239      0   stevel 
   2240      0   stevel 	movl	%edi, %ecx
   2241      0   stevel 
   2242      0   stevel 	jmp	freq_notsc_loop
   2243      0   stevel 
   2244      0   stevel freq_notsc_pit_did_not_wrap:
   2245      0   stevel 	shrl	$16, %eax
   2246      0   stevel 
   2247      0   stevel 	cmpw	$0x2000, %ax
   2248      0   stevel 	notw	%ax
   2249      0   stevel 	jb	freq_notsc_sufficient_duration
   2250      0   stevel 
   2251      0   stevel freq_notsc_calculate:
   2252      0   stevel 	/ in mode 0, the PIT loads the count into the CE on the first CLK pulse,
   2253      0   stevel 	/ then on the second CLK pulse the CE is decremented, therefore mode 0
   2254      0   stevel 	/ is really a (count + 1) counter, ugh
   2255      0   stevel 	xorl	%esi, %esi
   2256      0   stevel 	movw	%ax, %si
   2257      0   stevel 	incl	%esi
   2258      0   stevel 
   2259      0   stevel 	movl	%edi, %eax
   2260      0   stevel 	movl	$0xf000, %ecx
   2261      0   stevel 	mull	%ecx
   2262      0   stevel 
   2263      0   stevel 	/ tuck away (target_pit_count * loop_count)
   2264      0   stevel 	movl	%edx, %edi
   2265      0   stevel 	movl	%eax, %ecx
   2266      0   stevel 
   2267      0   stevel 	movl	%esi, %eax
   2268      0   stevel 	movl	$0xffffffff, %edx
   2269      0   stevel 	mull	%edx
   2270      0   stevel 
   2271      0   stevel 	addl	%esi, %eax
   2272      0   stevel 	adcl	$0, %edx
   2273      0   stevel 
   2274      0   stevel 	cmpl	%edi, %edx
   2275      0   stevel 	ja	freq_notsc_div_safe
   2276      0   stevel 	jb	freq_notsc_too_fast
   2277      0   stevel 
   2278      0   stevel 	cmpl	%ecx, %eax
   2279      0   stevel 	jbe	freq_notsc_too_fast
   2280      0   stevel 
   2281      0   stevel freq_notsc_div_safe:
   2282      0   stevel 	movl	%edi, %edx
   2283      0   stevel 	movl	%ecx, %eax
   2284      0   stevel 
   2285      0   stevel 	movl	%esi, %ecx
   2286      0   stevel 	divl	%ecx
   2287      0   stevel 
   2288      0   stevel 	movl	%eax, %ecx
   2289      0   stevel 
   2290      0   stevel 	jmp	freq_notsc_loop
   2291      0   stevel 
   2292      0   stevel freq_notsc_sufficient_duration:
   2293      0   stevel 	/ recall mode 0 is a (count + 1) counter
   2294      0   stevel 	incl	%eax
   2295      0   stevel 
   2296      0   stevel 	/ save the number of PIT counts
   2297      0   stevel 	movl	8(%ebp), %ebx
   2298      0   stevel 	movl	%eax, (%ebx)
   2299      0   stevel 
   2300      0   stevel 	/ calculate the number of cpu clock ticks that elapsed
   2301      0   stevel 	cmpl	$X86_VENDOR_Cyrix, x86_vendor
   2302      0   stevel 	jz	freq_notsc_notcyrix
   2303      0   stevel 
   2304      0   stevel 	/ freq_notsc_perf_loop takes 86 clock cycles on Cyrix 6x86 cores
   2305      0   stevel 	movl	$86, %eax
   2306      0   stevel 	jmp	freq_notsc_calculate_tsc
   2307      0   stevel 
   2308      0   stevel freq_notsc_notcyrix:
   2309      0   stevel 	/ freq_notsc_perf_loop takes 237 clock cycles on Intel Pentiums
   2310      0   stevel 	movl	$237, %eax
   2311      0   stevel 
   2312      0   stevel freq_notsc_calculate_tsc:
   2313      0   stevel 	mull	%edi
   2314      0   stevel 
   2315      0   stevel 	jmp	freq_notsc_end
   2316      0   stevel 
   2317      0   stevel freq_notsc_too_fast:
   2318      0   stevel 	/ return 0 as a 64 bit quantity
   2319      0   stevel 	xorl	%eax, %eax
   2320      0   stevel 	xorl	%edx, %edx
   2321      0   stevel 
   2322      0   stevel freq_notsc_end:
   2323      0   stevel 	popl	%ebx
   2324      0   stevel 	popl	%esi
   2325      0   stevel 	popl	%edi
   2326      0   stevel 	popl	%ebp
   2327      0   stevel 
   2328      0   stevel 	ret
   2329      0   stevel 	SET_SIZE(freq_notsc)
   2330      0   stevel 
   2331      0   stevel #endif	/* __lint */
   2332      0   stevel #endif	/* !__amd64 */
   2333      0   stevel 
   2334      0   stevel #if !defined(__lint)
   2335      0   stevel 	.data
   2336      0   stevel #if !defined(__amd64)
   2337      0   stevel 	.align	4
   2338      0   stevel cpu_vendor:
   2339      0   stevel 	.long	0, 0, 0		/* Vendor ID string returned */
   2340      0   stevel 
   2341      0   stevel 	.globl	CyrixInstead
   2342      0   stevel 
   2343      0   stevel 	.globl	x86_feature
   2344      0   stevel 	.globl	x86_type
   2345      0   stevel 	.globl	x86_vendor
   2346      0   stevel #endif
   2347      0   stevel 
   2348      0   stevel #endif	/* __lint */
   2349