xref: /onnv-gate/usr/src/uts/i86pc/os/mlsetup.c (revision 4581:b6104e41b06c)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52006Sandrei  * Common Development and Distribution License (the "License").
62006Sandrei  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
223434Sesaxe  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/types.h>
293446Smrj #include <sys/sysmacros.h>
300Sstevel@tonic-gate #include <sys/disp.h>
310Sstevel@tonic-gate #include <sys/promif.h>
320Sstevel@tonic-gate #include <sys/clock.h>
330Sstevel@tonic-gate #include <sys/cpuvar.h>
340Sstevel@tonic-gate #include <sys/stack.h>
350Sstevel@tonic-gate #include <vm/as.h>
360Sstevel@tonic-gate #include <vm/hat.h>
370Sstevel@tonic-gate #include <sys/reboot.h>
380Sstevel@tonic-gate #include <sys/avintr.h>
390Sstevel@tonic-gate #include <sys/vtrace.h>
400Sstevel@tonic-gate #include <sys/proc.h>
410Sstevel@tonic-gate #include <sys/thread.h>
420Sstevel@tonic-gate #include <sys/cpupart.h>
430Sstevel@tonic-gate #include <sys/pset.h>
440Sstevel@tonic-gate #include <sys/copyops.h>
453434Sesaxe #include <sys/pg.h>
460Sstevel@tonic-gate #include <sys/disp.h>
470Sstevel@tonic-gate #include <sys/debug.h>
480Sstevel@tonic-gate #include <sys/sunddi.h>
490Sstevel@tonic-gate #include <sys/x86_archext.h>
500Sstevel@tonic-gate #include <sys/privregs.h>
510Sstevel@tonic-gate #include <sys/machsystm.h>
520Sstevel@tonic-gate #include <sys/ontrap.h>
530Sstevel@tonic-gate #include <sys/bootconf.h>
543446Smrj #include <sys/kdi_machimpl.h>
550Sstevel@tonic-gate #include <sys/archsystm.h>
560Sstevel@tonic-gate #include <sys/promif.h>
570Sstevel@tonic-gate #include <sys/bootconf.h>
580Sstevel@tonic-gate #include <sys/kobj.h>
590Sstevel@tonic-gate #include <sys/kobj_lex.h>
60748Sdmick #include <sys/pci_cfgspace.h>
610Sstevel@tonic-gate 
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate  * some globals for patching the result of cpuid
640Sstevel@tonic-gate  * to solve problems w/ creative cpu vendors
650Sstevel@tonic-gate  */
660Sstevel@tonic-gate 
670Sstevel@tonic-gate extern uint32_t cpuid_feature_ecx_include;
680Sstevel@tonic-gate extern uint32_t cpuid_feature_ecx_exclude;
690Sstevel@tonic-gate extern uint32_t cpuid_feature_edx_include;
700Sstevel@tonic-gate extern uint32_t cpuid_feature_edx_exclude;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
73783Sdmick  * Dummy spl priority masks
74783Sdmick  */
753446Smrj static unsigned char dummy_cpu_pri[MAXIPL + 1] = {
76783Sdmick 	0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf,
77783Sdmick 	0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf
78783Sdmick };
79783Sdmick 
800Sstevel@tonic-gate 
810Sstevel@tonic-gate static uint32_t
822006Sandrei bootprop_getval(char *name)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate 	char prop[32];
850Sstevel@tonic-gate 	u_longlong_t ll;
860Sstevel@tonic-gate 	extern struct bootops *bootops;
870Sstevel@tonic-gate 	if ((BOP_GETPROPLEN(bootops, name) > sizeof (prop)) ||
880Sstevel@tonic-gate 	    (BOP_GETPROP(bootops, name, prop) < 0) ||
890Sstevel@tonic-gate 	    (kobj_getvalue(prop, &ll) == -1))
900Sstevel@tonic-gate 		return (0);
910Sstevel@tonic-gate 	return ((uint32_t)ll);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate  * Setup routine called right before main(). Interposing this function
960Sstevel@tonic-gate  * before main() allows us to call it in a machine-independent fashion.
970Sstevel@tonic-gate  */
980Sstevel@tonic-gate void
990Sstevel@tonic-gate mlsetup(struct regs *rp)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate 	extern struct classfuncs sys_classfuncs;
1020Sstevel@tonic-gate 	extern disp_t cpu0_disp;
1030Sstevel@tonic-gate 	extern char t0stack[];
1042006Sandrei 	int boot_ncpus;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	ASSERT_STACK_ALIGNED();
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	/*
1090Sstevel@tonic-gate 	 * initialize cpu_self
1100Sstevel@tonic-gate 	 */
1110Sstevel@tonic-gate 	cpu[0]->cpu_self = cpu[0];
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	/*
114783Sdmick 	 * Set up dummy cpu_pri_data values till psm spl code is
115783Sdmick 	 * installed.  This allows splx() to work on amd64.
116783Sdmick 	 */
117783Sdmick 
118783Sdmick 	cpu[0]->cpu_pri_data = dummy_cpu_pri;
119783Sdmick 
120783Sdmick 	/*
1210Sstevel@tonic-gate 	 * check if we've got special bits to clear or set
1220Sstevel@tonic-gate 	 * when checking cpu features
1230Sstevel@tonic-gate 	 */
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	cpuid_feature_ecx_include =
1262006Sandrei 	    bootprop_getval("cpuid_feature_ecx_include");
1270Sstevel@tonic-gate 	cpuid_feature_ecx_exclude =
1282006Sandrei 	    bootprop_getval("cpuid_feature_ecx_exclude");
1290Sstevel@tonic-gate 	cpuid_feature_edx_include =
1302006Sandrei 	    bootprop_getval("cpuid_feature_edx_include");
1310Sstevel@tonic-gate 	cpuid_feature_edx_exclude =
1322006Sandrei 	    bootprop_getval("cpuid_feature_edx_exclude");
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	/*
1350Sstevel@tonic-gate 	 * The first lightweight pass (pass0) through the cpuid data
1360Sstevel@tonic-gate 	 * was done in locore before mlsetup was called.  Do the next
1370Sstevel@tonic-gate 	 * pass in C code.
1380Sstevel@tonic-gate 	 *
1390Sstevel@tonic-gate 	 * The x86_feature bits are set here on the basis of the capabilities
1400Sstevel@tonic-gate 	 * of the boot CPU.  Note that if we choose to support CPUs that have
1410Sstevel@tonic-gate 	 * different feature sets (at which point we would almost certainly
1420Sstevel@tonic-gate 	 * want to set the feature bits to correspond to the feature
1430Sstevel@tonic-gate 	 * minimum) this value may be altered.
1440Sstevel@tonic-gate 	 */
1450Sstevel@tonic-gate 	x86_feature = cpuid_pass1(cpu[0]);
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	/*
1480Sstevel@tonic-gate 	 * Initialize idt0, gdt0, ldt0_default, ktss0 and dftss.
1490Sstevel@tonic-gate 	 */
1503446Smrj 	init_desctbls();
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 
1533446Smrj #if defined(__i386)
1540Sstevel@tonic-gate 	/*
1550Sstevel@tonic-gate 	 * Some i386 processors do not implement the rdtsc instruction,
1560Sstevel@tonic-gate 	 * or at least they do not implement it correctly.
1570Sstevel@tonic-gate 	 *
1580Sstevel@tonic-gate 	 * For those that do, patch in the rdtsc instructions in
1590Sstevel@tonic-gate 	 * various parts of the kernel right now while the text is
1600Sstevel@tonic-gate 	 * still writable.
1610Sstevel@tonic-gate 	 */
1620Sstevel@tonic-gate 	if (x86_feature & X86_TSC)
1630Sstevel@tonic-gate 		patch_tsc();
1643446Smrj #endif	/* __i386 */
1653446Smrj 
1663446Smrj 	/*
1673446Smrj 	 * While we're thinking about the TSC, let's set up %cr4 so that
1683446Smrj 	 * userland can issue rdtsc, and initialize the TSC_AUX value
1693446Smrj 	 * (the cpuid) for the rdtscp instruction on appropriately
1703446Smrj 	 * capable hardware.
1713446Smrj 	 */
1723446Smrj 	if (x86_feature & X86_TSC)
1733446Smrj 		setcr4(getcr4() & ~CR4_TSD);
1743446Smrj 
1753446Smrj 	if (x86_feature & X86_TSCP)
1763446Smrj 		(void) wrmsr(MSR_AMD_TSCAUX, 0);
1773446Smrj 
1783446Smrj 	if (x86_feature & X86_DE)
1793446Smrj 		setcr4(getcr4() | CR4_DE);
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	/*
1820Sstevel@tonic-gate 	 * initialize t0
1830Sstevel@tonic-gate 	 */
1840Sstevel@tonic-gate 	t0.t_stk = (caddr_t)rp - MINFRAME;
1850Sstevel@tonic-gate 	t0.t_stkbase = t0stack;
1860Sstevel@tonic-gate 	t0.t_pri = maxclsyspri - 3;
1870Sstevel@tonic-gate 	t0.t_schedflag = TS_LOAD | TS_DONT_SWAP;
1880Sstevel@tonic-gate 	t0.t_procp = &p0;
1890Sstevel@tonic-gate 	t0.t_plockp = &p0lock.pl_lock;
1900Sstevel@tonic-gate 	t0.t_lwp = &lwp0;
1910Sstevel@tonic-gate 	t0.t_forw = &t0;
1920Sstevel@tonic-gate 	t0.t_back = &t0;
1930Sstevel@tonic-gate 	t0.t_next = &t0;
1940Sstevel@tonic-gate 	t0.t_prev = &t0;
1950Sstevel@tonic-gate 	t0.t_cpu = cpu[0];
1960Sstevel@tonic-gate 	t0.t_disp_queue = &cpu0_disp;
1970Sstevel@tonic-gate 	t0.t_bind_cpu = PBIND_NONE;
1980Sstevel@tonic-gate 	t0.t_bind_pset = PS_NONE;
1990Sstevel@tonic-gate 	t0.t_cpupart = &cp_default;
2000Sstevel@tonic-gate 	t0.t_clfuncs = &sys_classfuncs.thread;
2010Sstevel@tonic-gate 	t0.t_copyops = NULL;
2020Sstevel@tonic-gate 	THREAD_ONPROC(&t0, CPU);
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	lwp0.lwp_thread = &t0;
2053446Smrj 	lwp0.lwp_regs = (void *)rp;
2060Sstevel@tonic-gate 	lwp0.lwp_procp = &p0;
2070Sstevel@tonic-gate 	t0.t_tid = p0.p_lwpcnt = p0.p_lwprcnt = p0.p_lwpid = 1;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	p0.p_exec = NULL;
2100Sstevel@tonic-gate 	p0.p_stat = SRUN;
2110Sstevel@tonic-gate 	p0.p_flag = SSYS;
2120Sstevel@tonic-gate 	p0.p_tlist = &t0;
2130Sstevel@tonic-gate 	p0.p_stksize = 2*PAGESIZE;
2140Sstevel@tonic-gate 	p0.p_stkpageszc = 0;
2150Sstevel@tonic-gate 	p0.p_as = &kas;
2160Sstevel@tonic-gate 	p0.p_lockp = &p0lock;
2170Sstevel@tonic-gate 	p0.p_brkpageszc = 0;
2184426Saguzovsk 	p0.p_t1_lgrpid = LGRP_NONE;
2194426Saguzovsk 	p0.p_tr_lgrpid = LGRP_NONE;
2200Sstevel@tonic-gate 	sigorset(&p0.p_ignore, &ignoredefault);
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	CPU->cpu_thread = &t0;
2230Sstevel@tonic-gate 	bzero(&cpu0_disp, sizeof (disp_t));
2240Sstevel@tonic-gate 	CPU->cpu_disp = &cpu0_disp;
2250Sstevel@tonic-gate 	CPU->cpu_disp->disp_cpu = CPU;
2260Sstevel@tonic-gate 	CPU->cpu_dispthread = &t0;
2270Sstevel@tonic-gate 	CPU->cpu_idle_thread = &t0;
2280Sstevel@tonic-gate 	CPU->cpu_flags = CPU_READY | CPU_RUNNING | CPU_EXISTS | CPU_ENABLE;
2290Sstevel@tonic-gate 	CPU->cpu_dispatch_pri = t0.t_pri;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	CPU->cpu_id = 0;
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	CPU->cpu_pri = 12;		/* initial PIL for the boot CPU */
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	/*
2361217Srab 	 * The kernel doesn't use LDTs unless a process explicitly requests one.
2370Sstevel@tonic-gate 	 */
2381217Srab 	p0.p_ldt_desc = zero_sdesc;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	/*
2413446Smrj 	 * Initialize thread/cpu microstate accounting
2420Sstevel@tonic-gate 	 */
2430Sstevel@tonic-gate 	init_mstate(&t0, LMS_SYSTEM);
2440Sstevel@tonic-gate 	init_cpu_mstate(CPU, CMS_SYSTEM);
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	/*
2470Sstevel@tonic-gate 	 * Initialize lists of available and active CPUs.
2480Sstevel@tonic-gate 	 */
2490Sstevel@tonic-gate 	cpu_list_init(CPU);
2500Sstevel@tonic-gate 
2513446Smrj 	/*
2523446Smrj 	 * Now that we have taken over the GDT, IDT and have initialized
2533446Smrj 	 * active CPU list it's time to inform kmdb if present.
2543446Smrj 	 */
2553446Smrj 	if (boothowto & RB_DEBUG)
2563446Smrj 		kdi_idt_sync();
2573446Smrj 
2583446Smrj 	/*
2593446Smrj 	 * If requested (boot -d) drop into kmdb.
2603446Smrj 	 *
2613446Smrj 	 * This must be done after cpu_list_init() on the 64-bit kernel
2623446Smrj 	 * since taking a trap requires that we re-compute gsbase based
2633446Smrj 	 * on the cpu list.
2643446Smrj 	 */
2653446Smrj 	if (boothowto & RB_DEBUGENTER)
2663446Smrj 		kmdb_enter();
2673446Smrj 
268414Skchow 	cpu_vm_data_init(CPU);
269414Skchow 
270748Sdmick 	/* lgrp_init() needs PCI config space access */
271748Sdmick 	pci_cfgspace_init();
272748Sdmick 
2730Sstevel@tonic-gate 	/*
2740Sstevel@tonic-gate 	 * Initialize the lgrp framework
2750Sstevel@tonic-gate 	 */
2760Sstevel@tonic-gate 	lgrp_init();
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	rp->r_fp = 0;	/* terminate kernel stack traces! */
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	prom_init("kernel", (void *)NULL);
2810Sstevel@tonic-gate 
2822006Sandrei 	boot_ncpus = bootprop_getval("boot-ncpus");
2832006Sandrei 
2842006Sandrei 	if (boot_ncpus <= 0 || boot_ncpus > NCPU)
2853446Smrj 		boot_ncpus = NCPU;
2862006Sandrei 
2872006Sandrei 	max_ncpus = boot_max_ncpus = boot_ncpus;
2882006Sandrei 
2890Sstevel@tonic-gate 	if (boothowto & RB_HALT) {
2900Sstevel@tonic-gate 		prom_printf("unix: kernel halted by -h flag\n");
2910Sstevel@tonic-gate 		prom_enter_mon();
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	ASSERT_STACK_ALIGNED();
2950Sstevel@tonic-gate 
296*4581Ssherrym 	/*
297*4581Ssherrym 	 * Fill out cpu_ucode_info.  Update microcode if necessary.
298*4581Ssherrym 	 */
299*4581Ssherrym 	ucode_check(CPU);
300*4581Ssherrym 
3010Sstevel@tonic-gate 	if (workaround_errata(CPU) != 0)
3020Sstevel@tonic-gate 		panic("critical workaround(s) missing for boot cpu");
3030Sstevel@tonic-gate }
304