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