author | kucharsk |
Thu, 27 Oct 2005 14:59:45 -0700 | |
changeset 770 | 0eda482eb80f |
parent 748 | 3a1ae73086e8 |
child 783 | 8a222da2fa5b |
permissions | -rw-r--r-- |
0 | 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, Version 1.0 only |
|
6 |
* (the "License"). You may not use this file except in compliance |
|
7 |
* with the License. |
|
8 |
* |
|
9 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
10 |
* or http://www.opensolaris.org/os/licensing. |
|
11 |
* See the License for the specific language governing permissions |
|
12 |
* and limitations under the License. |
|
13 |
* |
|
14 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
15 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
16 |
* If applicable, add the following below this CDDL HEADER, with the |
|
17 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
18 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
19 |
* |
|
20 |
* CDDL HEADER END |
|
21 |
*/ |
|
22 |
/* |
|
23 |
* Copyright 2005 Sun Microsystems, Inc. All rights reserved. |
|
24 |
* Use is subject to license terms. |
|
25 |
*/ |
|
26 |
||
27 |
#pragma ident "%Z%%M% %I% %E% SMI" |
|
28 |
||
29 |
#include <sys/types.h> |
|
30 |
#include <sys/disp.h> |
|
31 |
#include <sys/promif.h> |
|
32 |
#include <sys/clock.h> |
|
33 |
#include <sys/cpuvar.h> |
|
34 |
#include <sys/stack.h> |
|
35 |
#include <vm/as.h> |
|
36 |
#include <vm/hat.h> |
|
37 |
#include <sys/reboot.h> |
|
38 |
#include <sys/avintr.h> |
|
39 |
#include <sys/vtrace.h> |
|
40 |
#include <sys/proc.h> |
|
41 |
#include <sys/thread.h> |
|
42 |
#include <sys/cpupart.h> |
|
43 |
#include <sys/pset.h> |
|
44 |
#include <sys/copyops.h> |
|
45 |
#include <sys/chip.h> |
|
46 |
#include <sys/disp.h> |
|
47 |
#include <sys/debug.h> |
|
48 |
#include <sys/sunddi.h> |
|
49 |
#include <sys/x86_archext.h> |
|
50 |
#include <sys/privregs.h> |
|
51 |
#include <sys/machsystm.h> |
|
52 |
#include <sys/ontrap.h> |
|
53 |
#include <sys/bootconf.h> |
|
54 |
#include <sys/kdi.h> |
|
55 |
#include <sys/archsystm.h> |
|
56 |
#include <sys/promif.h> |
|
57 |
#include <sys/bootconf.h> |
|
58 |
#include <sys/kobj.h> |
|
59 |
#include <sys/kobj_lex.h> |
|
748
3a1ae73086e8
6338634 pci config-space routines really need to be present early in base kernel
dmick
parents:
414
diff
changeset
|
60 |
#include <sys/pci_cfgspace.h> |
0 | 61 |
#if defined(__amd64) |
62 |
#include <sys/bootsvcs.h> |
|
63 |
||
64 |
/* |
|
65 |
* XX64 This stuff deals with switching stacks in case a trapping |
|
66 |
* thread wants to call back into boot -after- boot has lost track |
|
67 |
* of the mappings but before the kernel owns the console. |
|
68 |
* |
|
69 |
* (A better way to hide this would be to add a 'this' pointer to |
|
70 |
* every boot syscall so that vmx could get at the resulting save |
|
71 |
* area.) |
|
72 |
*/ |
|
73 |
||
74 |
struct boot_syscalls *_vmx_sysp; |
|
75 |
static struct boot_syscalls __kbootsvcs; |
|
76 |
extern struct boot_syscalls *sysp; |
|
77 |
extern void _stack_safe_putchar(int c); |
|
78 |
#endif |
|
79 |
||
80 |
/* |
|
81 |
* some globals for patching the result of cpuid |
|
82 |
* to solve problems w/ creative cpu vendors |
|
83 |
*/ |
|
84 |
||
85 |
extern uint32_t cpuid_feature_ecx_include; |
|
86 |
extern uint32_t cpuid_feature_ecx_exclude; |
|
87 |
extern uint32_t cpuid_feature_edx_include; |
|
88 |
extern uint32_t cpuid_feature_edx_exclude; |
|
89 |
||
90 |
/* |
|
91 |
* External Routines: |
|
92 |
*/ |
|
93 |
||
94 |
extern void init_tables(void); |
|
95 |
||
96 |
||
97 |
static uint32_t |
|
98 |
cpuid_getval(char *name) |
|
99 |
{ |
|
100 |
char prop[32]; |
|
101 |
u_longlong_t ll; |
|
102 |
extern struct bootops *bootops; |
|
103 |
if ((BOP_GETPROPLEN(bootops, name) > sizeof (prop)) || |
|
104 |
(BOP_GETPROP(bootops, name, prop) < 0) || |
|
105 |
(kobj_getvalue(prop, &ll) == -1)) |
|
106 |
return (0); |
|
107 |
return ((uint32_t)ll); |
|
108 |
} |
|
109 |
||
110 |
/* |
|
111 |
* Setup routine called right before main(). Interposing this function |
|
112 |
* before main() allows us to call it in a machine-independent fashion. |
|
113 |
*/ |
|
114 |
void |
|
115 |
mlsetup(struct regs *rp) |
|
116 |
{ |
|
117 |
extern struct classfuncs sys_classfuncs; |
|
118 |
extern struct chip cpu0_chip; |
|
119 |
extern disp_t cpu0_disp; |
|
120 |
extern char t0stack[]; |
|
121 |
||
122 |
ASSERT_STACK_ALIGNED(); |
|
123 |
||
124 |
#if defined(__amd64) |
|
125 |
||
126 |
#if (BS_VERSION > 4) |
|
127 |
/* |
|
128 |
* When new boot_syscalls are added to the vector, this routine |
|
129 |
* must be modified to copy them into the kernel's copy of the |
|
130 |
* vector. |
|
131 |
*/ |
|
132 |
#error mlsetup() must be updated for amd64 to support new boot_syscalls |
|
133 |
#endif /* (BS_VERSION > 4) */ |
|
134 |
||
135 |
/* |
|
136 |
* XX64 This remaps vmx's putchar to use the kernel's version |
|
137 |
* that switches stacks before diving into vmx |
|
138 |
* See explanation/complaints in commentary above. |
|
139 |
*/ |
|
140 |
_vmx_sysp = sysp; |
|
141 |
sysp = &__kbootsvcs; |
|
142 |
||
143 |
sysp->bsvc_getchar = _vmx_sysp->bsvc_getchar; |
|
144 |
sysp->bsvc_putchar = _stack_safe_putchar; |
|
145 |
sysp->bsvc_ischar = _vmx_sysp->bsvc_ischar; |
|
146 |
#endif |
|
147 |
/* |
|
148 |
* initialize cpu_self |
|
149 |
*/ |
|
150 |
cpu[0]->cpu_self = cpu[0]; |
|
151 |
||
152 |
/* |
|
153 |
* check if we've got special bits to clear or set |
|
154 |
* when checking cpu features |
|
155 |
*/ |
|
156 |
||
157 |
cpuid_feature_ecx_include = |
|
158 |
cpuid_getval("cpuid_feature_ecx_include"); |
|
159 |
cpuid_feature_ecx_exclude = |
|
160 |
cpuid_getval("cpuid_feature_ecx_exclude"); |
|
161 |
cpuid_feature_edx_include = |
|
162 |
cpuid_getval("cpuid_feature_edx_include"); |
|
163 |
cpuid_feature_edx_exclude = |
|
164 |
cpuid_getval("cpuid_feature_edx_exclude"); |
|
165 |
||
166 |
/* |
|
167 |
* The first lightweight pass (pass0) through the cpuid data |
|
168 |
* was done in locore before mlsetup was called. Do the next |
|
169 |
* pass in C code. |
|
170 |
* |
|
171 |
* The x86_feature bits are set here on the basis of the capabilities |
|
172 |
* of the boot CPU. Note that if we choose to support CPUs that have |
|
173 |
* different feature sets (at which point we would almost certainly |
|
174 |
* want to set the feature bits to correspond to the feature |
|
175 |
* minimum) this value may be altered. |
|
176 |
*/ |
|
177 |
||
178 |
x86_feature = cpuid_pass1(cpu[0]); |
|
179 |
||
180 |
/* |
|
181 |
* Initialize idt0, gdt0, ldt0_default, ktss0 and dftss. |
|
182 |
*/ |
|
183 |
init_tables(); |
|
184 |
||
185 |
#if defined(__amd64) |
|
186 |
/*CSTYLED*/ |
|
187 |
{ |
|
188 |
/* |
|
189 |
* setup %gs for the kernel |
|
190 |
*/ |
|
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
748
diff
changeset
|
191 |
wrmsr(MSR_AMD_GSBASE, (uint64_t)&cpus[0]); |
0 | 192 |
/* |
193 |
* XX64 We should never dereference off "other gsbase" or |
|
194 |
* "fsbase". So, we should arrange to point FSBASE and |
|
195 |
* KGSBASE somewhere truly awful e.g. point it at the last |
|
196 |
* valid address below the hole so that any attempts to index |
|
197 |
* off them cause an exception. |
|
198 |
* |
|
199 |
* For now, point it at 8G -- at least it should be unmapped |
|
200 |
* until some 64-bit processes run. |
|
201 |
*/ |
|
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
748
diff
changeset
|
202 |
wrmsr(MSR_AMD_FSBASE, 0x200000000UL); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
748
diff
changeset
|
203 |
wrmsr(MSR_AMD_KGSBASE, 0x200000000UL); |
0 | 204 |
} |
205 |
||
206 |
#elif defined(__i386) |
|
207 |
/* |
|
208 |
* enable large page support right here. |
|
209 |
*/ |
|
210 |
if (x86_feature & X86_LARGEPAGE) { |
|
211 |
cr4_value |= CR4_PSE; |
|
212 |
if (x86_feature & X86_PGE) |
|
213 |
cr4_value |= CR4_PGE; |
|
214 |
setup_121_andcall(enable_big_page_support, cr4_value); |
|
215 |
} |
|
216 |
||
217 |
/* |
|
218 |
* Some i386 processors do not implement the rdtsc instruction, |
|
219 |
* or at least they do not implement it correctly. |
|
220 |
* |
|
221 |
* For those that do, patch in the rdtsc instructions in |
|
222 |
* various parts of the kernel right now while the text is |
|
223 |
* still writable. |
|
224 |
*/ |
|
225 |
if (x86_feature & X86_TSC) |
|
226 |
patch_tsc(); |
|
227 |
#endif |
|
228 |
||
229 |
/* |
|
230 |
* initialize t0 |
|
231 |
*/ |
|
232 |
t0.t_stk = (caddr_t)rp - MINFRAME; |
|
233 |
t0.t_stkbase = t0stack; |
|
234 |
t0.t_pri = maxclsyspri - 3; |
|
235 |
t0.t_schedflag = TS_LOAD | TS_DONT_SWAP; |
|
236 |
t0.t_procp = &p0; |
|
237 |
t0.t_plockp = &p0lock.pl_lock; |
|
238 |
t0.t_lwp = &lwp0; |
|
239 |
t0.t_forw = &t0; |
|
240 |
t0.t_back = &t0; |
|
241 |
t0.t_next = &t0; |
|
242 |
t0.t_prev = &t0; |
|
243 |
t0.t_cpu = cpu[0]; |
|
244 |
t0.t_disp_queue = &cpu0_disp; |
|
245 |
t0.t_bind_cpu = PBIND_NONE; |
|
246 |
t0.t_bind_pset = PS_NONE; |
|
247 |
t0.t_cpupart = &cp_default; |
|
248 |
t0.t_clfuncs = &sys_classfuncs.thread; |
|
249 |
t0.t_copyops = NULL; |
|
250 |
THREAD_ONPROC(&t0, CPU); |
|
251 |
||
252 |
lwp0.lwp_thread = &t0; |
|
253 |
lwp0.lwp_regs = (void *) rp; |
|
254 |
lwp0.lwp_procp = &p0; |
|
255 |
t0.t_tid = p0.p_lwpcnt = p0.p_lwprcnt = p0.p_lwpid = 1; |
|
256 |
||
257 |
p0.p_exec = NULL; |
|
258 |
p0.p_stat = SRUN; |
|
259 |
p0.p_flag = SSYS; |
|
260 |
p0.p_tlist = &t0; |
|
261 |
p0.p_stksize = 2*PAGESIZE; |
|
262 |
p0.p_stkpageszc = 0; |
|
263 |
p0.p_as = &kas; |
|
264 |
p0.p_lockp = &p0lock; |
|
265 |
p0.p_brkpageszc = 0; |
|
266 |
sigorset(&p0.p_ignore, &ignoredefault); |
|
267 |
||
268 |
CPU->cpu_thread = &t0; |
|
269 |
bzero(&cpu0_disp, sizeof (disp_t)); |
|
270 |
CPU->cpu_disp = &cpu0_disp; |
|
271 |
CPU->cpu_disp->disp_cpu = CPU; |
|
272 |
CPU->cpu_dispthread = &t0; |
|
273 |
CPU->cpu_idle_thread = &t0; |
|
274 |
CPU->cpu_flags = CPU_READY | CPU_RUNNING | CPU_EXISTS | CPU_ENABLE; |
|
275 |
CPU->cpu_dispatch_pri = t0.t_pri; |
|
276 |
||
277 |
CPU->cpu_mask = 1; |
|
278 |
CPU->cpu_id = 0; |
|
279 |
||
280 |
CPU->cpu_tss = &ktss0; |
|
281 |
||
282 |
CPU->cpu_pri = 12; /* initial PIL for the boot CPU */ |
|
283 |
||
284 |
CPU->cpu_ldt = ldt0_default; /* default LDT */ |
|
285 |
CPU->cpu_gdt = gdt0; |
|
286 |
||
287 |
/* |
|
288 |
* This must be done _after_ init_tables(), called above, has set up |
|
289 |
* ldt0_default_desc. |
|
290 |
*/ |
|
291 |
#if defined(__amd64) |
|
292 |
/* |
|
293 |
* ldt0_default64 contains all invalid entries. We use that as p0's LDT |
|
294 |
* because p0 should never have any reason to use the LDT. This will |
|
295 |
* catch things early if such a scenario should ever occur. |
|
296 |
*/ |
|
297 |
p0.p_ldt_desc = ldt0_default64_desc; |
|
298 |
#else |
|
299 |
p0.p_ldt_desc = ldt0_default_desc; |
|
300 |
#endif /* __amd64 */ |
|
301 |
||
302 |
/* |
|
303 |
* Kernel IDT. |
|
304 |
*/ |
|
305 |
CPU->cpu_idt = idt0; |
|
306 |
||
307 |
/* |
|
308 |
* Initialize thread/cpu microstate accounting here |
|
309 |
*/ |
|
310 |
init_mstate(&t0, LMS_SYSTEM); |
|
311 |
init_cpu_mstate(CPU, CMS_SYSTEM); |
|
312 |
||
313 |
/* |
|
314 |
* Initialize lists of available and active CPUs. |
|
315 |
*/ |
|
316 |
cpu_list_init(CPU); |
|
317 |
||
414 | 318 |
cpu_vm_data_init(CPU); |
319 |
||
748
3a1ae73086e8
6338634 pci config-space routines really need to be present early in base kernel
dmick
parents:
414
diff
changeset
|
320 |
/* lgrp_init() needs PCI config space access */ |
3a1ae73086e8
6338634 pci config-space routines really need to be present early in base kernel
dmick
parents:
414
diff
changeset
|
321 |
pci_cfgspace_init(); |
3a1ae73086e8
6338634 pci config-space routines really need to be present early in base kernel
dmick
parents:
414
diff
changeset
|
322 |
|
0 | 323 |
/* |
324 |
* Initialize the lgrp framework |
|
325 |
*/ |
|
326 |
lgrp_init(); |
|
327 |
||
328 |
/* |
|
329 |
* The lgroup code needs to at least know about a CPU's |
|
330 |
* chip association, but it's too early to fully initialize |
|
331 |
* cpu0_chip, since the device node for the boot CPU doesn't |
|
332 |
* exist yet. Initialize enough of it to get by until formal |
|
333 |
* initialization. |
|
334 |
*/ |
|
335 |
CPU->cpu_rechoose = rechoose_interval; |
|
336 |
CPU->cpu_chip = &cpu0_chip; |
|
337 |
||
338 |
rp->r_fp = 0; /* terminate kernel stack traces! */ |
|
339 |
||
340 |
prom_init("kernel", (void *)NULL); |
|
341 |
||
342 |
if (boothowto & RB_HALT) { |
|
343 |
prom_printf("unix: kernel halted by -h flag\n"); |
|
344 |
prom_enter_mon(); |
|
345 |
} |
|
346 |
||
347 |
ASSERT_STACK_ALIGNED(); |
|
348 |
||
349 |
if (workaround_errata(CPU) != 0) |
|
350 |
panic("critical workaround(s) missing for boot cpu"); |
|
351 |
} |