| @@ -1,936 +1,936 @@ | | | @@ -1,936 +1,936 @@ |
1 | /* $NetBSD: machdep.c,v 1.96 2014/01/11 08:07:16 tsutsui Exp $ */ | | 1 | /* $NetBSD: machdep.c,v 1.97 2014/01/11 16:34:05 tsutsui Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Tohru Nishimura. | | 8 | * by Tohru Nishimura. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | | 32 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ |
33 | | | 33 | |
34 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.96 2014/01/11 08:07:16 tsutsui Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.97 2014/01/11 16:34:05 tsutsui Exp $"); |
35 | | | 35 | |
36 | #include "opt_ddb.h" | | 36 | #include "opt_ddb.h" |
37 | #include "opt_kgdb.h" | | 37 | #include "opt_kgdb.h" |
38 | #include "opt_compat_sunos.h" | | 38 | #include "opt_compat_sunos.h" |
39 | #include "opt_modular.h" | | 39 | #include "opt_modular.h" |
40 | #include "opt_panicbutton.h" | | 40 | #include "opt_panicbutton.h" |
41 | #include "opt_m68k_arch.h" | | 41 | #include "opt_m68k_arch.h" |
42 | | | 42 | |
43 | #include <sys/param.h> | | 43 | #include <sys/param.h> |
44 | #include <sys/systm.h> | | 44 | #include <sys/systm.h> |
45 | #include <sys/kernel.h> | | 45 | #include <sys/kernel.h> |
46 | #include <sys/proc.h> | | 46 | #include <sys/proc.h> |
47 | #include <sys/buf.h> | | 47 | #include <sys/buf.h> |
48 | #include <sys/reboot.h> | | 48 | #include <sys/reboot.h> |
49 | #include <sys/conf.h> | | 49 | #include <sys/conf.h> |
50 | #include <sys/file.h> | | 50 | #include <sys/file.h> |
51 | #include <sys/device.h> | | 51 | #include <sys/device.h> |
52 | #include <sys/malloc.h> | | 52 | #include <sys/malloc.h> |
53 | #include <sys/mbuf.h> | | 53 | #include <sys/mbuf.h> |
54 | #include <sys/msgbuf.h> | | 54 | #include <sys/msgbuf.h> |
55 | #include <sys/ioctl.h> | | 55 | #include <sys/ioctl.h> |
56 | #include <sys/tty.h> | | 56 | #include <sys/tty.h> |
57 | #include <sys/mount.h> | | 57 | #include <sys/mount.h> |
58 | #include <sys/exec.h> | | 58 | #include <sys/exec.h> |
59 | #include <sys/exec_aout.h> /* for MID_* */ | | 59 | #include <sys/exec_aout.h> /* for MID_* */ |
60 | #include <sys/core.h> | | 60 | #include <sys/core.h> |
61 | #include <sys/kauth.h> | | 61 | #include <sys/kauth.h> |
62 | #include <sys/kcore.h> | | 62 | #include <sys/kcore.h> |
63 | #include <sys/vnode.h> | | 63 | #include <sys/vnode.h> |
64 | #include <sys/syscallargs.h> | | 64 | #include <sys/syscallargs.h> |
65 | #include <sys/ksyms.h> | | 65 | #include <sys/ksyms.h> |
66 | #include <sys/module.h> | | 66 | #include <sys/module.h> |
67 | #ifdef KGDB | | 67 | #ifdef KGDB |
68 | #include <sys/kgdb.h> | | 68 | #include <sys/kgdb.h> |
69 | #endif | | 69 | #endif |
70 | #include <sys/boot_flag.h> | | 70 | #include <sys/boot_flag.h> |
71 | #define ELFSIZE 32 | | 71 | #define ELFSIZE 32 |
72 | #include <sys/exec_elf.h> | | 72 | #include <sys/exec_elf.h> |
73 | | | 73 | |
74 | #include <uvm/uvm_extern.h> | | 74 | #include <uvm/uvm_extern.h> |
75 | | | 75 | |
76 | #include <sys/sysctl.h> | | 76 | #include <sys/sysctl.h> |
77 | | | 77 | |
78 | #include <machine/bootinfo.h> | | 78 | #include <machine/bootinfo.h> |
79 | #include <machine/cpu.h> | | 79 | #include <machine/cpu.h> |
80 | #include <machine/reg.h> | | 80 | #include <machine/reg.h> |
81 | #include <machine/pcb.h> | | 81 | #include <machine/pcb.h> |
82 | #include <machine/psl.h> | | 82 | #include <machine/psl.h> |
83 | #include <machine/pte.h> | | 83 | #include <machine/pte.h> |
84 | #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ | | 84 | #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ |
85 | | | 85 | |
86 | #include <dev/cons.h> | | 86 | #include <dev/cons.h> |
87 | #include <dev/mm.h> | | 87 | #include <dev/mm.h> |
88 | | | 88 | |
89 | #if defined(DDB) | | 89 | #if defined(DDB) |
90 | #include <machine/db_machdep.h> | | 90 | #include <machine/db_machdep.h> |
91 | #include <ddb/db_sym.h> | | 91 | #include <ddb/db_sym.h> |
92 | #include <ddb/db_extern.h> | | 92 | #include <ddb/db_extern.h> |
93 | #endif | | 93 | #endif |
94 | | | 94 | |
95 | #include "ksyms.h" | | 95 | #include "ksyms.h" |
96 | | | 96 | |
97 | /* | | 97 | /* |
98 | * Info for CTL_HW | | 98 | * Info for CTL_HW |
99 | */ | | 99 | */ |
100 | char machine[] = MACHINE; | | 100 | char machine[] = MACHINE; |
101 | char cpu_model[120]; | | 101 | char cpu_model[120]; |
102 | | | 102 | |
103 | /* Our exported CPU info; we can have only one. */ | | 103 | /* Our exported CPU info; we can have only one. */ |
104 | struct cpu_info cpu_info_store; | | 104 | struct cpu_info cpu_info_store; |
105 | | | 105 | |
106 | struct vm_map *phys_map = NULL; | | 106 | struct vm_map *phys_map = NULL; |
107 | | | 107 | |
108 | int maxmem; /* max memory per process */ | | 108 | int maxmem; /* max memory per process */ |
109 | | | 109 | |
110 | extern u_int lowram; | | 110 | extern u_int lowram; |
111 | | | 111 | |
112 | void luna68k_init(void); | | 112 | void luna68k_init(void); |
113 | void identifycpu(void); | | 113 | void identifycpu(void); |
114 | void dumpsys(void); | | 114 | void dumpsys(void); |
115 | | | 115 | |
116 | void straytrap(int, u_short); | | 116 | void straytrap(int, u_short); |
117 | void nmihand(struct frame); | | 117 | void nmihand(struct frame); |
118 | | | 118 | |
119 | int cpu_dumpsize(void); | | 119 | int cpu_dumpsize(void); |
120 | int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); | | 120 | int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *); |
121 | void cpu_init_kcore_hdr(void); | | 121 | void cpu_init_kcore_hdr(void); |
122 | | | 122 | |
123 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 123 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
124 | vsize_t symtab_size(vaddr_t); | | 124 | vsize_t symtab_size(vaddr_t); |
125 | #endif | | 125 | #endif |
126 | extern char end[]; | | 126 | extern char end[]; |
127 | extern void *esym; | | 127 | extern void *esym; |
128 | | | 128 | |
129 | /* | | 129 | /* |
130 | * Machine-independent crash dump header info. | | 130 | * Machine-independent crash dump header info. |
131 | */ | | 131 | */ |
132 | cpu_kcore_hdr_t cpu_kcore_hdr; | | 132 | cpu_kcore_hdr_t cpu_kcore_hdr; |
133 | | | 133 | |
134 | int machtype; /* model: 1 for LUNA-1, 2 for LUNA-2 */ | | 134 | int machtype; /* model: 1 for LUNA-1, 2 for LUNA-2 */ |
135 | int sysconsole; /* console: 0 for ttya, 1 for video */ | | 135 | int sysconsole; /* console: 0 for ttya, 1 for video */ |
136 | | | 136 | |
137 | extern struct consdev syscons; | | 137 | extern struct consdev syscons; |
138 | extern void omfb_cnattach(void); | | 138 | extern void omfb_cnattach(void); |
139 | extern void ws_cnattach(void); | | 139 | extern void ws_cnattach(void); |
140 | extern void syscnattach(int); | | 140 | extern void syscnattach(int); |
141 | | | 141 | |
142 | /* | | 142 | /* |
143 | * On the 68020/68030, the value of delay_divisor is roughly | | 143 | * On the 68020/68030, the value of delay_divisor is roughly |
144 | * 2048 / cpuspeed (where cpuspeed is in MHz). | | 144 | * 2048 / cpuspeed (where cpuspeed is in MHz). |
145 | * | | 145 | * |
146 | * On the 68040/68060(?), the value of delay_divisor is roughly | | 146 | * On the 68040/68060(?), the value of delay_divisor is roughly |
147 | * 759 / cpuspeed (where cpuspeed is in MHz). | | 147 | * 759 / cpuspeed (where cpuspeed is in MHz). |
148 | * XXX -- is the above formula correct? | | 148 | * XXX -- is the above formula correct? |
149 | */ | | 149 | */ |
150 | int cpuspeed = 25; /* only used for printing later */ | | 150 | int cpuspeed = 25; /* only used for printing later */ |
151 | int delay_divisor = 30; /* for delay() loop count */ | | 151 | int delay_divisor = 30; /* for delay() loop count */ |
152 | | | 152 | |
153 | /* | | 153 | /* |
154 | * Early initialization, before main() is called. | | 154 | * Early initialization, before main() is called. |
155 | */ | | 155 | */ |
156 | void | | 156 | void |
157 | luna68k_init(void) | | 157 | luna68k_init(void) |
158 | { | | 158 | { |
159 | volatile uint8_t *pio0 = (void *)0x49000000; | | 159 | volatile uint8_t *pio0 = (void *)0x49000000; |
160 | int sw1, i; | | 160 | int sw1, i; |
161 | char *cp; | | 161 | char *cp; |
162 | extern char bootarg[64]; | | 162 | extern char bootarg[64]; |
163 | | | 163 | |
164 | extern paddr_t avail_start, avail_end; | | 164 | extern paddr_t avail_start, avail_end; |
165 | | | 165 | |
166 | /* initialize cn_tab for early console */ | | 166 | /* initialize cn_tab for early console */ |
167 | #if 1 | | 167 | #if 1 |
168 | cn_tab = &syscons; | | 168 | cn_tab = &syscons; |
169 | #else | | 169 | #else |
170 | cn_tab = &romcons; | | 170 | cn_tab = &romcons; |
171 | #endif | | 171 | #endif |
172 | | | 172 | |
173 | /* | | 173 | /* |
174 | * Tell the VM system about available physical memory. The | | 174 | * Tell the VM system about available physical memory. The |
175 | * luna68k only has one segment. | | 175 | * luna68k only has one segment. |
176 | */ | | 176 | */ |
177 | uvm_page_physload(atop(avail_start), atop(avail_end), | | 177 | uvm_page_physload(atop(avail_start), atop(avail_end), |
178 | atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); | | 178 | atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); |
179 | | | 179 | |
180 | /* | | 180 | /* |
181 | * Initialize error message buffer (at end of core). | | 181 | * Initialize error message buffer (at end of core). |
182 | * avail_end was pre-decremented in pmap_bootstrap to compensate. | | 182 | * avail_end was pre-decremented in pmap_bootstrap to compensate. |
183 | */ | | 183 | */ |
184 | for (i = 0; i < btoc(MSGBUFSIZE); i++) | | 184 | for (i = 0; i < btoc(MSGBUFSIZE); i++) |
185 | pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, | | 185 | pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE, |
186 | avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0); | | 186 | avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0); |
187 | pmap_update(pmap_kernel()); | | 187 | pmap_update(pmap_kernel()); |
188 | initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); | | 188 | initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); |
189 | | | 189 | |
190 | | | 190 | |
191 | pio0[3] = 0xb6; | | 191 | pio0[3] = 0xb6; |
192 | pio0[2] = 1 << 6; /* enable parity check */ | | 192 | pio0[2] = 1 << 6; /* enable parity check */ |
193 | pio0[3] = 0xb6; | | 193 | pio0[3] = 0xb6; |
194 | sw1 = pio0[0]; /* dip sw1 value */ | | 194 | sw1 = pio0[0]; /* dip sw1 value */ |
195 | sw1 ^= 0xff; | | 195 | sw1 ^= 0xff; |
196 | sysconsole = !(sw1 & 0x2); /* console selection */ | | 196 | sysconsole = !(sw1 & 0x2); /* console selection */ |
197 | | | 197 | |
198 | /* | | 198 | /* |
199 | * Check if boothowto and bootdev values are passed by our bootloader. | | 199 | * Check if boothowto and bootdev values are passed by our bootloader. |
200 | */ | | 200 | */ |
201 | if ((bootdev & B_MAGICMASK) == B_DEVMAGIC) { | | 201 | if ((bootdev & B_MAGICMASK) == B_DEVMAGIC) { |
202 | /* Valid value is set; no need to parse bootarg. */ | | 202 | /* Valid value is set; no need to parse bootarg. */ |
203 | return; | | 203 | return; |
204 | } | | 204 | } |
205 | | | 205 | |
206 | /* | | 206 | /* |
207 | * No valid bootdev value is set. | | 207 | * No valid bootdev value is set. |
208 | * Assume we are booted by ROM monitor directly using a.out kernel | | 208 | * Assume we are booted by ROM monitor directly using a.out kernel |
209 | * and we have to parse bootarg passed from the monitor to set | | 209 | * and we have to parse bootarg passed from the monitor to set |
210 | * proper boothowto and check netboot. | | 210 | * proper boothowto and check netboot. |
211 | */ | | 211 | */ |
212 | | | 212 | |
213 | /* set default to "sd0a" with no howto flags */ | | 213 | /* set default to "sd0a" with no howto flags */ |
214 | bootdev = MAKEBOOTDEV(0, LUNA68K_BOOTADPT_SPC, 0, 0, 0); | | 214 | bootdev = MAKEBOOTDEV(0, LUNA68K_BOOTADPT_SPC, 0, 0, 0); |
215 | boothowto = 0; | | 215 | boothowto = 0; |
216 | | | 216 | |
217 | /* | | 217 | /* |
218 | * 'bootarg' on LUNA has: | | 218 | * 'bootarg' on LUNA has: |
219 | * "<args of x command> ENADDR=<addr> HOST=<host> SERVER=<name>" | | 219 | * "<args of x command> ENADDR=<addr> HOST=<host> SERVER=<name>" |
220 | * where <addr> is MAC address of which network loader used (not | | 220 | * where <addr> is MAC address of which network loader used (not |
221 | * necessarily same as one at 0x4101.FFE0), <host> and <name> | | 221 | * necessarily same as one at 0x4101.FFE0), <host> and <name> |
222 | * are the values of HOST and SERVER environment variables. | | 222 | * are the values of HOST and SERVER environment variables. |
223 | * | | 223 | * |
224 | * 'bootarg' on LUNA-II has "<args of x command>" only. | | 224 | * 'bootarg' on LUNA-II has "<args of x command>" only. |
225 | * | | 225 | * |
226 | * NetBSD/luna68k cares only the first argment; any of "sda". | | 226 | * NetBSD/luna68k cares only the first argment; any of "sda". |
227 | */ | | 227 | */ |
228 | bootarg[63] = '\0'; | | 228 | bootarg[63] = '\0'; |
229 | for (cp = bootarg; *cp != '\0'; cp++) { | | 229 | for (cp = bootarg; *cp != '\0'; cp++) { |
230 | if (*cp == '-') { | | 230 | if (*cp == '-') { |
231 | char c; | | 231 | char c; |
232 | while ((c = *cp) != '\0' && c != ' ') { | | 232 | while ((c = *cp) != '\0' && c != ' ') { |
233 | BOOT_FLAG(c, boothowto); | | 233 | BOOT_FLAG(c, boothowto); |
234 | cp++; | | 234 | cp++; |
235 | } | | 235 | } |
236 | } else if (*cp == 'E' && memcmp("ENADDR=", cp, 7) == 0) { | | 236 | } else if (*cp == 'E' && memcmp("ENADDR=", cp, 7) == 0) { |
237 | bootdev = | | 237 | bootdev = |
238 | MAKEBOOTDEV(0, LUNA68K_BOOTADPT_LANCE, 0, 0, 0); | | 238 | MAKEBOOTDEV(0, LUNA68K_BOOTADPT_LANCE, 0, 0, 0); |
239 | } | | 239 | } |
240 | } | | 240 | } |
241 | } | | 241 | } |
242 | | | 242 | |
243 | /* | | 243 | /* |
244 | * Console initialization: called early on from main, | | 244 | * Console initialization: called early on from main, |
245 | */ | | 245 | */ |
246 | void | | 246 | void |
247 | consinit(void) | | 247 | consinit(void) |
248 | { | | 248 | { |
249 | | | 249 | |
250 | if (sysconsole == 0) | | 250 | if (sysconsole == 0) |
251 | syscnattach(0); | | 251 | syscnattach(0); |
252 | else { | | 252 | else { |
253 | omfb_cnattach(); | | 253 | omfb_cnattach(); |
254 | ws_cnattach(); | | 254 | ws_cnattach(); |
255 | } | | 255 | } |
256 | | | 256 | |
257 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 257 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
258 | ksyms_addsyms_elf((esym != NULL) ? 1 : 0, (void *)&end, esym); | | 258 | ksyms_addsyms_elf((esym != NULL) ? 1 : 0, (void *)&end, esym); |
259 | #endif | | 259 | #endif |
260 | #ifdef DDB | | 260 | #ifdef DDB |
261 | if (boothowto & RB_KDB) | | 261 | if (boothowto & RB_KDB) |
262 | cpu_Debugger(); | | 262 | cpu_Debugger(); |
263 | #endif | | 263 | #endif |
264 | } | | 264 | } |
265 | | | 265 | |
266 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 266 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
267 | | | 267 | |
268 | /* | | 268 | /* |
269 | * Check and compute size of DDB symbols and strings. | | 269 | * Check and compute size of DDB symbols and strings. |
270 | * | | 270 | * |
271 | * Note this function could be called from locore.s before MMU is turned on | | 271 | * Note this function could be called from locore.s before MMU is turned on |
272 | * so we should avoid global variables and function calls. | | 272 | * so we should avoid global variables and function calls. |
273 | */ | | 273 | */ |
274 | vsize_t | | 274 | vsize_t |
275 | symtab_size(vaddr_t hdr) | | 275 | symtab_size(vaddr_t hdr) |
276 | { | | 276 | { |
277 | int i; | | 277 | int i; |
278 | Elf_Ehdr *ehdr; | | 278 | Elf_Ehdr *ehdr; |
279 | Elf_Shdr *shp; | | 279 | Elf_Shdr *shp; |
280 | vaddr_t maxsym; | | 280 | vaddr_t maxsym; |
281 | | | 281 | |
282 | /* | | 282 | /* |
283 | * Check the ELF headers. | | 283 | * Check the ELF headers. |
284 | */ | | 284 | */ |
285 | | | 285 | |
286 | ehdr = (void *)hdr; | | 286 | ehdr = (void *)hdr; |
287 | if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || | | 287 | if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || |
288 | ehdr->e_ident[EI_MAG1] != ELFMAG1 || | | 288 | ehdr->e_ident[EI_MAG1] != ELFMAG1 || |
289 | ehdr->e_ident[EI_MAG2] != ELFMAG2 || | | 289 | ehdr->e_ident[EI_MAG2] != ELFMAG2 || |
290 | ehdr->e_ident[EI_MAG3] != ELFMAG3 || | | 290 | ehdr->e_ident[EI_MAG3] != ELFMAG3 || |
291 | ehdr->e_ident[EI_CLASS] != ELFCLASS32) { | | 291 | ehdr->e_ident[EI_CLASS] != ELFCLASS32) { |
292 | return 0; | | 292 | return 0; |
293 | } | | 293 | } |
294 | | | 294 | |
295 | /* | | 295 | /* |
296 | * Find the end of the symbols and strings. | | 296 | * Find the end of the symbols and strings. |
297 | */ | | 297 | */ |
298 | | | 298 | |
299 | maxsym = 0; | | 299 | maxsym = 0; |
300 | shp = (Elf_Shdr *)(hdr + ehdr->e_shoff); | | 300 | shp = (Elf_Shdr *)(hdr + ehdr->e_shoff); |
301 | for (i = 0; i < ehdr->e_shnum; i++) { | | 301 | for (i = 0; i < ehdr->e_shnum; i++) { |
302 | if (shp[i].sh_type != SHT_SYMTAB && | | 302 | if (shp[i].sh_type != SHT_SYMTAB && |
303 | shp[i].sh_type != SHT_STRTAB) { | | 303 | shp[i].sh_type != SHT_STRTAB) { |
304 | continue; | | 304 | continue; |
305 | } | | 305 | } |
306 | maxsym = max(maxsym, shp[i].sh_offset + shp[i].sh_size); | | 306 | maxsym = max(maxsym, shp[i].sh_offset + shp[i].sh_size); |
307 | } | | 307 | } |
308 | | | 308 | |
309 | return maxsym; | | 309 | return maxsym; |
310 | } | | 310 | } |
311 | #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */ | | 311 | #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */ |
312 | | | 312 | |
313 | /* | | 313 | /* |
314 | * cpu_startup: allocate memory for variable-sized tables. | | 314 | * cpu_startup: allocate memory for variable-sized tables. |
315 | */ | | 315 | */ |
316 | void | | 316 | void |
317 | cpu_startup(void) | | 317 | cpu_startup(void) |
318 | { | | 318 | { |
319 | vaddr_t minaddr, maxaddr; | | 319 | vaddr_t minaddr, maxaddr; |
320 | char pbuf[9]; | | 320 | char pbuf[9]; |
321 | extern void greeting(void); | | 321 | extern void greeting(void); |
322 | | | 322 | |
323 | if (fputype != FPU_NONE) | | 323 | if (fputype != FPU_NONE) |
324 | m68k_make_fpu_idle_frame(); | | 324 | m68k_make_fpu_idle_frame(); |
325 | | | 325 | |
326 | /* | | 326 | /* |
327 | * Initialize the kernel crash dump header. | | 327 | * Initialize the kernel crash dump header. |
328 | */ | | 328 | */ |
329 | cpu_init_kcore_hdr(); | | 329 | cpu_init_kcore_hdr(); |
330 | | | 330 | |
331 | /* | | 331 | /* |
332 | * Good {morning,afternoon,evening,night}. | | 332 | * Good {morning,afternoon,evening,night}. |
333 | */ | | 333 | */ |
334 | printf("%s%s", copyright, version); | | 334 | printf("%s%s", copyright, version); |
335 | identifycpu(); | | 335 | identifycpu(); |
336 | | | 336 | |
337 | format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); | | 337 | format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); |
338 | printf("total memory = %s\n", pbuf); | | 338 | printf("total memory = %s\n", pbuf); |
339 | | | 339 | |
340 | minaddr = 0; | | 340 | minaddr = 0; |
341 | | | 341 | |
342 | /* | | 342 | /* |
343 | * Allocate a submap for physio | | 343 | * Allocate a submap for physio |
344 | */ | | 344 | */ |
345 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 345 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
346 | VM_PHYS_SIZE, 0, false, NULL); | | 346 | VM_PHYS_SIZE, 0, false, NULL); |
347 | | | 347 | |
348 | format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); | | 348 | format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); |
349 | printf("avail memory = %s\n", pbuf); | | 349 | printf("avail memory = %s\n", pbuf); |
350 | | | 350 | |
351 | /* | | 351 | /* |
352 | * Say "Hi" to the world | | 352 | * Say "Hi" to the world |
353 | */ | | 353 | */ |
354 | greeting(); | | 354 | greeting(); |
355 | } | | 355 | } |
356 | | | 356 | |
357 | void | | 357 | void |
358 | identifycpu(void) | | 358 | identifycpu(void) |
359 | { | | 359 | { |
360 | extern int cputype; | | 360 | extern int cputype; |
361 | const char *model, *fpu; | | 361 | const char *model, *fpu; |
362 | | | 362 | |
363 | memset(cpu_model, 0, sizeof(cpu_model)); | | 363 | memset(cpu_model, 0, sizeof(cpu_model)); |
364 | switch (cputype) { | | 364 | switch (cputype) { |
365 | case CPU_68030: | | 365 | case CPU_68030: |
366 | model ="LUNA-I"; | | 366 | model ="LUNA-I"; |
367 | switch (fputype) { | | 367 | switch (fputype) { |
368 | case FPU_68881: | | 368 | case FPU_68881: |
369 | fpu = "MC68881"; | | 369 | fpu = "MC68881"; |
370 | break; | | 370 | break; |
371 | case FPU_68882: | | 371 | case FPU_68882: |
372 | fpu = "MC68882"; | | 372 | fpu = "MC68882"; |
373 | break; | | 373 | break; |
374 | case FPU_NONE: | | 374 | case FPU_NONE: |
375 | fpu = "no"; | | 375 | fpu = "no"; |
376 | break; | | 376 | break; |
377 | default: | | 377 | default: |
378 | fpu = "unknown"; | | 378 | fpu = "unknown"; |
379 | break; | | 379 | break; |
380 | } | | 380 | } |
381 | snprintf(cpu_model, sizeof(cpu_model), | | 381 | snprintf(cpu_model, sizeof(cpu_model), |
382 | "%s (MC68030 CPU+MMU, %s FPU)", model, fpu); | | 382 | "%s (MC68030 CPU+MMU, %s FPU)", model, fpu); |
383 | machtype = LUNA_I; | | 383 | machtype = LUNA_I; |
384 | /* 20MHz 68030 */ | | 384 | /* 20MHz 68030 */ |
385 | cpuspeed = 20; | | 385 | cpuspeed = 20; |
386 | delay_divisor = 102; | | 386 | delay_divisor = 102; |
387 | hz = 60; | | 387 | hz = 60; |
388 | break; | | 388 | break; |
389 | #if defined(M68040) | | 389 | #if defined(M68040) |
390 | case CPU_68040: | | 390 | case CPU_68040: |
391 | model ="LUNA-II"; | | 391 | model ="LUNA-II"; |
392 | snprintf(cpu_model, sizeof(cpu_model), | | 392 | snprintf(cpu_model, sizeof(cpu_model), |
393 | "%s (MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches)", | | 393 | "%s (MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches)", |
394 | model); | | 394 | model); |
395 | machtype = LUNA_II; | | 395 | machtype = LUNA_II; |
396 | /* 25MHz 68040 */ | | 396 | /* 25MHz 68040 */ |
397 | cpuspeed = 25; | | 397 | cpuspeed = 25; |
398 | delay_divisor = 30; | | 398 | delay_divisor = 30; |
399 | /* hz = 100 on LUNA-II */ | | 399 | /* hz = 100 on LUNA-II */ |
400 | break; | | 400 | break; |
401 | #endif | | 401 | #endif |
402 | default: | | 402 | default: |
403 | panic("unknown CPU type"); | | 403 | panic("unknown CPU type"); |
404 | } | | 404 | } |
405 | printf("%s\n", cpu_model); | | 405 | printf("%s\n", cpu_model); |
406 | } | | 406 | } |
407 | | | 407 | |
408 | /* | | 408 | /* |
409 | * machine dependent system variables. | | 409 | * machine dependent system variables. |
410 | */ | | 410 | */ |
411 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") | | 411 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") |
412 | { | | 412 | { |
413 | | | 413 | |
414 | sysctl_createv(clog, 0, NULL, NULL, | | 414 | sysctl_createv(clog, 0, NULL, NULL, |
415 | CTLFLAG_PERMANENT, | | 415 | CTLFLAG_PERMANENT, |
416 | CTLTYPE_NODE, "machdep", NULL, | | 416 | CTLTYPE_NODE, "machdep", NULL, |
417 | NULL, 0, NULL, 0, | | 417 | NULL, 0, NULL, 0, |
418 | CTL_MACHDEP, CTL_EOL); | | 418 | CTL_MACHDEP, CTL_EOL); |
419 | | | 419 | |
420 | sysctl_createv(clog, 0, NULL, NULL, | | 420 | sysctl_createv(clog, 0, NULL, NULL, |
421 | CTLFLAG_PERMANENT, | | 421 | CTLFLAG_PERMANENT, |
422 | CTLTYPE_STRUCT, "console_device", NULL, | | 422 | CTLTYPE_STRUCT, "console_device", NULL, |
423 | sysctl_consdev, 0, NULL, sizeof(dev_t), | | 423 | sysctl_consdev, 0, NULL, sizeof(dev_t), |
424 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); | | 424 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); |
425 | } | | 425 | } |
426 | | | 426 | |
427 | int waittime = -1; | | 427 | int waittime = -1; |
428 | | | 428 | |
429 | void | | 429 | void |
430 | cpu_reboot(int howto, char *bootstr) | | 430 | cpu_reboot(int howto, char *bootstr) |
431 | { | | 431 | { |
432 | struct pcb *pcb = lwp_getpcb(curlwp); | | 432 | struct pcb *pcb = lwp_getpcb(curlwp); |
433 | extern void doboot(void); | | 433 | extern void doboot(void); |
434 | | | 434 | |
435 | /* take a snap shot before clobbering any registers */ | | 435 | /* take a snap shot before clobbering any registers */ |
436 | if (pcb != NULL) | | 436 | if (pcb != NULL) |
437 | savectx(pcb); | | 437 | savectx(pcb); |
438 | | | 438 | |
439 | /* If system is hold, just halt. */ | | 439 | /* If system is hold, just halt. */ |
440 | if (cold) { | | 440 | if (cold) { |
441 | howto |= RB_HALT; | | 441 | howto |= RB_HALT; |
442 | goto haltsys; | | 442 | goto haltsys; |
443 | } | | 443 | } |
444 | | | 444 | |
445 | boothowto = howto; | | 445 | boothowto = howto; |
446 | if ((howto & RB_NOSYNC) == 0 && waittime < 0) { | | 446 | if ((howto & RB_NOSYNC) == 0 && waittime < 0) { |
447 | waittime = 0; | | 447 | waittime = 0; |
448 | vfs_shutdown(); | | 448 | vfs_shutdown(); |
449 | /* | | 449 | /* |
450 | * If we've been adjusting the clock, the todr | | 450 | * If we've been adjusting the clock, the todr |
451 | * will be out of synch; adjust it now. | | 451 | * will be out of synch; adjust it now. |
452 | */ | | 452 | */ |
453 | resettodr(); | | 453 | resettodr(); |
454 | } | | 454 | } |
455 | | | 455 | |
456 | /* Disable interrupts. */ | | 456 | /* Disable interrupts. */ |
457 | splhigh(); | | 457 | splhigh(); |
458 | | | 458 | |
459 | /* If rebooting and a dump is requested, do it. */ | | 459 | /* If rebooting and a dump is requested, do it. */ |
460 | if (howto & RB_DUMP) | | 460 | if (howto & RB_DUMP) |
461 | dumpsys(); | | 461 | dumpsys(); |
462 | | | 462 | |
463 | haltsys: | | 463 | haltsys: |
464 | /* Run any shutdown hooks. */ | | 464 | /* Run any shutdown hooks. */ |
465 | doshutdownhooks(); | | 465 | doshutdownhooks(); |
466 | | | 466 | |
467 | pmf_system_shutdown(boothowto); | | 467 | pmf_system_shutdown(boothowto); |
468 | | | 468 | |
469 | /* Finally, halt/reboot the system. */ | | 469 | /* Finally, halt/reboot the system. */ |
470 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { | | 470 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { |
471 | volatile uint8_t *pio = (void *)0x4d000000; | | 471 | volatile uint8_t *pio = (void *)0x4d000000; |
472 | | | 472 | |
473 | printf("power is going down.\n"); | | 473 | printf("power is going down.\n"); |
474 | DELAY(100000); | | 474 | DELAY(100000); |
475 | pio[3] = 0x94; | | 475 | pio[3] = 0x94; |
476 | pio[2] = 0 << 4; | | 476 | pio[2] = 0 << 4; |
477 | for (;;) | | 477 | for (;;) |
478 | /* NOP */; | | 478 | /* NOP */; |
479 | } | | 479 | } |
480 | if (howto & RB_HALT) { | | 480 | if (howto & RB_HALT) { |
481 | printf("System halted. Hit any key to reboot.\n\n"); | | 481 | printf("System halted. Hit any key to reboot.\n\n"); |
482 | (void)cngetc(); | | 482 | (void)cngetc(); |
483 | } | | 483 | } |
484 | | | 484 | |
485 | printf("rebooting...\n"); | | 485 | printf("rebooting...\n"); |
486 | DELAY(100000); | | 486 | DELAY(100000); |
487 | doboot(); | | 487 | doboot(); |
488 | /*NOTREACHED*/ | | 488 | /*NOTREACHED*/ |
489 | for (;;) | | 489 | for (;;) |
490 | ; | | 490 | ; |
491 | } | | 491 | } |
492 | | | 492 | |
493 | /* | | 493 | /* |
494 | * Initialize the kernel crash dump header. | | 494 | * Initialize the kernel crash dump header. |
495 | */ | | 495 | */ |
496 | void | | 496 | void |
497 | cpu_init_kcore_hdr(void) | | 497 | cpu_init_kcore_hdr(void) |
498 | { | | 498 | { |
499 | cpu_kcore_hdr_t *h = &cpu_kcore_hdr; | | 499 | cpu_kcore_hdr_t *h = &cpu_kcore_hdr; |
500 | struct m68k_kcore_hdr *m = &h->un._m68k; | | 500 | struct m68k_kcore_hdr *m = &h->un._m68k; |
501 | | | 501 | |
502 | memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); | | 502 | memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr)); |
503 | | | 503 | |
504 | /* | | 504 | /* |
505 | * Initialize the `dispatcher' portion of the header. | | 505 | * Initialize the `dispatcher' portion of the header. |
506 | */ | | 506 | */ |
507 | strcpy(h->name, machine); | | 507 | strcpy(h->name, machine); |
508 | h->page_size = PAGE_SIZE; | | 508 | h->page_size = PAGE_SIZE; |
509 | h->kernbase = KERNBASE; | | 509 | h->kernbase = KERNBASE; |
510 | | | 510 | |
511 | /* | | 511 | /* |
512 | * Fill in information about our MMU configuration. | | 512 | * Fill in information about our MMU configuration. |
513 | */ | | 513 | */ |
514 | m->mmutype = mmutype; | | 514 | m->mmutype = mmutype; |
515 | m->sg_v = SG_V; | | 515 | m->sg_v = SG_V; |
516 | m->sg_frame = SG_FRAME; | | 516 | m->sg_frame = SG_FRAME; |
517 | m->sg_ishift = SG_ISHIFT; | | 517 | m->sg_ishift = SG_ISHIFT; |
518 | m->sg_pmask = SG_PMASK; | | 518 | m->sg_pmask = SG_PMASK; |
519 | m->sg40_shift1 = SG4_SHIFT1; | | 519 | m->sg40_shift1 = SG4_SHIFT1; |
520 | m->sg40_mask2 = SG4_MASK2; | | 520 | m->sg40_mask2 = SG4_MASK2; |
521 | m->sg40_shift2 = SG4_SHIFT2; | | 521 | m->sg40_shift2 = SG4_SHIFT2; |
522 | m->sg40_mask3 = SG4_MASK3; | | 522 | m->sg40_mask3 = SG4_MASK3; |
523 | m->sg40_shift3 = SG4_SHIFT3; | | 523 | m->sg40_shift3 = SG4_SHIFT3; |
524 | m->sg40_addr1 = SG4_ADDR1; | | 524 | m->sg40_addr1 = SG4_ADDR1; |
525 | m->sg40_addr2 = SG4_ADDR2; | | 525 | m->sg40_addr2 = SG4_ADDR2; |
526 | m->pg_v = PG_V; | | 526 | m->pg_v = PG_V; |
527 | m->pg_frame = PG_FRAME; | | 527 | m->pg_frame = PG_FRAME; |
528 | | | 528 | |
529 | /* | | 529 | /* |
530 | * Initialize pointer to kernel segment table. | | 530 | * Initialize pointer to kernel segment table. |
531 | */ | | 531 | */ |
532 | m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); | | 532 | m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa); |
533 | | | 533 | |
534 | /* | | 534 | /* |
535 | * Initialize relocation value such that: | | 535 | * Initialize relocation value such that: |
536 | * | | 536 | * |
537 | * pa = (va - KERNBASE) + reloc | | 537 | * pa = (va - KERNBASE) + reloc |
538 | * | | 538 | * |
539 | * Since we're linked and loaded at the same place, | | 539 | * Since we're linked and loaded at the same place, |
540 | * and the kernel is mapped va == pa, this is 0. | | 540 | * and the kernel is mapped va == pa, this is 0. |
541 | */ | | 541 | */ |
542 | m->reloc = 0; | | 542 | m->reloc = 0; |
543 | | | 543 | |
544 | /* | | 544 | /* |
545 | * Define the end of the relocatable range. | | 545 | * Define the end of the relocatable range. |
546 | */ | | 546 | */ |
547 | m->relocend = (uint32_t)end; | | 547 | m->relocend = (uint32_t)end; |
548 | | | 548 | |
549 | /* | | 549 | /* |
550 | * The luna68k has one contiguous memory segment. | | 550 | * The luna68k has one contiguous memory segment. |
551 | */ | | 551 | */ |
552 | m->ram_segs[0].start = 0 /* lowram */; | | 552 | m->ram_segs[0].start = 0 /* lowram */; |
553 | m->ram_segs[0].size = ctob(physmem); | | 553 | m->ram_segs[0].size = ctob(physmem); |
554 | } | | 554 | } |
555 | | | 555 | |
556 | /* | | 556 | /* |
557 | * Compute the size of the machine-dependent crash dump header. | | 557 | * Compute the size of the machine-dependent crash dump header. |
558 | * Returns size in disk blocks. | | 558 | * Returns size in disk blocks. |
559 | */ | | 559 | */ |
560 | | | 560 | |
561 | #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) | | 561 | #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t))) |
562 | #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) | | 562 | #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1)) |
563 | | | 563 | |
564 | int | | 564 | int |
565 | cpu_dumpsize(void) | | 565 | cpu_dumpsize(void) |
566 | { | | 566 | { |
567 | | | 567 | |
568 | return btodb(MDHDRSIZE); | | 568 | return btodb(MDHDRSIZE); |
569 | } | | 569 | } |
570 | | | 570 | |
571 | /* | | 571 | /* |
572 | * Called by dumpsys() to dump the machine-dependent header. | | 572 | * Called by dumpsys() to dump the machine-dependent header. |
573 | */ | | 573 | */ |
574 | int | | 574 | int |
575 | cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) | | 575 | cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop) |
576 | { | | 576 | { |
577 | int buf[MDHDRSIZE / sizeof(int)]; | | 577 | int buf[MDHDRSIZE / sizeof(int)]; |
578 | cpu_kcore_hdr_t *chdr; | | 578 | cpu_kcore_hdr_t *chdr; |
579 | kcore_seg_t *kseg; | | 579 | kcore_seg_t *kseg; |
580 | int error; | | 580 | int error; |
581 | | | 581 | |
582 | kseg = (kcore_seg_t *)buf; | | 582 | kseg = (kcore_seg_t *)buf; |
583 | chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / | | 583 | chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / |
584 | sizeof(int)]; | | 584 | sizeof(int)]; |
585 | | | 585 | |
586 | /* Create the segment header. */ | | 586 | /* Create the segment header. */ |
587 | CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); | | 587 | CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); |
588 | kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); | | 588 | kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t)); |
589 | | | 589 | |
590 | memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); | | 590 | memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t)); |
591 | error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); | | 591 | error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf)); |
592 | *blknop += btodb(sizeof(buf)); | | 592 | *blknop += btodb(sizeof(buf)); |
593 | return error; | | 593 | return error; |
594 | } | | 594 | } |
595 | | | 595 | |
596 | /* | | 596 | /* |
597 | * These variables are needed by /sbin/savecore | | 597 | * These variables are needed by /sbin/savecore |
598 | */ | | 598 | */ |
599 | uint32_t dumpmag = 0x8fca0101; /* magic number */ | | 599 | uint32_t dumpmag = 0x8fca0101; /* magic number */ |
600 | int dumpsize = 0; /* pages */ | | 600 | int dumpsize = 0; /* pages */ |
601 | long dumplo = 0; /* blocks */ | | 601 | long dumplo = 0; /* blocks */ |
602 | | | 602 | |
603 | /* | | 603 | /* |
604 | * This is called by main to set dumplo and dumpsize. | | 604 | * This is called by main to set dumplo and dumpsize. |
605 | * Dumps always skip the first PAGE_SIZE of disk space | | 605 | * Dumps always skip the first PAGE_SIZE of disk space |
606 | * in case there might be a disk label stored there. | | 606 | * in case there might be a disk label stored there. |
607 | * If there is extra space, put dump at the end to | | 607 | * If there is extra space, put dump at the end to |
608 | * reduce the chance that swapping trashes it. | | 608 | * reduce the chance that swapping trashes it. |
609 | */ | | 609 | */ |
610 | void | | 610 | void |
611 | cpu_dumpconf(void) | | 611 | cpu_dumpconf(void) |
612 | { | | 612 | { |
613 | int chdrsize; /* size of dump header */ | | 613 | int chdrsize; /* size of dump header */ |
614 | int nblks; /* size of dump area */ | | 614 | int nblks; /* size of dump area */ |
615 | | | 615 | |
616 | if (dumpdev == NODEV) | | 616 | if (dumpdev == NODEV) |
617 | return; | | 617 | return; |
618 | nblks = bdev_size(dumpdev); | | 618 | nblks = bdev_size(dumpdev); |
619 | chdrsize = cpu_dumpsize(); | | 619 | chdrsize = cpu_dumpsize(); |
620 | | | 620 | |
621 | dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); | | 621 | dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); |
622 | | | 622 | |
623 | /* | | 623 | /* |
624 | * Check do see if we will fit. Note we always skip the | | 624 | * Check do see if we will fit. Note we always skip the |
625 | * first PAGE_SIZE in case there is a disk label there. | | 625 | * first PAGE_SIZE in case there is a disk label there. |
626 | */ | | 626 | */ |
627 | if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { | | 627 | if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { |
628 | dumpsize = 0; | | 628 | dumpsize = 0; |
629 | dumplo = -1; | | 629 | dumplo = -1; |
630 | return; | | 630 | return; |
631 | } | | 631 | } |
632 | | | 632 | |
633 | /* | | 633 | /* |
634 | * Put dump at the end of the partition. | | 634 | * Put dump at the end of the partition. |
635 | */ | | 635 | */ |
636 | dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; | | 636 | dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; |
637 | } | | 637 | } |
638 | | | 638 | |
639 | /* | | 639 | /* |
640 | * Dump physical memory onto the dump device. Called by cpu_reboot(). | | 640 | * Dump physical memory onto the dump device. Called by cpu_reboot(). |
641 | */ | | 641 | */ |
642 | void | | 642 | void |
643 | dumpsys(void) | | 643 | dumpsys(void) |
644 | { | | 644 | { |
645 | const struct bdevsw *bdev; | | 645 | const struct bdevsw *bdev; |
646 | daddr_t blkno; /* current block to write */ | | 646 | daddr_t blkno; /* current block to write */ |
647 | /* dump routine */ | | 647 | /* dump routine */ |
648 | int (*dump)(dev_t, daddr_t, void *, size_t); | | 648 | int (*dump)(dev_t, daddr_t, void *, size_t); |
649 | int pg; /* page being dumped */ | | 649 | int pg; /* page being dumped */ |
650 | paddr_t maddr; /* PA being dumped */ | | 650 | paddr_t maddr; /* PA being dumped */ |
651 | int error; /* error code from (*dump)() */ | | 651 | int error; /* error code from (*dump)() */ |
652 | | | 652 | |
653 | /* XXX initialized here because of gcc lossage */ | | 653 | /* XXX initialized here because of gcc lossage */ |
654 | maddr = 0 /* lowram */; | | 654 | maddr = 0 /* lowram */; |
655 | pg = 0; | | 655 | pg = 0; |
656 | | | 656 | |
657 | /* Make sure dump device is valid. */ | | 657 | /* Make sure dump device is valid. */ |
658 | if (dumpdev == NODEV) | | 658 | if (dumpdev == NODEV) |
659 | return; | | 659 | return; |
660 | bdev = bdevsw_lookup(dumpdev); | | 660 | bdev = bdevsw_lookup(dumpdev); |
661 | if (bdev == NULL) | | 661 | if (bdev == NULL) |
662 | return; | | 662 | return; |
663 | if (dumpsize == 0) { | | 663 | if (dumpsize == 0) { |
664 | cpu_dumpconf(); | | 664 | cpu_dumpconf(); |
665 | if (dumpsize == 0) | | 665 | if (dumpsize == 0) |
666 | return; | | 666 | return; |
667 | } | | 667 | } |
668 | if (dumplo <= 0) { | | 668 | if (dumplo <= 0) { |
669 | printf("\ndump to dev %u,%u not possible\n", | | 669 | printf("\ndump to dev %u,%u not possible\n", |
670 | major(dumpdev), minor(dumpdev)); | | 670 | major(dumpdev), minor(dumpdev)); |
671 | return; | | 671 | return; |
672 | } | | 672 | } |
673 | dump = bdev->d_dump; | | 673 | dump = bdev->d_dump; |
674 | blkno = dumplo; | | 674 | blkno = dumplo; |
675 | | | 675 | |
676 | printf("\ndumping to dev %u,%u offset %ld\n", | | 676 | printf("\ndumping to dev %u,%u offset %ld\n", |
677 | major(dumpdev), minor(dumpdev), dumplo); | | 677 | major(dumpdev), minor(dumpdev), dumplo); |
678 | | | 678 | |
679 | printf("dump "); | | 679 | printf("dump "); |
680 | | | 680 | |
681 | /* Write the dump header. */ | | 681 | /* Write the dump header. */ |
682 | error = cpu_dump(dump, &blkno); | | 682 | error = cpu_dump(dump, &blkno); |
683 | if (error) | | 683 | if (error) |
684 | goto bad; | | 684 | goto bad; |
685 | | | 685 | |
686 | for (pg = 0; pg < dumpsize; pg++) { | | 686 | for (pg = 0; pg < dumpsize; pg++) { |
687 | #define NPGMB (1024*1024/PAGE_SIZE) | | 687 | #define NPGMB (1024*1024/PAGE_SIZE) |
688 | /* print out how many MBs we have dumped */ | | 688 | /* print out how many MBs we have dumped */ |
689 | if (pg && (pg % NPGMB) == 0) | | 689 | if (pg && (pg % NPGMB) == 0) |
690 | printf("%d ", pg / NPGMB); | | 690 | printf("%d ", pg / NPGMB); |
691 | #undef NPGMB | | 691 | #undef NPGMB |
692 | pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, | | 692 | pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, |
693 | VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); | | 693 | VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); |
694 | | | 694 | |
695 | pmap_update(pmap_kernel()); | | 695 | pmap_update(pmap_kernel()); |
696 | error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); | | 696 | error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE); |
697 | bad: | | 697 | bad: |
698 | switch (error) { | | 698 | switch (error) { |
699 | case 0: | | 699 | case 0: |
700 | maddr += PAGE_SIZE; | | 700 | maddr += PAGE_SIZE; |
701 | blkno += btodb(PAGE_SIZE); | | 701 | blkno += btodb(PAGE_SIZE); |
702 | break; | | 702 | break; |
703 | | | 703 | |
704 | case ENXIO: | | 704 | case ENXIO: |
705 | printf("device bad\n"); | | 705 | printf("device bad\n"); |
706 | return; | | 706 | return; |
707 | | | 707 | |
708 | case EFAULT: | | 708 | case EFAULT: |
709 | printf("device not ready\n"); | | 709 | printf("device not ready\n"); |
710 | return; | | 710 | return; |
711 | | | 711 | |
712 | case EINVAL: | | 712 | case EINVAL: |
713 | printf("area improper\n"); | | 713 | printf("area improper\n"); |
714 | return; | | 714 | return; |
715 | | | 715 | |
716 | case EIO: | | 716 | case EIO: |
717 | printf("i/o error\n"); | | 717 | printf("i/o error\n"); |
718 | return; | | 718 | return; |
719 | | | 719 | |
720 | case EINTR: | | 720 | case EINTR: |
721 | printf("aborted from console\n"); | | 721 | printf("aborted from console\n"); |
722 | return; | | 722 | return; |
723 | | | 723 | |
724 | default: | | 724 | default: |
725 | printf("error %d\n", error); | | 725 | printf("error %d\n", error); |
726 | return; | | 726 | return; |
727 | } | | 727 | } |
728 | } | | 728 | } |
729 | printf("succeeded\n"); | | 729 | printf("succeeded\n"); |
730 | } | | 730 | } |
731 | | | 731 | |
732 | void | | 732 | void |
733 | straytrap(int pc, u_short evec) | | 733 | straytrap(int pc, u_short evec) |
734 | { | | 734 | { |
735 | | | 735 | |
736 | printf("unexpected trap (vector offset %x) from %x\n", | | 736 | printf("unexpected trap (vector offset %x) from %x\n", |
737 | evec & 0xFFF, pc); | | 737 | evec & 0xFFF, pc); |
738 | } | | 738 | } |
739 | | | 739 | |
740 | int *nofault; | | 740 | int *nofault; |
741 | | | 741 | |
742 | int | | 742 | int |
743 | badaddr(register void *addr, int nbytes) | | 743 | badaddr(register void *addr, int nbytes) |
744 | { | | 744 | { |
745 | register int i; | | 745 | register int i; |
746 | label_t faultbuf; | | 746 | label_t faultbuf; |
747 | | | 747 | |
748 | #ifdef lint | | 748 | #ifdef lint |
749 | i = *addr; if (i) return (0); | | 749 | i = *addr; if (i) return (0); |
750 | #endif | | 750 | #endif |
751 | | | 751 | |
752 | nofault = (int *)&faultbuf; | | 752 | nofault = (int *)&faultbuf; |
753 | if (setjmp((label_t *)nofault)) { | | 753 | if (setjmp((label_t *)nofault)) { |
754 | nofault = (int *)0; | | 754 | nofault = (int *)0; |
755 | return 1; | | 755 | return 1; |
756 | } | | 756 | } |
757 | | | 757 | |
758 | switch (nbytes) { | | 758 | switch (nbytes) { |
759 | case 1: | | 759 | case 1: |
760 | i = *(volatile int8_t *)addr; | | 760 | i = *(volatile int8_t *)addr; |
761 | break; | | 761 | break; |
762 | | | 762 | |
763 | case 2: | | 763 | case 2: |
764 | i = *(volatile int16_t *)addr; | | 764 | i = *(volatile int16_t *)addr; |
765 | break; | | 765 | break; |
766 | | | 766 | |
767 | case 4: | | 767 | case 4: |
768 | i = *(volatile int32_t *)addr; | | 768 | i = *(volatile int32_t *)addr; |
769 | break; | | 769 | break; |
770 | | | 770 | |
771 | default: | | 771 | default: |
772 | panic("badaddr: bad request"); | | 772 | panic("badaddr: bad request"); |
773 | } | | 773 | } |
774 | nofault = (int *)0; | | 774 | nofault = (int *)0; |
775 | return 0; | | 775 | return 0; |
776 | } | | 776 | } |
777 | | | 777 | |
778 | void luna68k_abort(const char *); | | 778 | void luna68k_abort(const char *); |
779 | | | 779 | |
780 | static int innmihand; /* simple mutex */ | | 780 | static int innmihand; /* simple mutex */ |
781 | | | 781 | |
782 | /* | | 782 | /* |
783 | * Level 7 interrupts are caused by e.g. the ABORT switch. | | 783 | * Level 7 interrupts are caused by e.g. the ABORT switch. |
784 | * | | 784 | * |
785 | * If we have DDB, then break into DDB on ABORT. In a production | | 785 | * If we have DDB, then break into DDB on ABORT. In a production |
786 | * environment, bumping the ABORT switch would be bad, so we enable | | 786 | * environment, bumping the ABORT switch would be bad, so we enable |
787 | * panic'ing on ABORT with the kernel option "PANICBUTTON". | | 787 | * panic'ing on ABORT with the kernel option "PANICBUTTON". |
788 | */ | | 788 | */ |
789 | void | | 789 | void |
790 | nmihand(struct frame frame) | | 790 | nmihand(struct frame frame) |
791 | { | | 791 | { |
792 | | | 792 | |
793 | /* Prevent unwanted recursion */ | | 793 | /* Prevent unwanted recursion */ |
794 | if (innmihand) | | 794 | if (innmihand) |
795 | return; | | 795 | return; |
796 | innmihand = 1; | | 796 | innmihand = 1; |
797 | | | 797 | |
798 | luna68k_abort("ABORT SWITCH"); | | 798 | luna68k_abort("ABORT SWITCH"); |
799 | | | 799 | |
800 | innmihand = 0; | | 800 | innmihand = 0; |
801 | } | | 801 | } |
802 | | | 802 | |
803 | /* | | 803 | /* |
804 | * Common code for handling ABORT signals from buttons, switches, | | 804 | * Common code for handling ABORT signals from buttons, switches, |
805 | * serial lines, etc. | | 805 | * serial lines, etc. |
806 | */ | | 806 | */ |
807 | void | | 807 | void |
808 | luna68k_abort(const char *cp) | | 808 | luna68k_abort(const char *cp) |
809 | { | | 809 | { |
810 | | | 810 | |
811 | #ifdef DDB | | 811 | #ifdef DDB |
812 | printf("%s\n", cp); | | 812 | printf("%s\n", cp); |
813 | cpu_Debugger(); | | 813 | cpu_Debugger(); |
814 | #else | | 814 | #else |
815 | #ifdef PANICBUTTON | | 815 | #ifdef PANICBUTTON |
816 | panic(cp); | | 816 | panic(cp); |
817 | #else | | 817 | #else |
818 | printf("%s ignored\n", cp); | | 818 | printf("%s ignored\n", cp); |
819 | #endif /* PANICBUTTON */ | | 819 | #endif /* PANICBUTTON */ |
820 | #endif /* DDB */ | | 820 | #endif /* DDB */ |
821 | } | | 821 | } |
822 | | | 822 | |
823 | /* | | 823 | /* |
824 | * cpu_exec_aout_makecmds(): | | 824 | * cpu_exec_aout_makecmds(): |
825 | * CPU-dependent a.out format hook for execve(). | | 825 | * CPU-dependent a.out format hook for execve(). |
826 | * | | 826 | * |
827 | * Determine of the given exec package refers to something which we | | 827 | * Determine of the given exec package refers to something which we |
828 | * understand and, if so, set up the vmcmds for it. | | 828 | * understand and, if so, set up the vmcmds for it. |
829 | */ | | 829 | */ |
830 | int | | 830 | int |
831 | cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) | | 831 | cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp) |
832 | { | | 832 | { |
833 | int error = ENOEXEC; | | 833 | int error = ENOEXEC; |
834 | #ifdef COMPAT_SUNOS | | 834 | #ifdef COMPAT_SUNOS |
835 | extern sunos_exec_aout_makecmds(struct proc *, struct exec_package *); | | 835 | extern sunos_exec_aout_makecmds(struct proc *, struct exec_package *); |
836 | | | 836 | |
837 | if ((error = sunos_exec_aout_makecmds(l->l_proc, epp)) == 0) | | 837 | if ((error = sunos_exec_aout_makecmds(l->l_proc, epp)) == 0) |
838 | return 0; | | 838 | return 0; |
839 | #endif | | 839 | #endif |
840 | return error; | | 840 | return error; |
841 | } | | 841 | } |
842 | | | 842 | |
843 | #ifdef MODULAR | | 843 | #ifdef MODULAR |
844 | /* | | 844 | /* |
845 | * Push any modules loaded by the bootloader etc. | | 845 | * Push any modules loaded by the bootloader etc. |
846 | */ | | 846 | */ |
847 | void | | 847 | void |
848 | module_init_md(void) | | 848 | module_init_md(void) |
849 | { | | 849 | { |
850 | } | | 850 | } |
851 | #endif | | 851 | #endif |
852 | | | 852 | |
853 | #ifdef notyet | | 853 | #ifdef notyet |
854 | /* | | 854 | /* |
855 | * romcons is useful until m68k TC register is initialized. | | 855 | * romcons is useful until m68k TC register is initialized. |
856 | */ | | 856 | */ |
857 | int romcngetc(dev_t); | | 857 | int romcngetc(dev_t); |
858 | void romcnputc(dev_t, int); | | 858 | void romcnputc(dev_t, int); |
859 | | | 859 | |
860 | struct consdev romcons = { | | 860 | struct consdev romcons = { |
861 | NULL, | | 861 | NULL, |
862 | NULL, | | 862 | NULL, |
863 | romcngetc, | | 863 | romcngetc, |
864 | romcnputc, | | 864 | romcnputc, |
865 | nullcnpollc, | | 865 | nullcnpollc, |
866 | makedev(7, 0), /* XXX */ | | 866 | makedev(7, 0), /* XXX */ |
867 | CN_DEAD, | | 867 | CN_DEAD, |
868 | }; | | 868 | }; |
869 | | | 869 | |
870 | #define __ ((int **)0x41000000) | | 870 | #define __ ((int **)0x41000000) |
871 | #define GETC() (*(int (*)())__[6])() | | 871 | #define GETC() (*(int (*)())__[6])() |
872 | #define PUTC(x) (*(void (*)())__[7])(x) | | 872 | #define PUTC(x) (*(void (*)())__[7])(x) |
873 | | | 873 | |
874 | #define ROMPUTC(x) \ | | 874 | #define ROMPUTC(x) \ |
875 | ({ \ | | 875 | ({ \ |
876 | register _r; \ | | 876 | register _r; \ |
877 | __asm volatile (" \ | | 877 | __asm volatile (" \ |
878 | movc %%vbr,%0 ; \ | | 878 | movc %%vbr,%0 ; \ |
879 | movel %0,%%sp@- ; \ | | 879 | movel %0,%%sp@- ; \ |
880 | clrl %0 ; \ | | 880 | clrl %0 ; \ |
881 | movc %0,%%vbr" \ | | 881 | movc %0,%%vbr" \ |
882 | : "=r" (_r)); \ | | 882 | : "=r" (_r)); \ |
883 | PUTC(x); \ | | 883 | PUTC(x); \ |
884 | __asm volatile (" \ | | 884 | __asm volatile (" \ |
885 | movel %%sp@+,%0 ; \ | | 885 | movel %%sp@+,%0 ; \ |
886 | movc %0,%%vbr" \ | | 886 | movc %0,%%vbr" \ |
887 | : "=r" (_r)); \ | | 887 | : "=r" (_r)); \ |
888 | }) | | 888 | }) |
889 | | | 889 | |
890 | #define ROMGETC() \ | | 890 | #define ROMGETC() \ |
891 | ({ \ | | 891 | ({ \ |
892 | register _r, _c; \ | | 892 | register _r, _c; \ |
893 | __asm volatile (" \ | | 893 | __asm volatile (" \ |
894 | movc %%vbr,%0 ; \ | | 894 | movc %%vbr,%0 ; \ |
895 | movel %0,%%sp@- ; \ | | 895 | movel %0,%%sp@- ; \ |
896 | clrl %0 ; \ | | 896 | clrl %0 ; \ |
897 | movc %0,%%vbr" \ | | 897 | movc %0,%%vbr" \ |
898 | : "=r" (_r)); \ | | 898 | : "=r" (_r)); \ |
899 | _c = GETC(); \ | | 899 | _c = GETC(); \ |
900 | __asm volatile (" \ | | 900 | __asm volatile (" \ |
901 | movel %%sp@+,%0 ; \ | | 901 | movel %%sp@+,%0 ; \ |
902 | movc %0,%%vbr" \ | | 902 | movc %0,%%vbr" \ |
903 | : "=r" (_r)); \ | | 903 | : "=r" (_r)); \ |
904 | _c; \ | | 904 | _c; \ |
905 | }) | | 905 | }) |
906 | | | 906 | |
907 | void | | 907 | void |
908 | romcnputc(dev_t dev, int c) | | 908 | romcnputc(dev_t dev, int c) |
909 | { | | 909 | { |
910 | int s; | | 910 | int s; |
911 | | | 911 | |
912 | s = splhigh(); | | 912 | s = splhigh(); |
913 | ROMPUTC(c); | | 913 | ROMPUTC(c); |
914 | splx(s); | | 914 | splx(s); |
915 | } | | 915 | } |
916 | | | 916 | |
917 | int | | 917 | int |
918 | romcngetc(dev_t dev) | | 918 | romcngetc(dev_t dev) |
919 | { | | 919 | { |
920 | int s, c; | | 920 | int s, c; |
921 | | | 921 | |
922 | do { | | 922 | do { |
923 | s = splhigh(); | | 923 | s = splhigh(); |
924 | c = ROMGETC(); | | 924 | c = ROMGETC(); |
925 | splx(s); | | 925 | splx(s); |
926 | } while (c == -1); | | 926 | } while (c == -1); |
927 | return c; | | 927 | return c; |
928 | } | | 928 | } |
929 | #endif | | 929 | #endif |
930 | | | 930 | |
931 | int | | 931 | int |
932 | mm_md_physacc(paddr_t pa, vm_prot_t prot) | | 932 | mm_md_physacc(paddr_t pa, vm_prot_t prot) |
933 | { | | 933 | { |
934 | | | 934 | |
935 | return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0; | | 935 | return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0; |
936 | } | | 936 | } |