2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
30 #include <kern/misc_protos.h>
31 #include <kern/thread.h>
32 #include <kern/processor.h>
33 #include <machine/machine_routines.h>
35 #include <ppc/proc_reg.h>
36 #include <ppc/misc_protos.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>
45 #include <pexpert/pexpert.h>
47 extern const char version
[];
48 extern const char version_variant
[];
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 */
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 */
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 */
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) */
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) */
124 int pc_trace_buf
[1024] = {0};
125 int pc_trace_cnt
= 1024;
127 void ppc_init(boot_args
*args
)
130 unsigned long *src
,*dst
;
132 unsigned long addr
, videoAddr
;
135 extern vm_offset_t static_memory_end
;
138 * Setup per_proc info for first cpu.
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)
155 per_proc_info
[0].cpu_data
= (unsigned int)
157 per_proc_info
[0].active_stacks
= (unsigned int)
159 per_proc_info
[0].need_ast
= (unsigned int)
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;
166 machine_slot
[0].is_cpu
= TRUE
;
171 * Setup some processor related structures to satisfy funnels.
172 * Must be done before using unparallelized device drivers.
174 processor_ptr
[0] = &processor_array
[0];
176 master_processor
= cpu_to_processor(master_cpu
);
178 /* Set up segment registers as VM through space 0 */
179 for (i
=0; i
<=15; i
++) {
181 mtsrin((KERNEL_SEG_REG0_VALUE
| (i
<< 20)), i
* 0x10000000);
185 static_memory_end
= round_page(args
->topOfKernelData
);;
186 /* Get platform expert set up */
187 PE_init_platform(FALSE
, args
);
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 */
196 /* If v_baseAddr is non zero, use DBAT3 to map the video segment */
197 videoAddr
= args
->Video
.v_baseAddr
& 0xF0000000;
199 /* start off specifying 1-1 mapping of video seg */
200 bat
.upper
.word
= videoAddr
;
201 bat
.lower
.word
= videoAddr
;
203 bat
.upper
.bits
.bl
= 0x7ff; /* size = 256M */
204 bat
.upper
.bits
.vs
= 1;
205 bat
.upper
.bits
.vp
= 0;
207 bat
.lower
.bits
.wimg
= PTE_WIMG_IO
;
208 bat
.lower
.bits
.pp
= 2; /* read/write access */
211 mtdbatu(3, BAT_INVALID
); /* invalidate old mapping */
212 mtdbatl(3, bat
.lower
.word
);
213 mtdbatu(3, bat
.upper
.word
);
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
;
224 bat
.upper
.bits
.bl
= 0x7ff; /* size = 256M */
225 bat
.upper
.bits
.vs
= 1;
226 bat
.upper
.bits
.vp
= 0;
228 bat
.lower
.bits
.wimg
= PTE_WIMG_IO
;
229 bat
.lower
.bits
.pp
= 2; /* read/write access */
232 mtdbatu(2, BAT_INVALID
); /* invalidate old mapping */
233 mtdbatl(2, bat
.lower
.word
);
234 mtdbatu(2, bat
.upper
.word
);
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 */
242 GratefulDebInit((bootBumbleC
*)&(args
->Video
)); /* Initialize the GratefulDeb debugger */
245 printf_init(); /* Init this in case we need debugger */
246 panic_init(); /* Init this in case we need debugger */
248 /* setup debugging output if one has been chosen */
249 PE_init_kprintf(FALSE
);
250 kprintf("kprintf initialized\n");
252 /* create the console for verbose or pretty mode */
255 /* setup console output */
256 PE_init_printf(FALSE
);
258 kprintf("version_variant = %s\n", version_variant
);
259 kprintf("version = %s\n", version
);
262 printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n",
263 __GNUC__
,__GNUC_MINOR__
);
265 /* Processor version information */
268 __asm__ ("mfpvr %0" : "=r" (pvr
));
269 printf("processor version register : 0x%08x\n",pvr
);
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
);
280 * VM initialization, after this we're using page tables...
282 if (!PE_parse_boot_arg("maxmem", &maxmem
))
285 maxmem
= maxmem
* (1024 * 1024);
287 ppc_vm_init(maxmem
, args
);
289 PE_init_platform(TRUE
, args
);
291 machine_startup(args
);
295 struct per_proc_info
*proc_info
)
299 savectl
*sctl
; /* Savearea controls */
301 if(proc_info
->savedSave
) { /* Do we have a savearea set up already? */
302 mtsprg(1, proc_info
->savedSave
); /* Set saved address of savearea */
305 gph
= (unsigned int)save_get_phys(); /* Get a savearea (physical addressing) */
306 mtsprg(1, gph
); /* Set physical address of savearea */
311 proc_info
->Lastpmap
= 0; /* Clear last used space */
313 /* Set up segment registers as VM through space 0 */
314 for (i
=0; i
<=15; i
++) {
316 mtsrin((KERNEL_SEG_REG0_VALUE
| (i
<< 20)), i
* 0x10000000);
320 ppc_vm_cpu_init(proc_info
);
322 ml_thrm_init(); /* Start thermal monitoring on this processor */