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