]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/ppc_vm_init.c
xnu-344.32.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 *
de355530
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 *
de355530
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,
de355530
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>
de355530 47#include <ppc/pmap_internals.h>
1c79356b
A
48#include <ppc/mem.h>
49#include <ppc/mappings.h>
50#include <ppc/exception.h>
51#include <ppc/mp.h>
52
de355530 53#ifdef __MACHO__
1c79356b 54#include <mach-o/mach_header.h>
de355530 55#endif
1c79356b 56
de355530
A
57extern unsigned int intstack[]; /* declared in start.s */
58extern unsigned int intstack_top_ss; /* declared in start.s */
1c79356b 59
de355530
A
60vm_offset_t mem_size; /* Size of actual physical memory present
61 minus any performance buffer and possibly limited
62 by mem_limit in bytes */
63vm_offset_t mem_actual; /* The "One True" physical memory size
64 actually, it's the highest physical address + 1 */
65
1c79356b 66
de355530
A
67mem_region_t pmap_mem_regions[PMAP_MEM_REGION_MAX];
68int pmap_mem_regions_count = 0; /* No non-contiguous memory regions */
1c79356b 69
de355530
A
70mem_region_t free_regions[FREE_REGION_MAX];
71int free_regions_count;
d7e50217 72
de355530
A
73#ifndef __MACHO__
74extern unsigned long etext;
75#endif
1c79356b
A
76
77unsigned int avail_remaining = 0;
78vm_offset_t first_avail;
79vm_offset_t static_memory_end;
de355530 80extern vm_offset_t avail_next;
1c79356b 81
de355530 82#ifdef __MACHO__
1c79356b
A
83extern struct mach_header _mh_execute_header;
84vm_offset_t sectTEXTB;
85int sectSizeTEXT;
86vm_offset_t sectDATAB;
87int sectSizeDATA;
1c79356b
A
88vm_offset_t sectLINKB;
89int sectSizeLINK;
90vm_offset_t sectKLDB;
91int sectSizeKLD;
92
93vm_offset_t end, etext, edata;
de355530 94#endif
1c79356b
A
95
96extern unsigned long exception_entry;
97extern unsigned long exception_end;
98
99
de355530 100void ppc_vm_init(unsigned int mem_limit, boot_args *args)
1c79356b
A
101{
102 unsigned int htabmask;
de355530
A
103 unsigned int i, j, batsize, kmapsize;
104 vm_offset_t addr;
1c79356b
A
105 int boot_task_end_offset;
106 const char *cpus;
107 mapping *mp;
de355530 108 vm_offset_t first_phys_avail;
1c79356b
A
109 vm_offset_t sizeadj, oldstart;
110
de355530
A
111 /* Now retrieve addresses for end, edata, and etext
112 * from MACH-O headers.
113 */
114 sectTEXTB = (vm_offset_t)getsegdatafromheader(
115 &_mh_execute_header, "__TEXT", &sectSizeTEXT);
116 sectDATAB = (vm_offset_t)getsegdatafromheader(
117 &_mh_execute_header, "__DATA", &sectSizeDATA);
118 sectLINKB = (vm_offset_t)getsegdatafromheader(
119 &_mh_execute_header, "__LINKEDIT", &sectSizeLINK);
120 sectKLDB = (vm_offset_t)getsegdatafromheader(
121 &_mh_execute_header, "__KLD", &sectSizeKLD);
1c79356b 122
de355530
A
123 etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
124 edata = (vm_offset_t) sectDATAB + sectSizeDATA;
125 end = round_page(getlastaddr()); /* Force end to next page */
126#if DEBUG
127 kprintf("sectTEXT: %x, size: %x\n", sectTEXTB, sectSizeTEXT);
128 kprintf("sectDATA: %x, size: %x\n", sectDATAB, sectSizeDATA);
129 kprintf("sectLINK: %x, size: %x\n", sectLINKB, sectSizeLINK);
130 kprintf("sectKLD: %x, size: %x\n", sectKLDB, sectSizeKLD);
131 kprintf("end: %x\n", end);
132#endif
133
134/* Stitch valid memory regions together - they may be contiguous
135 * even though they're not already glued together
1c79356b 136 */
de355530
A
137 mem_actual = args->PhysicalDRAM[0].base + args->PhysicalDRAM[0].size; /* Initialize to the first region size */
138 addr = 0; /* temp use as pointer to previous memory region... */
139 for (i = 1; i < kMaxDRAMBanks; i++) {
140
141 if (args->PhysicalDRAM[i].size == 0) continue; /* If region is empty, skip it */
142
143 if((args->PhysicalDRAM[i].base + args->PhysicalDRAM[i].size) > mem_actual) { /* New high? */
144 mem_actual = args->PhysicalDRAM[i].base + args->PhysicalDRAM[i].size; /* Take the high bid */
145 }
146
147 if (args->PhysicalDRAM[i].base == /* Does the end of the last hit the start of the next? */
148 args->PhysicalDRAM[addr].base +
149 args->PhysicalDRAM[addr].size) {
150 kprintf("region 0x%08x size 0x%08x joining region 0x%08x size 0x%08x\n",
151 args->PhysicalDRAM[addr].base, args->PhysicalDRAM[addr].size,
152 args->PhysicalDRAM[i].base, args->PhysicalDRAM[i].size);
153
154 args->PhysicalDRAM[addr].size += args->PhysicalDRAM[i].size; /* Join them */
155 args->PhysicalDRAM[i].size = 0;
156 continue;
157 }
158 /* This is now last non-zero region to compare against */
159 addr = i;
160 }
1c79356b 161
de355530 162 /* Go through the list of memory regions passed in via the args
1c79356b
A
163 * and copy valid entries into the pmap_mem_regions table, adding
164 * further calculated entries.
165 */
166
167 pmap_mem_regions_count = 0;
de355530 168 mem_size = 0; /* Will use to total memory found so far */
1c79356b 169
de355530
A
170 for (i = 0; i < kMaxDRAMBanks; i++) {
171 if (args->PhysicalDRAM[i].size == 0)
172 continue;
1c79356b 173
de355530
A
174 /* The following should only happen if memory size has
175 been artificially reduced with -m */
176 if (mem_limit > 0 &&
177 mem_size + args->PhysicalDRAM[i].size > mem_limit)
178 args->PhysicalDRAM[i].size = mem_limit - mem_size;
1c79356b 179
de355530 180 /* We've found a region, tally memory */
1c79356b 181
de355530
A
182 pmap_mem_regions[pmap_mem_regions_count].start =
183 args->PhysicalDRAM[i].base;
184 pmap_mem_regions[pmap_mem_regions_count].end =
185 args->PhysicalDRAM[i].base +
186 args->PhysicalDRAM[i].size;
1c79356b 187
de355530
A
188 /* Regions must be provided in ascending order */
189 assert ((pmap_mem_regions_count == 0) ||
190 pmap_mem_regions[pmap_mem_regions_count].start >
191 pmap_mem_regions[pmap_mem_regions_count-1].start);
192
193 if (pmap_mem_regions_count > 0) {
194 /* we add on any pages not in the first memory
195 * region to the avail_remaining count. The first
196 * memory region is used for mapping everything for
197 * bootup and is taken care of specially.
198 */
199 avail_remaining +=
200 args->PhysicalDRAM[i].size / PPC_PGBYTES;
201 }
202
203 /* Keep track of how much memory we've found */
1c79356b 204
de355530 205 mem_size += args->PhysicalDRAM[i].size;
1c79356b 206
de355530
A
207 /* incremement number of regions found */
208 pmap_mem_regions_count++;
209 }
d7e50217 210
de355530 211 kprintf("mem_size: %d M\n",mem_size / (1024 * 1024));
d7e50217 212
de355530
A
213 /*
214 * Initialize the pmap system, using space above `first_avail'
215 * for the necessary data structures.
216 * NOTE : assume that we'll have enough space mapped in already
217 */
d7e50217 218
de355530
A
219 first_phys_avail = static_memory_end;
220 first_avail = adjust_bat_limit(first_phys_avail, 0, FALSE, FALSE);
1c79356b 221
de355530
A
222 kmapsize = (round_page(exception_end) - trunc_page(exception_entry)) + /* Get size we will map later */
223 (round_page(sectTEXTB+sectSizeTEXT) - trunc_page(sectTEXTB)) +
224 (round_page(sectDATAB+sectSizeDATA) - trunc_page(sectDATAB)) +
225 (round_page(sectLINKB+sectSizeLINK) - trunc_page(sectLINKB)) +
226 (round_page(sectKLDB+sectSizeKLD) - trunc_page(sectKLDB)) +
227 (round_page(static_memory_end) - trunc_page(end));
d7e50217 228
de355530 229 pmap_bootstrap(mem_size,&first_avail,&first_phys_avail, kmapsize);
d7e50217 230
de355530
A
231#ifdef __MACHO__
232#if DEBUG
233 kprintf("Mapping memory:\n");
234 kprintf(" exception vector: %08X, %08X - %08X\n", trunc_page(exception_entry),
235 trunc_page(exception_entry), round_page(exception_end));
236 kprintf(" sectTEXTB: %08X, %08X - %08X\n", trunc_page(sectTEXTB),
237 trunc_page(sectTEXTB), round_page(sectTEXTB+sectSizeTEXT));
238 kprintf(" sectDATAB: %08X, %08X - %08X\n", trunc_page(sectDATAB),
239 trunc_page(sectDATAB), round_page(sectDATAB+sectSizeDATA));
240 kprintf(" sectLINKB: %08X, %08X - %08X\n", trunc_page(sectLINKB),
241 trunc_page(sectLINKB), round_page(sectLINKB+sectSizeLINK));
242 kprintf(" sectKLDB: %08X, %08X - %08X\n", trunc_page(sectKLDB),
243 trunc_page(sectKLDB), round_page(sectKLDB+sectSizeKLD));
244 kprintf(" end: %08X, %08X - %08X\n", trunc_page(end),
245 trunc_page(end), static_memory_end);
246#endif /* DEBUG */
247 pmap_map(trunc_page(exception_entry), trunc_page(exception_entry),
248 round_page(exception_end), VM_PROT_READ|VM_PROT_EXECUTE);
249 pmap_map(trunc_page(sectTEXTB), trunc_page(sectTEXTB),
250 round_page(sectTEXTB+sectSizeTEXT), VM_PROT_READ|VM_PROT_EXECUTE);
251 pmap_map(trunc_page(sectDATAB), trunc_page(sectDATAB),
252 round_page(sectDATAB+sectSizeDATA), VM_PROT_READ|VM_PROT_WRITE);
253
254
255 /* The KLD and LINKEDIT segments are unloaded in toto after boot completes,
256 * but via ml_static_mfree(), through IODTFreeLoaderInfo(). Hence, we have
257 * to map both segments page-by-page.
258 */
259 for (addr = trunc_page(sectKLDB);
260 addr < round_page(sectKLDB+sectSizeKLD);
1c79356b
A
261 addr += PAGE_SIZE) {
262
de355530 263 pmap_enter(kernel_pmap, addr, addr,
9bccf70c
A
264 VM_PROT_READ|VM_PROT_WRITE,
265 VM_WIMG_USE_DEFAULT, TRUE);
1c79356b
A
266 }
267
de355530
A
268 for (addr = trunc_page(sectLINKB);
269 addr < round_page(sectLINKB+sectSizeLINK);
1c79356b
A
270 addr += PAGE_SIZE) {
271
de355530 272 pmap_enter(kernel_pmap, addr, addr,
9bccf70c
A
273 VM_PROT_READ|VM_PROT_WRITE,
274 VM_WIMG_USE_DEFAULT, TRUE);
1c79356b
A
275 }
276
277/*
278 * We need to map the remainder page-by-page because some of this will
279 * be released later, but not all. Ergo, no block mapping here
280 */
de355530
A
281 for(addr = trunc_page(end); addr < round_page(static_memory_end); addr += PAGE_SIZE) {
282 pmap_enter(kernel_pmap, addr, addr,
9bccf70c
A
283 VM_PROT_READ|VM_PROT_WRITE,
284 VM_WIMG_USE_DEFAULT, TRUE);
1c79356b 285 }
de355530 286#endif /* __MACHO__ */
d7e50217 287
de355530
A
288#if DEBUG
289 for (i=0 ; i < free_regions_count; i++) {
290 kprintf("Free region start 0x%08x end 0x%08x\n",
291 free_regions[i].start,free_regions[i].end);
292 }
293#endif
1c79356b 294
d52fe63f 295/*
de355530 296 * Note: the shadow BAT registers were already loaded in ppc_init.c
d52fe63f 297 */
1c79356b 298
1c79356b 299
de355530
A
300 LoadIBATs((unsigned int *)&shadow_BAT.IBATs[0]); /* Load up real IBATs from shadows */
301 LoadDBATs((unsigned int *)&shadow_BAT.DBATs[0]); /* Load up real DBATs from shadows */
1c79356b 302
1c79356b 303#if DEBUG
de355530
A
304 for(i=0; i<4; i++) kprintf("DBAT%1d: %08X %08X\n",
305 i, shadow_BAT.DBATs[i].upper, shadow_BAT.DBATs[i].lower);
306 for(i=0; i<4; i++) kprintf("IBAT%1d: %08X %08X\n",
307 i, shadow_BAT.IBATs[i].upper, shadow_BAT.IBATs[i].lower);
1c79356b
A
308#endif
309}
310
311void ppc_vm_cpu_init(
312 struct per_proc_info *proc_info)
313{
de355530
A
314 hash_table_init(hash_table_base, hash_table_size);
315
316 LoadIBATs((unsigned int *)&shadow_BAT.IBATs[0]);
317 LoadDBATs((unsigned int *)&shadow_BAT.DBATs[0]);
318
319 sync();isync();
1c79356b 320}