Print this page
de-linting of .s files
m

*** 41,63 **** #include <sys/psw.h> #include <sys/reboot.h> #include <sys/x86_archext.h> #include <sys/machparam.h> - #if defined(__lint) - - #include <sys/types.h> - #include <sys/thread.h> - #include <sys/systm.h> - #include <sys/lgrp.h> - #include <sys/regset.h> - #include <sys/link.h> - #include <sys/bootconf.h> - #include <sys/bootsvcs.h> - - #else /* __lint */ - #include <sys/segments.h> #include <sys/pcb.h> #include <sys/trap.h> #include <sys/ftrace.h> #include <sys/traptrace.h> --- 41,50 ----
*** 131,154 **** */ .data .comm t0stack, DEFAULTSTKSZ, 32 .comm t0, 4094, 32 - #endif /* __lint */ - - #if defined(__amd64) - - #if defined(__lint) - - /* ARGSUSED */ - void - _locore_start(struct boot_syscalls *sysp, ulong_t rsi, struct bootops *bop) - {} - - #else /* __lint */ - /* * kobj_init() vectors us back to here with (note) a slightly different * set of arguments than _start is given (see lint prototypes above). * * XXX Make this less vile, please. --- 118,128 ----
*** 227,241 **** leaq __return_from_main(%rip), %rdi xorl %eax, %eax call panic SET_SIZE(_locore_start) - #endif /* __amd64 */ - #endif /* __lint */ - - #if !defined(__lint) - __return_from_main: .string "main() returned" __unsupported_cpu: .string "486 style cpu detected - no longer supported!" --- 201,210 ----
*** 242,1107 **** #if defined(DEBUG) _no_pending_updates: .string "locore.s:%d lwp_rtt(lwp %p) but pcb_rupdate != 1" #endif - #endif /* !__lint */ - - #if !defined(__amd64) - - #if defined(__lint) - - /* ARGSUSED */ - void - _locore_start(struct boot_syscalls *sysp, struct bootops *bop) - {} - - #else /* __lint */ - - /* - * kobj_init() vectors us back to here with (note) a slightly different - * set of arguments than _start is given (see lint prototypes above). - * - * XXX Make this less vile, please. - */ - ENTRY_NP(_locore_start) - - /* - * %ecx = boot services (should die someday) - * %ebx = bootops - */ - mov $edata, %ebp / edata needs to be defined for ksyms - movl $0, (%ebp) / limit stack back trace - - /* - * Initialize our stack pointer to the thread 0 stack (t0stack) - * and leave room for a phony "struct regs". - */ - movl $t0stack + DEFAULTSTKSZ - REGSIZE, %esp - - /* - * Save call back for special x86 boot services vector - */ - mov %ecx, sysp / save call back for boot services - - mov %ebx, bootops / save bootops - movl $bootops, bootopsp - - - /* - * Save all registers and flags - */ - pushal - pushfl - - #if !defined(__xpv) - /* - * Override bios settings and enable write protect and - * alignment check faults. - */ - movl %cr0, %eax - - /* - * enable WP for detecting faults, and enable alignment checking. - */ - orl $_CONST(CR0_WP|CR0_AM), %eax - andl $_BITNOT(CR0_WT|CR0_CE), %eax - movl %eax, %cr0 / set the cr0 register correctly and - / override the BIOS setup - - /* - * If bit 21 of eflags can be flipped, then cpuid is present - * and enabled. - */ - pushfl - popl %ecx - movl %ecx, %eax - xorl $PS_ID, %eax / try complemented bit - pushl %eax - popfl - pushfl - popl %eax - cmpl %eax, %ecx - jne have_cpuid - - /* - * cpuid may be disabled on Cyrix, try to detect Cyrix by the 5/2 test - * div does not modify the cc flags on Cyrix, even though this may - * also be true for other vendors, this is generally true only for - * newer models from those vendors that support and do not disable - * cpuid (usually because cpuid cannot be disabled) - */ - - /* - * clear cc flags - */ - xorb %ah, %ah - sahf - - /* - * perform 5/2 test - */ - movw $5, %ax - movb $2, %bl - divb %bl - - lahf - cmpb $2, %ah - jne cpu_486 - - /* - * div did not modify the cc flags, chances are the vendor is Cyrix - * assume the vendor is Cyrix and use the CCR's to enable cpuid - */ - .set CYRIX_CRI, 0x22 / CR Index Register - .set CYRIX_CRD, 0x23 / CR Data Register - - .set CYRIX_CCR3, 0xc3 / Config Control Reg 3 - .set CYRIX_CCR4, 0xe8 / Config Control Reg 4 - .set CYRIX_DIR0, 0xfe / Device Identification Reg 0 - .set CYRIX_DIR1, 0xff / Device Identification Reg 1 - - /* - * even if the cpu vendor is Cyrix and the motherboard/chipset - * vendor decided to ignore lines A1-A4 for I/O addresses, I/O port - * 0x21 corresponds with 0x23 and since 0x22 is still untouched, - * the reads and writes of 0x21 are guaranteed to be off-chip of - * the cpu - */ - - /* - * enable read of ISR at I/O port 0x20 - */ - movb $0xb, %al - outb $MCMD_PORT - - /* - * read IMR and store in %bl - */ - inb $MIMR_PORT - movb %al, %bl - - /* - * mask out all interrupts so that ISR will not change - */ - movb $0xff, %al - outb $MIMR_PORT - - /* - * reads of I/O port 0x22 on Cyrix are always directed off-chip - * make use of I/O pull-up to test for an unknown device on 0x22 - */ - inb $CYRIX_CRI - cmpb $0xff, %al - je port_22_free - - /* - * motherboard/chipset vendor may be ignoring line A1 of I/O address - */ - movb %al, %cl - - /* - * if the ISR and the value read from 0x22 do not match then we have - * detected some unknown device, probably a chipset, at 0x22 - */ - inb $MCMD_PORT - cmpb %al, %cl - jne restore_IMR - - port_22_free: - /* - * now test to see if some unknown device is using I/O port 0x23 - * - * read the external I/O port at 0x23 - */ - inb $CYRIX_CRD - - /* - * Test for pull-up at 0x23 or if I/O address line A1 is being ignored. - * IMR is 0xff so both tests are performed simultaneously. - */ - cmpb $0xff, %al - jne restore_IMR - - /* - * We are a Cyrix part. In case we are some model of Cx486 or a Cx586, - * record the type and fix it later if not. - */ - movl $X86_VENDOR_Cyrix, x86_vendor - movl $X86_TYPE_CYRIX_486, x86_type - - /* - * Try to read CCR3. All Cyrix cpu's which support cpuid have CCR3. - * - * load CCR3 index into CCR index register - */ - - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - /* - * If we are not a Cyrix cpu, then we have performed an external I/O - * cycle. If the CCR index was not valid for this Cyrix model, we may - * have performed an external I/O cycle as well. In these cases and - * if the motherboard/chipset vendor ignores I/O address line A1, - * then the PIC will have IRQ3 set at the lowest priority as a side - * effect of the above outb. We are reasonalbly confident that there - * is not an unknown device on I/O port 0x22, so there should have been - * no unpredictable side-effect of the above outb. - */ - - /* - * read CCR3 - */ - inb $CYRIX_CRD - - /* - * If we are not a Cyrix cpu the inb above produced an external I/O - * cycle. If we are a Cyrix model that does not support CCR3 wex - * produced an external I/O cycle. In all known Cyrix models 6x86 and - * above, bit 3 of CCR3 is reserved and cannot be set to 1. In all - * Cyrix models prior to the 6x86 that supported CCR3, bits 4-7 are - * reserved as well. It is highly unlikely that CCR3 contains the value - * 0xff. We test to see if I/O port 0x23 is pull-up or the IMR and - * deduce we are not a Cyrix with support for cpuid if so. - */ - cmpb $0xff, %al - je restore_PIC - - /* - * There exist 486 ISA Cyrix chips that support CCR3 but do not support - * DIR0 and DIR1. If we try to read DIR0, we may generate external I/O - * cycles, the exact behavior is model specific and undocumented. - * Unfortunately these external I/O cycles may confuse some PIC's beyond - * recovery. Fortunatetly we can use the following undocumented trick: - * if bit 4 of CCR3 can be toggled, then DIR0 and DIR1 are supported. - * Pleasantly MAPEN contains bit 4 of CCR3, so this trick is guaranteed - * to work on all Cyrix cpu's which support cpuid. - */ - movb %al, %dl - xorb $0x10, %dl - movb %al, %cl - - /* - * write back CRR3 with toggled bit 4 to CCR3 - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - movb %dl, %al - outb $CYRIX_CRD - - /* - * read CCR3 - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - movb %al, %dl - - /* - * restore CCR3 - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - movb %cl, %al - outb $CYRIX_CRD - - /* - * if bit 4 was not toggled DIR0 and DIR1 are not supported in which - * case we do not have cpuid anyway - */ - andb $0x10, %al - andb $0x10, %dl - cmpb %al, %dl - je restore_PIC - - /* - * read DIR0 - */ - movb $CYRIX_DIR0, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - - /* - * test for pull-up - */ - cmpb $0xff, %al - je restore_PIC - - /* - * Values of 0x20-0x27 in DIR0 are currently reserved by Cyrix for - * future use. If Cyrix ever produces a cpu that supports cpuid with - * these ids, the following test will have to change. For now we remain - * pessimistic since the formats of the CRR's may be different then. - * - * test for at least a 6x86, to see if we support both MAPEN and CPUID - */ - cmpb $0x30, %al - jb restore_IMR - - /* - * enable MAPEN - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - andb $0xf, %cl - movb %cl, %al - orb $0x10, %al - outb $CYRIX_CRD - - /* - * select CCR4 - */ - movb $CYRIX_CCR4, %al - outb $CYRIX_CRI - - /* - * read CCR4 - */ - inb $CYRIX_CRD - - /* - * enable cpuid - */ - orb $0x80, %al - movb %al, %dl - - /* - * select CCR4 - */ - movb $CYRIX_CCR4, %al - outb $CYRIX_CRI - - /* - * write CCR4 - */ - movb %dl, %al - outb $CYRIX_CRD - - /* - * select CCR3 - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - /* - * disable MAPEN and write CCR3 - */ - movb %cl, %al - outb $CYRIX_CRD - - /* - * restore IMR - */ - movb %bl, %al - outb $MIMR_PORT - - /* - * test to see if cpuid available - */ - pushfl - popl %ecx - movl %ecx, %eax - xorl $PS_ID, %eax / try complemented bit - pushl %eax - popfl - pushfl - popl %eax - cmpl %eax, %ecx - jne have_cpuid - jmp cpu_486 - - restore_PIC: - /* - * In case the motherboard/chipset vendor is ignoring line A1 of the - * I/O address, we set the PIC priorities to sane values. - */ - movb $0xc7, %al / irq 7 lowest priority - outb $MCMD_PORT - - restore_IMR: - movb %bl, %al - outb $MIMR_PORT - jmp cpu_486 - - have_cpuid: - /* - * cpuid instruction present - */ - bts $X86FSET_CPUID, x86_featureset / Just to set; Ignore the CF - movl $0, %eax - cpuid - - movl %ebx, cpu_vendor - movl %edx, cpu_vendor+4 - movl %ecx, cpu_vendor+8 - - /* - * early cyrix cpus are somewhat strange and need to be - * probed in curious ways to determine their identity - */ - - leal cpu_vendor, %esi - leal CyrixInstead, %edi - movl $12, %ecx - repz - cmpsb - je vendor_is_cyrix - - / let mlsetup()/cpuid_pass1() handle everything else in C - - jmp cpu_done - - is486: - /* - * test to see if a useful cpuid - */ - testl %eax, %eax - jz isa486 - - movl $1, %eax - cpuid - - movl %eax, %ebx - andl $0xF00, %ebx - cmpl $0x400, %ebx - je isa486 - - rep; ret /* use 2 byte return instruction */ - /* AMD Software Optimization Guide - Section 6.2 */ - isa486: - /* - * lose the return address - */ - popl %eax - jmp cpu_486 - - vendor_is_cyrix: - call is486 - - /* - * Processor signature and feature flags for Cyrix are insane. - * BIOS can play with semi-documented registers, so cpuid must be used - * cautiously. Since we are Cyrix that has cpuid, we have DIR0 and DIR1 - * Keep the family in %ebx and feature flags in %edx until not needed - */ - - /* - * read DIR0 - */ - movb $CYRIX_DIR0, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - - /* - * First we handle the cases where we are a 6x86 or 6x86L. - * The 6x86 is basically a 486, the only reliable bit in the - * feature flags is for FPU. The 6x86L is better, unfortunately - * there is no really good way to distinguish between these two - * cpu's. We are pessimistic and when in doubt assume 6x86. - */ - - cmpb $0x40, %al - jae maybeGX - - /* - * We are an M1, either a 6x86 or 6x86L. - */ - cmpb $0x30, %al - je maybe6x86L - cmpb $0x31, %al - je maybe6x86L - cmpb $0x34, %al - je maybe6x86L - cmpb $0x35, %al - je maybe6x86L - - /* - * although it is possible that we are a 6x86L, the cpu and - * documentation are so buggy, we just do not care. - */ - jmp likely6x86 - - maybe6x86L: - /* - * read DIR1 - */ - movb $CYRIX_DIR1, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - cmpb $0x22, %al - jb likely6x86 - - /* - * We are a 6x86L, or at least a 6x86 with honest cpuid feature flags - */ - movl $X86_TYPE_CYRIX_6x86L, x86_type - jmp coma_bug - - likely6x86: - /* - * We are likely a 6x86, or a 6x86L without a way of knowing - * - * The 6x86 has NO Pentium or Pentium Pro compatible features even - * though it claims to be a Pentium Pro compatible! - * - * The 6x86 core used in the 6x86 may have most of the Pentium system - * registers and largely conform to the Pentium System Programming - * Reference. Documentation on these parts is long gone. Treat it as - * a crippled Pentium and hope for the best. - */ - - movl $X86_TYPE_CYRIX_6x86, x86_type - jmp coma_bug - - maybeGX: - /* - * Now we check whether we are a MediaGX or GXm. We have particular - * reason for concern here. Even though most of the GXm's - * report having TSC in the cpuid feature flags, the TSC may be - * horribly broken. What is worse, is that MediaGX's are basically - * 486's while the good GXm's are more like Pentium Pro's! - */ - - cmpb $0x50, %al - jae maybeM2 - - /* - * We are either a MediaGX (sometimes called a Gx86) or GXm - */ - - cmpb $41, %al - je maybeMediaGX - - cmpb $44, %al - jb maybeGXm - - cmpb $47, %al - jbe maybeMediaGX - - /* - * We do not honestly know what we are, so assume a MediaGX - */ - jmp media_gx - - maybeGXm: - /* - * It is still possible we are either a MediaGX or GXm, trust cpuid - * family should be 5 on a GXm - */ - cmpl $0x500, %ebx - je GXm - - /* - * BIOS/Cyrix might set family to 6 on a GXm - */ - cmpl $0x600, %ebx - jne media_gx - - GXm: - movl $X86_TYPE_CYRIX_GXm, x86_type - jmp cpu_done - - maybeMediaGX: - /* - * read DIR1 - */ - movb $CYRIX_DIR1, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - - cmpb $0x30, %al - jae maybeGXm - - /* - * we are a MediaGX for which we do not trust cpuid - */ - media_gx: - movl $X86_TYPE_CYRIX_MediaGX, x86_type - jmp cpu_486 - - maybeM2: - /* - * Now we check whether we are a 6x86MX or MII. These cpu's are - * virtually identical, but we care because for the 6x86MX, we - * must work around the coma bug. Also for 6x86MX prior to revision - * 1.4, the TSC may have serious bugs. - */ - - cmpb $0x60, %al - jae maybeM3 - - /* - * family should be 6, but BIOS/Cyrix might set it to 5 - */ - cmpl $0x600, %ebx - ja cpu_486 - - /* - * read DIR1 - */ - movb $CYRIX_DIR1, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - - cmpb $0x8, %al - jb cyrix6x86MX - cmpb $0x80, %al - jb MII - - cyrix6x86MX: - /* - * It is altogether unclear how the revision stamped on the cpu - * maps to the values in DIR0 and DIR1. Just assume TSC is broken. - */ - movl $X86_TYPE_CYRIX_6x86MX, x86_type - jmp coma_bug - - MII: - movl $X86_TYPE_CYRIX_MII, x86_type - likeMII: - jmp cpu_done - - maybeM3: - /* - * We are some chip that we cannot identify yet, an MIII perhaps. - * We will be optimistic and hope that the chip is much like an MII, - * and that cpuid is sane. Cyrix seemed to have gotten it right in - * time for the MII, we can only hope it stayed that way. - * Maybe the BIOS or Cyrix is trying to hint at something - */ - cmpl $0x500, %ebx - je GXm - - cmpb $0x80, %al - jae likelyM3 - - /* - * Just test for the features Cyrix is known for - */ - - jmp MII - - likelyM3: - /* - * DIR0 with values from 0x80 to 0x8f indicates a VIA Cyrix III, aka - * the Cyrix MIII. There may be parts later that use the same ranges - * for DIR0 with special values in DIR1, maybe the VIA CIII, but for - * now we will call anything with a DIR0 of 0x80 or higher an MIII. - * The MIII is supposed to support large pages, but we will believe - * it when we see it. For now we just enable and test for MII features. - */ - movl $X86_TYPE_VIA_CYRIX_III, x86_type - jmp likeMII - - coma_bug: - /* - * With NO_LOCK set to 0 in CCR1, the usual state that BIOS enforces, some - * bus cycles are issued with LOCK# asserted. With NO_LOCK set to 1, all bus - * cycles except page table accesses and interrupt ACK cycles do not assert - * LOCK#. xchgl is an instruction that asserts LOCK# if NO_LOCK is set to 0. - * Due to a bug in the cpu core involving over-optimization of branch - * prediction, register renaming, and execution of instructions down both the - * X and Y pipes for the xchgl instruction, short loops can be written that - * never de-assert LOCK# from one invocation of the loop to the next, ad - * infinitum. The undesirable effect of this situation is that interrupts are - * not serviced. The ideal workaround to this bug would be to set NO_LOCK to - * 1. Unfortunately bus cycles that would otherwise have asserted LOCK# no - * longer do, unless they are page table accesses or interrupt ACK cycles. - * With LOCK# not asserted, these bus cycles are now cached. This can cause - * undesirable behaviour if the ARR's are not configured correctly. Solaris - * does not configure the ARR's, nor does it provide any useful mechanism for - * doing so, thus the ideal workaround is not viable. Fortunately, the only - * known exploits for this bug involve the xchgl instruction specifically. - * There is a group of undocumented registers on Cyrix 6x86, 6x86L, and - * 6x86MX cpu's which can be used to specify one instruction as a serializing - * instruction. With the xchgl instruction serialized, LOCK# is still - * asserted, but it is the sole instruction for which LOCK# is asserted. - * There is now some added penalty for the xchgl instruction, but the usual - * bus locking is preserved. This ingenious workaround was discovered by - * disassembling a binary provided by Cyrix as a workaround for this bug on - * Windows, but its not documented anywhere by Cyrix, nor is the bug actually - * mentioned in any public errata! The only concern for this workaround is - * that there may be similar undiscovered bugs with other instructions that - * assert LOCK# that may be leveraged to similar ends. The fact that Cyrix - * fixed this bug sometime late in 1997 and no other exploits other than - * xchgl have been discovered is good indication that this workaround is - * reasonable. - */ - - .set CYRIX_DBR0, 0x30 / Debug Register 0 - .set CYRIX_DBR1, 0x31 / Debug Register 1 - .set CYRIX_DBR2, 0x32 / Debug Register 2 - .set CYRIX_DBR3, 0x33 / Debug Register 3 - .set CYRIX_DOR, 0x3c / Debug Opcode Register - - /* - * What is known about DBR1, DBR2, DBR3, and DOR is that for normal - * cpu execution DBR1, DBR2, and DBR3 are set to 0. To obtain opcode - * serialization, DBR1, DBR2, and DBR3 are loaded with 0xb8, 0x7f, - * and 0xff. Then, DOR is loaded with the one byte opcode. - */ - - /* - * select CCR3 - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - /* - * read CCR3 and mask out MAPEN - */ - inb $CYRIX_CRD - andb $0xf, %al - - /* - * save masked CCR3 in %ah - */ - movb %al, %ah - - /* - * select CCR3 - */ - movb $CYRIX_CCR3, %al - outb $CYRIX_CRI - - /* - * enable MAPEN - */ - movb %ah, %al - orb $0x10, %al - outb $CYRIX_CRD - - /* - * read DBR0 - */ - movb $CYRIX_DBR0, %al - outb $CYRIX_CRI - inb $CYRIX_CRD - - /* - * disable MATCH and save in %bh - */ - orb $0x80, %al - movb %al, %bh - - /* - * write DBR0 - */ - movb $CYRIX_DBR0, %al - outb $CYRIX_CRI - movb %bh, %al - outb $CYRIX_CRD - - /* - * write DBR1 - */ - movb $CYRIX_DBR1, %al - outb $CYRIX_CRI - movb $0xf8, %al - outb $CYRIX_CRD - - /* - * write DBR2 - */ - movb $CYRIX_DBR2, %al - outb $CYRIX_CRI - movb $0x7f, %al - outb $CYRIX_CRD - - /* - * write DBR3 - */ - movb $CYRIX_DBR3, %al - outb $CYRIX_CRI - xorb %al, %al - outb $CYRIX_CRD - - /* - * write DOR - */ - movb $CYRIX_DOR, %al - outb $CYRIX_CRI - movb $0x87, %al - outb $CYRIX_CRD - - /* - * enable MATCH - */ - movb $CYRIX_DBR0, %al - outb $CYRIX_CRI - movb %bh, %al - andb $0x7f, %al - outb $CYRIX_CRD - - /* - * disable MAPEN - */ - movb $0xc3, %al - outb $CYRIX_CRI - movb %ah, %al - outb $CYRIX_CRD - - jmp cpu_done - - cpu_done: - - popfl /* Restore original FLAGS */ - popal /* Restore all registers */ - - #endif /* !__xpv */ - - /* - * mlsetup(%esp) gets called. - */ - pushl %esp - call mlsetup - addl $4, %esp - - /* - * We change our appearance to look like the real thread 0. - * (NOTE: making ourselves to be a real thread may be a noop) - * main() gets called. (NOTE: main() never returns). - */ - call main - /* NOTREACHED */ - pushl $__return_from_main - call panic - - /* NOTREACHED */ - cpu_486: - pushl $__unsupported_cpu - call panic - SET_SIZE(_locore_start) - - #endif /* __lint */ - #endif /* !__amd64 */ - - - /* * For stack layout, see privregs.h * When cmntrap gets called, the error code and trap number have been pushed. * When cmntrap_pushed gets called, the entire struct regs has been pushed. */ - #if defined(__lint) - - /* ARGSUSED */ - void - cmntrap() - {} - - #else /* __lint */ - .globl trap /* C handler called below */ - #if defined(__amd64) - ENTRY_NP2(cmntrap, _cmntrap) INTR_PUSH ALTENTRY(cmntrap_pushed) --- 211,228 ----
*** 1204,1318 **** call panic SET_SIZE(cmntrap_pushed) SET_SIZE(cmntrap) SET_SIZE(_cmntrap) - #elif defined(__i386) - - - ENTRY_NP2(cmntrap, _cmntrap) - - INTR_PUSH - - ALTENTRY(cmntrap_pushed) - - movl %esp, %ebp - - /* - * - if this is a #pf i.e. T_PGFLT, %esi is live - * and contains the faulting address i.e. a copy of %cr2 - * - * - if this is a #db i.e. T_SGLSTP, %esi is live - * and contains the value of %db6 - */ - - TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ - TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ - TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ - - /* - * We must first check if DTrace has set its NOFAULT bit. This - * regrettably must happen before the trap stack is recorded, because - * this requires a call to getpcstack() and may induce recursion if an - * fbt::getpcstack: enabling is inducing the bad load. - */ - movl %gs:CPU_ID, %eax - shll $CPU_CORE_SHIFT, %eax - addl $cpu_core, %eax - movw CPUC_DTRACE_FLAGS(%eax), %cx - testw $CPU_DTRACE_NOFAULT, %cx - jnz .dtrace_induced - - TRACE_STACK(%edi) - - pushl %gs:CPU_ID - pushl %esi /* fault address for PGFLTs */ - pushl %ebp /* &regs */ - - /* - * We know that this isn't a DTrace non-faulting load; we can now safely - * reenable interrupts. (In the case of pagefaults, we enter through an - * interrupt gate.) - */ - ENABLE_INTR_FLAGS - - call trap /* trap(rp, addr, cpuid) handles all traps */ - addl $12, %esp /* get argument off stack */ - jmp _sys_rtt - - .dtrace_induced: - cmpw $KCS_SEL, REGOFF_CS(%ebp) /* test CS for user-mode trap */ - jne 3f /* if from user, panic */ - - cmpl $T_PGFLT, REGOFF_TRAPNO(%ebp) - je 1f - - cmpl $T_GPFLT, REGOFF_TRAPNO(%ebp) - je 0f - - cmpl $T_ZERODIV, REGOFF_TRAPNO(%ebp) - jne 4f /* if not PF/GP/UD/DE, panic */ - - orw $CPU_DTRACE_DIVZERO, %cx - movw %cx, CPUC_DTRACE_FLAGS(%eax) - jmp 2f - - 0: - /* - * If we've taken a GPF, we don't (unfortunately) have the address that - * induced the fault. So instead of setting the fault to BADADDR, - * we'll set the fault to ILLOP. - */ - orw $CPU_DTRACE_ILLOP, %cx - movw %cx, CPUC_DTRACE_FLAGS(%eax) - jmp 2f - 1: - orw $CPU_DTRACE_BADADDR, %cx - movw %cx, CPUC_DTRACE_FLAGS(%eax) /* set fault to bad addr */ - movl %esi, CPUC_DTRACE_ILLVAL(%eax) - /* fault addr is illegal value */ - 2: - pushl REGOFF_EIP(%ebp) - call dtrace_instr_size - addl $4, %esp - movl REGOFF_EIP(%ebp), %ecx - addl %eax, %ecx - movl %ecx, REGOFF_EIP(%ebp) - INTR_POP_KERNEL - IRET - /*NOTREACHED*/ - 3: - pushl $dtrace_badflags - call panic - 4: - pushl $dtrace_badtrap - call panic - SET_SIZE(cmntrap) - SET_SIZE(_cmntrap) - - #endif /* __i386 */ - /* * Declare a uintptr_t which has the size of _cmntrap to enable stack * traceback code to know when a regs structure is on the stack. */ .globl _cmntrap_size --- 325,334 ----
*** 1325,1355 **** .string "bad DTrace flags" dtrace_badtrap: .string "bad DTrace trap" - #endif /* __lint */ - - #if defined(__lint) - - /* ARGSUSED */ - void - cmninttrap() - {} - - #if !defined(__xpv) - void - bop_trap_handler(void) - {} - #endif - - #else /* __lint */ - .globl trap /* C handler called below */ - #if defined(__amd64) - ENTRY_NP(cmninttrap) INTR_PUSH INTGATE_INIT_KERNEL_FLAGS --- 341,352 ----
*** 1378,1439 **** sub $8, %rsp call bop_trap SET_SIZE(bop_trap_handler) #endif - #elif defined(__i386) - - ENTRY_NP(cmninttrap) - - INTR_PUSH - INTGATE_INIT_KERNEL_FLAGS - - TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ - TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ - TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ - - movl %esp, %ebp - - TRACE_STACK(%edi) - - pushl %gs:CPU_ID - pushl $0 - pushl %ebp - call trap /* trap(rp, addr, cpuid) handles all traps */ - addl $12, %esp - jmp _sys_rtt - SET_SIZE(cmninttrap) - - #if !defined(__xpv) - /* - * Handle traps early in boot. Just revectors into C quickly as - * these are always fatal errors. - */ - ENTRY(bop_trap_handler) - movl %esp, %eax - pushl %eax - call bop_trap - SET_SIZE(bop_trap_handler) - #endif - - #endif /* __i386 */ - - #endif /* __lint */ - - #if defined(__lint) - - /* ARGSUSED */ - void - dtrace_trap() - {} - - #else /* __lint */ - .globl dtrace_user_probe - #if defined(__amd64) - ENTRY_NP(dtrace_trap) INTR_PUSH TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) /* Uses labels 8 and 9 */ --- 375,386 ----
*** 1456,1519 **** call dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */ jmp _sys_rtt SET_SIZE(dtrace_trap) - #elif defined(__i386) - - ENTRY_NP(dtrace_trap) - - INTR_PUSH - - TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_TRAP) /* Uses labels 8 and 9 */ - TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ - TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ - - movl %esp, %ebp - - pushl %gs:CPU_ID - #if defined(__xpv) - movl %gs:CPU_VCPU_INFO, %eax - movl VCPU_INFO_ARCH_CR2(%eax), %eax - #else - movl %cr2, %eax - #endif - pushl %eax - pushl %ebp - - ENABLE_INTR_FLAGS - - call dtrace_user_probe /* dtrace_user_probe(rp, addr, cpuid) */ - addl $12, %esp /* get argument off stack */ - - jmp _sys_rtt - SET_SIZE(dtrace_trap) - - #endif /* __i386 */ - - #endif /* __lint */ - /* * Return from _sys_trap routine. */ - #if defined(__lint) - - void - lwp_rtt_initial(void) - {} - - void - lwp_rtt(void) - {} - - void - _sys_rtt(void) - {} - - #else /* __lint */ - ENTRY_NP(lwp_rtt_initial) movq %gs:CPU_THREAD, %r15 movq T_STACK(%r15), %rsp /* switch to the thread stack */ movq %rsp, %rbp call __dtrace_probe___proc_start --- 403,416 ----
*** 1634,1669 **** SET_SIZE(_sys_rtt_ints_disabled) SET_SIZE(_sys_rtt) SET_SIZE(sys_rtt_syscall) SET_SIZE(sys_rtt_syscall32) - #endif /* __lint */ - - #if defined(__lint) - - /* - * So why do we have to deal with all this crud in the world of ia32? - * - * Basically there are four classes of ia32 implementations, those that do not - * have a TSC, those that have a marginal TSC that is broken to the extent - * that it is useless, those that have a marginal TSC that is not quite so - * horribly broken and can be used with some care, and those that have a - * reliable TSC. This crud has to be here in order to sift through all the - * variants. - */ - - /*ARGSUSED*/ - uint64_t - freq_tsc(uint32_t *pit_counter) - { - return (0); - } - - #else /* __lint */ - - #if defined(__amd64) - /* * XX64 quick and dirty port from the i386 version. Since we * believe the amd64 tsc is more reliable, could this code be * simpler? */ --- 531,540 ----
*** 1865,2276 **** popq %rbx leaveq ret SET_SIZE(freq_tsc) - #elif defined(__i386) - - ENTRY_NP(freq_tsc) - pushl %ebp - movl %esp, %ebp - pushl %edi - pushl %esi - pushl %ebx - - / We have a TSC, but we have no way in general to know how reliable it is. - / Usually a marginal TSC behaves appropriately unless not enough time - / elapses between reads. A reliable TSC can be read as often and as rapidly - / as desired. The simplistic approach of reading the TSC counter and - / correlating to the PIT counter cannot be naively followed. Instead estimates - / have to be taken to successively refine a guess at the speed of the cpu - / and then the TSC and PIT counter are correlated. In practice very rarely - / is more than one quick loop required for an estimate. Measures have to be - / taken to prevent the PIT counter from wrapping beyond its resolution and for - / measuring the clock rate of very fast processors. - / - / The following constant can be tuned. It should be such that the loop does - / not take too many nor too few PIT counts to execute. If this value is too - / large, then on slow machines the loop will take a long time, or the PIT - / counter may even wrap. If this value is too small, then on fast machines - / the PIT counter may count so few ticks that the resolution of the PIT - / itself causes a bad guess. Because this code is used in machines with - / marginal TSC's and/or IO, if this value is too small on those, it may - / cause the calculated cpu frequency to vary slightly from boot to boot. - / - / In all cases even if this constant is set inappropriately, the algorithm - / will still work and the caller should be able to handle variances in the - / calculation of cpu frequency, but the calculation will be inefficient and - / take a disproportionate amount of time relative to a well selected value. - / As the slowest supported cpu becomes faster, this constant should be - / carefully increased. - - movl $0x8000, %ecx - - / to make sure the instruction cache has been warmed - clc - - jmp freq_tsc_loop - - / The following block of code up to and including the latching of the PIT - / counter after freq_tsc_perf_loop is very critical and very carefully - / written, it should only be modified with great care. freq_tsc_loop to - / freq_tsc_perf_loop fits exactly in 16 bytes as do the instructions in - / freq_tsc_perf_loop up to the unlatching of the PIT counter. - - .align 32 - freq_tsc_loop: - / save the loop count in %ebx - movl %ecx, %ebx - - / initialize the PIT counter and start a count down - movb $PIT_LOADMODE, %al - outb $PITCTL_PORT - movb $0xff, %al - outb $PITCTR0_PORT - outb $PITCTR0_PORT - - / read the TSC and store the TS in %edi:%esi - rdtsc - movl %eax, %esi - - freq_tsc_perf_loop: - movl %edx, %edi - movl %eax, %esi - movl %edx, %edi - loop freq_tsc_perf_loop - - / read the TSC and store the LSW in %ecx - rdtsc - movl %eax, %ecx - - / latch the PIT counter and status - movb $_CONST(PIT_READBACK|PIT_READBACKC0), %al - outb $PITCTL_PORT - - / remember if the icache has been warmed - setc %ah - - / read the PIT status - inb $PITCTR0_PORT - shll $8, %eax - - / read PIT count - inb $PITCTR0_PORT - shll $8, %eax - inb $PITCTR0_PORT - bswap %eax - - / check to see if the PIT count was loaded into the CE - btw $_CONST(PITSTAT_NULLCNT+8), %ax - jc freq_tsc_increase_count - - / check to see if PIT counter wrapped - btw $_CONST(PITSTAT_OUTPUT+8), %ax - jnc freq_tsc_pit_did_not_wrap - - / halve count - shrl $1, %ebx - movl %ebx, %ecx - - / the instruction cache has been warmed - stc - - jmp freq_tsc_loop - - freq_tsc_increase_count: - shll $1, %ebx - jc freq_tsc_too_fast - - movl %ebx, %ecx - - / the instruction cache has been warmed - stc - - jmp freq_tsc_loop - - freq_tsc_pit_did_not_wrap: - roll $16, %eax - - cmpw $0x2000, %ax - notw %ax - jb freq_tsc_sufficient_duration - - freq_tsc_calculate: - / in mode 0, the PIT loads the count into the CE on the first CLK pulse, - / then on the second CLK pulse the CE is decremented, therefore mode 0 - / is really a (count + 1) counter, ugh - xorl %esi, %esi - movw %ax, %si - incl %esi - - movl $0xf000, %eax - mull %ebx - - / tuck away (target_pit_count * loop_count) - movl %edx, %ecx - movl %eax, %ebx - - movl %esi, %eax - movl $0xffffffff, %edx - mull %edx - - addl %esi, %eax - adcl $0, %edx - - cmpl %ecx, %edx - ja freq_tsc_div_safe - jb freq_tsc_too_fast - - cmpl %ebx, %eax - jbe freq_tsc_too_fast - - freq_tsc_div_safe: - movl %ecx, %edx - movl %ebx, %eax - - movl %esi, %ecx - divl %ecx - - movl %eax, %ecx - - / the instruction cache has been warmed - stc - - jmp freq_tsc_loop - - freq_tsc_sufficient_duration: - / test to see if the icache has been warmed - btl $16, %eax - jnc freq_tsc_calculate - - / recall mode 0 is a (count + 1) counter - andl $0xffff, %eax - incl %eax - - / save the number of PIT counts - movl 8(%ebp), %ebx - movl %eax, (%ebx) - - / calculate the number of TS's that elapsed - movl %ecx, %eax - subl %esi, %eax - sbbl %edi, %edx - - jmp freq_tsc_end - - freq_tsc_too_fast: - / return 0 as a 64 bit quantity - xorl %eax, %eax - xorl %edx, %edx - - freq_tsc_end: - popl %ebx - popl %esi - popl %edi - popl %ebp - ret - SET_SIZE(freq_tsc) - - #endif /* __i386 */ - #endif /* __lint */ - - #if !defined(__amd64) - #if defined(__lint) - - /* - * We do not have a TSC so we use a block of instructions with well known - * timings. - */ - - /*ARGSUSED*/ - uint64_t - freq_notsc(uint32_t *pit_counter) - { - return (0); - } - - #else /* __lint */ - ENTRY_NP(freq_notsc) - pushl %ebp - movl %esp, %ebp - pushl %edi - pushl %esi - pushl %ebx - - / initial count for the idivl loop - movl $0x1000, %ecx - - / load the divisor - movl $1, %ebx - - jmp freq_notsc_loop - - .align 16 - freq_notsc_loop: - / set high 32 bits of dividend to zero - xorl %edx, %edx - - / save the loop count in %edi - movl %ecx, %edi - - / initialize the PIT counter and start a count down - movb $PIT_LOADMODE, %al - outb $PITCTL_PORT - movb $0xff, %al - outb $PITCTR0_PORT - outb $PITCTR0_PORT - - / set low 32 bits of dividend to zero - xorl %eax, %eax - - / It is vital that the arguments to idivl be set appropriately because on some - / cpu's this instruction takes more or less clock ticks depending on its - / arguments. - freq_notsc_perf_loop: - idivl %ebx - idivl %ebx - idivl %ebx - idivl %ebx - idivl %ebx - loop freq_notsc_perf_loop - - / latch the PIT counter and status - movb $_CONST(PIT_READBACK|PIT_READBACKC0), %al - outb $PITCTL_PORT - - / read the PIT status - inb $PITCTR0_PORT - shll $8, %eax - - / read PIT count - inb $PITCTR0_PORT - shll $8, %eax - inb $PITCTR0_PORT - bswap %eax - - / check to see if the PIT count was loaded into the CE - btw $_CONST(PITSTAT_NULLCNT+8), %ax - jc freq_notsc_increase_count - - / check to see if PIT counter wrapped - btw $_CONST(PITSTAT_OUTPUT+8), %ax - jnc freq_notsc_pit_did_not_wrap - - / halve count - shrl $1, %edi - movl %edi, %ecx - - jmp freq_notsc_loop - - freq_notsc_increase_count: - shll $1, %edi - jc freq_notsc_too_fast - - movl %edi, %ecx - - jmp freq_notsc_loop - - freq_notsc_pit_did_not_wrap: - shrl $16, %eax - - cmpw $0x2000, %ax - notw %ax - jb freq_notsc_sufficient_duration - - freq_notsc_calculate: - / in mode 0, the PIT loads the count into the CE on the first CLK pulse, - / then on the second CLK pulse the CE is decremented, therefore mode 0 - / is really a (count + 1) counter, ugh - xorl %esi, %esi - movw %ax, %si - incl %esi - - movl %edi, %eax - movl $0xf000, %ecx - mull %ecx - - / tuck away (target_pit_count * loop_count) - movl %edx, %edi - movl %eax, %ecx - - movl %esi, %eax - movl $0xffffffff, %edx - mull %edx - - addl %esi, %eax - adcl $0, %edx - - cmpl %edi, %edx - ja freq_notsc_div_safe - jb freq_notsc_too_fast - - cmpl %ecx, %eax - jbe freq_notsc_too_fast - - freq_notsc_div_safe: - movl %edi, %edx - movl %ecx, %eax - - movl %esi, %ecx - divl %ecx - - movl %eax, %ecx - - jmp freq_notsc_loop - - freq_notsc_sufficient_duration: - / recall mode 0 is a (count + 1) counter - incl %eax - - / save the number of PIT counts - movl 8(%ebp), %ebx - movl %eax, (%ebx) - - / calculate the number of cpu clock ticks that elapsed - cmpl $X86_VENDOR_Cyrix, x86_vendor - jz freq_notsc_notcyrix - - / freq_notsc_perf_loop takes 86 clock cycles on Cyrix 6x86 cores - movl $86, %eax - jmp freq_notsc_calculate_tsc - - freq_notsc_notcyrix: - / freq_notsc_perf_loop takes 237 clock cycles on Intel Pentiums - movl $237, %eax - - freq_notsc_calculate_tsc: - mull %edi - - jmp freq_notsc_end - - freq_notsc_too_fast: - / return 0 as a 64 bit quantity - xorl %eax, %eax - xorl %edx, %edx - - freq_notsc_end: - popl %ebx - popl %esi - popl %edi - popl %ebp - - ret - SET_SIZE(freq_notsc) - - #endif /* __lint */ - #endif /* !__amd64 */ - - #if !defined(__lint) - .data - #if !defined(__amd64) - .align 4 - cpu_vendor: - .long 0, 0, 0 /* Vendor ID string returned */ - - .globl CyrixInstead - - .globl x86_featureset - .globl x86_type - .globl x86_vendor - #endif - - #endif /* __lint */ --- 736,740 ----