author | marx |
Tue, 25 Sep 2007 13:11:35 -0700 | |
changeset 5129 | 5dc46a0fd425 |
parent 5107 | bb9efa2ee1e8 |
child 5159 | 6cdd421a2458 |
permissions | -rw-r--r-- |
0 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
1455
b43f098fa50c
6378953 allocation of interrupt threads could be more common
andrei
parents:
1417
diff
changeset
|
5 |
* Common Development and Distribution License (the "License"). |
b43f098fa50c
6378953 allocation of interrupt threads could be more common
andrei
parents:
1417
diff
changeset
|
6 |
* You may not use this file except in compliance with the License. |
0 | 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 |
/* |
|
3434 | 22 |
* Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
0 | 23 |
* Use is subject to license terms. |
24 |
*/ |
|
25 |
||
26 |
#pragma ident "%Z%%M% %I% %E% SMI" |
|
27 |
||
28 |
#include <sys/types.h> |
|
29 |
#include <sys/t_lock.h> |
|
30 |
#include <sys/param.h> |
|
31 |
#include <sys/sysmacros.h> |
|
32 |
#include <sys/signal.h> |
|
33 |
#include <sys/systm.h> |
|
34 |
#include <sys/user.h> |
|
35 |
#include <sys/mman.h> |
|
36 |
#include <sys/vm.h> |
|
37 |
#include <sys/conf.h> |
|
38 |
#include <sys/avintr.h> |
|
39 |
#include <sys/autoconf.h> |
|
40 |
#include <sys/disp.h> |
|
41 |
#include <sys/class.h> |
|
42 |
#include <sys/bitmap.h> |
|
43 |
||
44 |
#include <sys/privregs.h> |
|
45 |
||
46 |
#include <sys/proc.h> |
|
47 |
#include <sys/buf.h> |
|
48 |
#include <sys/kmem.h> |
|
3446 | 49 |
#include <sys/mem.h> |
0 | 50 |
#include <sys/kstat.h> |
51 |
||
52 |
#include <sys/reboot.h> |
|
53 |
||
54 |
#include <sys/cred.h> |
|
55 |
#include <sys/vnode.h> |
|
56 |
#include <sys/file.h> |
|
57 |
||
58 |
#include <sys/procfs.h> |
|
59 |
||
60 |
#include <sys/vfs.h> |
|
61 |
#include <sys/cmn_err.h> |
|
62 |
#include <sys/utsname.h> |
|
63 |
#include <sys/debug.h> |
|
64 |
#include <sys/kdi.h> |
|
65 |
||
66 |
#include <sys/dumphdr.h> |
|
67 |
#include <sys/bootconf.h> |
|
68 |
#include <sys/varargs.h> |
|
69 |
#include <sys/promif.h> |
|
5084 | 70 |
#include <sys/modctl.h> |
0 | 71 |
|
72 |
#include <sys/sunddi.h> |
|
73 |
#include <sys/sunndi.h> |
|
74 |
#include <sys/ndi_impldefs.h> |
|
75 |
#include <sys/ddidmareq.h> |
|
76 |
#include <sys/psw.h> |
|
77 |
#include <sys/regset.h> |
|
78 |
#include <sys/clock.h> |
|
79 |
#include <sys/pte.h> |
|
80 |
#include <sys/tss.h> |
|
81 |
#include <sys/stack.h> |
|
82 |
#include <sys/trap.h> |
|
83 |
#include <sys/fp.h> |
|
84 |
#include <vm/anon.h> |
|
85 |
#include <vm/as.h> |
|
86 |
#include <vm/page.h> |
|
87 |
#include <vm/seg.h> |
|
88 |
#include <vm/seg_dev.h> |
|
89 |
#include <vm/seg_kmem.h> |
|
90 |
#include <vm/seg_kpm.h> |
|
91 |
#include <vm/seg_map.h> |
|
92 |
#include <vm/seg_vn.h> |
|
93 |
#include <vm/seg_kp.h> |
|
94 |
#include <sys/memnode.h> |
|
95 |
#include <vm/vm_dep.h> |
|
96 |
#include <sys/thread.h> |
|
97 |
#include <sys/sysconf.h> |
|
98 |
#include <sys/vm_machparam.h> |
|
99 |
#include <sys/archsystm.h> |
|
100 |
#include <sys/machsystm.h> |
|
101 |
#include <vm/hat.h> |
|
102 |
#include <vm/hat_i86.h> |
|
103 |
#include <sys/pmem.h> |
|
104 |
#include <sys/smp_impldefs.h> |
|
105 |
#include <sys/x86_archext.h> |
|
106 |
#include <sys/segments.h> |
|
107 |
#include <sys/clconf.h> |
|
108 |
#include <sys/kobj.h> |
|
109 |
#include <sys/kobj_lex.h> |
|
110 |
#include <sys/cpc_impl.h> |
|
111 |
#include <sys/x86_archext.h> |
|
1414
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
112 |
#include <sys/cpu_module.h> |
437 | 113 |
#include <sys/smbios.h> |
3446 | 114 |
#include <sys/debug_info.h> |
5107 | 115 |
#include <sys/ddi_timer.h> |
3446 | 116 |
|
5084 | 117 |
#ifdef __xpv |
118 |
#include <sys/hypervisor.h> |
|
119 |
#include <sys/xen_mmu.h> |
|
120 |
#include <sys/evtchn_impl.h> |
|
121 |
#include <sys/gnttab.h> |
|
122 |
#include <sys/xpv_panic.h> |
|
123 |
#include <xen/sys/xenbus_comms.h> |
|
124 |
#include <xen/public/physdev.h> |
|
125 |
extern void xen_late_startup(void); |
|
126 |
extern struct xen_evt_data cpu0_evt_data; |
|
127 |
#endif |
|
3446 | 128 |
|
129 |
#include <sys/bootinfo.h> |
|
130 |
#include <vm/kboot_mmu.h> |
|
0 | 131 |
|
132 |
extern void progressbar_init(void); |
|
133 |
extern void progressbar_start(void); |
|
2712
f74a135872bc
PSARC/2005/471 BrandZ: Support for non-native zones
nn35248
parents:
2621
diff
changeset
|
134 |
extern void brand_init(void); |
0 | 135 |
|
4878 | 136 |
extern int size_pse_array(pgcnt_t, int); |
137 |
||
0 | 138 |
/* |
139 |
* XXX make declaration below "static" when drivers no longer use this |
|
140 |
* interface. |
|
141 |
*/ |
|
142 |
extern caddr_t p0_va; /* Virtual address for accessing physical page 0 */ |
|
143 |
||
144 |
/* |
|
145 |
* segkp |
|
146 |
*/ |
|
147 |
extern int segkp_fromheap; |
|
148 |
||
149 |
static void kvm_init(void); |
|
150 |
static void startup_init(void); |
|
151 |
static void startup_memlist(void); |
|
3446 | 152 |
static void startup_kmem(void); |
0 | 153 |
static void startup_modules(void); |
154 |
static void startup_vm(void); |
|
155 |
static void startup_end(void); |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
156 |
static void layout_kernel_va(void); |
0 | 157 |
|
158 |
/* |
|
159 |
* Declare these as initialized data so we can patch them. |
|
160 |
*/ |
|
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
161 |
#ifdef __i386 |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
162 |
|
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
163 |
/* |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
164 |
* Due to virtual address space limitations running in 32 bit mode, restrict |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
165 |
* the amount of physical memory configured to a max of PHYSMEM pages (16g). |
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
166 |
* |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
167 |
* If the physical max memory size of 64g were allowed to be configured, the |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
168 |
* size of user virtual address space will be less than 1g. A limited user |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
169 |
* address space greatly reduces the range of applications that can run. |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
170 |
* |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
171 |
* If more physical memory than PHYSMEM is required, users should preferably |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
172 |
* run in 64 bit mode which has far looser virtual address space limitations. |
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
173 |
* |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
174 |
* If 64 bit mode is not available (as in IA32) and/or more physical memory |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
175 |
* than PHYSMEM is required in 32 bit mode, physmem can be set to the desired |
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
176 |
* value or to 0 (to configure all available memory) via eeprom(1M). kernelbase |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
177 |
* should also be carefully tuned to balance out the need of the user |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
178 |
* application while minimizing the risk of kernel heap exhaustion due to |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
179 |
* kernelbase being set too high. |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
180 |
*/ |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
181 |
#define PHYSMEM 0x400000 |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
182 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
183 |
#else /* __amd64 */ |
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
184 |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
185 |
/* |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
186 |
* For now we can handle memory with physical addresses up to about |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
187 |
* 64 Terabytes. This keeps the kernel above the VA hole, leaving roughly |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
188 |
* half the VA space for seg_kpm. When systems get bigger than 64TB this |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
189 |
* code will need revisiting. There is an implicit assumption that there |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
190 |
* are no *huge* holes in the physical address space too. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
191 |
*/ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
192 |
#define TERABYTE (1ul << 40) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
193 |
#define PHYSMEM_MAX64 mmu_btop(64 * TERABYTE) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
194 |
#define PHYSMEM PHYSMEM_MAX64 |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
195 |
#define AMD64_VA_HOLE_END 0xFFFF800000000000ul |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
196 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
197 |
#endif /* __amd64 */ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
198 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
199 |
pgcnt_t physmem = PHYSMEM; |
0 | 200 |
pgcnt_t obp_pages; /* Memory used by PROM for its text and data */ |
201 |
||
202 |
char *kobj_file_buf; |
|
203 |
int kobj_file_bufsize; /* set in /etc/system */ |
|
204 |
||
205 |
/* Global variables for MP support. Used in mp_startup */ |
|
206 |
caddr_t rm_platter_va; |
|
207 |
uint32_t rm_platter_pa; |
|
208 |
||
841
814b4a127357
6344639 system spends all its time trying and failing to make big pages
kchow
parents:
810
diff
changeset
|
209 |
int auto_lpg_disable = 1; |
814b4a127357
6344639 system spends all its time trying and failing to make big pages
kchow
parents:
810
diff
changeset
|
210 |
|
0 | 211 |
/* |
212 |
* Some CPUs have holes in the middle of the 64-bit virtual address range. |
|
213 |
*/ |
|
214 |
uintptr_t hole_start, hole_end; |
|
215 |
||
216 |
/* |
|
217 |
* kpm mapping window |
|
218 |
*/ |
|
219 |
caddr_t kpm_vbase; |
|
220 |
size_t kpm_size; |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
221 |
static int kpm_desired; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
222 |
#ifdef __amd64 |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
223 |
static uintptr_t segkpm_base = (uintptr_t)SEGKPM_BASE; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
224 |
#endif |
0 | 225 |
|
226 |
/* |
|
227 |
* Configuration parameters set at boot time. |
|
228 |
*/ |
|
229 |
||
230 |
caddr_t econtig; /* end of first block of contiguous kernel */ |
|
231 |
||
232 |
struct bootops *bootops = 0; /* passed in from boot */ |
|
233 |
struct bootops **bootopsp; |
|
234 |
struct boot_syscalls *sysp; /* passed in from boot */ |
|
235 |
||
236 |
char bootblock_fstype[16]; |
|
237 |
||
238 |
char kern_bootargs[OBP_MAXPATHLEN]; |
|
239 |
||
240 |
/* |
|
3290 | 241 |
* ZFS zio segment. This allows us to exclude large portions of ZFS data that |
242 |
* gets cached in kmem caches on the heap. If this is set to zero, we allocate |
|
243 |
* zio buffers from their own segment, otherwise they are allocated from the |
|
244 |
* heap. The optimization of allocating zio buffers from their own segment is |
|
245 |
* only valid on 64-bit kernels. |
|
246 |
*/ |
|
247 |
#if defined(__amd64) |
|
248 |
int segzio_fromheap = 0; |
|
249 |
#else |
|
250 |
int segzio_fromheap = 1; |
|
251 |
#endif |
|
252 |
||
253 |
/* |
|
0 | 254 |
* new memory fragmentations are possible in startup() due to BOP_ALLOCs. this |
255 |
* depends on number of BOP_ALLOC calls made and requested size, memory size |
|
256 |
* combination and whether boot.bin memory needs to be freed. |
|
257 |
*/ |
|
258 |
#define POSS_NEW_FRAGMENTS 12 |
|
259 |
||
260 |
/* |
|
261 |
* VM data structures |
|
262 |
*/ |
|
263 |
long page_hashsz; /* Size of page hash table (power of two) */ |
|
264 |
struct page *pp_base; /* Base of initial system page struct array */ |
|
265 |
struct page **page_hash; /* Page hash table */ |
|
4878 | 266 |
pad_mutex_t *pse_mutex; /* Locks protecting pp->p_selock */ |
267 |
size_t pse_table_size; /* Number of mutexes in pse_mutex[] */ |
|
268 |
int pse_shift; /* log2(pse_table_size) */ |
|
0 | 269 |
struct seg ktextseg; /* Segment used for kernel executable image */ |
270 |
struct seg kvalloc; /* Segment used for "valloc" mapping */ |
|
271 |
struct seg kpseg; /* Segment used for pageable kernel virt mem */ |
|
272 |
struct seg kmapseg; /* Segment used for generic kernel mappings */ |
|
273 |
struct seg kdebugseg; /* Segment used for the kernel debugger */ |
|
274 |
||
275 |
struct seg *segkmap = &kmapseg; /* Kernel generic mapping segment */ |
|
3446 | 276 |
static struct seg *segmap = &kmapseg; /* easier to use name for in here */ |
277 |
||
0 | 278 |
struct seg *segkp = &kpseg; /* Pageable kernel virtual memory segment */ |
279 |
||
280 |
#if defined(__amd64) |
|
281 |
struct seg kvseg_core; /* Segment used for the core heap */ |
|
282 |
struct seg kpmseg; /* Segment used for physical mapping */ |
|
283 |
struct seg *segkpm = &kpmseg; /* 64bit kernel physical mapping segment */ |
|
284 |
#else |
|
285 |
struct seg *segkpm = NULL; /* Unused on IA32 */ |
|
286 |
#endif |
|
287 |
||
288 |
caddr_t segkp_base; /* Base address of segkp */ |
|
3290 | 289 |
caddr_t segzio_base; /* Base address of segzio */ |
0 | 290 |
#if defined(__amd64) |
291 |
pgcnt_t segkpsize = btop(SEGKPDEFSIZE); /* size of segkp segment in pages */ |
|
292 |
#else |
|
293 |
pgcnt_t segkpsize = 0; |
|
294 |
#endif |
|
3290 | 295 |
pgcnt_t segziosize = 0; /* size of zio segment in pages */ |
0 | 296 |
|
3446 | 297 |
/* |
298 |
* VA range available to the debugger |
|
299 |
*/ |
|
300 |
const caddr_t kdi_segdebugbase = (const caddr_t)SEGDEBUGBASE; |
|
301 |
const size_t kdi_segdebugsize = SEGDEBUGSIZE; |
|
302 |
||
0 | 303 |
struct memseg *memseg_base; |
304 |
struct vnode unused_pages_vp; |
|
305 |
||
306 |
#define FOURGB 0x100000000LL |
|
307 |
||
308 |
struct memlist *memlist; |
|
309 |
||
310 |
caddr_t s_text; /* start of kernel text segment */ |
|
311 |
caddr_t e_text; /* end of kernel text segment */ |
|
312 |
caddr_t s_data; /* start of kernel data segment */ |
|
313 |
caddr_t e_data; /* end of kernel data segment */ |
|
314 |
caddr_t modtext; /* start of loadable module text reserved */ |
|
315 |
caddr_t e_modtext; /* end of loadable module text reserved */ |
|
316 |
caddr_t moddata; /* start of loadable module data reserved */ |
|
317 |
caddr_t e_moddata; /* end of loadable module data reserved */ |
|
318 |
||
319 |
struct memlist *phys_install; /* Total installed physical memory */ |
|
320 |
struct memlist *phys_avail; /* Total available physical memory */ |
|
321 |
||
322 |
/* |
|
323 |
* kphysm_init returns the number of pages that were processed |
|
324 |
*/ |
|
3446 | 325 |
static pgcnt_t kphysm_init(page_t *, pgcnt_t); |
0 | 326 |
|
327 |
#define IO_PROP_SIZE 64 /* device property size */ |
|
328 |
||
329 |
/* |
|
330 |
* a couple useful roundup macros |
|
331 |
*/ |
|
332 |
#define ROUND_UP_PAGE(x) \ |
|
333 |
((uintptr_t)P2ROUNDUP((uintptr_t)(x), (uintptr_t)MMU_PAGESIZE)) |
|
334 |
#define ROUND_UP_LPAGE(x) \ |
|
335 |
((uintptr_t)P2ROUNDUP((uintptr_t)(x), mmu.level_size[1])) |
|
336 |
#define ROUND_UP_4MEG(x) \ |
|
3446 | 337 |
((uintptr_t)P2ROUNDUP((uintptr_t)(x), (uintptr_t)FOUR_MEG)) |
0 | 338 |
#define ROUND_UP_TOPLEVEL(x) \ |
339 |
((uintptr_t)P2ROUNDUP((uintptr_t)(x), mmu.level_size[mmu.max_level])) |
|
340 |
||
341 |
/* |
|
342 |
* 32-bit Kernel's Virtual memory layout. |
|
343 |
* +-----------------------+ |
|
3446 | 344 |
* | | |
0 | 345 |
* 0xFFC00000 -|-----------------------|- ARGSBASE |
346 |
* | debugger | |
|
347 |
* 0xFF800000 -|-----------------------|- SEGDEBUGBASE |
|
348 |
* | Kernel Data | |
|
349 |
* 0xFEC00000 -|-----------------------| |
|
350 |
* | Kernel Text | |
|
5084 | 351 |
* 0xFE800000 -|-----------------------|- KERNEL_TEXT (0xFB400000 on Xen) |
3446 | 352 |
* |--- GDT ---|- GDT page (GDT_VA) |
353 |
* |--- debug info ---|- debug info (DEBUG_INFO_VA) |
|
354 |
* | | |
|
355 |
* | page_t structures | |
|
0 | 356 |
* | memsegs, memlists, | |
357 |
* | page hash, etc. | |
|
3446 | 358 |
* --- -|-----------------------|- ekernelheap, valloc_base (floating) |
359 |
* | | (segkp is just an arena in the heap) |
|
0 | 360 |
* | | |
361 |
* | kvseg | |
|
362 |
* | | |
|
363 |
* | | |
|
364 |
* --- -|-----------------------|- kernelheap (floating) |
|
365 |
* | Segkmap | |
|
3446 | 366 |
* 0xC3002000 -|-----------------------|- segmap_start (floating) |
0 | 367 |
* | Red Zone | |
368 |
* 0xC3000000 -|-----------------------|- kernelbase / userlimit (floating) |
|
369 |
* | | || |
|
370 |
* | Shared objects | \/ |
|
371 |
* | | |
|
372 |
* : : |
|
373 |
* | user data | |
|
374 |
* |-----------------------| |
|
375 |
* | user text | |
|
376 |
* 0x08048000 -|-----------------------| |
|
377 |
* | user stack | |
|
378 |
* : : |
|
379 |
* | invalid | |
|
380 |
* 0x00000000 +-----------------------+ |
|
381 |
* |
|
382 |
* |
|
383 |
* 64-bit Kernel's Virtual memory layout. (assuming 64 bit app) |
|
384 |
* +-----------------------+ |
|
3446 | 385 |
* | | |
0 | 386 |
* 0xFFFFFFFF.FFC00000 |-----------------------|- ARGSBASE |
387 |
* | debugger (?) | |
|
388 |
* 0xFFFFFFFF.FF800000 |-----------------------|- SEGDEBUGBASE |
|
389 |
* | unused | |
|
390 |
* +-----------------------+ |
|
391 |
* | Kernel Data | |
|
392 |
* 0xFFFFFFFF.FBC00000 |-----------------------| |
|
393 |
* | Kernel Text | |
|
394 |
* 0xFFFFFFFF.FB800000 |-----------------------|- KERNEL_TEXT |
|
3446 | 395 |
* |--- GDT ---|- GDT page (GDT_VA) |
396 |
* |--- debug info ---|- debug info (DEBUG_INFO_VA) |
|
397 |
* | | |
|
0 | 398 |
* | Core heap | (used for loadable modules) |
399 |
* 0xFFFFFFFF.C0000000 |-----------------------|- core_base / ekernelheap |
|
400 |
* | Kernel | |
|
401 |
* | heap | |
|
402 |
* 0xFFFFFXXX.XXX00000 |-----------------------|- kernelheap (floating) |
|
3446 | 403 |
* | segmap | |
404 |
* 0xFFFFFXXX.XXX00000 |-----------------------|- segmap_start (floating) |
|
0 | 405 |
* | device mappings | |
406 |
* 0xFFFFFXXX.XXX00000 |-----------------------|- toxic_addr (floating) |
|
3290 | 407 |
* | segzio | |
408 |
* 0xFFFFFXXX.XXX00000 |-----------------------|- segzio_base (floating) |
|
0 | 409 |
* | segkp | |
3446 | 410 |
* --- |-----------------------|- segkp_base (floating) |
411 |
* | page_t structures | valloc_base + valloc_sz |
|
412 |
* | memsegs, memlists, | |
|
413 |
* | page hash, etc. | |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
414 |
* 0xFFFFFF00.00000000 |-----------------------|- valloc_base (lower if > 1TB) |
0 | 415 |
* | segkpm | |
416 |
* 0xFFFFFE00.00000000 |-----------------------| |
|
417 |
* | Red Zone | |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
418 |
* 0xFFFFFD80.00000000 |-----------------------|- KERNELBASE (lower if > 1TB) |
0 | 419 |
* | User stack |- User space memory |
420 |
* | | |
|
421 |
* | shared objects, etc | (grows downwards) |
|
422 |
* : : |
|
423 |
* | | |
|
424 |
* 0xFFFF8000.00000000 |-----------------------| |
|
425 |
* | | |
|
426 |
* | VA Hole / unused | |
|
427 |
* | | |
|
428 |
* 0x00008000.00000000 |-----------------------| |
|
429 |
* | | |
|
430 |
* | | |
|
431 |
* : : |
|
432 |
* | user heap | (grows upwards) |
|
433 |
* | | |
|
434 |
* | user data | |
|
435 |
* |-----------------------| |
|
436 |
* | user text | |
|
437 |
* 0x00000000.04000000 |-----------------------| |
|
438 |
* | invalid | |
|
439 |
* 0x00000000.00000000 +-----------------------+ |
|
440 |
* |
|
441 |
* A 32 bit app on the 64 bit kernel sees the same layout as on the 32 bit |
|
442 |
* kernel, except that userlimit is raised to 0xfe000000 |
|
443 |
* |
|
444 |
* Floating values: |
|
445 |
* |
|
446 |
* valloc_base: start of the kernel's memory management/tracking data |
|
3446 | 447 |
* structures. This region contains page_t structures for |
448 |
* physical memory, memsegs, memlists, and the page hash. |
|
0 | 449 |
* |
450 |
* core_base: start of the kernel's "core" heap area on 64-bit systems. |
|
451 |
* This area is intended to be used for global data as well as for module |
|
452 |
* text/data that does not fit into the nucleus pages. The core heap is |
|
453 |
* restricted to a 2GB range, allowing every address within it to be |
|
454 |
* accessed using rip-relative addressing |
|
455 |
* |
|
456 |
* ekernelheap: end of kernelheap and start of segmap. |
|
457 |
* |
|
458 |
* kernelheap: start of kernel heap. On 32-bit systems, this starts right |
|
459 |
* above a red zone that separates the user's address space from the |
|
460 |
* kernel's. On 64-bit systems, it sits above segkp and segkpm. |
|
461 |
* |
|
3446 | 462 |
* segmap_start: start of segmap. The length of segmap can be modified |
0 | 463 |
* by changing segmapsize in /etc/system (preferred) or eeprom (deprecated). |
464 |
* The default length is 16MB on 32-bit systems and 64MB on 64-bit systems. |
|
465 |
* |
|
466 |
* kernelbase: On a 32-bit kernel the default value of 0xd4000000 will be |
|
467 |
* decreased by 2X the size required for page_t. This allows the kernel |
|
468 |
* heap to grow in size with physical memory. With sizeof(page_t) == 80 |
|
469 |
* bytes, the following shows the values of kernelbase and kernel heap |
|
470 |
* sizes for different memory configurations (assuming default segmap and |
|
471 |
* segkp sizes). |
|
472 |
* |
|
473 |
* mem size for kernelbase kernel heap |
|
474 |
* size page_t's size |
|
475 |
* ---- --------- ---------- ----------- |
|
476 |
* 1gb 0x01400000 0xd1800000 684MB |
|
477 |
* 2gb 0x02800000 0xcf000000 704MB |
|
478 |
* 4gb 0x05000000 0xca000000 744MB |
|
479 |
* 6gb 0x07800000 0xc5000000 784MB |
|
480 |
* 8gb 0x0a000000 0xc0000000 824MB |
|
481 |
* 16gb 0x14000000 0xac000000 984MB |
|
482 |
* 32gb 0x28000000 0x84000000 1304MB |
|
483 |
* 64gb 0x50000000 0x34000000 1944MB (*) |
|
484 |
* |
|
485 |
* kernelbase is less than the abi minimum of 0xc0000000 for memory |
|
486 |
* configurations above 8gb. |
|
487 |
* |
|
488 |
* (*) support for memory configurations above 32gb will require manual tuning |
|
489 |
* of kernelbase to balance out the need of user applications. |
|
490 |
*/ |
|
491 |
||
492 |
/* real-time-clock initialization parameters */ |
|
3446 | 493 |
extern time_t process_rtc_config_file(void); |
0 | 494 |
|
495 |
uintptr_t kernelbase; |
|
3446 | 496 |
uintptr_t postbootkernelbase; /* not set till boot loader is gone */ |
0 | 497 |
uintptr_t eprom_kernelbase; |
498 |
size_t segmapsize; |
|
3446 | 499 |
uintptr_t segmap_start; |
0 | 500 |
int segmapfreelists; |
501 |
pgcnt_t npages; |
|
3446 | 502 |
pgcnt_t orig_npages; |
0 | 503 |
size_t core_size; /* size of "core" heap */ |
504 |
uintptr_t core_base; /* base address of "core" heap */ |
|
505 |
||
506 |
/* |
|
507 |
* List of bootstrap pages. We mark these as allocated in startup. |
|
508 |
* release_bootstrap() will free them when we're completely done with |
|
509 |
* the bootstrap. |
|
510 |
*/ |
|
3446 | 511 |
static page_t *bootpages; |
512 |
||
513 |
/* |
|
514 |
* boot time pages that have a vnode from the ramdisk will keep that forever. |
|
515 |
*/ |
|
516 |
static page_t *rd_pages; |
|
0 | 517 |
|
518 |
struct system_hardware system_hardware; |
|
519 |
||
520 |
/* |
|
521 |
* Enable some debugging messages concerning memory usage... |
|
522 |
*/ |
|
523 |
static void |
|
3446 | 524 |
print_memlist(char *title, struct memlist *mp) |
0 | 525 |
{ |
526 |
prom_printf("MEMLIST: %s:\n", title); |
|
527 |
while (mp != NULL) { |
|
528 |
prom_printf("\tAddress 0x%" PRIx64 ", size 0x%" PRIx64 "\n", |
|
529 |
mp->address, mp->size); |
|
530 |
mp = mp->next; |
|
531 |
} |
|
532 |
} |
|
533 |
||
534 |
/* |
|
535 |
* XX64 need a comment here.. are these just default values, surely |
|
536 |
* we read the "cpuid" type information to figure this out. |
|
537 |
*/ |
|
538 |
int l2cache_sz = 0x80000; |
|
539 |
int l2cache_linesz = 0x40; |
|
540 |
int l2cache_assoc = 1; |
|
541 |
||
4426 | 542 |
static size_t textrepl_min_gb = 10; |
543 |
||
0 | 544 |
/* |
545 |
* on 64 bit we use a predifined VA range for mapping devices in the kernel |
|
546 |
* on 32 bit the mappings are intermixed in the heap, so we use a bit map |
|
547 |
*/ |
|
548 |
#ifdef __amd64 |
|
549 |
||
550 |
vmem_t *device_arena; |
|
551 |
uintptr_t toxic_addr = (uintptr_t)NULL; |
|
3446 | 552 |
size_t toxic_size = 1024 * 1024 * 1024; /* Sparc uses 1 gig too */ |
0 | 553 |
|
554 |
#else /* __i386 */ |
|
555 |
||
556 |
ulong_t *toxic_bit_map; /* one bit for each 4k of VA in heap_arena */ |
|
557 |
size_t toxic_bit_map_len = 0; /* in bits */ |
|
558 |
||
559 |
#endif /* __i386 */ |
|
560 |
||
561 |
/* |
|
562 |
* Simple boot time debug facilities |
|
563 |
*/ |
|
564 |
static char *prm_dbg_str[] = { |
|
565 |
"%s:%d: '%s' is 0x%x\n", |
|
566 |
"%s:%d: '%s' is 0x%llx\n" |
|
567 |
}; |
|
568 |
||
569 |
int prom_debug; |
|
570 |
||
571 |
#define PRM_DEBUG(q) if (prom_debug) \ |
|
572 |
prom_printf(prm_dbg_str[sizeof (q) >> 3], "startup.c", __LINE__, #q, q); |
|
573 |
#define PRM_POINT(q) if (prom_debug) \ |
|
574 |
prom_printf("%s:%d: %s\n", "startup.c", __LINE__, q); |
|
575 |
||
576 |
/* |
|
577 |
* This structure is used to keep track of the intial allocations |
|
578 |
* done in startup_memlist(). The value of NUM_ALLOCATIONS needs to |
|
579 |
* be >= the number of ADD_TO_ALLOCATIONS() executed in the code. |
|
580 |
*/ |
|
581 |
#define NUM_ALLOCATIONS 7 |
|
582 |
int num_allocations = 0; |
|
583 |
struct { |
|
584 |
void **al_ptr; |
|
585 |
size_t al_size; |
|
586 |
} allocations[NUM_ALLOCATIONS]; |
|
587 |
size_t valloc_sz = 0; |
|
588 |
uintptr_t valloc_base; |
|
589 |
||
590 |
#define ADD_TO_ALLOCATIONS(ptr, size) { \ |
|
591 |
size = ROUND_UP_PAGE(size); \ |
|
592 |
if (num_allocations == NUM_ALLOCATIONS) \ |
|
593 |
panic("too many ADD_TO_ALLOCATIONS()"); \ |
|
594 |
allocations[num_allocations].al_ptr = (void**)&ptr; \ |
|
595 |
allocations[num_allocations].al_size = size; \ |
|
596 |
valloc_sz += size; \ |
|
597 |
++num_allocations; \ |
|
598 |
} |
|
599 |
||
3446 | 600 |
/* |
601 |
* Allocate all the initial memory needed by the page allocator. |
|
602 |
*/ |
|
0 | 603 |
static void |
604 |
perform_allocations(void) |
|
605 |
{ |
|
606 |
caddr_t mem; |
|
607 |
int i; |
|
3446 | 608 |
int valloc_align; |
0 | 609 |
|
3446 | 610 |
PRM_DEBUG(valloc_base); |
611 |
PRM_DEBUG(valloc_sz); |
|
612 |
valloc_align = mmu.level_size[mmu.max_page_level > 0]; |
|
613 |
mem = BOP_ALLOC(bootops, (caddr_t)valloc_base, valloc_sz, valloc_align); |
|
0 | 614 |
if (mem != (caddr_t)valloc_base) |
615 |
panic("BOP_ALLOC() failed"); |
|
616 |
bzero(mem, valloc_sz); |
|
617 |
for (i = 0; i < num_allocations; ++i) { |
|
618 |
*allocations[i].al_ptr = (void *)mem; |
|
619 |
mem += allocations[i].al_size; |
|
620 |
} |
|
621 |
} |
|
622 |
||
623 |
/* |
|
624 |
* Our world looks like this at startup time. |
|
625 |
* |
|
626 |
* In a 32-bit OS, boot loads the kernel text at 0xfe800000 and kernel data |
|
627 |
* at 0xfec00000. On a 64-bit OS, kernel text and data are loaded at |
|
628 |
* 0xffffffff.fe800000 and 0xffffffff.fec00000 respectively. Those |
|
629 |
* addresses are fixed in the binary at link time. |
|
630 |
* |
|
631 |
* On the text page: |
|
632 |
* unix/genunix/krtld/module text loads. |
|
633 |
* |
|
634 |
* On the data page: |
|
3446 | 635 |
* unix/genunix/krtld/module data loads. |
636 |
* |
|
0 | 637 |
* Machine-dependent startup code |
638 |
*/ |
|
639 |
void |
|
640 |
startup(void) |
|
641 |
{ |
|
5084 | 642 |
#if !defined(__xpv) |
1494 | 643 |
extern void startup_bios_disk(void); |
644 |
extern void startup_pci_bios(void); |
|
5084 | 645 |
#endif |
646 |
/* |
|
647 |
* Make sure that nobody tries to use sekpm until we have |
|
648 |
* initialized it properly. |
|
649 |
*/ |
|
0 | 650 |
#if defined(__amd64) |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
651 |
kpm_desired = 1; |
0 | 652 |
#endif |
653 |
kpm_enable = 0; |
|
654 |
||
5084 | 655 |
#if defined(__xpv) /* XXPV fix me! */ |
656 |
{ |
|
657 |
extern int segvn_use_regions; |
|
658 |
segvn_use_regions = 0; |
|
659 |
} |
|
660 |
#endif |
|
0 | 661 |
progressbar_init(); |
662 |
startup_init(); |
|
663 |
startup_memlist(); |
|
3446 | 664 |
startup_kmem(); |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
665 |
startup_vm(); |
5084 | 666 |
#if !defined(__xpv) |
1494 | 667 |
startup_pci_bios(); |
5084 | 668 |
#endif |
0 | 669 |
startup_modules(); |
5084 | 670 |
#if !defined(__xpv) |
0 | 671 |
startup_bios_disk(); |
5084 | 672 |
#endif |
0 | 673 |
startup_end(); |
674 |
progressbar_start(); |
|
675 |
} |
|
676 |
||
677 |
static void |
|
678 |
startup_init() |
|
679 |
{ |
|
680 |
PRM_POINT("startup_init() starting..."); |
|
681 |
||
682 |
/* |
|
683 |
* Complete the extraction of cpuid data |
|
684 |
*/ |
|
685 |
cpuid_pass2(CPU); |
|
686 |
||
687 |
(void) check_boot_version(BOP_GETVERSION(bootops)); |
|
688 |
||
689 |
/* |
|
690 |
* Check for prom_debug in boot environment |
|
691 |
*/ |
|
692 |
if (BOP_GETPROPLEN(bootops, "prom_debug") >= 0) { |
|
693 |
++prom_debug; |
|
694 |
PRM_POINT("prom_debug found in boot enviroment"); |
|
695 |
} |
|
696 |
||
697 |
/* |
|
698 |
* Collect node, cpu and memory configuration information. |
|
699 |
*/ |
|
700 |
get_system_configuration(); |
|
701 |
||
702 |
/* |
|
703 |
* Halt if this is an unsupported processor. |
|
704 |
*/ |
|
705 |
if (x86_type == X86_TYPE_486 || x86_type == X86_TYPE_CYRIX_486) { |
|
706 |
printf("\n486 processor (\"%s\") detected.\n", |
|
707 |
CPU->cpu_brandstr); |
|
708 |
halt("This processor is not supported by this release " |
|
709 |
"of Solaris."); |
|
710 |
} |
|
711 |
||
712 |
PRM_POINT("startup_init() done"); |
|
713 |
} |
|
714 |
||
715 |
/* |
|
716 |
* Callback for copy_memlist_filter() to filter nucleus, kadb/kmdb, (ie. |
|
717 |
* everything mapped above KERNEL_TEXT) pages from phys_avail. Note it |
|
718 |
* also filters out physical page zero. There is some reliance on the |
|
719 |
* boot loader allocating only a few contiguous physical memory chunks. |
|
720 |
*/ |
|
721 |
static void |
|
722 |
avail_filter(uint64_t *addr, uint64_t *size) |
|
723 |
{ |
|
724 |
uintptr_t va; |
|
725 |
uintptr_t next_va; |
|
726 |
pfn_t pfn; |
|
727 |
uint64_t pfn_addr; |
|
728 |
uint64_t pfn_eaddr; |
|
729 |
uint_t prot; |
|
730 |
size_t len; |
|
731 |
uint_t change; |
|
732 |
||
733 |
if (prom_debug) |
|
734 |
prom_printf("\tFilter: in: a=%" PRIx64 ", s=%" PRIx64 "\n", |
|
735 |
*addr, *size); |
|
736 |
||
737 |
/* |
|
738 |
* page zero is required for BIOS.. never make it available |
|
739 |
*/ |
|
740 |
if (*addr == 0) { |
|
741 |
*addr += MMU_PAGESIZE; |
|
742 |
*size -= MMU_PAGESIZE; |
|
743 |
} |
|
744 |
||
745 |
/* |
|
3446 | 746 |
* First we trim from the front of the range. Since kbm_probe() |
0 | 747 |
* walks ranges in virtual order, but addr/size are physical, we need |
748 |
* to the list until no changes are seen. This deals with the case |
|
749 |
* where page "p" is mapped at v, page "p + PAGESIZE" is mapped at w |
|
750 |
* but w < v. |
|
751 |
*/ |
|
752 |
do { |
|
753 |
change = 0; |
|
754 |
for (va = KERNEL_TEXT; |
|
3446 | 755 |
*size > 0 && kbm_probe(&va, &len, &pfn, &prot) != 0; |
0 | 756 |
va = next_va) { |
757 |
||
758 |
next_va = va + len; |
|
3446 | 759 |
pfn_addr = pfn_to_pa(pfn); |
0 | 760 |
pfn_eaddr = pfn_addr + len; |
761 |
||
762 |
if (pfn_addr <= *addr && pfn_eaddr > *addr) { |
|
763 |
change = 1; |
|
764 |
while (*size > 0 && len > 0) { |
|
765 |
*addr += MMU_PAGESIZE; |
|
766 |
*size -= MMU_PAGESIZE; |
|
767 |
len -= MMU_PAGESIZE; |
|
768 |
} |
|
769 |
} |
|
770 |
} |
|
771 |
if (change && prom_debug) |
|
772 |
prom_printf("\t\ttrim: a=%" PRIx64 ", s=%" PRIx64 "\n", |
|
773 |
*addr, *size); |
|
774 |
} while (change); |
|
775 |
||
776 |
/* |
|
777 |
* Trim pages from the end of the range. |
|
778 |
*/ |
|
779 |
for (va = KERNEL_TEXT; |
|
3446 | 780 |
*size > 0 && kbm_probe(&va, &len, &pfn, &prot) != 0; |
0 | 781 |
va = next_va) { |
782 |
||
783 |
next_va = va + len; |
|
3446 | 784 |
pfn_addr = pfn_to_pa(pfn); |
0 | 785 |
|
786 |
if (pfn_addr >= *addr && pfn_addr < *addr + *size) |
|
787 |
*size = pfn_addr - *addr; |
|
788 |
} |
|
789 |
||
790 |
if (prom_debug) |
|
791 |
prom_printf("\tFilter out: a=%" PRIx64 ", s=%" PRIx64 "\n", |
|
792 |
*addr, *size); |
|
793 |
} |
|
794 |
||
795 |
static void |
|
796 |
kpm_init() |
|
797 |
{ |
|
798 |
struct segkpm_crargs b; |
|
799 |
||
800 |
/* |
|
801 |
* These variables were all designed for sfmmu in which segkpm is |
|
802 |
* mapped using a single pagesize - either 8KB or 4MB. On x86, we |
|
803 |
* might use 2+ page sizes on a single machine, so none of these |
|
804 |
* variables have a single correct value. They are set up as if we |
|
805 |
* always use a 4KB pagesize, which should do no harm. In the long |
|
806 |
* run, we should get rid of KPM's assumption that only a single |
|
807 |
* pagesize is used. |
|
808 |
*/ |
|
809 |
kpm_pgshft = MMU_PAGESHIFT; |
|
810 |
kpm_pgsz = MMU_PAGESIZE; |
|
811 |
kpm_pgoff = MMU_PAGEOFFSET; |
|
812 |
kpmp2pshft = 0; |
|
813 |
kpmpnpgs = 1; |
|
814 |
ASSERT(((uintptr_t)kpm_vbase & (kpm_pgsz - 1)) == 0); |
|
815 |
||
816 |
PRM_POINT("about to create segkpm"); |
|
817 |
rw_enter(&kas.a_lock, RW_WRITER); |
|
818 |
||
819 |
if (seg_attach(&kas, kpm_vbase, kpm_size, segkpm) < 0) |
|
820 |
panic("cannot attach segkpm"); |
|
821 |
||
822 |
b.prot = PROT_READ | PROT_WRITE; |
|
823 |
b.nvcolors = 1; |
|
824 |
||
825 |
if (segkpm_create(segkpm, (caddr_t)&b) != 0) |
|
826 |
panic("segkpm_create segkpm"); |
|
827 |
||
828 |
rw_exit(&kas.a_lock); |
|
829 |
} |
|
830 |
||
831 |
/* |
|
3446 | 832 |
* The debug info page provides enough information to allow external |
833 |
* inspectors (e.g. when running under a hypervisor) to bootstrap |
|
834 |
* themselves into allowing full-blown kernel debugging. |
|
835 |
*/ |
|
836 |
static void |
|
837 |
init_debug_info(void) |
|
838 |
{ |
|
839 |
caddr_t mem; |
|
840 |
debug_info_t *di; |
|
841 |
||
842 |
#ifndef __lint |
|
843 |
ASSERT(sizeof (debug_info_t) < MMU_PAGESIZE); |
|
844 |
#endif |
|
845 |
||
846 |
mem = BOP_ALLOC(bootops, (caddr_t)DEBUG_INFO_VA, MMU_PAGESIZE, |
|
847 |
MMU_PAGESIZE); |
|
848 |
||
849 |
if (mem != (caddr_t)DEBUG_INFO_VA) |
|
850 |
panic("BOP_ALLOC() failed"); |
|
851 |
bzero(mem, MMU_PAGESIZE); |
|
852 |
||
853 |
di = (debug_info_t *)mem; |
|
854 |
||
855 |
di->di_magic = DEBUG_INFO_MAGIC; |
|
856 |
di->di_version = DEBUG_INFO_VERSION; |
|
5084 | 857 |
di->di_modules = (uintptr_t)&modules; |
858 |
di->di_s_text = (uintptr_t)s_text; |
|
859 |
di->di_e_text = (uintptr_t)e_text; |
|
860 |
di->di_s_data = (uintptr_t)s_data; |
|
861 |
di->di_e_data = (uintptr_t)e_data; |
|
862 |
di->di_hat_htable_off = offsetof(hat_t, hat_htable); |
|
863 |
di->di_ht_pfn_off = offsetof(htable_t, ht_pfn); |
|
3446 | 864 |
} |
865 |
||
866 |
/* |
|
867 |
* Build the memlists and other kernel essential memory system data structures. |
|
868 |
* This is everything at valloc_base. |
|
0 | 869 |
*/ |
870 |
static void |
|
871 |
startup_memlist(void) |
|
872 |
{ |
|
873 |
size_t memlist_sz; |
|
874 |
size_t memseg_sz; |
|
875 |
size_t pagehash_sz; |
|
876 |
size_t pp_sz; |
|
877 |
uintptr_t va; |
|
878 |
size_t len; |
|
879 |
uint_t prot; |
|
880 |
pfn_t pfn; |
|
881 |
int memblocks; |
|
882 |
caddr_t pagecolor_mem; |
|
883 |
size_t pagecolor_memsz; |
|
884 |
caddr_t page_ctrs_mem; |
|
885 |
size_t page_ctrs_size; |
|
4878 | 886 |
size_t pse_table_alloc_size; |
0 | 887 |
struct memlist *current; |
888 |
extern void startup_build_mem_nodes(struct memlist *); |
|
889 |
||
890 |
/* XX64 fix these - they should be in include files */ |
|
891 |
extern size_t page_coloring_init(uint_t, int, int); |
|
892 |
extern void page_coloring_setup(caddr_t); |
|
893 |
||
894 |
PRM_POINT("startup_memlist() starting..."); |
|
895 |
||
896 |
/* |
|
897 |
* Use leftover large page nucleus text/data space for loadable modules. |
|
898 |
* Use at most MODTEXT/MODDATA. |
|
899 |
*/ |
|
3446 | 900 |
len = kbm_nucleus_size; |
901 |
ASSERT(len > MMU_PAGESIZE); |
|
0 | 902 |
|
3446 | 903 |
moddata = (caddr_t)ROUND_UP_PAGE(e_data); |
904 |
e_moddata = (caddr_t)P2ROUNDUP((uintptr_t)e_data, (uintptr_t)len); |
|
905 |
if (e_moddata - moddata > MODDATA) |
|
906 |
e_moddata = moddata + MODDATA; |
|
0 | 907 |
|
3446 | 908 |
modtext = (caddr_t)ROUND_UP_PAGE(e_text); |
909 |
e_modtext = (caddr_t)P2ROUNDUP((uintptr_t)e_text, (uintptr_t)len); |
|
910 |
if (e_modtext - modtext > MODTEXT) |
|
911 |
e_modtext = modtext + MODTEXT; |
|
0 | 912 |
|
913 |
econtig = e_moddata; |
|
914 |
||
915 |
PRM_DEBUG(modtext); |
|
916 |
PRM_DEBUG(e_modtext); |
|
917 |
PRM_DEBUG(moddata); |
|
918 |
PRM_DEBUG(e_moddata); |
|
919 |
PRM_DEBUG(econtig); |
|
920 |
||
921 |
/* |
|
3446 | 922 |
* Examine the boot loader physical memory map to find out: |
0 | 923 |
* - total memory in system - physinstalled |
924 |
* - the max physical address - physmax |
|
3446 | 925 |
* - the number of discontiguous segments of memory. |
0 | 926 |
*/ |
927 |
if (prom_debug) |
|
3446 | 928 |
print_memlist("boot physinstalled", |
0 | 929 |
bootops->boot_mem->physinstalled); |
930 |
installed_top_size(bootops->boot_mem->physinstalled, &physmax, |
|
931 |
&physinstalled, &memblocks); |
|
932 |
PRM_DEBUG(physmax); |
|
933 |
PRM_DEBUG(physinstalled); |
|
934 |
PRM_DEBUG(memblocks); |
|
935 |
||
936 |
/* |
|
937 |
* Initialize hat's mmu parameters. |
|
938 |
* Check for enforce-prot-exec in boot environment. It's used to |
|
939 |
* enable/disable support for the page table entry NX bit. |
|
940 |
* The default is to enforce PROT_EXEC on processors that support NX. |
|
941 |
* Boot seems to round up the "len", but 8 seems to be big enough. |
|
942 |
*/ |
|
943 |
mmu_init(); |
|
944 |
||
945 |
#ifdef __i386 |
|
946 |
/* |
|
947 |
* physmax is lowered if there is more memory than can be |
|
948 |
* physically addressed in 32 bit (PAE/non-PAE) modes. |
|
949 |
*/ |
|
950 |
if (mmu.pae_hat) { |
|
951 |
if (PFN_ABOVE64G(physmax)) { |
|
952 |
physinstalled -= (physmax - (PFN_64G - 1)); |
|
953 |
physmax = PFN_64G - 1; |
|
954 |
} |
|
955 |
} else { |
|
956 |
if (PFN_ABOVE4G(physmax)) { |
|
957 |
physinstalled -= (physmax - (PFN_4G - 1)); |
|
958 |
physmax = PFN_4G - 1; |
|
959 |
} |
|
960 |
} |
|
961 |
#endif |
|
962 |
||
963 |
startup_build_mem_nodes(bootops->boot_mem->physinstalled); |
|
964 |
||
965 |
if (BOP_GETPROPLEN(bootops, "enforce-prot-exec") >= 0) { |
|
966 |
int len = BOP_GETPROPLEN(bootops, "enforce-prot-exec"); |
|
967 |
char value[8]; |
|
968 |
||
969 |
if (len < 8) |
|
970 |
(void) BOP_GETPROP(bootops, "enforce-prot-exec", value); |
|
971 |
else |
|
972 |
(void) strcpy(value, ""); |
|
973 |
if (strcmp(value, "off") == 0) |
|
974 |
mmu.pt_nx = 0; |
|
975 |
} |
|
976 |
PRM_DEBUG(mmu.pt_nx); |
|
977 |
||
978 |
/* |
|
979 |
* We will need page_t's for every page in the system, except for |
|
980 |
* memory mapped at or above above the start of the kernel text segment. |
|
981 |
* |
|
982 |
* pages above e_modtext are attributed to kernel debugger (obp_pages) |
|
983 |
*/ |
|
984 |
npages = physinstalled - 1; /* avail_filter() skips page 0, so "- 1" */ |
|
985 |
obp_pages = 0; |
|
986 |
va = KERNEL_TEXT; |
|
3446 | 987 |
while (kbm_probe(&va, &len, &pfn, &prot) != 0) { |
0 | 988 |
npages -= len >> MMU_PAGESHIFT; |
989 |
if (va >= (uintptr_t)e_moddata) |
|
990 |
obp_pages += len >> MMU_PAGESHIFT; |
|
991 |
va += len; |
|
992 |
} |
|
993 |
PRM_DEBUG(npages); |
|
994 |
PRM_DEBUG(obp_pages); |
|
995 |
||
996 |
/* |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
997 |
* If physmem is patched to be non-zero, use it instead of the computed |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
998 |
* value unless it is larger than the actual amount of memory on hand. |
0 | 999 |
*/ |
1417
fa316336e215
6377034 setting physmem in /etc/system does not have desired effect on x86
kchow
parents:
1414
diff
changeset
|
1000 |
if (physmem == 0 || physmem > npages) { |
0 | 1001 |
physmem = npages; |
1417
fa316336e215
6377034 setting physmem in /etc/system does not have desired effect on x86
kchow
parents:
1414
diff
changeset
|
1002 |
} else if (physmem < npages) { |
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1003 |
orig_npages = npages; |
0 | 1004 |
npages = physmem; |
1417
fa316336e215
6377034 setting physmem in /etc/system does not have desired effect on x86
kchow
parents:
1414
diff
changeset
|
1005 |
} |
0 | 1006 |
PRM_DEBUG(physmem); |
1007 |
||
1008 |
/* |
|
1009 |
* We now compute the sizes of all the initial allocations for |
|
1010 |
* structures the kernel needs in order do kmem_alloc(). These |
|
1011 |
* include: |
|
1012 |
* memsegs |
|
1013 |
* memlists |
|
1014 |
* page hash table |
|
1015 |
* page_t's |
|
1016 |
* page coloring data structs |
|
1017 |
*/ |
|
1018 |
memseg_sz = sizeof (struct memseg) * (memblocks + POSS_NEW_FRAGMENTS); |
|
1019 |
ADD_TO_ALLOCATIONS(memseg_base, memseg_sz); |
|
1020 |
PRM_DEBUG(memseg_sz); |
|
1021 |
||
1022 |
/* |
|
3446 | 1023 |
* Reserve space for memlists. There's no real good way to know exactly |
1024 |
* how much room we'll need, but this should be a good upper bound. |
|
0 | 1025 |
*/ |
1026 |
memlist_sz = ROUND_UP_PAGE(2 * sizeof (struct memlist) * |
|
1027 |
(memblocks + POSS_NEW_FRAGMENTS)); |
|
1028 |
ADD_TO_ALLOCATIONS(memlist, memlist_sz); |
|
1029 |
PRM_DEBUG(memlist_sz); |
|
1030 |
||
1031 |
/* |
|
1032 |
* The page structure hash table size is a power of 2 |
|
1033 |
* such that the average hash chain length is PAGE_HASHAVELEN. |
|
1034 |
*/ |
|
1035 |
page_hashsz = npages / PAGE_HASHAVELEN; |
|
1036 |
page_hashsz = 1 << highbit(page_hashsz); |
|
1037 |
pagehash_sz = sizeof (struct page *) * page_hashsz; |
|
1038 |
ADD_TO_ALLOCATIONS(page_hash, pagehash_sz); |
|
1039 |
PRM_DEBUG(pagehash_sz); |
|
1040 |
||
1041 |
/* |
|
3446 | 1042 |
* Set aside room for the page structures themselves. |
0 | 1043 |
*/ |
3446 | 1044 |
PRM_DEBUG(npages); |
1045 |
pp_sz = sizeof (struct page) * npages; |
|
0 | 1046 |
ADD_TO_ALLOCATIONS(pp_base, pp_sz); |
1047 |
PRM_DEBUG(pp_sz); |
|
1048 |
||
1049 |
/* |
|
1050 |
* determine l2 cache info and memory size for page coloring |
|
1051 |
*/ |
|
1052 |
(void) getl2cacheinfo(CPU, |
|
1053 |
&l2cache_sz, &l2cache_linesz, &l2cache_assoc); |
|
1054 |
pagecolor_memsz = |
|
1055 |
page_coloring_init(l2cache_sz, l2cache_linesz, l2cache_assoc); |
|
1056 |
ADD_TO_ALLOCATIONS(pagecolor_mem, pagecolor_memsz); |
|
1057 |
PRM_DEBUG(pagecolor_memsz); |
|
1058 |
||
1059 |
page_ctrs_size = page_ctrs_sz(); |
|
1060 |
ADD_TO_ALLOCATIONS(page_ctrs_mem, page_ctrs_size); |
|
1061 |
PRM_DEBUG(page_ctrs_size); |
|
1062 |
||
4878 | 1063 |
/* |
1064 |
* Allocate the array that protects pp->p_selock. |
|
1065 |
*/ |
|
1066 |
pse_shift = size_pse_array(physmem, max_ncpus); |
|
1067 |
pse_table_size = 1 << pse_shift; |
|
1068 |
pse_table_alloc_size = pse_table_size * sizeof (pad_mutex_t); |
|
1069 |
ADD_TO_ALLOCATIONS(pse_mutex, pse_table_alloc_size); |
|
1070 |
||
3446 | 1071 |
#if defined(__amd64) |
1072 |
valloc_sz = ROUND_UP_LPAGE(valloc_sz); |
|
1073 |
valloc_base = VALLOC_BASE; |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1074 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1075 |
/* |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1076 |
* The default values of VALLOC_BASE and SEGKPM_BASE should work |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1077 |
* for values of physmax up to 1 Terabyte. They need adjusting when |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1078 |
* memory is at addresses above 1 TB. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1079 |
*/ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1080 |
if (physmax + 1 > mmu_btop(TERABYTE)) { |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1081 |
uint64_t kpm_resv_amount = mmu_ptob(physmax + 1); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1082 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1083 |
/* Round to largest possible pagesize for now */ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1084 |
kpm_resv_amount = P2ROUNDUP(kpm_resv_amount, ONE_GIG); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1085 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1086 |
segkpm_base = -(2 * kpm_resv_amount); /* down from top VA */ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1087 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1088 |
/* make sure we leave some space for user apps above hole */ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1089 |
segkpm_base = MAX(segkpm_base, AMD64_VA_HOLE_END + TERABYTE); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1090 |
if (segkpm_base > SEGKPM_BASE) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1091 |
segkpm_base = SEGKPM_BASE; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1092 |
PRM_DEBUG(segkpm_base); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1093 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1094 |
valloc_base = segkpm_base + kpm_resv_amount; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1095 |
PRM_DEBUG(valloc_base); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1096 |
} |
3446 | 1097 |
#else /* __i386 */ |
1098 |
valloc_base = (uintptr_t)(MISC_VA_BASE - valloc_sz); |
|
1099 |
valloc_base = P2ALIGN(valloc_base, mmu.level_size[1]); |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1100 |
PRM_DEBUG(valloc_base); |
3446 | 1101 |
#endif /* __i386 */ |
1102 |
||
0 | 1103 |
/* |
3446 | 1104 |
* do all the initial allocations |
1105 |
*/ |
|
1106 |
perform_allocations(); |
|
1107 |
||
1108 |
/* |
|
1109 |
* Build phys_install and phys_avail in kernel memspace. |
|
1110 |
* - phys_install should be all memory in the system. |
|
1111 |
* - phys_avail is phys_install minus any memory mapped before this |
|
1112 |
* point above KERNEL_TEXT. |
|
1113 |
*/ |
|
1114 |
current = phys_install = memlist; |
|
1115 |
copy_memlist_filter(bootops->boot_mem->physinstalled, ¤t, NULL); |
|
1116 |
if ((caddr_t)current > (caddr_t)memlist + memlist_sz) |
|
1117 |
panic("physinstalled was too big!"); |
|
1118 |
if (prom_debug) |
|
1119 |
print_memlist("phys_install", phys_install); |
|
1120 |
||
1121 |
phys_avail = current; |
|
1122 |
PRM_POINT("Building phys_avail:\n"); |
|
1123 |
copy_memlist_filter(bootops->boot_mem->physinstalled, ¤t, |
|
1124 |
avail_filter); |
|
1125 |
if ((caddr_t)current > (caddr_t)memlist + memlist_sz) |
|
1126 |
panic("physavail was too big!"); |
|
1127 |
if (prom_debug) |
|
1128 |
print_memlist("phys_avail", phys_avail); |
|
1129 |
||
1130 |
/* |
|
1131 |
* setup page coloring |
|
0 | 1132 |
*/ |
3446 | 1133 |
page_coloring_setup(pagecolor_mem); |
1134 |
page_lock_init(); /* currently a no-op */ |
|
1135 |
||
1136 |
/* |
|
1137 |
* free page list counters |
|
1138 |
*/ |
|
1139 |
(void) page_ctrs_alloc(page_ctrs_mem); |
|
1140 |
||
1141 |
/* |
|
1142 |
* Initialize the page structures from the memory lists. |
|
1143 |
*/ |
|
1144 |
availrmem_initial = availrmem = freemem = 0; |
|
1145 |
PRM_POINT("Calling kphysm_init()..."); |
|
1146 |
npages = kphysm_init(pp_base, npages); |
|
1147 |
PRM_POINT("kphysm_init() done"); |
|
1148 |
PRM_DEBUG(npages); |
|
1149 |
||
1150 |
init_debug_info(); |
|
1151 |
||
1152 |
/* |
|
1153 |
* Now that page_t's have been initialized, remove all the |
|
1154 |
* initial allocation pages from the kernel free page lists. |
|
1155 |
*/ |
|
1156 |
boot_mapin((caddr_t)valloc_base, valloc_sz); |
|
1157 |
boot_mapin((caddr_t)GDT_VA, MMU_PAGESIZE); |
|
1158 |
boot_mapin((caddr_t)DEBUG_INFO_VA, MMU_PAGESIZE); |
|
1159 |
PRM_POINT("startup_memlist() done"); |
|
1160 |
||
1161 |
PRM_DEBUG(valloc_sz); |
|
4426 | 1162 |
|
4748
3bb903eb8ac9
6582037 don't enable text replication on 32bit kernels
aguzovsk
parents:
4426
diff
changeset
|
1163 |
#if defined(__amd64) |
3bb903eb8ac9
6582037 don't enable text replication on 32bit kernels
aguzovsk
parents:
4426
diff
changeset
|
1164 |
if ((availrmem >> (30 - MMU_PAGESHIFT)) >= |
3bb903eb8ac9
6582037 don't enable text replication on 32bit kernels
aguzovsk
parents:
4426
diff
changeset
|
1165 |
textrepl_min_gb && l2cache_sz <= 2 << 20) { |
3bb903eb8ac9
6582037 don't enable text replication on 32bit kernels
aguzovsk
parents:
4426
diff
changeset
|
1166 |
extern size_t textrepl_size_thresh; |
4426 | 1167 |
textrepl_size_thresh = (16 << 20) - 1; |
1168 |
} |
|
4748
3bb903eb8ac9
6582037 don't enable text replication on 32bit kernels
aguzovsk
parents:
4426
diff
changeset
|
1169 |
#endif |
3446 | 1170 |
} |
1171 |
||
1172 |
/* |
|
1173 |
* Layout the kernel's part of address space and initialize kmem allocator. |
|
1174 |
*/ |
|
1175 |
static void |
|
1176 |
startup_kmem(void) |
|
1177 |
{ |
|
3717
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1178 |
extern void page_set_colorequiv_arr(void); |
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1179 |
|
3446 | 1180 |
PRM_POINT("startup_kmem() starting..."); |
0 | 1181 |
|
1182 |
#if defined(__amd64) |
|
1183 |
if (eprom_kernelbase && eprom_kernelbase != KERNELBASE) |
|
1184 |
cmn_err(CE_NOTE, "!kernelbase cannot be changed on 64-bit " |
|
1185 |
"systems."); |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1186 |
kernelbase = segkpm_base - KERNEL_REDZONE_SIZE; |
0 | 1187 |
core_base = (uintptr_t)COREHEAP_BASE; |
3446 | 1188 |
core_size = (size_t)MISC_VA_BASE - COREHEAP_BASE; |
0 | 1189 |
#else /* __i386 */ |
1190 |
/* |
|
1191 |
* We configure kernelbase based on: |
|
1192 |
* |
|
1193 |
* 1. user specified kernelbase via eeprom command. Value cannot exceed |
|
1194 |
* KERNELBASE_MAX. we large page align eprom_kernelbase |
|
1195 |
* |
|
1196 |
* 2. Default to KERNELBASE and adjust to 2X less the size for page_t. |
|
1197 |
* On large memory systems we must lower kernelbase to allow |
|
1198 |
* enough room for page_t's for all of memory. |
|
1199 |
* |
|
1200 |
* The value set here, might be changed a little later. |
|
1201 |
*/ |
|
1202 |
if (eprom_kernelbase) { |
|
1203 |
kernelbase = eprom_kernelbase & mmu.level_mask[1]; |
|
1204 |
if (kernelbase > KERNELBASE_MAX) |
|
1205 |
kernelbase = KERNELBASE_MAX; |
|
1206 |
} else { |
|
1207 |
kernelbase = (uintptr_t)KERNELBASE; |
|
1208 |
kernelbase -= ROUND_UP_4MEG(2 * valloc_sz); |
|
1209 |
} |
|
1210 |
ASSERT((kernelbase & mmu.level_offset[1]) == 0); |
|
3446 | 1211 |
core_base = valloc_base; |
0 | 1212 |
core_size = 0; |
3446 | 1213 |
#endif /* __i386 */ |
0 | 1214 |
|
1215 |
PRM_DEBUG(core_base); |
|
1216 |
PRM_DEBUG(core_size); |
|
3446 | 1217 |
PRM_DEBUG(kernelbase); |
0 | 1218 |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1219 |
#if defined(__i386) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1220 |
segkp_fromheap = 1; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1221 |
#endif /* __i386 */ |
3446 | 1222 |
|
1223 |
ekernelheap = (char *)core_base; |
|
1224 |
PRM_DEBUG(ekernelheap); |
|
0 | 1225 |
|
1226 |
/* |
|
1227 |
* Now that we know the real value of kernelbase, |
|
1228 |
* update variables that were initialized with a value of |
|
1229 |
* KERNELBASE (in common/conf/param.c). |
|
1230 |
* |
|
1231 |
* XXX The problem with this sort of hackery is that the |
|
1232 |
* compiler just may feel like putting the const declarations |
|
1233 |
* (in param.c) into the .text section. Perhaps they should |
|
1234 |
* just be declared as variables there? |
|
1235 |
*/ |
|
1236 |
||
1237 |
*(uintptr_t *)&_kernelbase = kernelbase; |
|
1238 |
*(uintptr_t *)&_userlimit = kernelbase; |
|
4875 | 1239 |
#if defined(__amd64) |
1240 |
*(uintptr_t *)&_userlimit -= KERNELBASE - USERLIMIT; |
|
1241 |
#else |
|
0 | 1242 |
*(uintptr_t *)&_userlimit32 = _userlimit; |
1243 |
#endif |
|
1244 |
PRM_DEBUG(_kernelbase); |
|
1245 |
PRM_DEBUG(_userlimit); |
|
1246 |
PRM_DEBUG(_userlimit32); |
|
1247 |
||
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1248 |
layout_kernel_va(); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1249 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1250 |
#if defined(__i386) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1251 |
/* |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1252 |
* If segmap is too large we can push the bottom of the kernel heap |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1253 |
* higher than the base. Or worse, it could exceed the top of the |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1254 |
* VA space entirely, causing it to wrap around. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1255 |
*/ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1256 |
if (kernelheap >= ekernelheap || (uintptr_t)kernelheap < kernelbase) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1257 |
panic("too little address space available for kernelheap," |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1258 |
" use eeprom for lower kernelbase or smaller segmapsize"); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1259 |
#endif /* __i386 */ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1260 |
|
0 | 1261 |
/* |
1262 |
* Initialize the kernel heap. Note 3rd argument must be > 1st. |
|
1263 |
*/ |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1264 |
kernelheap_init(kernelheap, ekernelheap, |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1265 |
kernelheap + MMU_PAGESIZE, |
3446 | 1266 |
(void *)core_base, (void *)(core_base + core_size)); |
0 | 1267 |
|
5084 | 1268 |
#if defined(__xpv) |
1269 |
/* |
|
1270 |
* Link pending events struct into cpu struct |
|
1271 |
*/ |
|
1272 |
CPU->cpu_m.mcpu_evt_pend = &cpu0_evt_data; |
|
1273 |
#endif |
|
0 | 1274 |
/* |
1275 |
* Initialize kernel memory allocator. |
|
1276 |
*/ |
|
1277 |
kmem_init(); |
|
1278 |
||
1279 |
/* |
|
3717
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1280 |
* Factor in colorequiv to check additional 'equivalent' bins |
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1281 |
*/ |
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1282 |
page_set_colorequiv_arr(); |
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1283 |
|
5084 | 1284 |
#if defined(__xpv) |
1285 |
xen_version(); |
|
1286 |
#endif |
|
1287 |
||
3717
8471164f3e47
6527696 /etc/system colorequiv setting has no impact
dp78419
parents:
3552
diff
changeset
|
1288 |
/* |
0 | 1289 |
* print this out early so that we know what's going on |
1290 |
*/ |
|
1291 |
cmn_err(CE_CONT, "?features: %b\n", x86_feature, FMT_X86_FEATURE); |
|
1292 |
||
1293 |
/* |
|
1294 |
* Initialize bp_mapin(). |
|
1295 |
*/ |
|
1296 |
bp_init(MMU_PAGESIZE, HAT_STORECACHING_OK); |
|
1297 |
||
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1298 |
/* |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1299 |
* orig_npages is non-zero if physmem has been configured for less |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1300 |
* than the available memory. |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1301 |
*/ |
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1302 |
if (orig_npages) { |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1303 |
cmn_err(CE_WARN, "!%slimiting physmem to 0x%lx of 0x%lx pages", |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1304 |
(npages == PHYSMEM ? "Due to virtual address space " : ""), |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1305 |
npages, orig_npages); |
1479
33ca002df1d5
6373609 Solaris install fails on 16-way 64GB system with s10u1_19a.
kchow
parents:
1455
diff
changeset
|
1306 |
} |
0 | 1307 |
#if defined(__i386) |
1308 |
if (eprom_kernelbase && (eprom_kernelbase != kernelbase)) |
|
1309 |
cmn_err(CE_WARN, "kernelbase value, User specified 0x%lx, " |
|
1310 |
"System using 0x%lx", |
|
1311 |
(uintptr_t)eprom_kernelbase, (uintptr_t)kernelbase); |
|
1312 |
#endif |
|
1313 |
||
1314 |
#ifdef KERNELBASE_ABI_MIN |
|
1315 |
if (kernelbase < (uintptr_t)KERNELBASE_ABI_MIN) { |
|
1316 |
cmn_err(CE_NOTE, "!kernelbase set to 0x%lx, system is not " |
|
1317 |
"i386 ABI compliant.", (uintptr_t)kernelbase); |
|
1318 |
} |
|
1319 |
#endif |
|
1320 |
||
5084 | 1321 |
#ifdef __xpv |
1322 |
/* |
|
1323 |
* Some of the xen start information has to be relocated up |
|
1324 |
* into the kernel's permanent address space. |
|
1325 |
*/ |
|
1326 |
PRM_POINT("calling xen_relocate_start_info()"); |
|
1327 |
xen_relocate_start_info(); |
|
1328 |
PRM_POINT("xen_relocate_start_info() done"); |
|
1329 |
||
1330 |
/* |
|
1331 |
* (Update the vcpu pointer in our cpu structure to point into |
|
1332 |
* the relocated shared info.) |
|
1333 |
*/ |
|
1334 |
CPU->cpu_m.mcpu_vcpu_info = |
|
1335 |
&HYPERVISOR_shared_info->vcpu_info[CPU->cpu_id]; |
|
1336 |
#endif |
|
1337 |
||
3446 | 1338 |
PRM_POINT("startup_kmem() done"); |
0 | 1339 |
} |
1340 |
||
1341 |
static void |
|
1342 |
startup_modules(void) |
|
1343 |
{ |
|
1344 |
unsigned int i; |
|
1345 |
extern void prom_setup(void); |
|
1346 |
||
1347 |
PRM_POINT("startup_modules() starting..."); |
|
5084 | 1348 |
|
1349 |
#ifndef __xpv |
|
0 | 1350 |
/* |
1351 |
* Initialize ten-micro second timer so that drivers will |
|
1352 |
* not get short changed in their init phase. This was |
|
1353 |
* not getting called until clkinit which, on fast cpu's |
|
1354 |
* caused the drv_usecwait to be way too short. |
|
1355 |
*/ |
|
1356 |
microfind(); |
|
5084 | 1357 |
#endif |
0 | 1358 |
|
1359 |
/* |
|
1360 |
* Read the GMT lag from /etc/rtc_config. |
|
1361 |
*/ |
|
3446 | 1362 |
sgmtl(process_rtc_config_file()); |
0 | 1363 |
|
1364 |
/* |
|
1365 |
* Calculate default settings of system parameters based upon |
|
1366 |
* maxusers, yet allow to be overridden via the /etc/system file. |
|
1367 |
*/ |
|
1368 |
param_calc(0); |
|
1369 |
||
1370 |
mod_setup(); |
|
1371 |
||
1372 |
/* |
|
1373 |
* Initialize system parameters. |
|
1374 |
*/ |
|
1375 |
param_init(); |
|
1376 |
||
1377 |
/* |
|
2712
f74a135872bc
PSARC/2005/471 BrandZ: Support for non-native zones
nn35248
parents:
2621
diff
changeset
|
1378 |
* Initialize the default brands |
f74a135872bc
PSARC/2005/471 BrandZ: Support for non-native zones
nn35248
parents:
2621
diff
changeset
|
1379 |
*/ |
f74a135872bc
PSARC/2005/471 BrandZ: Support for non-native zones
nn35248
parents:
2621
diff
changeset
|
1380 |
brand_init(); |
f74a135872bc
PSARC/2005/471 BrandZ: Support for non-native zones
nn35248
parents:
2621
diff
changeset
|
1381 |
|
f74a135872bc
PSARC/2005/471 BrandZ: Support for non-native zones
nn35248
parents:
2621
diff
changeset
|
1382 |
/* |
0 | 1383 |
* maxmem is the amount of physical memory we're playing with. |
1384 |
*/ |
|
1385 |
maxmem = physmem; |
|
1386 |
||
1387 |
/* |
|
1388 |
* Initialize segment management stuff. |
|
1389 |
*/ |
|
1390 |
seg_init(); |
|
1391 |
||
1392 |
if (modload("fs", "specfs") == -1) |
|
1393 |
halt("Can't load specfs"); |
|
1394 |
||
1395 |
if (modload("fs", "devfs") == -1) |
|
1396 |
halt("Can't load devfs"); |
|
1397 |
||
2621 | 1398 |
if (modload("fs", "dev") == -1) |
1399 |
halt("Can't load dev"); |
|
1400 |
||
1676 | 1401 |
(void) modloadonly("sys", "lbl_edition"); |
1402 |
||
0 | 1403 |
dispinit(); |
1404 |
||
1405 |
/* |
|
1406 |
* This is needed here to initialize hw_serial[] for cluster booting. |
|
1407 |
*/ |
|
1408 |
if ((i = modload("misc", "sysinit")) != (unsigned int)-1) |
|
1409 |
(void) modunload(i); |
|
1410 |
else |
|
1411 |
cmn_err(CE_CONT, "sysinit load failed"); |
|
1412 |
||
1413 |
/* Read cluster configuration data. */ |
|
1414 |
clconf_init(); |
|
1415 |
||
5084 | 1416 |
#if defined(__xpv) |
1417 |
ec_init(); |
|
1418 |
gnttab_init(); |
|
1419 |
(void) xs_early_init(); |
|
1420 |
#endif /* __xpv */ |
|
1421 |
||
0 | 1422 |
/* |
1423 |
* Create a kernel device tree. First, create rootnex and |
|
1424 |
* then invoke bus specific code to probe devices. |
|
1425 |
*/ |
|
1426 |
setup_ddi(); |
|
1414
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1427 |
|
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1428 |
/* |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1429 |
* Set up the CPU module subsystem. Modifies the device tree, so it |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1430 |
* must be done after setup_ddi(). |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1431 |
*/ |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1432 |
cmi_init(); |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1433 |
|
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1434 |
/* |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1435 |
* Initialize the MCA handlers |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1436 |
*/ |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1437 |
if (x86_feature & X86_MCA) |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1438 |
cmi_mca_init(); |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
1439 |
|
0 | 1440 |
/* |
1441 |
* Fake a prom tree such that /dev/openprom continues to work |
|
1442 |
*/ |
|
3446 | 1443 |
PRM_POINT("startup_modules: calling prom_setup..."); |
0 | 1444 |
prom_setup(); |
3446 | 1445 |
PRM_POINT("startup_modules: done"); |
0 | 1446 |
|
1447 |
/* |
|
1448 |
* Load all platform specific modules |
|
1449 |
*/ |
|
3446 | 1450 |
PRM_POINT("startup_modules: calling psm_modload..."); |
0 | 1451 |
psm_modload(); |
1452 |
||
1453 |
PRM_POINT("startup_modules() done"); |
|
1454 |
} |
|
1455 |
||
3446 | 1456 |
/* |
1457 |
* claim a "setaside" boot page for use in the kernel |
|
1458 |
*/ |
|
1459 |
page_t * |
|
1460 |
boot_claim_page(pfn_t pfn) |
|
0 | 1461 |
{ |
3446 | 1462 |
page_t *pp; |
1463 |
||
1464 |
pp = page_numtopp_nolock(pfn); |
|
1465 |
ASSERT(pp != NULL); |
|
0 | 1466 |
|
3446 | 1467 |
if (PP_ISBOOTPAGES(pp)) { |
1468 |
if (pp->p_next != NULL) |
|
1469 |
pp->p_next->p_prev = pp->p_prev; |
|
1470 |
if (pp->p_prev == NULL) |
|
1471 |
bootpages = pp->p_next; |
|
1472 |
else |
|
1473 |
pp->p_prev->p_next = pp->p_next; |
|
1474 |
} else { |
|
1475 |
/* |
|
1476 |
* htable_attach() expects a base pagesize page |
|
1477 |
*/ |
|
1478 |
if (pp->p_szc != 0) |
|
1479 |
page_boot_demote(pp); |
|
1480 |
pp = page_numtopp(pfn, SE_EXCL); |
|
1481 |
} |
|
1482 |
return (pp); |
|
0 | 1483 |
} |
1484 |
||
1485 |
/* |
|
1486 |
* Walk through the pagetables looking for pages mapped in by boot. If the |
|
1487 |
* setaside flag is set the pages are expected to be returned to the |
|
1488 |
* kernel later in boot, so we add them to the bootpages list. |
|
1489 |
*/ |
|
1490 |
static void |
|
1491 |
protect_boot_range(uintptr_t low, uintptr_t high, int setaside) |
|
1492 |
{ |
|
1493 |
uintptr_t va = low; |
|
1494 |
size_t len; |
|
1495 |
uint_t prot; |
|
1496 |
pfn_t pfn; |
|
1497 |
page_t *pp; |
|
1498 |
pgcnt_t boot_protect_cnt = 0; |
|
1499 |
||
3446 | 1500 |
while (kbm_probe(&va, &len, &pfn, &prot) != 0 && va < high) { |
0 | 1501 |
if (va + len >= high) |
1502 |
panic("0x%lx byte mapping at 0x%p exceeds boot's " |
|
1503 |
"legal range.", len, (void *)va); |
|
1504 |
||
1505 |
while (len > 0) { |
|
1506 |
pp = page_numtopp_alloc(pfn); |
|
1507 |
if (pp != NULL) { |
|
1508 |
if (setaside == 0) |
|
1509 |
panic("Unexpected mapping by boot. " |
|
1510 |
"addr=%p pfn=%lx\n", |
|
1511 |
(void *)va, pfn); |
|
1512 |
||
1513 |
pp->p_next = bootpages; |
|
3446 | 1514 |
pp->p_prev = NULL; |
1515 |
PP_SETBOOTPAGES(pp); |
|
1516 |
if (bootpages != NULL) { |
|
1517 |
bootpages->p_prev = pp; |
|
1518 |
} |
|
0 | 1519 |
bootpages = pp; |
1520 |
++boot_protect_cnt; |
|
1521 |
} |
|
1522 |
||
1523 |
++pfn; |
|
1524 |
len -= MMU_PAGESIZE; |
|
1525 |
va += MMU_PAGESIZE; |
|
1526 |
} |
|
1527 |
} |
|
1528 |
PRM_DEBUG(boot_protect_cnt); |
|
1529 |
} |
|
1530 |
||
3446 | 1531 |
/* |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1532 |
* |
3446 | 1533 |
*/ |
0 | 1534 |
static void |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1535 |
layout_kernel_va(void) |
0 | 1536 |
{ |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1537 |
PRM_POINT("layout_kernel_va() starting..."); |
0 | 1538 |
/* |
3446 | 1539 |
* Establish the final size of the kernel's heap, size of segmap, |
1540 |
* segkp, etc. |
|
0 | 1541 |
*/ |
1542 |
||
1543 |
#if defined(__amd64) |
|
1544 |
||
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1545 |
kpm_vbase = (caddr_t)segkpm_base; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1546 |
kpm_size = ROUND_UP_LPAGE(mmu_ptob(physmax + 1)); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1547 |
if ((uintptr_t)kpm_vbase + kpm_size > (uintptr_t)valloc_base) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1548 |
panic("not enough room for kpm!"); |
3446 | 1549 |
PRM_DEBUG(kpm_size); |
1550 |
PRM_DEBUG(kpm_vbase); |
|
0 | 1551 |
|
1552 |
/* |
|
3446 | 1553 |
* By default we create a seg_kp in 64 bit kernels, it's a little |
1554 |
* faster to access than embedding it in the heap. |
|
0 | 1555 |
*/ |
3446 | 1556 |
segkp_base = (caddr_t)valloc_base + valloc_sz; |
0 | 1557 |
if (!segkp_fromheap) { |
1558 |
size_t sz = mmu_ptob(segkpsize); |
|
1559 |
||
1560 |
/* |
|
3446 | 1561 |
* determine size of segkp |
0 | 1562 |
*/ |
1563 |
if (sz < SEGKPMINSIZE || sz > SEGKPMAXSIZE) { |
|
1564 |
sz = SEGKPDEFSIZE; |
|
1565 |
cmn_err(CE_WARN, "!Illegal value for segkpsize. " |
|
1566 |
"segkpsize has been reset to %ld pages", |
|
1567 |
mmu_btop(sz)); |
|
1568 |
} |
|
1569 |
sz = MIN(sz, MAX(SEGKPMINSIZE, mmu_ptob(physmem))); |
|
1570 |
||
1571 |
segkpsize = mmu_btop(ROUND_UP_LPAGE(sz)); |
|
1572 |
} |
|
3446 | 1573 |
PRM_DEBUG(segkp_base); |
1574 |
PRM_DEBUG(segkpsize); |
|
0 | 1575 |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1576 |
/* |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1577 |
* segzio is used for ZFS cached data. It uses a distinct VA |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1578 |
* segment (from kernel heap) so that we can easily tell not to |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1579 |
* include it in kernel crash dumps on 64 bit kernels. The trick is |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1580 |
* to give it lots of VA, but not constrain the kernel heap. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1581 |
* We scale the size of segzio linearly with physmem up to |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1582 |
* SEGZIOMAXSIZE. Above that amount it scales at 50% of physmem. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1583 |
*/ |
3446 | 1584 |
segzio_base = segkp_base + mmu_ptob(segkpsize); |
1585 |
if (segzio_fromheap) { |
|
1586 |
segziosize = 0; |
|
1587 |
} else { |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1588 |
size_t physmem_size = mmu_ptob(physmem); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1589 |
size_t size = (segziosize == 0) ? |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1590 |
physmem_size : mmu_ptob(segziosize); |
3290 | 1591 |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1592 |
if (size < SEGZIOMINSIZE) |
3290 | 1593 |
size = SEGZIOMINSIZE; |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1594 |
if (size > SEGZIOMAXSIZE) { |
3552
ea34919c6784
6520051 segzio's sizing policy needs further optimization
johansen
parents:
3446
diff
changeset
|
1595 |
size = SEGZIOMAXSIZE; |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1596 |
if (physmem_size > size) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1597 |
size += (physmem_size - size) / 2; |
3290 | 1598 |
} |
1599 |
segziosize = mmu_btop(ROUND_UP_LPAGE(size)); |
|
1600 |
} |
|
3446 | 1601 |
PRM_DEBUG(segziosize); |
1602 |
PRM_DEBUG(segzio_base); |
|
3290 | 1603 |
|
0 | 1604 |
/* |
3446 | 1605 |
* Put the range of VA for device mappings next, kmdb knows to not |
1606 |
* grep in this range of addresses. |
|
0 | 1607 |
*/ |
3446 | 1608 |
toxic_addr = |
1609 |
ROUND_UP_LPAGE((uintptr_t)segzio_base + mmu_ptob(segziosize)); |
|
0 | 1610 |
PRM_DEBUG(toxic_addr); |
3446 | 1611 |
segmap_start = ROUND_UP_LPAGE(toxic_addr + toxic_size); |
1612 |
#else /* __i386 */ |
|
1613 |
segmap_start = ROUND_UP_LPAGE(kernelbase); |
|
1614 |
#endif /* __i386 */ |
|
1615 |
PRM_DEBUG(segmap_start); |
|
0 | 1616 |
|
1617 |
/* |
|
1618 |
* Users can change segmapsize through eeprom or /etc/system. |
|
1619 |
* If the variable is tuned through eeprom, there is no upper |
|
1620 |
* bound on the size of segmap. If it is tuned through |
|
1621 |
* /etc/system on 32-bit systems, it must be no larger than we |
|
1622 |
* planned for in startup_memlist(). |
|
1623 |
*/ |
|
1624 |
segmapsize = MAX(ROUND_UP_LPAGE(segmapsize), SEGMAPDEFAULT); |
|
1625 |
||
1626 |
#if defined(__i386) |
|
1627 |
/* |
|
1628 |
* 32-bit systems don't have segkpm or segkp, so segmap appears at |
|
1629 |
* the bottom of the kernel's address range. Set aside space for a |
|
3446 | 1630 |
* small red zone just below the start of segmap. |
0 | 1631 |
*/ |
3446 | 1632 |
segmap_start += KERNEL_REDZONE_SIZE; |
0 | 1633 |
segmapsize -= KERNEL_REDZONE_SIZE; |
1634 |
#endif |
|
3446 | 1635 |
|
1636 |
PRM_DEBUG(segmap_start); |
|
1637 |
PRM_DEBUG(segmapsize); |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1638 |
kernelheap = (caddr_t)ROUND_UP_LPAGE(segmap_start + segmapsize); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1639 |
PRM_DEBUG(kernelheap); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1640 |
PRM_POINT("layout_kernel_va() done..."); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1641 |
} |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1642 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1643 |
/* |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1644 |
* Finish initializing the VM system, now that we are no longer |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1645 |
* relying on the boot time memory allocators. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1646 |
*/ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1647 |
static void |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1648 |
startup_vm(void) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1649 |
{ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1650 |
struct segmap_crargs a; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1651 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1652 |
extern int use_brk_lpg, use_stk_lpg; |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1653 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1654 |
PRM_POINT("startup_vm() starting..."); |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1655 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1656 |
/* |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1657 |
* Initialize the hat layer. |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1658 |
*/ |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1659 |
hat_init(); |
3446 | 1660 |
|
1661 |
/* |
|
1662 |
* Do final allocations of HAT data structures that need to |
|
1663 |
* be allocated before quiescing the boot loader. |
|
1664 |
*/ |
|
1665 |
PRM_POINT("Calling hat_kern_alloc()..."); |
|
1666 |
hat_kern_alloc((caddr_t)segmap_start, segmapsize, ekernelheap); |
|
1667 |
PRM_POINT("hat_kern_alloc() done"); |
|
1668 |
||
5084 | 1669 |
#ifndef __xpv |
3446 | 1670 |
/* |
1671 |
* Setup MTRR (Memory type range registers) |
|
1672 |
*/ |
|
1673 |
setup_mtrr(); |
|
5084 | 1674 |
#endif |
3446 | 1675 |
|
1676 |
/* |
|
1677 |
* The next two loops are done in distinct steps in order |
|
1678 |
* to be sure that any page that is doubly mapped (both above |
|
1679 |
* KERNEL_TEXT and below kernelbase) is dealt with correctly. |
|
1680 |
* Note this may never happen, but it might someday. |
|
1681 |
*/ |
|
1682 |
bootpages = NULL; |
|
1683 |
PRM_POINT("Protecting boot pages"); |
|
0 | 1684 |
|
3446 | 1685 |
/* |
1686 |
* Protect any pages mapped above KERNEL_TEXT that somehow have |
|
1687 |
* page_t's. This can only happen if something weird allocated |
|
1688 |
* in this range (like kadb/kmdb). |
|
1689 |
*/ |
|
1690 |
protect_boot_range(KERNEL_TEXT, (uintptr_t)-1, 0); |
|
1691 |
||
1692 |
/* |
|
1693 |
* Before we can take over memory allocation/mapping from the boot |
|
1694 |
* loader we must remove from our free page lists any boot allocated |
|
1695 |
* pages that stay mapped until release_bootstrap(). |
|
1696 |
*/ |
|
1697 |
protect_boot_range(0, kernelbase, 1); |
|
1698 |
||
5084 | 1699 |
|
3446 | 1700 |
/* |
1701 |
* Switch to running on regular HAT (not boot_mmu) |
|
1702 |
*/ |
|
1703 |
PRM_POINT("Calling hat_kern_setup()..."); |
|
1704 |
hat_kern_setup(); |
|
1705 |
||
1706 |
/* |
|
1707 |
* It is no longer safe to call BOP_ALLOC(), so make sure we don't. |
|
1708 |
*/ |
|
1709 |
bop_no_more_mem(); |
|
1710 |
||
1711 |
PRM_POINT("hat_kern_setup() done"); |
|
1712 |
||
1713 |
hat_cpu_online(CPU); |
|
0 | 1714 |
|
1715 |
/* |
|
1716 |
* Initialize VM system |
|
1717 |
*/ |
|
1718 |
PRM_POINT("Calling kvm_init()..."); |
|
1719 |
kvm_init(); |
|
1720 |
PRM_POINT("kvm_init() done"); |
|
1721 |
||
1722 |
/* |
|
1723 |
* Tell kmdb that the VM system is now working |
|
1724 |
*/ |
|
1725 |
if (boothowto & RB_DEBUG) |
|
1726 |
kdi_dvec_vmready(); |
|
1727 |
||
5084 | 1728 |
#if defined(__xpv) |
1729 |
/* |
|
1730 |
* Populate the I/O pool on domain 0 |
|
1731 |
*/ |
|
1732 |
if (DOMAIN_IS_INITDOMAIN(xen_info)) { |
|
1733 |
extern long populate_io_pool(void); |
|
1734 |
long init_io_pool_cnt; |
|
1735 |
||
1736 |
PRM_POINT("Populating reserve I/O page pool"); |
|
1737 |
init_io_pool_cnt = populate_io_pool(); |
|
1738 |
PRM_DEBUG(init_io_pool_cnt); |
|
1739 |
} |
|
1740 |
#endif |
|
0 | 1741 |
/* |
1742 |
* Mangle the brand string etc. |
|
1743 |
*/ |
|
1744 |
cpuid_pass3(CPU); |
|
1745 |
||
1746 |
#if defined(__amd64) |
|
1747 |
||
1748 |
/* |
|
1749 |
* Create the device arena for toxic (to dtrace/kmdb) mappings. |
|
1750 |
*/ |
|
1751 |
device_arena = vmem_create("device", (void *)toxic_addr, |
|
1752 |
toxic_size, MMU_PAGESIZE, NULL, NULL, NULL, 0, VM_SLEEP); |
|
1753 |
||
1754 |
#else /* __i386 */ |
|
1755 |
||
1756 |
/* |
|
1757 |
* allocate the bit map that tracks toxic pages |
|
1758 |
*/ |
|
3446 | 1759 |
toxic_bit_map_len = btop((ulong_t)(valloc_base - kernelbase)); |
0 | 1760 |
PRM_DEBUG(toxic_bit_map_len); |
1761 |
toxic_bit_map = |
|
1762 |
kmem_zalloc(BT_SIZEOFMAP(toxic_bit_map_len), KM_NOSLEEP); |
|
1763 |
ASSERT(toxic_bit_map != NULL); |
|
1764 |
PRM_DEBUG(toxic_bit_map); |
|
1765 |
||
1766 |
#endif /* __i386 */ |
|
1767 |
||
1768 |
||
1769 |
/* |
|
1770 |
* Now that we've got more VA, as well as the ability to allocate from |
|
1771 |
* it, tell the debugger. |
|
1772 |
*/ |
|
1773 |
if (boothowto & RB_DEBUG) |
|
1774 |
kdi_dvec_memavail(); |
|
1775 |
||
1776 |
/* |
|
1777 |
* The following code installs a special page fault handler (#pf) |
|
1778 |
* to work around a pentium bug. |
|
1779 |
*/ |
|
5084 | 1780 |
#if !defined(__amd64) && !defined(__xpv) |
0 | 1781 |
if (x86_type == X86_TYPE_P5) { |
3446 | 1782 |
desctbr_t idtr; |
0 | 1783 |
gate_desc_t *newidt; |
3446 | 1784 |
struct machcpu *mcpu = &CPU->cpu_m; |
0 | 1785 |
|
1786 |
if ((newidt = kmem_zalloc(MMU_PAGESIZE, KM_NOSLEEP)) == NULL) |
|
1787 |
panic("failed to install pentium_pftrap"); |
|
1788 |
||
1789 |
bcopy(idt0, newidt, sizeof (idt0)); |
|
1790 |
set_gatesegd(&newidt[T_PGFLT], &pentium_pftrap, |
|
5084 | 1791 |
KCS_SEL, SDT_SYSIGT, TRP_KPL); |
0 | 1792 |
|
1793 |
(void) as_setprot(&kas, (caddr_t)newidt, MMU_PAGESIZE, |
|
1794 |
PROT_READ|PROT_EXEC); |
|
1795 |
||
3446 | 1796 |
mcpu->mcpu_idt = newidt; |
1797 |
idtr.dtr_base = (uintptr_t)mcpu->mcpu_idt; |
|
1798 |
idtr.dtr_limit = sizeof (idt0) - 1; |
|
1799 |
wr_idtr(&idtr); |
|
0 | 1800 |
} |
1801 |
#endif /* !__amd64 */ |
|
1802 |
||
5084 | 1803 |
#if !defined(__xpv) |
0 | 1804 |
/* |
1805 |
* Map page pfn=0 for drivers, such as kd, that need to pick up |
|
1806 |
* parameters left there by controllers/BIOS. |
|
1807 |
*/ |
|
1808 |
PRM_POINT("setup up p0_va"); |
|
1809 |
p0_va = i86devmap(0, 1, PROT_READ); |
|
1810 |
PRM_DEBUG(p0_va); |
|
5084 | 1811 |
#endif |
0 | 1812 |
|
1813 |
cmn_err(CE_CONT, "?mem = %luK (0x%lx)\n", |
|
1814 |
physinstalled << (MMU_PAGESHIFT - 10), ptob(physinstalled)); |
|
1815 |
||
841
814b4a127357
6344639 system spends all its time trying and failing to make big pages
kchow
parents:
810
diff
changeset
|
1816 |
/* |
814b4a127357
6344639 system spends all its time trying and failing to make big pages
kchow
parents:
810
diff
changeset
|
1817 |
* disable automatic large pages for small memory systems or |
814b4a127357
6344639 system spends all its time trying and failing to make big pages
kchow
parents:
810
diff
changeset
|
1818 |
* when the disable flag is set. |
814b4a127357
6344639 system spends all its time trying and failing to make big pages
kchow
parents:
810
diff
changeset
|
1819 |
*/ |
2991
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1820 |
if (!auto_lpg_disable && mmu.max_page_level > 0) { |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1821 |
max_uheap_lpsize = LEVEL_SIZE(1); |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1822 |
max_ustack_lpsize = LEVEL_SIZE(1); |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1823 |
max_privmap_lpsize = LEVEL_SIZE(1); |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1824 |
max_uidata_lpsize = LEVEL_SIZE(1); |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1825 |
max_utext_lpsize = LEVEL_SIZE(1); |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1826 |
max_shm_lpsize = LEVEL_SIZE(1); |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1827 |
} |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1828 |
if (physmem < privm_lpg_min_physmem || mmu.max_page_level == 0 || |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1829 |
auto_lpg_disable) { |
423
6cbc492798ce
6294795 The behavior of malloc is different between solaris 10 and nevada
davemq
parents:
0
diff
changeset
|
1830 |
use_brk_lpg = 0; |
6cbc492798ce
6294795 The behavior of malloc is different between solaris 10 and nevada
davemq
parents:
0
diff
changeset
|
1831 |
use_stk_lpg = 0; |
2991
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1832 |
} |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1833 |
if (mmu.max_page_level > 0) { |
4b13d6c49c6b
6254029 memcntl() MC_HAT_ADVISE with page size 0 may cause segment page sizes to be demoted
susans
parents:
2712
diff
changeset
|
1834 |
mcntl0_lpsize = LEVEL_SIZE(1); |
423
6cbc492798ce
6294795 The behavior of malloc is different between solaris 10 and nevada
davemq
parents:
0
diff
changeset
|
1835 |
} |
6cbc492798ce
6294795 The behavior of malloc is different between solaris 10 and nevada
davemq
parents:
0
diff
changeset
|
1836 |
|
0 | 1837 |
PRM_POINT("Calling hat_init_finish()..."); |
1838 |
hat_init_finish(); |
|
1839 |
PRM_POINT("hat_init_finish() done"); |
|
1840 |
||
1841 |
/* |
|
1842 |
* Initialize the segkp segment type. |
|
1843 |
*/ |
|
1844 |
rw_enter(&kas.a_lock, RW_WRITER); |
|
3446 | 1845 |
PRM_POINT("Attaching segkp"); |
1846 |
if (segkp_fromheap) { |
|
0 | 1847 |
segkp->s_as = &kas; |
3446 | 1848 |
} else if (seg_attach(&kas, (caddr_t)segkp_base, mmu_ptob(segkpsize), |
1849 |
segkp) < 0) { |
|
1850 |
panic("startup: cannot attach segkp"); |
|
1851 |
/*NOTREACHED*/ |
|
0 | 1852 |
} |
3446 | 1853 |
PRM_POINT("Doing segkp_create()"); |
0 | 1854 |
if (segkp_create(segkp) != 0) { |
1855 |
panic("startup: segkp_create failed"); |
|
1856 |
/*NOTREACHED*/ |
|
1857 |
} |
|
1858 |
PRM_DEBUG(segkp); |
|
1859 |
rw_exit(&kas.a_lock); |
|
1860 |
||
1861 |
/* |
|
1862 |
* kpm segment |
|
1863 |
*/ |
|
1864 |
segmap_kpm = 0; |
|
1865 |
if (kpm_desired) { |
|
1866 |
kpm_init(); |
|
1867 |
kpm_enable = 1; |
|
1841
9d7ebafcda38
6256083 Need a lightweight file page mapping mechanism to substitute segmap
praks
parents:
1676
diff
changeset
|
1868 |
vpm_enable = 1; |
0 | 1869 |
} |
1870 |
||
1871 |
/* |
|
1872 |
* Now create segmap segment. |
|
1873 |
*/ |
|
1874 |
rw_enter(&kas.a_lock, RW_WRITER); |
|
3446 | 1875 |
if (seg_attach(&kas, (caddr_t)segmap_start, segmapsize, segmap) < 0) { |
1876 |
panic("cannot attach segmap"); |
|
0 | 1877 |
/*NOTREACHED*/ |
1878 |
} |
|
3446 | 1879 |
PRM_DEBUG(segmap); |
0 | 1880 |
|
1881 |
a.prot = PROT_READ | PROT_WRITE; |
|
1882 |
a.shmsize = 0; |
|
1883 |
a.nfreelist = segmapfreelists; |
|
1884 |
||
3446 | 1885 |
if (segmap_create(segmap, (caddr_t)&a) != 0) |
1886 |
panic("segmap_create segmap"); |
|
0 | 1887 |
rw_exit(&kas.a_lock); |
1888 |
||
1889 |
setup_vaddr_for_ppcopy(CPU); |
|
1890 |
||
1891 |
segdev_init(); |
|
5084 | 1892 |
#if defined(__xpv) |
1893 |
if (DOMAIN_IS_INITDOMAIN(xen_info)) |
|
1894 |
#endif |
|
1895 |
pmem_init(); |
|
3446 | 1896 |
|
0 | 1897 |
PRM_POINT("startup_vm() done"); |
1898 |
} |
|
1899 |
||
3446 | 1900 |
/* |
1901 |
* Load a tod module for the non-standard tod part found on this system. |
|
1902 |
*/ |
|
1903 |
static void |
|
1904 |
load_tod_module(char *todmod) |
|
1905 |
{ |
|
1906 |
if (modload("tod", todmod) == -1) |
|
1907 |
halt("Can't load TOD module"); |
|
1908 |
} |
|
1909 |
||
0 | 1910 |
static void |
1911 |
startup_end(void) |
|
1912 |
{ |
|
5107 | 1913 |
int i; |
0 | 1914 |
extern void setx86isalist(void); |
1915 |
||
1916 |
PRM_POINT("startup_end() starting..."); |
|
1917 |
||
1918 |
/* |
|
1919 |
* Perform tasks that get done after most of the VM |
|
1920 |
* initialization has been done but before the clock |
|
1921 |
* and other devices get started. |
|
1922 |
*/ |
|
1923 |
kern_setup1(); |
|
1924 |
||
1925 |
/* |
|
1926 |
* Perform CPC initialization for this CPU. |
|
1927 |
*/ |
|
1928 |
kcpc_hw_init(CPU); |
|
1929 |
||
1582
eb879d43ab47
6323525 Mutual exclusion primitives don't work as expected on Opteron systems
kchow
parents:
1494
diff
changeset
|
1930 |
#if defined(OPTERON_WORKAROUND_6323525) |
eb879d43ab47
6323525 Mutual exclusion primitives don't work as expected on Opteron systems
kchow
parents:
1494
diff
changeset
|
1931 |
if (opteron_workaround_6323525) |
eb879d43ab47
6323525 Mutual exclusion primitives don't work as expected on Opteron systems
kchow
parents:
1494
diff
changeset
|
1932 |
patch_workaround_6323525(); |
eb879d43ab47
6323525 Mutual exclusion primitives don't work as expected on Opteron systems
kchow
parents:
1494
diff
changeset
|
1933 |
#endif |
0 | 1934 |
/* |
3446 | 1935 |
* If needed, load TOD module now so that ddi_get_time(9F) etc. work |
1936 |
* (For now, "needed" is defined as set tod_module_name in /etc/system) |
|
1937 |
*/ |
|
1938 |
if (tod_module_name != NULL) { |
|
1939 |
PRM_POINT("load_tod_module()"); |
|
1940 |
load_tod_module(tod_module_name); |
|
1941 |
} |
|
1942 |
||
5084 | 1943 |
#if defined(__xpv) |
1944 |
/* |
|
1945 |
* Forceload interposing TOD module for the hypervisor. |
|
1946 |
*/ |
|
1947 |
PRM_POINT("load_tod_module()"); |
|
1948 |
load_tod_module("xpvtod"); |
|
1949 |
#endif |
|
1950 |
||
3446 | 1951 |
/* |
0 | 1952 |
* Configure the system. |
1953 |
*/ |
|
1954 |
PRM_POINT("Calling configure()..."); |
|
1955 |
configure(); /* set up devices */ |
|
1956 |
PRM_POINT("configure() done"); |
|
1957 |
||
1958 |
/* |
|
1959 |
* Set the isa_list string to the defined instruction sets we |
|
1960 |
* support. |
|
1961 |
*/ |
|
1962 |
setx86isalist(); |
|
1455
b43f098fa50c
6378953 allocation of interrupt threads could be more common
andrei
parents:
1417
diff
changeset
|
1963 |
cpu_intr_alloc(CPU, NINTR_THREADS); |
0 | 1964 |
psm_install(); |
1965 |
||
1966 |
/* |
|
1967 |
* We're done with bootops. We don't unmap the bootstrap yet because |
|
1968 |
* we're still using bootsvcs. |
|
1969 |
*/ |
|
3446 | 1970 |
PRM_POINT("NULLing out bootops"); |
1971 |
*bootopsp = (struct bootops *)NULL; |
|
0 | 1972 |
bootops = (struct bootops *)NULL; |
1973 |
||
5084 | 1974 |
#if defined(__xpv) |
1975 |
ec_init_debug_irq(); |
|
1976 |
xs_domu_init(); |
|
1977 |
#endif |
|
0 | 1978 |
PRM_POINT("Enabling interrupts"); |
1979 |
(*picinitf)(); |
|
1980 |
sti(); |
|
5084 | 1981 |
#if defined(__xpv) |
1982 |
ASSERT(CPU->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask == 0); |
|
1983 |
xen_late_startup(); |
|
1984 |
#endif |
|
0 | 1985 |
|
1986 |
(void) add_avsoftintr((void *)&softlevel1_hdl, 1, softlevel1, |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
1987 |
"softlevel1", NULL, NULL); /* XXX to be moved later */ |
0 | 1988 |
|
5107 | 1989 |
/* |
1990 |
* Register these software interrupts for ddi timer. |
|
1991 |
* Software interrupts up to the level 10 are supported. |
|
1992 |
*/ |
|
1993 |
for (i = DDI_IPL_1; i <= DDI_IPL_10; i++) { |
|
1994 |
char name[sizeof ("timer_softintr") + 2]; |
|
1995 |
(void) sprintf(name, "timer_softintr%02d", i); |
|
1996 |
(void) add_avsoftintr((void *)&softlevel_hdl[i-1], i, |
|
1997 |
(avfunc)timer_softintr, name, (caddr_t)(uintptr_t)i, NULL); |
|
1998 |
} |
|
1999 |
||
0 | 2000 |
PRM_POINT("startup_end() done"); |
2001 |
} |
|
2002 |
||
2003 |
extern char hw_serial[]; |
|
2004 |
char *_hs1107 = hw_serial; |
|
2005 |
ulong_t _bdhs34; |
|
2006 |
||
2007 |
void |
|
2008 |
post_startup(void) |
|
2009 |
{ |
|
2010 |
/* |
|
2011 |
* Set the system wide, processor-specific flags to be passed |
|
2012 |
* to userland via the aux vector for performance hints and |
|
2013 |
* instruction set extensions. |
|
2014 |
*/ |
|
2015 |
bind_hwcap(); |
|
2016 |
||
5084 | 2017 |
#ifdef __xpv |
2018 |
if (DOMAIN_IS_INITDOMAIN(xen_info)) |
|
2019 |
#endif |
|
2020 |
{ |
|
2021 |
/* |
|
2022 |
* Load the System Management BIOS into the global ksmbios |
|
2023 |
* handle, if an SMBIOS is present on this system. |
|
2024 |
*/ |
|
2025 |
ksmbios = smbios_open(NULL, SMB_VERSION, ksmbios_flags, NULL); |
|
2026 |
||
2027 |
#if defined(__xpv) |
|
2028 |
xpv_panic_init(); |
|
2029 |
#else |
|
2030 |
/* |
|
2031 |
* Startup the memory scrubber. |
|
2032 |
* XXPV This should be running somewhere .. |
|
2033 |
*/ |
|
2034 |
memscrub_init(); |
|
2035 |
#endif |
|
2036 |
} |
|
0 | 2037 |
|
2038 |
/* |
|
1414
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
2039 |
* Complete CPU module initialization |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
2040 |
*/ |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
2041 |
cmi_post_init(); |
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
2042 |
|
b4126407ac5b
PSARC 2006/020 FMA for Athlon 64 and Opteron Processors
cindi
parents:
851
diff
changeset
|
2043 |
/* |
0 | 2044 |
* Perform forceloading tasks for /etc/system. |
2045 |
*/ |
|
2046 |
(void) mod_sysctl(SYS_FORCELOAD, NULL); |
|
2047 |
||
2048 |
/* |
|
2049 |
* ON4.0: Force /proc module in until clock interrupt handle fixed |
|
2050 |
* ON4.0: This must be fixed or restated in /etc/systems. |
|
2051 |
*/ |
|
2052 |
(void) modload("fs", "procfs"); |
|
2053 |
||
5129 | 2054 |
(void) i_ddi_attach_hw_nodes("pit_beep"); |
2055 |
||
0 | 2056 |
#if defined(__i386) |
2057 |
/* |
|
2058 |
* Check for required functional Floating Point hardware, |
|
2059 |
* unless FP hardware explicitly disabled. |
|
2060 |
*/ |
|
2061 |
if (fpu_exists && (fpu_pentium_fdivbug || fp_kind == FP_NO)) |
|
2062 |
halt("No working FP hardware found"); |
|
2063 |
#endif |
|
2064 |
||
2065 |
maxmem = freemem; |
|
2066 |
||
2067 |
add_cpunode2devtree(CPU->cpu_id, CPU->cpu_m.mcpu_cpi); |
|
2068 |
} |
|
2069 |
||
2070 |
static int |
|
2071 |
pp_in_ramdisk(page_t *pp) |
|
2072 |
{ |
|
2073 |
extern uint64_t ramdisk_start, ramdisk_end; |
|
2074 |
||
2075 |
return ((pp->p_pagenum >= btop(ramdisk_start)) && |
|
2076 |
(pp->p_pagenum < btopr(ramdisk_end))); |
|
2077 |
} |
|
2078 |
||
2079 |
void |
|
2080 |
release_bootstrap(void) |
|
2081 |
{ |
|
2082 |
int root_is_ramdisk; |
|
2083 |
page_t *pp; |
|
2084 |
extern void kobj_boot_unmountroot(void); |
|
2085 |
extern dev_t rootdev; |
|
2086 |
||
2087 |
/* unmount boot ramdisk and release kmem usage */ |
|
2088 |
kobj_boot_unmountroot(); |
|
2089 |
||
2090 |
/* |
|
2091 |
* We're finished using the boot loader so free its pages. |
|
2092 |
*/ |
|
2093 |
PRM_POINT("Unmapping lower boot pages"); |
|
3446 | 2094 |
clear_boot_mappings(0, _userlimit); |
2095 |
postbootkernelbase = kernelbase; |
|
0 | 2096 |
|
2097 |
/* |
|
2098 |
* If root isn't on ramdisk, destroy the hardcoded |
|
2099 |
* ramdisk node now and release the memory. Else, |
|
2100 |
* ramdisk memory is kept in rd_pages. |
|
2101 |
*/ |
|
2102 |
root_is_ramdisk = (getmajor(rootdev) == ddi_name_to_major("ramdisk")); |
|
2103 |
if (!root_is_ramdisk) { |
|
2104 |
dev_info_t *dip = ddi_find_devinfo("ramdisk", -1, 0); |
|
2105 |
ASSERT(dip && ddi_get_parent(dip) == ddi_root_node()); |
|
2106 |
ndi_rele_devi(dip); /* held from ddi_find_devinfo */ |
|
2107 |
(void) ddi_remove_child(dip, 0); |
|
2108 |
} |
|
2109 |
||
2110 |
PRM_POINT("Releasing boot pages"); |
|
2111 |
while (bootpages) { |
|
2112 |
pp = bootpages; |
|
2113 |
bootpages = pp->p_next; |
|
2114 |
if (root_is_ramdisk && pp_in_ramdisk(pp)) { |
|
2115 |
pp->p_next = rd_pages; |
|
2116 |
rd_pages = pp; |
|
2117 |
continue; |
|
2118 |
} |
|
2119 |
pp->p_next = (struct page *)0; |
|
3446 | 2120 |
pp->p_prev = (struct page *)0; |
2121 |
PP_CLRBOOTPAGES(pp); |
|
0 | 2122 |
page_free(pp, 1); |
2123 |
} |
|
3446 | 2124 |
PRM_POINT("Boot pages released"); |
0 | 2125 |
|
5084 | 2126 |
#if !defined(__xpv) |
2127 |
/* XXPV -- note this following bunch of code needs to be revisited in Xen 3.0 */ |
|
0 | 2128 |
/* |
2129 |
* Find 1 page below 1 MB so that other processors can boot up. |
|
2130 |
* Make sure it has a kernel VA as well as a 1:1 mapping. |
|
2131 |
* We should have just free'd one up. |
|
2132 |
*/ |
|
2133 |
if (use_mp) { |
|
3446 | 2134 |
pfn_t pfn; |
2135 |
||
0 | 2136 |
for (pfn = 1; pfn < btop(1*1024*1024); pfn++) { |
2137 |
if (page_numtopp_alloc(pfn) == NULL) |
|
2138 |
continue; |
|
2139 |
rm_platter_va = i86devmap(pfn, 1, |
|
2140 |
PROT_READ | PROT_WRITE | PROT_EXEC); |
|
2141 |
rm_platter_pa = ptob(pfn); |
|
2142 |
hat_devload(kas.a_hat, |
|
2143 |
(caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE, |
|
2144 |
pfn, PROT_READ | PROT_WRITE | PROT_EXEC, |
|
2145 |
HAT_LOAD_NOCONSIST); |
|
2146 |
break; |
|
2147 |
} |
|
2148 |
if (pfn == btop(1*1024*1024)) |
|
2149 |
panic("No page available for starting " |
|
2150 |
"other processors"); |
|
2151 |
} |
|
5084 | 2152 |
#endif /* !__xpv */ |
0 | 2153 |
} |
2154 |
||
2155 |
/* |
|
2156 |
* Initialize the platform-specific parts of a page_t. |
|
2157 |
*/ |
|
2158 |
void |
|
2159 |
add_physmem_cb(page_t *pp, pfn_t pnum) |
|
2160 |
{ |
|
2161 |
pp->p_pagenum = pnum; |
|
2162 |
pp->p_mapping = NULL; |
|
2163 |
pp->p_embed = 0; |
|
2164 |
pp->p_share = 0; |
|
2165 |
pp->p_mlentry = 0; |
|
2166 |
} |
|
2167 |
||
2168 |
/* |
|
2169 |
* kphysm_init() initializes physical memory. |
|
2170 |
*/ |
|
2171 |
static pgcnt_t |
|
2172 |
kphysm_init( |
|
3446 | 2173 |
page_t *pp, |
0 | 2174 |
pgcnt_t npages) |
2175 |
{ |
|
2176 |
struct memlist *pmem; |
|
2177 |
struct memseg *cur_memseg; |
|
2178 |
pfn_t base_pfn; |
|
2179 |
pgcnt_t num; |
|
2180 |
pgcnt_t pages_done = 0; |
|
2181 |
uint64_t addr; |
|
2182 |
uint64_t size; |
|
2183 |
extern pfn_t ddiphysmin; |
|
2184 |
||
2185 |
ASSERT(page_hash != NULL && page_hashsz != 0); |
|
2186 |
||
3446 | 2187 |
cur_memseg = memseg_base; |
0 | 2188 |
for (pmem = phys_avail; pmem && npages; pmem = pmem->next) { |
2189 |
/* |
|
2190 |
* In a 32 bit kernel can't use higher memory if we're |
|
2191 |
* not booting in PAE mode. This check takes care of that. |
|
2192 |
*/ |
|
2193 |
addr = pmem->address; |
|
2194 |
size = pmem->size; |
|
2195 |
if (btop(addr) > physmax) |
|
2196 |
continue; |
|
2197 |
||
2198 |
/* |
|
2199 |
* align addr and size - they may not be at page boundaries |
|
2200 |
*/ |
|
2201 |
if ((addr & MMU_PAGEOFFSET) != 0) { |
|
2202 |
addr += MMU_PAGEOFFSET; |
|
2203 |
addr &= ~(uint64_t)MMU_PAGEOFFSET; |
|
2204 |
size -= addr - pmem->address; |
|
2205 |
} |
|
2206 |
||
810
b238ce84deac
6342422 kernel panic with patch 118844-19 on Gateway 600YG
kchow
parents:
783
diff
changeset
|
2207 |
/* only process pages below or equal to physmax */ |
b238ce84deac
6342422 kernel panic with patch 118844-19 on Gateway 600YG
kchow
parents:
783
diff
changeset
|
2208 |
if ((btop(addr + size) - 1) > physmax) |
b238ce84deac
6342422 kernel panic with patch 118844-19 on Gateway 600YG
kchow
parents:
783
diff
changeset
|
2209 |
size = ptob(physmax - btop(addr) + 1); |
0 | 2210 |
|
2211 |
num = btop(size); |
|
2212 |
if (num == 0) |
|
2213 |
continue; |
|
2214 |
||
2215 |
if (num > npages) |
|
2216 |
num = npages; |
|
2217 |
||
2218 |
npages -= num; |
|
2219 |
pages_done += num; |
|
2220 |
base_pfn = btop(addr); |
|
2221 |
||
2222 |
if (prom_debug) |
|
2223 |
prom_printf("MEMSEG addr=0x%" PRIx64 |
|
2224 |
" pgs=0x%lx pfn 0x%lx-0x%lx\n", |
|
2225 |
addr, num, base_pfn, base_pfn + num); |
|
2226 |
||
2227 |
/* |
|
3446 | 2228 |
* Ignore pages below ddiphysmin to simplify ddi memory |
0 | 2229 |
* allocation with non-zero addr_lo requests. |
2230 |
*/ |
|
2231 |
if (base_pfn < ddiphysmin) { |
|
3446 | 2232 |
if (base_pfn + num <= ddiphysmin) |
0 | 2233 |
continue; |
2234 |
pp += (ddiphysmin - base_pfn); |
|
2235 |
num -= (ddiphysmin - base_pfn); |
|
2236 |
base_pfn = ddiphysmin; |
|
2237 |
} |
|
3446 | 2238 |
|
0 | 2239 |
/* |
2240 |
* Build the memsegs entry |
|
2241 |
*/ |
|
2242 |
cur_memseg->pages = pp; |
|
2243 |
cur_memseg->epages = pp + num; |
|
2244 |
cur_memseg->pages_base = base_pfn; |
|
2245 |
cur_memseg->pages_end = base_pfn + num; |
|
2246 |
||
2247 |
/* |
|
3446 | 2248 |
* Insert into memseg list in decreasing pfn range order. |
0 | 2249 |
* Low memory is typically more fragmented such that this |
2250 |
* ordering keeps the larger ranges at the front of the list |
|
2251 |
* for code that searches memseg. |
|
3446 | 2252 |
* This ASSERTS that the memsegs coming in from boot are in |
2253 |
* increasing physical address order and not contiguous. |
|
0 | 2254 |
*/ |
3446 | 2255 |
if (memsegs != NULL) { |
2256 |
ASSERT(cur_memseg->pages_base >= memsegs->pages_end); |
|
2257 |
cur_memseg->next = memsegs; |
|
0 | 2258 |
} |
3446 | 2259 |
memsegs = cur_memseg; |
0 | 2260 |
|
2261 |
/* |
|
2262 |
* add_physmem() initializes the PSM part of the page |
|
2263 |
* struct by calling the PSM back with add_physmem_cb(). |
|
2264 |
* In addition it coalesces pages into larger pages as |
|
2265 |
* it initializes them. |
|
2266 |
*/ |
|
2267 |
add_physmem(pp, num, base_pfn); |
|
2268 |
cur_memseg++; |
|
2269 |
availrmem_initial += num; |
|
2270 |
availrmem += num; |
|
2271 |
||
3446 | 2272 |
pp += num; |
0 | 2273 |
} |
2274 |
||
2275 |
PRM_DEBUG(availrmem_initial); |
|
2276 |
PRM_DEBUG(availrmem); |
|
2277 |
PRM_DEBUG(freemem); |
|
2278 |
build_pfn_hash(); |
|
2279 |
return (pages_done); |
|
2280 |
} |
|
2281 |
||
2282 |
/* |
|
2283 |
* Kernel VM initialization. |
|
2284 |
*/ |
|
2285 |
static void |
|
2286 |
kvm_init(void) |
|
2287 |
{ |
|
2288 |
ASSERT((((uintptr_t)s_text) & MMU_PAGEOFFSET) == 0); |
|
2289 |
||
2290 |
/* |
|
2291 |
* Put the kernel segments in kernel address space. |
|
2292 |
*/ |
|
2293 |
rw_enter(&kas.a_lock, RW_WRITER); |
|
2294 |
as_avlinit(&kas); |
|
2295 |
||
2296 |
(void) seg_attach(&kas, s_text, e_moddata - s_text, &ktextseg); |
|
2297 |
(void) segkmem_create(&ktextseg); |
|
2298 |
||
2299 |
(void) seg_attach(&kas, (caddr_t)valloc_base, valloc_sz, &kvalloc); |
|
2300 |
(void) segkmem_create(&kvalloc); |
|
2301 |
||
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2302 |
(void) seg_attach(&kas, kernelheap, |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2303 |
ekernelheap - kernelheap, &kvseg); |
0 | 2304 |
(void) segkmem_create(&kvseg); |
2305 |
||
3446 | 2306 |
if (core_size > 0) { |
2307 |
PRM_POINT("attaching kvseg_core"); |
|
2308 |
(void) seg_attach(&kas, (caddr_t)core_base, core_size, |
|
2309 |
&kvseg_core); |
|
2310 |
(void) segkmem_create(&kvseg_core); |
|
2311 |
} |
|
3290 | 2312 |
|
3446 | 2313 |
if (segziosize > 0) { |
2314 |
PRM_POINT("attaching segzio"); |
|
3290 | 2315 |
(void) seg_attach(&kas, segzio_base, mmu_ptob(segziosize), |
2316 |
&kzioseg); |
|
2317 |
(void) segkmem_zio_create(&kzioseg); |
|
2318 |
||
2319 |
/* create zio area covering new segment */ |
|
2320 |
segkmem_zio_init(segzio_base, mmu_ptob(segziosize)); |
|
2321 |
} |
|
0 | 2322 |
|
3446 | 2323 |
(void) seg_attach(&kas, kdi_segdebugbase, kdi_segdebugsize, &kdebugseg); |
0 | 2324 |
(void) segkmem_create(&kdebugseg); |
2325 |
||
2326 |
rw_exit(&kas.a_lock); |
|
2327 |
||
2328 |
/* |
|
2329 |
* Ensure that the red zone at kernelbase is never accessible. |
|
2330 |
*/ |
|
3446 | 2331 |
PRM_POINT("protecting redzone"); |
0 | 2332 |
(void) as_setprot(&kas, (caddr_t)kernelbase, KERNEL_REDZONE_SIZE, 0); |
2333 |
||
2334 |
/* |
|
2335 |
* Make the text writable so that it can be hot patched by DTrace. |
|
2336 |
*/ |
|
2337 |
(void) as_setprot(&kas, s_text, e_modtext - s_text, |
|
2338 |
PROT_READ | PROT_WRITE | PROT_EXEC); |
|
2339 |
||
2340 |
/* |
|
2341 |
* Make data writable until end. |
|
2342 |
*/ |
|
2343 |
(void) as_setprot(&kas, s_data, e_moddata - s_data, |
|
2344 |
PROT_READ | PROT_WRITE | PROT_EXEC); |
|
2345 |
} |
|
2346 |
||
5084 | 2347 |
#ifndef __xpv |
0 | 2348 |
/* |
2349 |
* These are MTTR registers supported by P6 |
|
2350 |
*/ |
|
2351 |
static struct mtrrvar mtrrphys_arr[MAX_MTRRVAR]; |
|
2352 |
static uint64_t mtrr64k, mtrr16k1, mtrr16k2; |
|
2353 |
static uint64_t mtrr4k1, mtrr4k2, mtrr4k3; |
|
2354 |
static uint64_t mtrr4k4, mtrr4k5, mtrr4k6; |
|
2355 |
static uint64_t mtrr4k7, mtrr4k8, mtrrcap; |
|
2356 |
uint64_t mtrrdef, pat_attr_reg; |
|
2357 |
||
2358 |
/* |
|
2359 |
* Disable reprogramming of MTRRs by default. |
|
2360 |
*/ |
|
2361 |
int enable_relaxed_mtrr = 0; |
|
2362 |
||
2363 |
void |
|
1676 | 2364 |
setup_mtrr(void) |
0 | 2365 |
{ |
2366 |
int i, ecx; |
|
2367 |
int vcnt; |
|
2368 |
struct mtrrvar *mtrrphys; |
|
2369 |
||
2370 |
if (!(x86_feature & X86_MTRR)) |
|
2371 |
return; |
|
2372 |
||
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2373 |
mtrrcap = rdmsr(REG_MTRRCAP); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2374 |
mtrrdef = rdmsr(REG_MTRRDEF); |
0 | 2375 |
if (mtrrcap & MTRRCAP_FIX) { |
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2376 |
mtrr64k = rdmsr(REG_MTRR64K); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2377 |
mtrr16k1 = rdmsr(REG_MTRR16K1); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2378 |
mtrr16k2 = rdmsr(REG_MTRR16K2); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2379 |
mtrr4k1 = rdmsr(REG_MTRR4K1); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2380 |
mtrr4k2 = rdmsr(REG_MTRR4K2); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2381 |
mtrr4k3 = rdmsr(REG_MTRR4K3); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2382 |
mtrr4k4 = rdmsr(REG_MTRR4K4); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2383 |
mtrr4k5 = rdmsr(REG_MTRR4K5); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2384 |
mtrr4k6 = rdmsr(REG_MTRR4K6); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2385 |
mtrr4k7 = rdmsr(REG_MTRR4K7); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2386 |
mtrr4k8 = rdmsr(REG_MTRR4K8); |
0 | 2387 |
} |
2388 |
if ((vcnt = (mtrrcap & MTRRCAP_VCNTMASK)) > MAX_MTRRVAR) |
|
2389 |
vcnt = MAX_MTRRVAR; |
|
2390 |
||
2391 |
for (i = 0, ecx = REG_MTRRPHYSBASE0, mtrrphys = mtrrphys_arr; |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2392 |
i < vcnt - 1; i++, ecx += 2, mtrrphys++) { |
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2393 |
mtrrphys->mtrrphys_base = rdmsr(ecx); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2394 |
mtrrphys->mtrrphys_mask = rdmsr(ecx + 1); |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2395 |
if ((x86_feature & X86_PAT) && enable_relaxed_mtrr) |
0 | 2396 |
mtrrphys->mtrrphys_mask &= ~MTRRPHYSMASK_V; |
2397 |
} |
|
2398 |
if (x86_feature & X86_PAT) { |
|
2399 |
if (enable_relaxed_mtrr) |
|
2400 |
mtrrdef = MTRR_TYPE_WB|MTRRDEF_FE|MTRRDEF_E; |
|
2401 |
pat_attr_reg = PAT_DEFAULT_ATTRIBUTE; |
|
2402 |
} |
|
2403 |
||
2404 |
mtrr_sync(); |
|
2405 |
} |
|
2406 |
||
2407 |
/* |
|
2408 |
* Sync current cpu mtrr with the incore copy of mtrr. |
|
2409 |
* This function has to be invoked with interrupts disabled |
|
2410 |
* Currently we do not capture other cpu's. This is invoked on cpu0 |
|
2411 |
* just after reading /etc/system. |
|
2412 |
* On other cpu's its invoked from mp_startup(). |
|
2413 |
*/ |
|
2414 |
void |
|
1676 | 2415 |
mtrr_sync(void) |
0 | 2416 |
{ |
2417 |
uint_t crvalue, cr0_orig; |
|
2418 |
int vcnt, i, ecx; |
|
2419 |
struct mtrrvar *mtrrphys; |
|
2420 |
||
2421 |
cr0_orig = crvalue = getcr0(); |
|
2422 |
crvalue |= CR0_CD; |
|
2423 |
crvalue &= ~CR0_NW; |
|
2424 |
setcr0(crvalue); |
|
2425 |
invalidate_cache(); |
|
2426 |
||
5084 | 2427 |
#if !defined(__xpv) |
3446 | 2428 |
reload_cr3(); |
5084 | 2429 |
#endif |
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2430 |
if (x86_feature & X86_PAT) |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2431 |
wrmsr(REG_MTRRPAT, pat_attr_reg); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2432 |
|
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2433 |
wrmsr(REG_MTRRDEF, rdmsr(REG_MTRRDEF) & |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2434 |
~((uint64_t)(uintptr_t)MTRRDEF_E)); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2435 |
|
0 | 2436 |
if (mtrrcap & MTRRCAP_FIX) { |
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2437 |
wrmsr(REG_MTRR64K, mtrr64k); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2438 |
wrmsr(REG_MTRR16K1, mtrr16k1); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2439 |
wrmsr(REG_MTRR16K2, mtrr16k2); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2440 |
wrmsr(REG_MTRR4K1, mtrr4k1); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2441 |
wrmsr(REG_MTRR4K2, mtrr4k2); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2442 |
wrmsr(REG_MTRR4K3, mtrr4k3); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2443 |
wrmsr(REG_MTRR4K4, mtrr4k4); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2444 |
wrmsr(REG_MTRR4K5, mtrr4k5); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2445 |
wrmsr(REG_MTRR4K6, mtrr4k6); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2446 |
wrmsr(REG_MTRR4K7, mtrr4k7); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2447 |
wrmsr(REG_MTRR4K8, mtrr4k8); |
0 | 2448 |
} |
2449 |
if ((vcnt = (mtrrcap & MTRRCAP_VCNTMASK)) > MAX_MTRRVAR) |
|
2450 |
vcnt = MAX_MTRRVAR; |
|
2451 |
for (i = 0, ecx = REG_MTRRPHYSBASE0, mtrrphys = mtrrphys_arr; |
|
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2452 |
i < vcnt - 1; i++, ecx += 2, mtrrphys++) { |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2453 |
wrmsr(ecx, mtrrphys->mtrrphys_base); |
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2454 |
wrmsr(ecx + 1, mtrrphys->mtrrphys_mask); |
0 | 2455 |
} |
770
0eda482eb80f
6311933 rdmsr/wrmsr do not need to set/pass values via memory pointers
kucharsk
parents:
437
diff
changeset
|
2456 |
wrmsr(REG_MTRRDEF, mtrrdef); |
3446 | 2457 |
|
5084 | 2458 |
#if !defined(__xpv) |
3446 | 2459 |
reload_cr3(); |
5084 | 2460 |
#endif |
0 | 2461 |
invalidate_cache(); |
2462 |
setcr0(cr0_orig); |
|
2463 |
} |
|
2464 |
||
2465 |
/* |
|
2466 |
* resync mtrr so that BIOS is happy. Called from mdboot |
|
2467 |
*/ |
|
2468 |
void |
|
1676 | 2469 |
mtrr_resync(void) |
0 | 2470 |
{ |
2471 |
if ((x86_feature & X86_PAT) && enable_relaxed_mtrr) { |
|
2472 |
/* |
|
2473 |
* We could have changed the default mtrr definition. |
|
2474 |
* Put it back to uncached which is what it is at power on |
|
2475 |
*/ |
|
2476 |
mtrrdef = MTRR_TYPE_UC|MTRRDEF_FE|MTRRDEF_E; |
|
2477 |
mtrr_sync(); |
|
2478 |
} |
|
2479 |
} |
|
5084 | 2480 |
#endif |
0 | 2481 |
|
2482 |
void |
|
1676 | 2483 |
get_system_configuration(void) |
0 | 2484 |
{ |
2485 |
char prop[32]; |
|
2486 |
u_longlong_t nodes_ll, cpus_pernode_ll, lvalue; |
|
2487 |
||
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2488 |
if (BOP_GETPROPLEN(bootops, "nodes") > sizeof (prop) || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2489 |
BOP_GETPROP(bootops, "nodes", prop) < 0 || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2490 |
kobj_getvalue(prop, &nodes_ll) == -1 || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2491 |
nodes_ll > MAXNODES || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2492 |
BOP_GETPROPLEN(bootops, "cpus_pernode") > sizeof (prop) || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2493 |
BOP_GETPROP(bootops, "cpus_pernode", prop) < 0 || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2494 |
kobj_getvalue(prop, &cpus_pernode_ll) == -1) { |
0 | 2495 |
system_hardware.hd_nodes = 1; |
2496 |
system_hardware.hd_cpus_per_node = 0; |
|
2497 |
} else { |
|
2498 |
system_hardware.hd_nodes = (int)nodes_ll; |
|
2499 |
system_hardware.hd_cpus_per_node = (int)cpus_pernode_ll; |
|
2500 |
} |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2501 |
|
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2502 |
if (BOP_GETPROPLEN(bootops, "kernelbase") > sizeof (prop) || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2503 |
BOP_GETPROP(bootops, "kernelbase", prop) < 0 || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2504 |
kobj_getvalue(prop, &lvalue) == -1) |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2505 |
eprom_kernelbase = NULL; |
0 | 2506 |
else |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2507 |
eprom_kernelbase = (uintptr_t)lvalue; |
0 | 2508 |
|
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2509 |
if (BOP_GETPROPLEN(bootops, "segmapsize") > sizeof (prop) || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2510 |
BOP_GETPROP(bootops, "segmapsize", prop) < 0 || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2511 |
kobj_getvalue(prop, &lvalue) == -1) |
0 | 2512 |
segmapsize = SEGMAPDEFAULT; |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2513 |
else |
0 | 2514 |
segmapsize = (uintptr_t)lvalue; |
2515 |
||
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2516 |
if (BOP_GETPROPLEN(bootops, "segmapfreelists") > sizeof (prop) || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2517 |
BOP_GETPROP(bootops, "segmapfreelists", prop) < 0 || |
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2518 |
kobj_getvalue(prop, &lvalue) == -1) |
0 | 2519 |
segmapfreelists = 0; /* use segmap driver default */ |
4828
f987c1d28068
6582841 boot_/final_kerneheap and kernelheap_extend() nonsense needs to be ripped out
josephb
parents:
4748
diff
changeset
|
2520 |
else |
0 | 2521 |
segmapfreelists = (int)lvalue; |
1417
fa316336e215
6377034 setting physmem in /etc/system does not have desired effect on x86
kchow
parents:
1414
diff
changeset
|
2522 |
|
4004
027a924f9ee3
6539804 panic[cpu0]/thread=fffffffffbc27f40: boot_mapin(): No pp for pfnum = 1ff849
josephb
parents:
3717
diff
changeset
|
2523 |
/* physmem used to be here, but moved much earlier to fakebop.c */ |
0 | 2524 |
} |
2525 |
||
2526 |
/* |
|
2527 |
* Add to a memory list. |
|
2528 |
* start = start of new memory segment |
|
2529 |
* len = length of new memory segment in bytes |
|
2530 |
* new = pointer to a new struct memlist |
|
2531 |
* memlistp = memory list to which to add segment. |
|
2532 |
*/ |
|
3446 | 2533 |
void |
0 | 2534 |
memlist_add( |
2535 |
uint64_t start, |
|
2536 |
uint64_t len, |
|
2537 |
struct memlist *new, |
|
2538 |
struct memlist **memlistp) |
|
2539 |
{ |
|
2540 |
struct memlist *cur; |
|
2541 |
uint64_t end = start + len; |
|
2542 |
||
2543 |
new->address = start; |
|
2544 |
new->size = len; |
|
2545 |
||
2546 |
cur = *memlistp; |
|
2547 |
||
2548 |
while (cur) { |
|
2549 |
if (cur->address >= end) { |
|
2550 |
new->next = cur; |
|
2551 |
*memlistp = new; |
|
2552 |
new->prev = cur->prev; |
|
2553 |
cur->prev = new; |
|
2554 |
return; |
|
2555 |
} |
|
2556 |
ASSERT(cur->address + cur->size <= start); |
|
2557 |
if (cur->next == NULL) { |
|
2558 |
cur->next = new; |
|
2559 |
new->prev = cur; |
|
2560 |
new->next = NULL; |
|
2561 |
return; |
|
2562 |
} |
|
2563 |
memlistp = &cur->next; |
|
2564 |
cur = cur->next; |
|
2565 |
} |
|
2566 |
} |
|
2567 |
||
2568 |
void |
|
2569 |
kobj_vmem_init(vmem_t **text_arena, vmem_t **data_arena) |
|
2570 |
{ |
|
2571 |
size_t tsize = e_modtext - modtext; |
|
2572 |
size_t dsize = e_moddata - moddata; |
|
2573 |
||
2574 |
*text_arena = vmem_create("module_text", tsize ? modtext : NULL, tsize, |
|
2575 |
1, segkmem_alloc, segkmem_free, heaptext_arena, 0, VM_SLEEP); |
|
2576 |
*data_arena = vmem_create("module_data", dsize ? moddata : NULL, dsize, |
|
2577 |
1, segkmem_alloc, segkmem_free, heap32_arena, 0, VM_SLEEP); |
|
2578 |
} |
|
2579 |
||
2580 |
caddr_t |
|
2581 |
kobj_text_alloc(vmem_t *arena, size_t size) |
|
2582 |
{ |
|
2583 |
return (vmem_alloc(arena, size, VM_SLEEP | VM_BESTFIT)); |
|
2584 |
} |
|
2585 |
||
2586 |
/*ARGSUSED*/ |
|
2587 |
caddr_t |
|
2588 |
kobj_texthole_alloc(caddr_t addr, size_t size) |
|
2589 |
{ |
|
2590 |
panic("unexpected call to kobj_texthole_alloc()"); |
|
2591 |
/*NOTREACHED*/ |
|
2592 |
return (0); |
|
2593 |
} |
|
2594 |
||
2595 |
/*ARGSUSED*/ |
|
2596 |
void |
|
2597 |
kobj_texthole_free(caddr_t addr, size_t size) |
|
2598 |
{ |
|
2599 |
panic("unexpected call to kobj_texthole_free()"); |
|
2600 |
} |
|
2601 |
||
2602 |
/* |
|
2603 |
* This is called just after configure() in startup(). |
|
2604 |
* |
|
2605 |
* The ISALIST concept is a bit hopeless on Intel, because |
|
2606 |
* there's no guarantee of an ever-more-capable processor |
|
2607 |
* given that various parts of the instruction set may appear |
|
2608 |
* and disappear between different implementations. |
|
2609 |
* |
|
2610 |
* While it would be possible to correct it and even enhance |
|
2611 |
* it somewhat, the explicit hardware capability bitmask allows |
|
2612 |
* more flexibility. |
|
2613 |
* |
|
2614 |
* So, we just leave this alone. |
|
2615 |
*/ |
|
2616 |
void |
|
2617 |
setx86isalist(void) |
|
2618 |
{ |
|
2619 |
char *tp; |
|
2620 |
size_t len; |
|
2621 |
extern char *isa_list; |
|
2622 |
||
2623 |
#define TBUFSIZE 1024 |
|
2624 |
||
2625 |
tp = kmem_alloc(TBUFSIZE, KM_SLEEP); |
|
2626 |
*tp = '\0'; |
|
2627 |
||
2628 |
#if defined(__amd64) |
|
2629 |
(void) strcpy(tp, "amd64 "); |
|
2630 |
#endif |
|
2631 |
||
2632 |
switch (x86_vendor) { |
|
2633 |
case X86_VENDOR_Intel: |
|
2634 |
case X86_VENDOR_AMD: |
|
2635 |
case X86_VENDOR_TM: |
|
2636 |
if (x86_feature & X86_CMOV) { |
|
2637 |
/* |
|
2638 |
* Pentium Pro or later |
|
2639 |
*/ |
|
2640 |
(void) strcat(tp, "pentium_pro"); |
|
2641 |
(void) strcat(tp, x86_feature & X86_MMX ? |
|
2642 |
"+mmx pentium_pro " : " "); |
|
2643 |
} |
|
2644 |
/*FALLTHROUGH*/ |
|
2645 |
case X86_VENDOR_Cyrix: |
|
2646 |
/* |
|
2647 |
* The Cyrix 6x86 does not have any Pentium features |
|
2648 |
* accessible while not at privilege level 0. |
|
2649 |
*/ |
|
2650 |
if (x86_feature & X86_CPUID) { |
|
2651 |
(void) strcat(tp, "pentium"); |
|
2652 |
(void) strcat(tp, x86_feature & X86_MMX ? |
|
2653 |
"+mmx pentium " : " "); |
|
2654 |
} |
|
2655 |
break; |
|
2656 |
default: |
|
2657 |
break; |
|
2658 |
} |
|
2659 |
(void) strcat(tp, "i486 i386 i86"); |
|
2660 |
len = strlen(tp) + 1; /* account for NULL at end of string */ |
|
2661 |
isa_list = strcpy(kmem_alloc(len, KM_SLEEP), tp); |
|
2662 |
kmem_free(tp, TBUFSIZE); |
|
2663 |
||
2664 |
#undef TBUFSIZE |
|
2665 |
} |
|
2666 |
||
2667 |
||
2668 |
#ifdef __amd64 |
|
2669 |
||
2670 |
void * |
|
2671 |
device_arena_alloc(size_t size, int vm_flag) |
|
2672 |
{ |
|
2673 |
return (vmem_alloc(device_arena, size, vm_flag)); |
|
2674 |
} |
|
2675 |
||
2676 |
void |
|
2677 |
device_arena_free(void *vaddr, size_t size) |
|
2678 |
{ |
|
2679 |
vmem_free(device_arena, vaddr, size); |
|
2680 |
} |
|
2681 |
||
3446 | 2682 |
#else /* __i386 */ |
0 | 2683 |
|
2684 |
void * |
|
2685 |
device_arena_alloc(size_t size, int vm_flag) |
|
2686 |
{ |
|
2687 |
caddr_t vaddr; |
|
2688 |
uintptr_t v; |
|
2689 |
size_t start; |
|
2690 |
size_t end; |
|
2691 |
||
2692 |
vaddr = vmem_alloc(heap_arena, size, vm_flag); |
|
2693 |
if (vaddr == NULL) |
|
2694 |
return (NULL); |
|
2695 |
||
2696 |
v = (uintptr_t)vaddr; |
|
2697 |
ASSERT(v >= kernelbase); |
|
3446 | 2698 |
ASSERT(v + size <= valloc_base); |
0 | 2699 |
|
2700 |
start = btop(v - kernelbase); |
|
2701 |
end = btop(v + size - 1 - kernelbase); |
|
2702 |
ASSERT(start < toxic_bit_map_len); |
|
2703 |
ASSERT(end < toxic_bit_map_len); |
|
2704 |
||
2705 |
while (start <= end) { |
|
2706 |
BT_ATOMIC_SET(toxic_bit_map, start); |
|
2707 |
++start; |
|
2708 |
} |
|
2709 |
return (vaddr); |
|
2710 |
} |
|
2711 |
||
2712 |
void |
|
2713 |
device_arena_free(void *vaddr, size_t size) |
|
2714 |
{ |
|
2715 |
uintptr_t v = (uintptr_t)vaddr; |
|
2716 |
size_t start; |
|
2717 |
size_t end; |
|
2718 |
||
2719 |
ASSERT(v >= kernelbase); |
|
3446 | 2720 |
ASSERT(v + size <= valloc_base); |
0 | 2721 |
|
2722 |
start = btop(v - kernelbase); |
|
2723 |
end = btop(v + size - 1 - kernelbase); |
|
2724 |
ASSERT(start < toxic_bit_map_len); |
|
2725 |
ASSERT(end < toxic_bit_map_len); |
|
2726 |
||
2727 |
while (start <= end) { |
|
2728 |
ASSERT(BT_TEST(toxic_bit_map, start) != 0); |
|
2729 |
BT_ATOMIC_CLEAR(toxic_bit_map, start); |
|
2730 |
++start; |
|
2731 |
} |
|
2732 |
vmem_free(heap_arena, vaddr, size); |
|
2733 |
} |
|
2734 |
||
2735 |
/* |
|
2736 |
* returns 1st address in range that is in device arena, or NULL |
|
2737 |
* if len is not NULL it returns the length of the toxic range |
|
2738 |
*/ |
|
2739 |
void * |
|
2740 |
device_arena_contains(void *vaddr, size_t size, size_t *len) |
|
2741 |
{ |
|
2742 |
uintptr_t v = (uintptr_t)vaddr; |
|
2743 |
uintptr_t eaddr = v + size; |
|
2744 |
size_t start; |
|
2745 |
size_t end; |
|
2746 |
||
2747 |
/* |
|
2748 |
* if called very early by kmdb, just return NULL |
|
2749 |
*/ |
|
2750 |
if (toxic_bit_map == NULL) |
|
2751 |
return (NULL); |
|
2752 |
||
2753 |
/* |
|
2754 |
* First check if we're completely outside the bitmap range. |
|
2755 |
*/ |
|
3446 | 2756 |
if (v >= valloc_base || eaddr < kernelbase) |
0 | 2757 |
return (NULL); |
2758 |
||
2759 |
/* |
|
2760 |
* Trim ends of search to look at only what the bitmap covers. |
|
2761 |
*/ |
|
2762 |
if (v < kernelbase) |
|
2763 |
v = kernelbase; |
|
2764 |
start = btop(v - kernelbase); |
|
2765 |
end = btop(eaddr - kernelbase); |
|
2766 |
if (end >= toxic_bit_map_len) |
|
2767 |
end = toxic_bit_map_len; |
|
2768 |
||
2769 |
if (bt_range(toxic_bit_map, &start, &end, end) == 0) |
|
2770 |
return (NULL); |
|
2771 |
||
2772 |
v = kernelbase + ptob(start); |
|
2773 |
if (len != NULL) |
|
2774 |
*len = ptob(end - start); |
|
2775 |
return ((void *)v); |
|
2776 |
} |
|
2777 |
||
3446 | 2778 |
#endif /* __i386 */ |