|
|
1.1 root 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:
43: #include <pexpert/pexpert.h>
44:
45: extern const char version[];
46:
47: extern unsigned int intstack_top_ss; /* declared in start.s */
48: #if MACH_KDP || MACH_KDB
49: extern unsigned int debstackptr; /* declared in start.s */
50: extern unsigned int debstack_top_ss; /* declared in start.s */
51: #endif /* MACH_KDP || MACH_KDB */
52:
53: unsigned int kernel_seg_regs[] = {
54: KERNEL_SEG_REG0_VALUE, /* 0 */
55: KERNEL_SEG_REG0_VALUE + 1, /* 1 */
56: KERNEL_SEG_REG0_VALUE + 2, /* 2 */
57: SEG_REG_INVALID, /* 3 */
58: SEG_REG_INVALID, /* 4 */
59: KERNEL_SEG_REG5_VALUE, /* 5 - I/O segment */
60: SEG_REG_INVALID, /* 6 */
61: SEG_REG_INVALID, /* 7 */
62: KERNEL_SEG_REG8_VALUE, /* 8-F are possible IO space */
63: KERNEL_SEG_REG9_VALUE,
64: KERNEL_SEG_REG10_VALUE,
65: KERNEL_SEG_REG11_VALUE,
66: KERNEL_SEG_REG12_VALUE,
67: KERNEL_SEG_REG13_VALUE,
68: KERNEL_SEG_REG14_VALUE, /* 14 - A/V video */
69: KERNEL_SEG_REG15_VALUE /* 15 - NuBus etc */
70: };
71:
72: extern void thandler(void); /* trap handler */
73: extern void ihandler(void); /* interrupt handler */
74: extern void shandler(void); /* syscall handler */
75: extern void fpu_switch(void); /* fp handler */
76: extern void vec_switch(void); /* vector handler */
77: extern void atomic_switch_trap(void); /* fast path atomic thread switch */
78:
79: void (*exception_handlers[])(void) = {
80: thandler, /* 0x000 INVALID EXCEPTION */
81: thandler, /* 0x100 System reset */
82: thandler, /* 0x200 Machine check */
83: thandler, /* 0x300 Data access */
84: thandler, /* 0x400 Instruction access */
85: ihandler, /* 0x500 External interrupt */
86: thandler, /* 0x600 Alignment */
87: thandler, /* 0x700 fp exc, ill/priv instr, trap */
88: fpu_switch, /* 0x800 Floating point disabled */
89: ihandler, /* 0x900 Decrementer */
90: thandler, /* 0xA00 I/O controller interface */
91: thandler, /* 0xB00 INVALID EXCEPTION */
92: shandler, /* 0xC00 System call exception */
93: thandler, /* 0xD00 Trace */
94: thandler, /* 0xE00 FP assist */
95: thandler, /* 0xF00 Performance monitor */
96: vec_switch, /* 0xF20 VMX */
97: thandler, /* 0x1000 INVALID EXCEPTION */
98: thandler, /* 0x1100 INVALID EXCEPTION */
99: thandler, /* 0x1200 INVALID EXCEPTION */
100: thandler, /* 0x1300 instruction breakpoint */
101: thandler, /* 0x1400 system management */
102: thandler, /* 0x1500 INVALID EXCEPTION */
103: thandler, /* 0x1600 Altivec Assist */
104: thandler, /* 0x1700 INVALID EXCEPTION */
105: thandler, /* 0x1800 INVALID EXCEPTION */
106: thandler, /* 0x1900 INVALID EXCEPTION */
107: thandler, /* 0x1A00 INVALID EXCEPTION */
108: thandler, /* 0x1B00 INVALID EXCEPTION */
109: thandler, /* 0x1C00 INVALID EXCEPTION */
110: thandler, /* 0x1D00 INVALID EXCEPTION */
111: thandler, /* 0x1E00 INVALID EXCEPTION */
112: thandler, /* 0x1F00 INVALID EXCEPTION */
113: thandler, /* 0x2000 Run Mode/Trace */
114: ihandler, /* 0x2100 Signal processor */
115: thandler /* 0x2200 Preemption */
116: };
117:
118: /*
119: * per_proc_info is accessed with VM switched off via sprg0
120: * Note that we always get enough space for an extra cache line.
121: * That is because for performance, we need to align the struct
122: * on a cache boundary. With the extra space, we can shift the
123: * array up to 31 bytes to align
124: */
125: unsigned char per_proc_area[NCPUS*sizeof(struct per_proc_info)+32] = {0};
126: struct per_proc_info *per_proc_info;
127:
128: void ppc_init(boot_args *args)
129: {
130: int i;
131: unsigned long *src,*dst;
132: char *str;
133: unsigned long addr, videoAddr;
134: unsigned int maxmem;
135: bat_t bat;
136: extern vm_offset_t static_memory_end;
137:
138: /*
139: * Setup per_proc info for first cpu.
140: */
141:
142: /* First align the per_proc_info to a cache line */
143: per_proc_info = (struct per_proc_info *)(((unsigned int)
144: (&per_proc_area[0])+31)
145: &(-32));
146: per_proc_info[0].cpu_number = 0;
147: per_proc_info[0].cpu_flags = 0;
148: per_proc_info[0].istackptr = 0; /* we're on the interrupt stack */
149: per_proc_info[0].intstack_top_ss = intstack_top_ss;
150: #if MACH_KDP || MACH_KDB
151: per_proc_info[0].debstackptr = debstackptr;
152: per_proc_info[0].debstack_top_ss = debstack_top_ss;
153: #endif /* MACH_KDP || MACH_KDB */
154: per_proc_info[0].phys_exception_handlers =
155: (vm_offset_t)&exception_handlers;
156: per_proc_info[0].get_interrupts_enabled =
157: fake_get_interrupts_enabled;
158: per_proc_info[0].set_interrupts_enabled =
159: fake_set_interrupts_enabled;
160: per_proc_info[0].virt_per_proc_info = (unsigned int)
161: &per_proc_info[0];
162: per_proc_info[0].active_kloaded = (unsigned int)
163: &active_kloaded[0];
164: per_proc_info[0].cpu_data = (unsigned int)
165: &cpu_data[0];
166: per_proc_info[0].active_stacks = (unsigned int)
167: &active_stacks[0];
168: per_proc_info[0].need_ast = (unsigned int)
169: &need_ast[0];
170: per_proc_info[0].FPU_thread = 0;
171:
172: machine_slot[0].is_cpu = TRUE;
173:
174: mtsprg(0, (unsigned int)&per_proc_info[0]); /* Point sprg 0 at it */
175:
176: cpu_init();
177:
178: /*
179: * Setup some processor related structures to satisfy funnels.
180: * Must be done before using unparallelized device drivers.
181: */
182: processor_ptr[0] = &processor_array[0];
183: master_cpu = 0;
184: master_processor = cpu_to_processor(master_cpu);
185:
186: /* Set up segment registers as VM through space 0 */
187: for (i=0; i<=15; i++) {
188: isync();
189: mtsrin((KERNEL_SEG_REG0_VALUE | (i << 20)), i * 0x10000000);
190: sync();
191: }
192:
193: static_memory_end = round_page(args->topOfKernelData);;
194: /* Get platform expert set up */
195: PE_init_platform(FALSE, args);
196:
197:
198: /* This is how the BATs get configured */
199: /* IBAT[0] maps Segment 0 1:1 */
200: /* DBAT[0] maps Segment 0 1:1 */
201: /* DBAT[2] maps the I/O Segment 1:1 */
202: /* DBAT[3] maps the Video Segment 1:1 */
203:
204: /* If v_baseAddr is non zero, use DBAT3 to map the video segment */
205: videoAddr = args->Video.v_baseAddr & 0xF0000000;
206: if (videoAddr) {
207: /* start off specifying 1-1 mapping of video seg */
208: bat.upper.word = videoAddr;
209: bat.lower.word = videoAddr;
210:
211: bat.upper.bits.bl = 0x7ff; /* size = 256M */
212: bat.upper.bits.vs = 1;
213: bat.upper.bits.vp = 0;
214:
215: bat.lower.bits.wimg = PTE_WIMG_IO;
216: bat.lower.bits.pp = 2; /* read/write access */
217:
218: sync();isync();
219: mtdbatu(3, BAT_INVALID); /* invalidate old mapping */
220: mtdbatl(3, bat.lower.word);
221: mtdbatu(3, bat.upper.word);
222: sync();isync();
223: }
224:
225: /* Use DBAT2 to map the io segment */
226: addr = get_io_base_addr() & 0xF0000000;
227: if (addr != videoAddr) {
228: /* start off specifying 1-1 mapping of io seg */
229: bat.upper.word = addr;
230: bat.lower.word = addr;
231:
232: bat.upper.bits.bl = 0x7ff; /* size = 256M */
233: bat.upper.bits.vs = 1;
234: bat.upper.bits.vp = 0;
235:
236: bat.lower.bits.wimg = PTE_WIMG_IO;
237: bat.lower.bits.pp = 2; /* read/write access */
238:
239: sync();isync();
240: mtdbatu(2, BAT_INVALID); /* invalidate old mapping */
241: mtdbatl(2, bat.lower.word);
242: mtdbatu(2, bat.upper.word);
243: sync();isync();
244: }
245:
246: #if 0
247: GratefulDebInit((bootBumbleC *)&(args->Video)); /* Initialize the GratefulDeb debugger */
248: #endif
249:
250: /* setup debugging output if one has been chosen */
251: PE_init_kprintf(FALSE);
252: kprintf("kprintf initialized\n");
253:
254: /* create the console for verbose or pretty mode */
255: PE_create_console();
256:
257: /* setup console output */
258: PE_init_printf(FALSE);
259:
260: #if DEBUG
261: printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n",
262: __GNUC__,__GNUC_MINOR__);
263:
264: /* Processor version information */
265: {
266: unsigned int pvr;
267: __asm__ ("mfpvr %0" : "=r" (pvr));
268: printf("processor version register : 0x%08x\n",pvr);
269: }
270: for (i = 0; i < kMaxDRAMBanks; i++) {
271: if (args->PhysicalDRAM[i].size)
272: printf("DRAM at 0x%08x size 0x%08x\n",
273: args->PhysicalDRAM[i].base,
274: args->PhysicalDRAM[i].size);
275: }
276: #endif /* DEBUG */
277:
278: /*
279: * VM initialization, after this we're using page tables...
280: */
281: if (!PE_parse_boot_arg("maxmem", &maxmem))
282: maxmem=0;
283: else
284: maxmem = maxmem * (1024 * 1024);
285:
286: ppc_vm_init(maxmem, args);
287:
288: PE_init_platform(TRUE, args);
289:
290: machine_startup(args);
291: }
292:
293: ppc_init_cpu(
294: struct per_proc_info *proc_info)
295: {
296: int i;
297: unsigned int gph;
298: savectl *sctl; /* Savearea controls */
299:
300: mtsprg(0, (unsigned int)proc_info); /* Point sprg 0 at the per_proc_area */
301:
302: gph = save_get_phys(); /* Get a savearea (physical addressing) */
303: mtsprg(1, gph); /* Set physical address of savearea */
304:
305: cpu_init();
306:
307: /* Set up segment registers as VM through space 0 */
308: for (i=0; i<=15; i++) {
309: isync();
310: mtsrin((KERNEL_SEG_REG0_VALUE | (i << 20)), i * 0x10000000);
311: sync();
312: }
313:
314: ppc_vm_cpu_init(proc_info);
315:
316: slave_main();
317: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.