]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/ppc_init.c
790a9ce1aa324df2fd477465c50542b56a2592c9
[apple/xnu.git] / osfmk / 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 * @OSF_COPYRIGHT@
27 */
28
29 #include <debug.h>
30 #include <mach_kdb.h>
31 #include <mach_kdp.h>
32
33 #include <kern/misc_protos.h>
34 #include <kern/thread.h>
35 #include <kern/processor.h>
36 #include <machine/machine_routines.h>
37 #include <ppc/boot.h>
38 #include <ppc/proc_reg.h>
39 #include <ppc/misc_protos.h>
40 #include <ppc/pmap.h>
41 #include <ppc/new_screen.h>
42 #include <ppc/exception.h>
43 #include <ppc/Firmware.h>
44 #include <ppc/savearea.h>
45 #include <ppc/low_trace.h>
46 #include <ppc/Diagnostics.h>
47 #include <ppc/mem.h>
48
49 #include <pexpert/pexpert.h>
50
51 extern const char version[];
52 extern const char version_variant[];
53
54 extern unsigned int intstack_top_ss; /* declared in start.s */
55 extern unsigned int debstackptr; /* declared in start.s */
56 extern unsigned int debstack_top_ss; /* declared in start.s */
57
58 extern void thandler(void); /* trap handler */
59 extern void ihandler(void); /* interrupt handler */
60 extern void shandler(void); /* syscall handler */
61 extern void chandler(void); /* system choke */
62 extern void fpu_switch(void); /* fp handler */
63 extern void vec_switch(void); /* vector handler */
64 extern void atomic_switch_trap(void); /* fast path atomic thread switch */
65
66 void (*exception_handlers[])(void) = {
67 thandler, /* 0x000 INVALID EXCEPTION (T_IN_VAIN) */
68 thandler, /* 0x100 System reset (T_RESET) */
69 thandler, /* 0x200 Machine check (T_MACHINE_CHECK) */
70 thandler, /* 0x300 Data access (T_DATA_ACCESS) */
71 thandler, /* 0x400 Instruction access (T_INSTRUCTION_ACCESS) */
72 ihandler, /* 0x500 External interrupt (T_INTERRUPT) */
73 thandler, /* 0x600 Alignment (T_ALIGNMENT) */
74 thandler, /* 0x700 fp exc, ill/priv instr, trap (T_PROGRAM) */
75 fpu_switch, /* 0x800 Floating point disabled (T_FP_UNAVAILABLE) */
76 ihandler, /* 0x900 Decrementer (T_DECREMENTER) */
77 thandler, /* 0xA00 I/O controller interface (T_IO_ERROR) */
78 thandler, /* 0xB00 INVALID EXCEPTION (T_RESERVED) */
79 shandler, /* 0xC00 System call exception (T_SYSTEM_CALL) */
80 thandler, /* 0xD00 Trace (T_TRACE) */
81 thandler, /* 0xE00 FP assist (T_FP_ASSIST) */
82 thandler, /* 0xF00 Performance monitor (T_PERF_MON) */
83 vec_switch, /* 0xF20 VMX (T_VMX) */
84 thandler, /* 0x1000 INVALID EXCEPTION (T_INVALID_EXCP0) */
85 thandler, /* 0x1100 INVALID EXCEPTION (T_INVALID_EXCP1) */
86 thandler, /* 0x1200 INVALID EXCEPTION (T_INVALID_EXCP2) */
87 thandler, /* 0x1300 instruction breakpoint (T_INSTRUCTION_BKPT) */
88 ihandler, /* 0x1400 system management (T_SYSTEM_MANAGEMENT) */
89 thandler, /* 0x1600 Altivec Assist (T_ALTIVEC_ASSIST) */
90 ihandler, /* 0x1700 Thermal interruption (T_THERMAL) */
91 thandler, /* 0x1800 INVALID EXCEPTION (T_INVALID_EXCP5) */
92 thandler, /* 0x1900 INVALID EXCEPTION (T_INVALID_EXCP6) */
93 thandler, /* 0x1A00 INVALID EXCEPTION (T_INVALID_EXCP7) */
94 thandler, /* 0x1B00 INVALID EXCEPTION (T_INVALID_EXCP8) */
95 thandler, /* 0x1C00 INVALID EXCEPTION (T_INVALID_EXCP9) */
96 thandler, /* 0x1D00 INVALID EXCEPTION (T_INVALID_EXCP10) */
97 thandler, /* 0x1E00 INVALID EXCEPTION (T_INVALID_EXCP11) */
98 thandler, /* 0x1F00 INVALID EXCEPTION (T_INVALID_EXCP12) */
99 thandler, /* 0x1F00 INVALID EXCEPTION (T_INVALID_EXCP13) */
100 thandler, /* 0x2000 Run Mode/Trace (T_RUNMODE_TRACE) */
101
102 ihandler, /* Software Signal processor (T_SIGP) */
103 thandler, /* Software Preemption (T_PREEMPT) */
104 ihandler, /* Software INVALID EXCEPTION (T_CSWITCH) */
105 ihandler, /* Software Shutdown Context (T_SHUTDOWN) */
106 chandler /* Software System choke (crash) (T_CHOKE) */
107 };
108
109 int pc_trace_buf[1024] = {0};
110 int pc_trace_cnt = 1024;
111
112 void ppc_init(boot_args *args)
113 {
114 int i;
115 unsigned long *src,*dst;
116 char *str;
117 unsigned long addr, videoAddr;
118 unsigned int maxmem;
119 unsigned int cputrace;
120 bat_t bat;
121 extern vm_offset_t static_memory_end;
122
123 /*
124 * Setup per_proc info for first cpu.
125 */
126
127 per_proc_info[0].cpu_number = 0;
128 per_proc_info[0].cpu_flags = 0;
129 per_proc_info[0].istackptr = 0; /* we're on the interrupt stack */
130 per_proc_info[0].intstack_top_ss = intstack_top_ss;
131 per_proc_info[0].debstackptr = debstackptr;
132 per_proc_info[0].debstack_top_ss = debstack_top_ss;
133 per_proc_info[0].interrupts_enabled = 0;
134 per_proc_info[0].active_kloaded = (unsigned int)
135 &active_kloaded[0];
136 set_machine_current_thread(&pageout_thread);
137 set_machine_current_act(&pageout_act);
138 pageout_thread.top_act = &pageout_act;
139 pageout_act.thread = &pageout_thread;
140 per_proc_info[0].pp_preemption_count = 1;
141 per_proc_info[0].pp_simple_lock_count = 0;
142 per_proc_info[0].pp_interrupt_level = 0;
143 per_proc_info[0].active_stacks = (unsigned int)
144 &active_stacks[0];
145 per_proc_info[0].need_ast = (unsigned int)
146 &need_ast[0];
147 per_proc_info[0].FPU_owner = 0;
148 per_proc_info[0].VMX_owner = 0;
149
150 machine_slot[0].is_cpu = TRUE;
151
152 cpu_init();
153
154 /*
155 * Setup some processor related structures to satisfy funnels.
156 * Must be done before using unparallelized device drivers.
157 */
158 processor_ptr[0] = &processor_array[0];
159 master_cpu = 0;
160 master_processor = cpu_to_processor(master_cpu);
161
162 /* Set up segment registers as VM through space 0 */
163 for (i=0; i<=15; i++) {
164 isync();
165 mtsrin((KERNEL_SEG_REG0_VALUE | (i << 20)), i * 0x10000000);
166 sync();
167 }
168
169 static_memory_end = round_page(args->topOfKernelData);;
170 /* Get platform expert set up */
171 PE_init_platform(FALSE, args);
172
173
174 /* This is how the BATs get configured */
175 /* IBAT[0] maps Segment 0 1:1 */
176 /* DBAT[0] maps Segment 0 1:1 */
177 /* DBAT[2] maps the I/O Segment 1:1 */
178 /* DBAT[3] maps the Video Segment 1:1 */
179
180
181 /* Initialize shadow IBATs */
182 shadow_BAT.IBATs[0].upper=BAT_INVALID;
183 shadow_BAT.IBATs[0].lower=BAT_INVALID;
184 shadow_BAT.IBATs[1].upper=BAT_INVALID;
185 shadow_BAT.IBATs[1].lower=BAT_INVALID;
186 shadow_BAT.IBATs[2].upper=BAT_INVALID;
187 shadow_BAT.IBATs[2].lower=BAT_INVALID;
188 shadow_BAT.IBATs[3].upper=BAT_INVALID;
189 shadow_BAT.IBATs[3].lower=BAT_INVALID;
190
191 /* Initialize shadow DBATs */
192 shadow_BAT.DBATs[0].upper=BAT_INVALID;
193 shadow_BAT.DBATs[0].lower=BAT_INVALID;
194 shadow_BAT.DBATs[1].upper=BAT_INVALID;
195 shadow_BAT.DBATs[1].lower=BAT_INVALID;
196 shadow_BAT.DBATs[2].upper=BAT_INVALID;
197 shadow_BAT.DBATs[2].lower=BAT_INVALID;
198 shadow_BAT.DBATs[3].upper=BAT_INVALID;
199 shadow_BAT.DBATs[3].lower=BAT_INVALID;
200
201
202 /* If v_baseAddr is non zero, use DBAT3 to map the video segment */
203 videoAddr = args->Video.v_baseAddr & 0xF0000000;
204 if (videoAddr) {
205 /* start off specifying 1-1 mapping of video seg */
206 bat.upper.word = videoAddr;
207 bat.lower.word = videoAddr;
208
209 bat.upper.bits.bl = 0x7ff; /* size = 256M */
210 bat.upper.bits.vs = 1;
211 bat.upper.bits.vp = 0;
212
213 bat.lower.bits.wimg = PTE_WIMG_IO;
214 bat.lower.bits.pp = 2; /* read/write access */
215
216 shadow_BAT.DBATs[3].upper = bat.upper.word;
217 shadow_BAT.DBATs[3].lower = bat.lower.word;
218
219 sync();isync();
220
221 mtdbatu(3, BAT_INVALID); /* invalidate old mapping */
222 mtdbatl(3, bat.lower.word);
223 mtdbatu(3, bat.upper.word);
224 sync();isync();
225 }
226
227 /* Use DBAT2 to map the io segment */
228 addr = get_io_base_addr() & 0xF0000000;
229 if (addr != videoAddr) {
230 /* start off specifying 1-1 mapping of io seg */
231 bat.upper.word = addr;
232 bat.lower.word = addr;
233
234 bat.upper.bits.bl = 0x7ff; /* size = 256M */
235 bat.upper.bits.vs = 1;
236 bat.upper.bits.vp = 0;
237
238 bat.lower.bits.wimg = PTE_WIMG_IO;
239 bat.lower.bits.pp = 2; /* read/write access */
240
241 shadow_BAT.DBATs[2].upper = bat.upper.word;
242 shadow_BAT.DBATs[2].lower = bat.lower.word;
243
244 sync();isync();
245 mtdbatu(2, BAT_INVALID); /* invalidate old mapping */
246 mtdbatl(2, bat.lower.word);
247 mtdbatu(2, bat.upper.word);
248 sync();isync();
249 }
250
251 if (!PE_parse_boot_arg("diag", &dgWork.dgFlags)) dgWork.dgFlags=0; /* Set diagnostic flags */
252 if(dgWork.dgFlags & enaExpTrace) trcWork.traceMask = 0xFFFFFFFF; /* If tracing requested, enable it */
253
254 if(PE_parse_boot_arg("ctrc", &cputrace)) { /* See if tracing is limited to a specific cpu */
255 trcWork.traceMask = (trcWork.traceMask & 0xFFFFFFF0) | (cputrace & 0xF); /* Limit to 4 */
256 }
257
258 #if 0
259 GratefulDebInit((bootBumbleC *)&(args->Video)); /* Initialize the GratefulDeb debugger */
260 #endif
261
262 printf_init(); /* Init this in case we need debugger */
263 panic_init(); /* Init this in case we need debugger */
264
265 /* setup debugging output if one has been chosen */
266 PE_init_kprintf(FALSE);
267 kprintf("kprintf initialized\n");
268
269 /* create the console for verbose or pretty mode */
270 PE_create_console();
271
272 /* setup console output */
273 PE_init_printf(FALSE);
274
275 kprintf("version_variant = %s\n", version_variant);
276 kprintf("version = %s\n", version);
277
278 #if DEBUG
279 printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n",
280 __GNUC__,__GNUC_MINOR__);
281
282 /* Processor version information */
283 {
284 unsigned int pvr;
285 __asm__ ("mfpvr %0" : "=r" (pvr));
286 printf("processor version register : 0x%08x\n",pvr);
287 }
288 for (i = 0; i < kMaxDRAMBanks; i++) {
289 if (args->PhysicalDRAM[i].size)
290 printf("DRAM at 0x%08x size 0x%08x\n",
291 args->PhysicalDRAM[i].base,
292 args->PhysicalDRAM[i].size);
293 }
294 #endif /* DEBUG */
295
296 /*
297 * VM initialization, after this we're using page tables...
298 */
299 if (!PE_parse_boot_arg("maxmem", &maxmem))
300 maxmem=0;
301 else
302 maxmem = maxmem * (1024 * 1024);
303
304 ppc_vm_init(maxmem, args);
305
306 PE_init_platform(TRUE, args);
307
308 machine_startup(args);
309 }
310
311 ppc_init_cpu(
312 struct per_proc_info *proc_info)
313 {
314 int i;
315
316 if(!(proc_info->next_savearea)) /* Do we have a savearea set up already? */
317 proc_info->next_savearea = (savearea *)save_get_init(); /* Get a savearea */
318
319 cpu_init();
320
321 proc_info->pp_preemption_count = 1;
322 proc_info->pp_simple_lock_count = 0;
323 proc_info->pp_interrupt_level = 0;
324
325 proc_info->Lastpmap = 0; /* Clear last used space */
326
327 /* Set up segment registers as VM through space 0 */
328 for (i=0; i<=15; i++) {
329 isync();
330 mtsrin((KERNEL_SEG_REG0_VALUE | (i << 20)), i * 0x10000000);
331 sync();
332 }
333
334 ppc_vm_cpu_init(proc_info);
335
336 ml_thrm_init(); /* Start thermal monitoring on this processor */
337
338 slave_main();
339 }