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