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