]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/ppc/ppc_init.c
85e0df88266937093400aaecf1a0386b8778d393
[apple/xnu.git] / bsd / dev / ppc / ppc_init.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 #include <mach/vm_types.h>
28 #include <mach/vm_param.h>
29 #include <mach/thread_status.h>
30 #include <kern/misc_protos.h>
31 #include <kern/assert.h>
32 #include <kern/cpu_number.h>
33
34 #include <ppc/proc_reg.h>
35 #include <ppc/boot.h>
36 #include <ppc/misc_protos.h>
37 #include <ppc/pmap.h>
38 #include <ppc/pmap_internals.h>
39 #include <ppc/mem.h>
40 #include <ppc/exception.h>
41 #include <ppc/gdb_defs.h>
42 #include <ppc/POWERMAC/video_board.h>
43 #include <ppc/POWERMAC/video_pdm.h>
44
45 #ifdef __MACHO__
46 #include <mach-o/mach_header.h>
47 #endif
48
49 /* External references */
50
51 extern unsigned int intstack[]; /* declared in start.s */
52 extern unsigned int intstack_top_ss; /* declared in start.s */
53 #if MACH_KGDB
54 extern unsigned int gdbstackptr; /* declared in start.s */
55 extern unsigned int gdbstack_top_ss; /* declared in start.s */
56 #endif /* MACH_KGDB */
57
58 /* Stuff declared in kern/bootstrap.c which we may need to initialise */
59
60 extern vm_offset_t boot_start;
61 extern vm_size_t boot_size;
62 extern vm_offset_t boot_region_desc;
63 extern vm_size_t boot_region_count;
64 extern int boot_thread_state_flavor;
65 extern thread_state_t boot_thread_state;
66 extern unsigned int boot_thread_state_count;
67
68 /* Trap handling function prototypes */
69
70 extern void thandler(void); /* trap handler */
71 extern void ihandler(void); /* interrupt handler */
72 extern void shandler(void); /* syscall handler */
73 extern void gdbhandler(void); /* debugger handler */
74 extern void fpu_switch(void); /* fp handler */
75 extern void atomic_switch_trap(void); /* fast path atomic thread switch */
76
77 /* definitions */
78
79 struct ppc_thread_state boot_task_thread_state;
80
81
82
83
84
85 #if 1 /* TODO NMGS - vm_map_steal_memory shouldn't use these - remove */
86 vm_offset_t avail_start;
87 vm_offset_t avail_end;
88 #endif
89 unsigned int avail_remaining = 0;
90 vm_offset_t first_avail;
91
92 /*
93 * Mach-O Support
94 */
95
96
97 #ifdef __MACHO__
98 extern struct mach_header _mh_execute_header;
99 void *sectTEXTB;
100 int sectSizeTEXT;
101 void *sectDATAB;
102 int sectSizeDATA;
103 void *sectOBJCB;
104 int sectSizeOBJC;
105 void *sectLINKB;
106 int sectSizeLINK;
107
108 vm_offset_t end, etext, edata;
109 #define ETEXT etext
110 #endif
111
112
113
114 void ppc_vm_init(unsigned int memory_size, boot_args *args)
115 {
116 unsigned int htabmask;
117 unsigned int i;
118 vm_offset_t addr;
119 int boot_task_end_offset;
120 #if NCPUS > 1
121 const char *cpus;
122 #endif /* NCPUS > 1 */
123
124 printf("mem_size = %d M\n",memory_size / (1024 * 1024));
125
126 #ifdef __MACHO__
127 /* Now retrieve addresses for end, edata, and etext
128 * from MACH-O headers.
129 */
130
131
132 etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
133 edata = (vm_offset_t) sectDATAB + sectSizeDATA;
134 end = getlastaddr();
135 #endif
136
137 /* Stitch valid memory regions together - they may be contiguous
138 * even though they're not already glued together
139 */
140
141 /* Go through the list of memory regions passed in via the args
142 * and copy valid entries into the pmap_mem_regions table, adding
143 * further calculated entries.
144 */
145
146
147 /* Initialise the pmap system, using space above `first_avail'*/
148
149 #ifndef __MACHO__
150 free_regions[free_regions_count].start =
151 round_page((unsigned int)&_ExceptionVectorsEnd -
152 (unsigned int)&_ExceptionVectorsStart);
153 #else
154 /* On MACH-O generated kernels, the Exception Vectors
155 * are already mapped and loaded at 0 -- no relocation
156 * or freeing of memory is needed
157 */
158
159 free_regions[free_regions_count].start = round_page((unsigned int)&_ExceptionVectorsEnd) + 4096;
160 #endif
161
162 /* If we are on a PDM machine memory at 1M might be used
163 * for video. TODO NMGS call video driver to do this
164 * somehow
165 */
166
167
168 /* For PowerMac, first_avail is set to above the bootstrap task.
169 * TODO NMGS - different screen modes - might free mem?
170 */
171
172 first_avail = round_page(args->first_avail);
173
174
175 /* map in the exception vectors */
176 /*
177 * map the kernel text, data and bss. Don't forget other regions too
178 */
179 for (i = 0; i < args->kern_info.region_count; i++) {
180 #if MACH_KDB
181 if (args->kern_info.regions[i].prot == VM_PROT_NONE &&
182 i == args->kern_info.region_count - 1) {
183 /* assume that's the kernel symbol table */
184 kern_sym_start = args->kern_info.regions[i].addr;
185 kern_sym_size = args->kern_info.regions[i].size;
186 printf("kernel symbol table at 0x%x size 0x%x\n",
187 kern_sym_start, kern_sym_size);
188 args->kern_info.regions[i].prot |=
189 (VM_PROT_WRITE|VM_PROT_READ);
190 }
191 #endif /* MACH_KDB */
192
193 #ifdef __MACHO__
194 /* Skip the VECTORS segment */
195 if (args->kern_info.regions[i].addr == 0)
196 continue;
197 #endif
198
199 boot_region_count = args->task_info.region_count;
200 boot_size = 0;
201 boot_task_end_offset = 0;
202 /* Map bootstrap task pages 1-1 so that user_bootstrap can find it */
203 for (i = 0; i < boot_region_count; i++) {
204 if (args->task_info.regions[i].mapped) {
205 /* kernel requires everything page aligned */
206 #if DEBUG
207 printf("mapping virt 0x%08x to phys 0x%08x end 0x%x, prot=0x%b\n",
208 ppc_trunc_page(args->task_info.base_addr +
209 args->task_info.regions[i].offset),
210 ppc_trunc_page(args->task_info.base_addr +
211 args->task_info.regions[i].offset),
212 ppc_round_page(args->task_info.base_addr +
213 args->task_info.regions[i].offset +
214 args->task_info.regions[i].size),
215 args->task_info.regions[i].prot,
216 "\x10\1READ\2WRITE\3EXEC");
217 #endif /* DEBUG */
218
219 (void)pmap_map(
220 ppc_trunc_page(args->task_info.base_addr +
221 args->task_info.regions[i].offset),
222 ppc_trunc_page(args->task_info.base_addr +
223 args->task_info.regions[i].offset),
224 ppc_round_page(args->task_info.base_addr +
225 args->task_info.regions[i].offset +
226 args->task_info.regions[i].size),
227 args->task_info.regions[i].prot);
228
229 /* Count the size of mapped space */
230 boot_size += args->task_info.regions[i].size;
231
232 /* There may be an overlapping physical page
233 * mapped to two different virtual addresses
234 */
235 if (boot_task_end_offset >
236 args->task_info.regions[i].offset) {
237 boot_size -= boot_task_end_offset -
238 args->task_info.regions[i].offset;
239 #if DEBUG
240 printf("WARNING - bootstrap overlaps regions\n");
241 #endif /* DEBUG */
242 }
243
244 boot_task_end_offset =
245 args->task_info.regions[i].offset +
246 args->task_info.regions[i].size;
247 }
248 }
249
250 if (boot_region_count) {
251
252 /* Add a new region to the bootstrap task for it's stack */
253 args->task_info.regions[boot_region_count].addr =
254 BOOT_STACK_BASE;
255 args->task_info.regions[boot_region_count].size =
256 BOOT_STACK_SIZE;
257 args->task_info.regions[boot_region_count].mapped = FALSE;
258 boot_region_count++;
259
260 boot_start = args->task_info.base_addr;
261 boot_region_desc = (vm_offset_t) args->task_info.regions;
262 /* TODO NMGS need to put param info onto top of boot stack */
263 boot_task_thread_state.r1 = BOOT_STACK_PTR-0x100;
264 boot_task_thread_state.srr0 = args->task_info.entry;
265 boot_task_thread_state.srr1 =
266 MSR_MARK_SYSCALL(MSR_EXPORT_MASK_SET);
267
268 boot_thread_state_flavor = PPC_THREAD_STATE;
269 boot_thread_state_count = PPC_THREAD_STATE_COUNT;
270 boot_thread_state =
271 (thread_state_t)&boot_task_thread_state;
272 }
273
274
275
276 }
277