]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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> | |
d52fe63f | 44 | #include <ppc/mem.h> |
1c79356b A |
45 | |
46 | #include <pexpert/pexpert.h> | |
47 | ||
48 | extern const char version[]; | |
49 | extern const char version_variant[]; | |
50 | ||
51 | extern unsigned int intstack_top_ss; /* declared in start.s */ | |
1c79356b A |
52 | extern unsigned int debstackptr; /* declared in start.s */ |
53 | extern unsigned int debstack_top_ss; /* declared in start.s */ | |
1c79356b A |
54 | |
55 | extern void thandler(void); /* trap handler */ | |
56 | extern void ihandler(void); /* interrupt handler */ | |
57 | extern void shandler(void); /* syscall handler */ | |
0b4e3aa0 | 58 | extern void chandler(void); /* system choke */ |
1c79356b A |
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) */ | |
0b4e3aa0 A |
102 | ihandler, /* Software Shutdown Context (T_SHUTDOWN) */ |
103 | chandler /* Software System choke (crash) (T_CHOKE) */ | |
1c79356b A |
104 | }; |
105 | ||
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; | |
116 | bat_t bat; | |
117 | extern vm_offset_t static_memory_end; | |
118 | ||
119 | /* | |
120 | * Setup per_proc info for first cpu. | |
121 | */ | |
122 | ||
123 | per_proc_info[0].cpu_number = 0; | |
124 | per_proc_info[0].cpu_flags = 0; | |
125 | per_proc_info[0].istackptr = 0; /* we're on the interrupt stack */ | |
126 | per_proc_info[0].intstack_top_ss = intstack_top_ss; | |
1c79356b A |
127 | per_proc_info[0].debstackptr = debstackptr; |
128 | per_proc_info[0].debstack_top_ss = debstack_top_ss; | |
0b4e3aa0 | 129 | per_proc_info[0].interrupts_enabled = 0; |
1c79356b A |
130 | per_proc_info[0].active_kloaded = (unsigned int) |
131 | &active_kloaded[0]; | |
132 | per_proc_info[0].cpu_data = (unsigned int) | |
133 | &cpu_data[0]; | |
134 | per_proc_info[0].active_stacks = (unsigned int) | |
135 | &active_stacks[0]; | |
136 | per_proc_info[0].need_ast = (unsigned int) | |
137 | &need_ast[0]; | |
138 | per_proc_info[0].FPU_thread = 0; | |
139 | per_proc_info[0].FPU_vmmCtx = 0; | |
140 | per_proc_info[0].VMX_thread = 0; | |
141 | per_proc_info[0].VMX_vmmCtx = 0; | |
142 | ||
143 | machine_slot[0].is_cpu = TRUE; | |
144 | ||
145 | cpu_init(); | |
146 | ||
147 | /* | |
148 | * Setup some processor related structures to satisfy funnels. | |
149 | * Must be done before using unparallelized device drivers. | |
150 | */ | |
151 | processor_ptr[0] = &processor_array[0]; | |
152 | master_cpu = 0; | |
153 | master_processor = cpu_to_processor(master_cpu); | |
154 | ||
155 | /* Set up segment registers as VM through space 0 */ | |
156 | for (i=0; i<=15; i++) { | |
157 | isync(); | |
158 | mtsrin((KERNEL_SEG_REG0_VALUE | (i << 20)), i * 0x10000000); | |
159 | sync(); | |
160 | } | |
161 | ||
162 | static_memory_end = round_page(args->topOfKernelData);; | |
163 | /* Get platform expert set up */ | |
164 | PE_init_platform(FALSE, args); | |
165 | ||
166 | ||
167 | /* This is how the BATs get configured */ | |
168 | /* IBAT[0] maps Segment 0 1:1 */ | |
169 | /* DBAT[0] maps Segment 0 1:1 */ | |
170 | /* DBAT[2] maps the I/O Segment 1:1 */ | |
171 | /* DBAT[3] maps the Video Segment 1:1 */ | |
172 | ||
d52fe63f A |
173 | |
174 | /* Initialize shadow IBATs */ | |
175 | shadow_BAT.IBATs[0].upper=BAT_INVALID; | |
176 | shadow_BAT.IBATs[0].lower=BAT_INVALID; | |
177 | shadow_BAT.IBATs[1].upper=BAT_INVALID; | |
178 | shadow_BAT.IBATs[1].lower=BAT_INVALID; | |
179 | shadow_BAT.IBATs[2].upper=BAT_INVALID; | |
180 | shadow_BAT.IBATs[2].lower=BAT_INVALID; | |
181 | shadow_BAT.IBATs[3].upper=BAT_INVALID; | |
182 | shadow_BAT.IBATs[3].lower=BAT_INVALID; | |
183 | ||
184 | /* Initialize shadow DBATs */ | |
185 | shadow_BAT.DBATs[0].upper=BAT_INVALID; | |
186 | shadow_BAT.DBATs[0].lower=BAT_INVALID; | |
187 | shadow_BAT.DBATs[1].upper=BAT_INVALID; | |
188 | shadow_BAT.DBATs[1].lower=BAT_INVALID; | |
189 | shadow_BAT.DBATs[2].upper=BAT_INVALID; | |
190 | shadow_BAT.DBATs[2].lower=BAT_INVALID; | |
191 | shadow_BAT.DBATs[3].upper=BAT_INVALID; | |
192 | shadow_BAT.DBATs[3].lower=BAT_INVALID; | |
193 | ||
194 | ||
1c79356b A |
195 | /* If v_baseAddr is non zero, use DBAT3 to map the video segment */ |
196 | videoAddr = args->Video.v_baseAddr & 0xF0000000; | |
197 | if (videoAddr) { | |
d52fe63f A |
198 | /* start off specifying 1-1 mapping of video seg */ |
199 | bat.upper.word = videoAddr; | |
200 | bat.lower.word = videoAddr; | |
201 | ||
202 | bat.upper.bits.bl = 0x7ff; /* size = 256M */ | |
203 | bat.upper.bits.vs = 1; | |
204 | bat.upper.bits.vp = 0; | |
205 | ||
206 | bat.lower.bits.wimg = PTE_WIMG_IO; | |
207 | bat.lower.bits.pp = 2; /* read/write access */ | |
208 | ||
209 | shadow_BAT.DBATs[3].upper = bat.upper.word; | |
210 | shadow_BAT.DBATs[3].lower = bat.lower.word; | |
211 | ||
212 | sync();isync(); | |
213 | ||
214 | mtdbatu(3, BAT_INVALID); /* invalidate old mapping */ | |
215 | mtdbatl(3, bat.lower.word); | |
216 | mtdbatu(3, bat.upper.word); | |
217 | sync();isync(); | |
1c79356b A |
218 | } |
219 | ||
220 | /* Use DBAT2 to map the io segment */ | |
221 | addr = get_io_base_addr() & 0xF0000000; | |
222 | if (addr != videoAddr) { | |
d52fe63f A |
223 | /* start off specifying 1-1 mapping of io seg */ |
224 | bat.upper.word = addr; | |
225 | bat.lower.word = addr; | |
226 | ||
227 | bat.upper.bits.bl = 0x7ff; /* size = 256M */ | |
228 | bat.upper.bits.vs = 1; | |
229 | bat.upper.bits.vp = 0; | |
230 | ||
231 | bat.lower.bits.wimg = PTE_WIMG_IO; | |
232 | bat.lower.bits.pp = 2; /* read/write access */ | |
233 | ||
234 | shadow_BAT.DBATs[2].upper = bat.upper.word; | |
235 | shadow_BAT.DBATs[2].lower = bat.lower.word; | |
236 | ||
237 | sync();isync(); | |
238 | mtdbatu(2, BAT_INVALID); /* invalidate old mapping */ | |
239 | mtdbatl(2, bat.lower.word); | |
240 | mtdbatu(2, bat.upper.word); | |
241 | sync();isync(); | |
1c79356b A |
242 | } |
243 | ||
244 | if (!PE_parse_boot_arg("diag", &dgWork.dgFlags)) dgWork.dgFlags=0; /* Set diagnostic flags */ | |
245 | if(dgWork.dgFlags & enaExpTrace) trcWork.traceMask = 0xFFFFFFFF; /* If tracing requested, enable it */ | |
246 | ||
247 | #if 0 | |
248 | GratefulDebInit((bootBumbleC *)&(args->Video)); /* Initialize the GratefulDeb debugger */ | |
249 | #endif | |
250 | ||
251 | printf_init(); /* Init this in case we need debugger */ | |
252 | panic_init(); /* Init this in case we need debugger */ | |
253 | ||
254 | /* setup debugging output if one has been chosen */ | |
255 | PE_init_kprintf(FALSE); | |
256 | kprintf("kprintf initialized\n"); | |
257 | ||
258 | /* create the console for verbose or pretty mode */ | |
259 | PE_create_console(); | |
260 | ||
261 | /* setup console output */ | |
262 | PE_init_printf(FALSE); | |
263 | ||
264 | kprintf("version_variant = %s\n", version_variant); | |
265 | kprintf("version = %s\n", version); | |
266 | ||
267 | #if DEBUG | |
268 | printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n", | |
269 | __GNUC__,__GNUC_MINOR__); | |
270 | ||
271 | /* Processor version information */ | |
272 | { | |
273 | unsigned int pvr; | |
274 | __asm__ ("mfpvr %0" : "=r" (pvr)); | |
275 | printf("processor version register : 0x%08x\n",pvr); | |
276 | } | |
277 | for (i = 0; i < kMaxDRAMBanks; i++) { | |
278 | if (args->PhysicalDRAM[i].size) | |
279 | printf("DRAM at 0x%08x size 0x%08x\n", | |
280 | args->PhysicalDRAM[i].base, | |
281 | args->PhysicalDRAM[i].size); | |
282 | } | |
283 | #endif /* DEBUG */ | |
284 | ||
285 | /* | |
286 | * VM initialization, after this we're using page tables... | |
287 | */ | |
288 | if (!PE_parse_boot_arg("maxmem", &maxmem)) | |
289 | maxmem=0; | |
290 | else | |
291 | maxmem = maxmem * (1024 * 1024); | |
292 | ||
293 | ppc_vm_init(maxmem, args); | |
294 | ||
295 | PE_init_platform(TRUE, args); | |
296 | ||
297 | machine_startup(args); | |
298 | } | |
299 | ||
300 | ppc_init_cpu( | |
301 | struct per_proc_info *proc_info) | |
302 | { | |
303 | int i; | |
304 | unsigned int gph; | |
305 | savectl *sctl; /* Savearea controls */ | |
306 | ||
307 | if(proc_info->savedSave) { /* Do we have a savearea set up already? */ | |
308 | mtsprg(1, proc_info->savedSave); /* Set saved address of savearea */ | |
309 | } | |
310 | else { | |
311 | gph = (unsigned int)save_get_phys(); /* Get a savearea (physical addressing) */ | |
312 | mtsprg(1, gph); /* Set physical address of savearea */ | |
313 | } | |
314 | ||
315 | cpu_init(); | |
316 | ||
317 | proc_info->Lastpmap = 0; /* Clear last used space */ | |
318 | ||
319 | /* Set up segment registers as VM through space 0 */ | |
320 | for (i=0; i<=15; i++) { | |
321 | isync(); | |
322 | mtsrin((KERNEL_SEG_REG0_VALUE | (i << 20)), i * 0x10000000); | |
323 | sync(); | |
324 | } | |
325 | ||
326 | ppc_vm_cpu_init(proc_info); | |
327 | ||
328 | ml_thrm_init(); /* Start thermal monitoring on this processor */ | |
329 | ||
330 | slave_main(); | |
331 | } |