1 /* $NetBSD: machdep.c,v 1.11 2009/11/26 00:19:17 matt Exp $ */
4 * Copyright (c) 2006 Jachym Holecek
7 * Written for DFC Design, s.r.o.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * Based on Walnut and Explora.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.11 2009/11/26 00:19:17 matt Exp $");
39 #include "opt_compat_netbsd.h"
41 #include "opt_ipkdb.h"
42 #include "opt_modular.h"
43 #include "opt_virtex.h"
46 #include <sys/param.h>
49 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/msgbuf.h>
54 #include <sys/reboot.h>
55 #include <sys/syscallargs.h>
56 #include <sys/syslog.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
59 #include <sys/boot_flag.h>
60 #include <sys/ksyms.h>
61 #include <sys/device.h>
63 #include <uvm/uvm_extern.h>
65 #include <net/netisr.h>
69 #include <machine/bus.h>
70 #include <machine/powerpc.h>
71 #include <machine/trap.h>
73 #include <powerpc/spr.h>
75 #include <evbppc/virtex/dcr.h>
76 #include <evbppc/virtex/virtex.h>
81 #include <machine/db_machdep.h>
82 #include <ddb/db_extern.h>
90 * Global variables used here and there
92 struct vm_map
*mb_map
= NULL
;
93 struct vm_map
*phys_map
= NULL
;
96 * This should probably be in autoconf! XXX
99 char machine
[] = MACHINE
; /* from <machine/param.h> */
100 char machine_arch
[] = MACHINE_ARCH
; /* from <machine/param.h> */
103 paddr_t msgbuf_paddr
;
104 vaddr_t msgbuf_vaddr
;
106 #if NKSYMS || defined(DDB) || defined(MODULAR)
107 void *startsym
, *endsym
;
111 void initppc(u_int
, u_int
);
113 static void dumpsys(void);
114 static void install_extint(void (*)(void));
115 static void trapcpy(int, void *, size_t);
118 /* These two live in powerpc/powerpc/trap_subr.S */
119 extern int extint
, extsize
;
120 extern u_long extint_call
;
122 extern int defaulttrap
, defaultsize
;
123 extern int sctrap
, scsize
;
124 extern int alitrap
, alisize
;
125 extern int dsitrap
, dsisize
;
126 extern int isitrap
, isisize
;
127 extern int mchktrap
, mchksize
;
128 extern int tlbimiss4xx
, tlbim4size
;
129 extern int tlbdmiss4xx
, tlbdm4size
;
130 extern int pitfitwdog
, pitfitwdogsize
;
131 extern int debugtrap
, debugsize
;
132 extern int errata51handler
, errata51size
;
134 extern int ddblow
, ddbsize
;
137 extern int ipkdblow
, ipkdbsize
;
140 /* BSS segment start & end. */
141 extern char edata
[], end
[];
143 /* One region holds all memory, the other is terminator expected by 405 pmap. */
145 struct mem_region physmemr
[MEMREGIONS
];
146 struct mem_region availmemr
[MEMREGIONS
];
153 /* EXC_EXI handled by install_extint(). */
154 { EXC_SC
, &sctrap
, &scsize
},
155 { EXC_ALI
, &alitrap
, &alisize
},
156 { EXC_DSI
, &dsitrap
, &dsisize
},
157 { EXC_ISI
, &isitrap
, &isisize
},
158 { EXC_MCHK
, &mchktrap
, &mchksize
},
159 { EXC_ITMISS
, &tlbimiss4xx
, &tlbim4size
},
160 { EXC_DTMISS
, &tlbdmiss4xx
, &tlbdm4size
},
162 /* EXC_{PIT, FIT, WDOG} handlers are spaced by 0x10 bytes only.. */
163 { EXC_PIT
, &pitfitwdog
, &pitfitwdogsize
},
164 { EXC_DEBUG
, &debugtrap
, &debugsize
},
166 /* PPC405GP Rev D errata item 51 */
167 { EXC_DTMISS
|EXC_ALI
, &errata51handler
, &errata51size
},
170 { EXC_PGM
, &ddblow
, &ddbsize
},
172 { EXC_PGM
, &ipkdblow
, &ipkdbsize
},
176 /* Maximum TLB page size. */
177 #define TLB_PG_SIZE (16*1024*1024)
180 initppc(u_int startkernel
, u_int endkernel
)
182 struct cpu_info
* const ci
= curcpu();
186 /* Initialize cache info for memcpy, memset, etc. */
189 memset(physmemr
, 0, sizeof(physmemr
)); /* [1].size = 0 */
190 memset(availmemr
, 0, sizeof(availmemr
)); /* [1].size = 0 */
192 memsize
= (PHYSMEM
* 1024 * 1024) & ~PGOFSET
;
194 physmemr
[0].start
= 0;
195 physmemr
[0].size
= memsize
;
197 availmemr
[0].start
= startkernel
;
198 availmemr
[0].size
= memsize
- availmemr
[0].start
;
200 /* Map kernel memory linearly. */
201 for (addr
= 0; addr
< endkernel
; addr
+= TLB_PG_SIZE
)
202 ppc4xx_tlb_reserve(addr
, addr
, TLB_PG_SIZE
, TLB_EX
);
204 /* Give design-specific code a hint for reserved mappings. */
205 virtex_machdep_init(roundup(memsize
, TLB_PG_SIZE
), TLB_PG_SIZE
,
206 physmemr
, availmemr
);
210 curpcb
= lwp_getpcb(&lwp0
);
211 memset(curpcb
, 0, sizeof(struct pcb
));
212 curpcb
->pcb_pm
= pmap_kernel();
214 for (exc
= EXC_RSVD
; exc
<= EXC_LAST
; exc
+= 0x100)
215 trapcpy(exc
, &defaulttrap
, (size_t)&defaultsize
);
217 for (i
= 0; i
< __arraycount(traps
); i
++)
218 trapcpy(traps
[i
].vector
, traps
[i
].addr
, (size_t)traps
[i
].size
);
220 __syncicache((void *)EXC_RST
, EXC_LAST
- EXC_RST
+ 0x100);
222 /* set exception vector base */
225 /* handle trap instruction as PGM exception */
226 dbcr0
= mfspr(SPR_DBCR0
) & ~DBCR0_TDE
;
227 mtspr(SPR_DBCR0
, dbcr0
);
229 install_extint(ext_intr
);
231 /* enable translation */
238 : : "r"(0), "K"(PSL_IR
| PSL_DR
| PSL_ME
));
240 /* now that we enabled MMU, we can map console */
244 pmap_bootstrap(startkernel
, endkernel
);
246 #if NKSYMS || defined(DDB) || defined(MODULAR)
247 ksyms_addsyms_elf((int)((u_int
)endsym
- (u_int
)startsym
), startsym
, endsym
);
250 if (boothowto
& RB_KDB
)
258 if (boothowto
& RB_KDB
)
272 * Install a trap vector. We cannot use memcpy because the
273 * destination may be zero. Borrowed from Explora.
276 trapcpy(int dest
, void *src
, size_t len
)
278 uint32_t *dest_p
= (void *)dest
;
279 uint32_t *src_p
= src
;
282 *dest_p
++ = *src_p
++;
283 len
-= sizeof(uint32_t);
288 install_extint(void (*handler
)(void))
290 u_long offset
= (u_long
)handler
- (u_long
)&extint_call
;
293 if (offset
> 0x1ffffff)
294 panic("install_extint: too far away");
297 /* Patch branch target in EXC_EXI handler. */
298 extint_call
= (extint_call
& 0xfc000003) | offset
;
300 memcpy((void *)EXC_EXI
, &extint
, (size_t)&extsize
);
301 __syncicache((void *)&extint_call
, sizeof(extint_call
));
302 __syncicache((void *)EXC_EXI
, (int)&extsize
);
306 * Machine dependent startup code.
309 char msgbuf
[MSGBUFSIZE
];
314 /* For use by propdb. */
315 static u_int memsize
= PHYSMEM
* 1024 * 1024;
316 static u_int cpuspeed
= CPUFREQ
* 1000 * 1000;
319 vaddr_t minaddr
, maxaddr
;
322 curcpu()->ci_khz
= cpuspeed
/ 1000;
324 /* Initialize error message buffer. */
325 initmsgbuf((void *)msgbuf
, round_page(MSGBUFSIZE
));
327 printf("%s%s", copyright
, version
);
329 format_bytes(pbuf
, sizeof(pbuf
), ctob(physmem
));
330 printf("total memory = %s\n", pbuf
);
334 * Allocate a submap for physio
336 phys_map
= uvm_km_suballoc(kernel_map
, &minaddr
, &maxaddr
,
337 VM_PHYS_SIZE
, 0, false, NULL
);
340 * No need to allocate an mbuf cluster submap. Mbuf clusters
341 * are allocated via the pool allocator, and we use direct-mapped
345 format_bytes(pbuf
, sizeof(pbuf
), ptoa(uvmexp
.free
));
346 printf("avail memory = %s\n", pbuf
);
349 * Set up the board properties database.
353 pn
= prop_number_create_integer(memsize
);
355 if (prop_dictionary_set(board_properties
, "mem-size", pn
) == false)
356 panic("setting mem-size");
357 prop_object_release(pn
);
359 pn
= prop_number_create_integer(cpuspeed
);
361 if (prop_dictionary_set(board_properties
, "processor-frequency",
363 panic("setting processor-frequency");
364 prop_object_release(pn
);
367 * Now that we have VM, malloc()s are OK in bus_space.
369 bus_space_mallocok();
377 printf("dumpsys: TBD\n");
380 /* Hook used by 405 pmap module. */
382 mem_regions(struct mem_region
**mem
, struct mem_region
**avail
)
389 * Halt or reboot the machine after syncing/dumping according to howto.
392 cpu_reboot(int howto
, char *what
)
395 static char str
[256];
396 char *ap
= str
, *ap1
= ap
;
399 if (!cold
&& !(howto
& RB_NOSYNC
) && !syncing
) {
401 vfs_shutdown(); /* sync */
402 resettodr(); /* set wall clock */
407 if (!cold
&& (howto
& RB_DUMP
))
412 pmf_system_shutdown(boothowto
);
414 if ((howto
& RB_POWERDOWN
) == RB_POWERDOWN
) {
415 /* Power off here if we know how...*/
418 if (howto
& RB_HALT
) {
419 printf("halted\n\n");
421 goto reboot
; /* XXX for now... */
424 printf("dropping to debugger\n");
429 printf("dropping to kgdb\n");
435 printf("rebooting\n\n");
437 if (strlen(what
) > sizeof str
- 5)
438 printf("boot string too large, ignored\n");
441 ap1
= ap
= str
+ strlen(str
);
446 if (howto
& RB_SINGLE
)
454 /* flush cache for msgbuf */
455 __syncicache((void *)msgbuf_paddr
, round_page(MSGBUFSIZE
));
460 printf("ppc4xx_reset() failed!\n");
477 return spllower(ipl
); /* XXX */