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