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