]>
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> | |
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 | } |