]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/ppc_vm_init.c
xnu-517.12.7.tar.gz
[apple/xnu.git] / osfmk / ppc / ppc_vm_init.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * @APPLE_FREE_COPYRIGHT@
27 */
28
29#include <mach_debug.h>
30#include <mach_kdb.h>
31#include <mach_kdp.h>
32#include <debug.h>
33#include <cpus.h>
34
35#include <mach/vm_types.h>
36#include <mach/vm_param.h>
37#include <mach/thread_status.h>
38#include <kern/misc_protos.h>
39#include <kern/assert.h>
40#include <kern/cpu_number.h>
41
42#include <ppc/proc_reg.h>
43#include <ppc/Firmware.h>
44#include <ppc/boot.h>
45#include <ppc/misc_protos.h>
46#include <ppc/pmap.h>
1c79356b
A
47#include <ppc/mem.h>
48#include <ppc/mappings.h>
49#include <ppc/exception.h>
50#include <ppc/mp.h>
55e303ae 51#include <ppc/lowglobals.h>
1c79356b 52
1c79356b 53#include <mach-o/mach_header.h>
1c79356b 54
55e303ae
A
55extern const char version[];
56extern const char version_variant[];
1c79356b 57
55e303ae
A
58extern unsigned int intstack[]; /* declared in aligned_data.s */
59extern unsigned int intstack_top_ss; /* declared in aligned_data.s */
1c79356b 60
55e303ae
A
61addr64_t hash_table_base; /* Hash table base */
62unsigned int hash_table_size; /* Hash table size */
63vm_offset_t taproot_addr; /* (BRINGUP) */
64unsigned int taproot_size; /* (BRINGUP) */
65unsigned int serialmode; /* Serial mode keyboard and console control */
66extern int disableConsoleOutput;
1c79356b 67
55e303ae 68struct shadowBAT shadow_BAT;
d7e50217 69
55e303ae
A
70/*
71 * NOTE: mem_size is bogus on large memory machines. We will pin it to 0x80000000 if there is more than 2 GB
72 * This is left only for compatibility and max_mem should be used.
73 */
74vm_offset_t mem_size; /* Size of actual physical memory present
75 minus any performance buffer and possibly limited
76 by mem_limit in bytes */
77uint64_t mem_actual; /* The "One True" physical memory size
78 actually, it's the highest physical address + 1 */
79uint64_t max_mem; /* Size of physical memory (bytes), adjusted by maxmem */
80uint64_t sane_size; /* Memory size to use for defaults calculations */
81
82
83mem_region_t pmap_mem_regions[PMAP_MEM_REGION_MAX + 1];
84int pmap_mem_regions_count = 0; /* Assume no non-contiguous memory regions */
1c79356b
A
85
86unsigned int avail_remaining = 0;
87vm_offset_t first_avail;
88vm_offset_t static_memory_end;
55e303ae 89addr64_t vm_last_addr = VM_MAX_KERNEL_ADDRESS; /* Highest kernel virtual address known to the VM system */
1c79356b 90
1c79356b
A
91extern struct mach_header _mh_execute_header;
92vm_offset_t sectTEXTB;
93int sectSizeTEXT;
94vm_offset_t sectDATAB;
95int sectSizeDATA;
1c79356b
A
96vm_offset_t sectLINKB;
97int sectSizeLINK;
98vm_offset_t sectKLDB;
99int sectSizeKLD;
55e303ae
A
100vm_offset_t sectPRELINKB;
101int sectSizePRELINK;
1c79356b
A
102
103vm_offset_t end, etext, edata;
1c79356b
A
104
105extern unsigned long exception_entry;
106extern unsigned long exception_end;
107
108
55e303ae 109void ppc_vm_init(uint64_t mem_limit, boot_args *args)
1c79356b
A
110{
111 unsigned int htabmask;
55e303ae
A
112 unsigned int i, j, batsize, kmapsize, pvr;
113 vm_offset_t addr, ioAddr, videoAddr;
1c79356b
A
114 int boot_task_end_offset;
115 const char *cpus;
116 mapping *mp;
1c79356b 117 vm_offset_t sizeadj, oldstart;
55e303ae
A
118 unsigned int *xtaproot, bank_shift;
119 uint64_t cbsize, xhid0;
1c79356b 120
de355530 121
55e303ae
A
122/*
123 * Invalidate all shadow BATs
1c79356b 124 */
1c79356b 125
55e303ae
A
126 /* Initialize shadow IBATs */
127 shadow_BAT.IBATs[0].upper=BAT_INVALID;
128 shadow_BAT.IBATs[0].lower=BAT_INVALID;
129 shadow_BAT.IBATs[1].upper=BAT_INVALID;
130 shadow_BAT.IBATs[1].lower=BAT_INVALID;
131 shadow_BAT.IBATs[2].upper=BAT_INVALID;
132 shadow_BAT.IBATs[2].lower=BAT_INVALID;
133 shadow_BAT.IBATs[3].upper=BAT_INVALID;
134 shadow_BAT.IBATs[3].lower=BAT_INVALID;
135
136 /* Initialize shadow DBATs */
137 shadow_BAT.DBATs[0].upper=BAT_INVALID;
138 shadow_BAT.DBATs[0].lower=BAT_INVALID;
139 shadow_BAT.DBATs[1].upper=BAT_INVALID;
140 shadow_BAT.DBATs[1].lower=BAT_INVALID;
141 shadow_BAT.DBATs[2].upper=BAT_INVALID;
142 shadow_BAT.DBATs[2].lower=BAT_INVALID;
143 shadow_BAT.DBATs[3].upper=BAT_INVALID;
144 shadow_BAT.DBATs[3].lower=BAT_INVALID;
145
146
147 /*
148 * Go through the list of memory regions passed in via the boot_args
1c79356b
A
149 * and copy valid entries into the pmap_mem_regions table, adding
150 * further calculated entries.
55e303ae
A
151 *
152 * boot_args version 1 has address instead of page numbers
153 * in the PhysicalDRAM banks, set bank_shift accordingly.
1c79356b
A
154 */
155
55e303ae
A
156 bank_shift = 0;
157 if (args->Version == kBootArgsVersion1) bank_shift = 12;
158
1c79356b 159 pmap_mem_regions_count = 0;
55e303ae
A
160 max_mem = 0; /* Will use to total memory found so far */
161 mem_actual = 0; /* Actual size of memory */
162
163 if (mem_limit == 0) mem_limit = 0xFFFFFFFFFFFFFFFFULL; /* If there is no set limit, use all */
164
165 for (i = 0; i < kMaxDRAMBanks; i++) { /* Look at all of the banks */
166
167 cbsize = (uint64_t)args->PhysicalDRAM[i].size << (12 - bank_shift); /* Remember current size */
168
169 if (!cbsize) continue; /* Skip if the bank is empty */
170
171 mem_actual = mem_actual + cbsize; /* Get true memory size */
1c79356b 172
55e303ae 173 if(mem_limit == 0) continue; /* If we hit restriction, just keep counting */
1c79356b 174
55e303ae
A
175 if (cbsize > mem_limit) cbsize = mem_limit; /* Trim to max allowed */
176 max_mem += cbsize; /* Total up what we have so far */
177 mem_limit = mem_limit - cbsize; /* Calculate amount left to do */
178
179 pmap_mem_regions[pmap_mem_regions_count].mrStart = args->PhysicalDRAM[i].base >> bank_shift; /* Set the start of the bank */
180 pmap_mem_regions[pmap_mem_regions_count].mrAStart = pmap_mem_regions[pmap_mem_regions_count].mrStart; /* Set the start of allocatable area */
181 pmap_mem_regions[pmap_mem_regions_count].mrEnd = ((uint64_t)args->PhysicalDRAM[i].base >> bank_shift) + (cbsize >> 12) - 1; /* Set the end address of bank */
182 pmap_mem_regions[pmap_mem_regions_count].mrAEnd = pmap_mem_regions[pmap_mem_regions_count].mrEnd; /* Set the end address of allocatable area */
1c79356b 183
de355530
A
184 /* Regions must be provided in ascending order */
185 assert ((pmap_mem_regions_count == 0) ||
55e303ae
A
186 pmap_mem_regions[pmap_mem_regions_count].mrStart >
187 pmap_mem_regions[pmap_mem_regions_count-1].mrStart);
1c79356b 188
55e303ae 189 pmap_mem_regions_count++; /* Count this region */
de355530 190 }
55e303ae
A
191
192 mem_size = (unsigned int)max_mem; /* Get size of memory */
193 if(max_mem > 0x0000000080000000ULL) mem_size = 0x80000000; /* Pin at 2 GB */
d7e50217 194
55e303ae
A
195 sane_size = max_mem; /* Calculate a sane value to use for init */
196 if(sane_size > (addr64_t)(VM_MAX_KERNEL_ADDRESS + 1))
197 sane_size = (addr64_t)(VM_MAX_KERNEL_ADDRESS + 1); /* If flush with ram, use addressible portion */
43866e37 198
d7e50217 199
55e303ae
A
200/*
201 * Initialize the pmap system, using space above `first_avail'
202 * for the necessary data structures.
203 * NOTE : assume that we'll have enough space mapped in already
204 */
205
206 first_avail = static_memory_end;
d7e50217 207
55e303ae
A
208/* Now retrieve addresses for end, edata, and etext
209 * from MACH-O headers.
210 */
211 sectTEXTB = (vm_offset_t)getsegdatafromheader(
212 &_mh_execute_header, "__TEXT", &sectSizeTEXT);
213 sectDATAB = (vm_offset_t)getsegdatafromheader(
214 &_mh_execute_header, "__DATA", &sectSizeDATA);
215 sectLINKB = (vm_offset_t)getsegdatafromheader(
216 &_mh_execute_header, "__LINKEDIT", &sectSizeLINK);
217 sectKLDB = (vm_offset_t)getsegdatafromheader(
218 &_mh_execute_header, "__KLD", &sectSizeKLD);
219 sectPRELINKB = (vm_offset_t)getsegdatafromheader(
220 &_mh_execute_header, "__PRELINK", &sectSizePRELINK);
221
222 etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
223 edata = (vm_offset_t) sectDATAB + sectSizeDATA;
224 end = round_page_32(getlastaddr()); /* Force end to next page */
1c79356b 225
55e303ae
A
226 kmapsize = (round_page_32(exception_end) - trunc_page_32(exception_entry)) + /* Get size we will map later */
227 (round_page_32(sectTEXTB+sectSizeTEXT) - trunc_page_32(sectTEXTB)) +
228 (round_page_32(sectDATAB+sectSizeDATA) - trunc_page_32(sectDATAB)) +
229 (round_page_32(sectLINKB+sectSizeLINK) - trunc_page_32(sectLINKB)) +
230 (round_page_32(sectKLDB+sectSizeKLD) - trunc_page_32(sectKLDB)) +
231 (round_page_32(sectPRELINKB+sectSizePRELINK) - trunc_page_32(sectPRELINKB)) +
232 (round_page_32(static_memory_end) - trunc_page_32(end));
d7e50217 233
55e303ae 234 pmap_bootstrap(max_mem, &first_avail, kmapsize);
d7e50217 235
55e303ae
A
236 pmap_map(trunc_page_32(exception_entry), trunc_page_32(exception_entry),
237 round_page_32(exception_end), VM_PROT_READ|VM_PROT_EXECUTE);
238
239 pmap_map(trunc_page_32(sectTEXTB), trunc_page_32(sectTEXTB),
240 round_page_32(sectTEXTB+sectSizeTEXT), VM_PROT_READ|VM_PROT_EXECUTE);
241
242 pmap_map(trunc_page_32(sectDATAB), trunc_page_32(sectDATAB),
243 round_page_32(sectDATAB+sectSizeDATA), VM_PROT_READ|VM_PROT_WRITE);
244
245/* The KLD and LINKEDIT segments are unloaded in toto after boot completes,
246* but via ml_static_mfree(), through IODTFreeLoaderInfo(). Hence, we have
247* to map both segments page-by-page.
248*/
249
250 for (addr = trunc_page_32(sectPRELINKB);
251 addr < round_page_32(sectPRELINKB+sectSizePRELINK);
1c79356b
A
252 addr += PAGE_SIZE) {
253
55e303ae 254 pmap_enter(kernel_pmap, addr, addr>>12,
9bccf70c
A
255 VM_PROT_READ|VM_PROT_WRITE,
256 VM_WIMG_USE_DEFAULT, TRUE);
55e303ae 257
1c79356b
A
258 }
259
55e303ae
A
260 for (addr = trunc_page_32(sectKLDB);
261 addr < round_page_32(sectKLDB+sectSizeKLD);
1c79356b
A
262 addr += PAGE_SIZE) {
263
55e303ae 264 pmap_enter(kernel_pmap, addr, addr>>12,
9bccf70c
A
265 VM_PROT_READ|VM_PROT_WRITE,
266 VM_WIMG_USE_DEFAULT, TRUE);
55e303ae 267
1c79356b
A
268 }
269
55e303ae
A
270 for (addr = trunc_page_32(sectLINKB);
271 addr < round_page_32(sectLINKB+sectSizeLINK);
272 addr += PAGE_SIZE) {
273
274 pmap_enter(kernel_pmap, addr, addr>>12,
275 VM_PROT_READ|VM_PROT_WRITE,
276 VM_WIMG_USE_DEFAULT, TRUE);
277
278 }
279
280 pmap_enter(kernel_pmap, &sharedPage, (unsigned int)&sharedPage >> 12, /* Make sure the sharedPage is mapped */
281 VM_PROT_READ|VM_PROT_WRITE,
282 VM_WIMG_USE_DEFAULT, TRUE);
283
284 pmap_enter(kernel_pmap, &lowGlo, (unsigned int)&lowGlo >> 12, /* Make sure the low memory globals are mapped */
285 VM_PROT_READ|VM_PROT_WRITE,
286 VM_WIMG_USE_DEFAULT, TRUE);
287
1c79356b
A
288/*
289 * We need to map the remainder page-by-page because some of this will
290 * be released later, but not all. Ergo, no block mapping here
291 */
55e303ae
A
292
293 for(addr = trunc_page_32(end); addr < round_page_32(static_memory_end); addr += PAGE_SIZE) {
294
295 pmap_enter(kernel_pmap, addr, addr>>12,
9bccf70c
A
296 VM_PROT_READ|VM_PROT_WRITE,
297 VM_WIMG_USE_DEFAULT, TRUE);
d7e50217 298
de355530 299 }
55e303ae
A
300
301 MapUserAddressSpaceInit(); /* Go initialize copy in/out */
1c79356b 302
d52fe63f 303/*
55e303ae
A
304 * At this point, there is enough mapped memory and all hw mapping structures are
305 * allocated and initialized. Here is where we turn on translation for the
306 * VERY first time....
307 *
308 * NOTE: Here is where our very first interruption will happen.
309 *
d52fe63f 310 */
1c79356b 311
55e303ae
A
312 hw_start_trans(); /* Start translating */
313
314#if 0
315 GratefulDebInit((bootBumbleC *)&(args->Video)); /* Initialize the GratefulDeb debugger */
316#endif
317
318
319 printf_init(); /* Init this in case we need debugger */
320 panic_init(); /* Init this in case we need debugger */
321 PE_init_kprintf(TRUE); /* Note on PPC we only call this after VM is set up */
322
323 kprintf("kprintf initialized\n");
324
325 serialmode = 0; /* Assume normal keyboard and console */
326 if(PE_parse_boot_arg("serial", &serialmode)) { /* Do we want a serial keyboard and/or console? */
327 kprintf("Serial mode specified: %08X\n", serialmode);
328 }
329 if(serialmode & 1) { /* Start serial if requested */
330 (void)switch_to_serial_console(); /* Switch into serial mode */
331 disableConsoleOutput = FALSE; /* Allow printfs to happen */
332 }
333
334 kprintf("max_mem: %ld M\n", (unsigned long)(max_mem >> 20));
335 kprintf("version_variant = %s\n", version_variant);
336 kprintf("version = %s\n\n", version);
337 __asm__ ("mfpvr %0" : "=r" (pvr));
338 kprintf("proc version = %08x\n", pvr);
339 if(per_proc_info[0].pf.Available & pf64Bit) { /* 64-bit processor? */
340 xhid0 = hid0get64(); /* Get the hid0 */
341 if(xhid0 & (1ULL << (63 - 19))) kprintf("Time base is externally clocked\n");
342 else kprintf("Time base is internally clocked\n");
343 }
344
345
346 taproot_size = PE_init_taproot(&taproot_addr); /* (BRINGUP) See if there is a taproot */
347 if(taproot_size) { /* (BRINGUP) */
348 kprintf("TapRoot card configured to use vaddr = %08X, size = %08X\n", taproot_addr, taproot_size);
349 bcopy_nc((void *)version, (void *)(taproot_addr + 16), strlen(version)); /* (BRINGUP) Pass it our kernel version */
350 __asm__ volatile("eieio"); /* (BRINGUP) */
351 xtaproot = (unsigned int *)taproot_addr; /* (BRINGUP) */
352 xtaproot[0] = 1; /* (BRINGUP) */
353 __asm__ volatile("eieio"); /* (BRINGUP) */
354 }
355
356 PE_create_console(); /* create the console for verbose or pretty mode */
1c79356b 357
55e303ae
A
358 /* setup console output */
359 PE_init_printf(FALSE);
1c79356b 360
1c79356b 361#if DEBUG
55e303ae
A
362 printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n",
363 __GNUC__,__GNUC_MINOR__);
364
365
366 /* Processor version information */
367 {
368 unsigned int pvr;
369 __asm__ ("mfpvr %0" : "=r" (pvr));
370 printf("processor version register : %08X\n", pvr);
371 }
372
373 kprintf("Args at %08X\n", args);
374 for (i = 0; i < pmap_mem_regions_count; i++) {
375 printf("DRAM at %08X size %08X\n",
376 args->PhysicalDRAM[i].base,
377 args->PhysicalDRAM[i].size);
378 }
379#endif /* DEBUG */
380
381#if DEBUG
382 kprintf("Mapped memory:\n");
383 kprintf(" exception vector: %08X, %08X - %08X\n", trunc_page_32(exception_entry),
384 trunc_page_32(exception_entry), round_page_32(exception_end));
385 kprintf(" sectTEXTB: %08X, %08X - %08X\n", trunc_page_32(sectTEXTB),
386 trunc_page_32(sectTEXTB), round_page_32(sectTEXTB+sectSizeTEXT));
387 kprintf(" sectDATAB: %08X, %08X - %08X\n", trunc_page_32(sectDATAB),
388 trunc_page_32(sectDATAB), round_page_32(sectDATAB+sectSizeDATA));
389 kprintf(" sectLINKB: %08X, %08X - %08X\n", trunc_page_32(sectLINKB),
390 trunc_page_32(sectLINKB), round_page_32(sectLINKB+sectSizeLINK));
391 kprintf(" sectKLDB: %08X, %08X - %08X\n", trunc_page_32(sectKLDB),
392 trunc_page_32(sectKLDB), round_page_32(sectKLDB+sectSizeKLD));
393 kprintf(" end: %08X, %08X - %08X\n", trunc_page_32(end),
394 trunc_page_32(end), static_memory_end);
395
1c79356b 396#endif
55e303ae
A
397
398 return;
1c79356b
A
399}
400
401void ppc_vm_cpu_init(
402 struct per_proc_info *proc_info)
403{
55e303ae
A
404 hw_setup_trans(); /* Set up hardware needed for translation */
405 hw_start_trans(); /* Start translating */
1c79356b 406}