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