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