| @@ -1,1986 +1,1994 @@ | | | @@ -1,1986 +1,1994 @@ |
1 | /* $NetBSD: machdep.c,v 1.374 2021/07/11 01:58:41 thorpej Exp $ */ | | 1 | /* $NetBSD: machdep.c,v 1.375 2021/07/22 01:39:18 thorpej Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 1999, 2000, 2019, 2020 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 1999, 2000, 2019, 2020 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 Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center and by Chris G. Demetriou. | | 9 | * NASA Ames Research Center and by Chris G. Demetriou. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the | | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. | | 18 | * documentation and/or other materials provided with the distribution. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. | | 34 | * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. |
35 | * All rights reserved. | | 35 | * All rights reserved. |
36 | * | | 36 | * |
37 | * Author: Chris G. Demetriou | | 37 | * Author: Chris G. Demetriou |
38 | * | | 38 | * |
39 | * Permission to use, copy, modify and distribute this software and | | 39 | * Permission to use, copy, modify and distribute this software and |
40 | * its documentation is hereby granted, provided that both the copyright | | 40 | * its documentation is hereby granted, provided that both the copyright |
41 | * notice and this permission notice appear in all copies of the | | 41 | * notice and this permission notice appear in all copies of the |
42 | * software, derivative works or modified versions, and any portions | | 42 | * software, derivative works or modified versions, and any portions |
43 | * thereof, and that both notices appear in supporting documentation. | | 43 | * thereof, and that both notices appear in supporting documentation. |
44 | * | | 44 | * |
45 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | | 45 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
46 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND | | 46 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND |
47 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | | 47 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
48 | * | | 48 | * |
49 | * Carnegie Mellon requests users of this software to return to | | 49 | * Carnegie Mellon requests users of this software to return to |
50 | * | | 50 | * |
51 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | | 51 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
52 | * School of Computer Science | | 52 | * School of Computer Science |
53 | * Carnegie Mellon University | | 53 | * Carnegie Mellon University |
54 | * Pittsburgh PA 15213-3890 | | 54 | * Pittsburgh PA 15213-3890 |
55 | * | | 55 | * |
56 | * any improvements or extensions that they make and grant Carnegie the | | 56 | * any improvements or extensions that they make and grant Carnegie the |
57 | * rights to redistribute these changes. | | 57 | * rights to redistribute these changes. |
58 | */ | | 58 | */ |
59 | | | 59 | |
60 | #include "opt_ddb.h" | | 60 | #include "opt_ddb.h" |
61 | #include "opt_kgdb.h" | | 61 | #include "opt_kgdb.h" |
62 | #include "opt_modular.h" | | 62 | #include "opt_modular.h" |
63 | #include "opt_multiprocessor.h" | | 63 | #include "opt_multiprocessor.h" |
64 | #include "opt_dec_3000_300.h" | | 64 | #include "opt_dec_3000_300.h" |
65 | #include "opt_dec_3000_500.h" | | 65 | #include "opt_dec_3000_500.h" |
66 | #include "opt_execfmt.h" | | 66 | #include "opt_execfmt.h" |
67 | | | 67 | |
68 | #define __RWLOCK_PRIVATE | | 68 | #define __RWLOCK_PRIVATE |
69 | | | 69 | |
70 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | | 70 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ |
71 | | | 71 | |
72 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.374 2021/07/11 01:58:41 thorpej Exp $"); | | 72 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.375 2021/07/22 01:39:18 thorpej Exp $"); |
73 | | | 73 | |
74 | #include <sys/param.h> | | 74 | #include <sys/param.h> |
75 | #include <sys/systm.h> | | 75 | #include <sys/systm.h> |
76 | #include <sys/signalvar.h> | | 76 | #include <sys/signalvar.h> |
77 | #include <sys/kernel.h> | | 77 | #include <sys/kernel.h> |
78 | #include <sys/cpu.h> | | 78 | #include <sys/cpu.h> |
79 | #include <sys/proc.h> | | 79 | #include <sys/proc.h> |
80 | #include <sys/ras.h> | | 80 | #include <sys/ras.h> |
81 | #include <sys/sched.h> | | 81 | #include <sys/sched.h> |
82 | #include <sys/reboot.h> | | 82 | #include <sys/reboot.h> |
83 | #include <sys/device.h> | | 83 | #include <sys/device.h> |
84 | #include <sys/module.h> | | 84 | #include <sys/module.h> |
85 | #include <sys/mman.h> | | 85 | #include <sys/mman.h> |
86 | #include <sys/msgbuf.h> | | 86 | #include <sys/msgbuf.h> |
87 | #include <sys/ioctl.h> | | 87 | #include <sys/ioctl.h> |
88 | #include <sys/tty.h> | | 88 | #include <sys/tty.h> |
89 | #include <sys/exec.h> | | 89 | #include <sys/exec.h> |
90 | #include <sys/exec_aout.h> /* for MID_* */ | | 90 | #include <sys/exec_aout.h> /* for MID_* */ |
91 | #include <sys/exec_ecoff.h> | | 91 | #include <sys/exec_ecoff.h> |
92 | #include <sys/core.h> | | 92 | #include <sys/core.h> |
93 | #include <sys/kcore.h> | | 93 | #include <sys/kcore.h> |
94 | #include <sys/ucontext.h> | | 94 | #include <sys/ucontext.h> |
95 | #include <sys/conf.h> | | 95 | #include <sys/conf.h> |
96 | #include <sys/ksyms.h> | | 96 | #include <sys/ksyms.h> |
97 | #include <sys/kauth.h> | | 97 | #include <sys/kauth.h> |
98 | #include <sys/atomic.h> | | 98 | #include <sys/atomic.h> |
99 | #include <sys/cpu.h> | | 99 | #include <sys/cpu.h> |
100 | #include <sys/rwlock.h> | | 100 | #include <sys/rwlock.h> |
101 | | | 101 | |
102 | #include <machine/kcore.h> | | 102 | #include <machine/kcore.h> |
103 | #include <machine/fpu.h> | | 103 | #include <machine/fpu.h> |
104 | | | 104 | |
105 | #include <sys/mount.h> | | 105 | #include <sys/mount.h> |
106 | #include <sys/syscallargs.h> | | 106 | #include <sys/syscallargs.h> |
107 | | | 107 | |
108 | #include <uvm/uvm.h> | | 108 | #include <uvm/uvm.h> |
109 | #include <sys/sysctl.h> | | 109 | #include <sys/sysctl.h> |
110 | | | 110 | |
111 | #include <dev/cons.h> | | 111 | #include <dev/cons.h> |
112 | #include <dev/mm.h> | | 112 | #include <dev/mm.h> |
113 | | | 113 | |
114 | #include <machine/autoconf.h> | | 114 | #include <machine/autoconf.h> |
115 | #include <machine/reg.h> | | 115 | #include <machine/reg.h> |
116 | #include <machine/rpb.h> | | 116 | #include <machine/rpb.h> |
117 | #include <machine/prom.h> | | 117 | #include <machine/prom.h> |
118 | #include <machine/cpuconf.h> | | 118 | #include <machine/cpuconf.h> |
119 | #include <machine/ieeefp.h> | | 119 | #include <machine/ieeefp.h> |
120 | | | 120 | |
121 | #ifdef DDB | | 121 | #ifdef DDB |
122 | #include <machine/db_machdep.h> | | 122 | #include <machine/db_machdep.h> |
123 | #include <ddb/db_access.h> | | 123 | #include <ddb/db_access.h> |
124 | #include <ddb/db_sym.h> | | 124 | #include <ddb/db_sym.h> |
125 | #include <ddb/db_extern.h> | | 125 | #include <ddb/db_extern.h> |
126 | #include <ddb/db_interface.h> | | 126 | #include <ddb/db_interface.h> |
127 | #endif | | 127 | #endif |
128 | | | 128 | |
129 | #ifdef KGDB | | 129 | #ifdef KGDB |
130 | #include <sys/kgdb.h> | | 130 | #include <sys/kgdb.h> |
131 | #endif | | 131 | #endif |
132 | | | 132 | |
133 | #ifdef DEBUG | | 133 | #ifdef DEBUG |
134 | #include <machine/sigdebug.h> | | 134 | #include <machine/sigdebug.h> |
135 | int sigdebug = 0x0; | | 135 | int sigdebug = 0x0; |
136 | int sigpid = 0; | | 136 | int sigpid = 0; |
137 | #endif | | 137 | #endif |
138 | | | 138 | |
139 | /* Assert some assumptions made in lock_stubs.s */ | | 139 | /* Assert some assumptions made in lock_stubs.s */ |
140 | __CTASSERT(RW_READER == 0); | | 140 | __CTASSERT(RW_READER == 0); |
141 | __CTASSERT(RW_HAS_WAITERS == 1); | | 141 | __CTASSERT(RW_HAS_WAITERS == 1); |
142 | | | 142 | |
143 | #include <machine/alpha.h> | | 143 | #include <machine/alpha.h> |
144 | | | 144 | |
145 | #include "ksyms.h" | | 145 | #include "ksyms.h" |
146 | | | 146 | |
147 | struct vm_map *phys_map = NULL; | | 147 | struct vm_map *phys_map = NULL; |
148 | | | 148 | |
149 | void *msgbufaddr; | | 149 | void *msgbufaddr; |
150 | | | 150 | |
151 | int maxmem; /* max memory per process */ | | 151 | int maxmem; /* max memory per process */ |
152 | | | 152 | |
153 | int totalphysmem; /* total amount of physical memory in system */ | | 153 | int totalphysmem; /* total amount of physical memory in system */ |
154 | int resvmem; /* amount of memory reserved for PROM */ | | 154 | int resvmem; /* amount of memory reserved for PROM */ |
155 | int unusedmem; /* amount of memory for OS that we don't use */ | | 155 | int unusedmem; /* amount of memory for OS that we don't use */ |
156 | int unknownmem; /* amount of memory with an unknown use */ | | 156 | int unknownmem; /* amount of memory with an unknown use */ |
157 | | | 157 | |
158 | int cputype; /* system type, from the RPB */ | | 158 | int cputype; /* system type, from the RPB */ |
159 | bool alpha_is_qemu; /* true if we've detected runnnig in qemu */ | | 159 | bool alpha_is_qemu; /* true if we've detected runnnig in qemu */ |
160 | | | 160 | |
161 | int bootdev_debug = 0; /* patchable, or from DDB */ | | 161 | int bootdev_debug = 0; /* patchable, or from DDB */ |
162 | | | 162 | |
163 | /* | | 163 | /* |
164 | * XXX We need an address to which we can assign things so that they | | 164 | * XXX We need an address to which we can assign things so that they |
165 | * won't be optimized away because we didn't use the value. | | 165 | * won't be optimized away because we didn't use the value. |
166 | */ | | 166 | */ |
167 | uint32_t no_optimize; | | 167 | uint32_t no_optimize; |
168 | | | 168 | |
169 | /* the following is used externally (sysctl_hw) */ | | 169 | /* the following is used externally (sysctl_hw) */ |
170 | char machine[] = MACHINE; /* from <machine/param.h> */ | | 170 | char machine[] = MACHINE; /* from <machine/param.h> */ |
171 | char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ | | 171 | char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ |
172 | | | 172 | |
173 | /* Number of machine cycles per microsecond */ | | 173 | /* Number of machine cycles per microsecond */ |
174 | uint64_t cycles_per_usec; | | 174 | uint64_t cycles_per_usec; |
175 | | | 175 | |
176 | /* number of CPUs in the box. really! */ | | 176 | /* number of CPUs in the box. really! */ |
177 | int ncpus; | | 177 | int ncpus; |
178 | | | 178 | |
179 | struct bootinfo_kernel bootinfo; | | 179 | struct bootinfo_kernel bootinfo; |
180 | | | 180 | |
181 | /* For built-in TCDS */ | | 181 | /* For built-in TCDS */ |
182 | #if defined(DEC_3000_300) || defined(DEC_3000_500) | | 182 | #if defined(DEC_3000_300) || defined(DEC_3000_500) |
183 | uint8_t dec_3000_scsiid[3], dec_3000_scsifast[3]; | | 183 | uint8_t dec_3000_scsiid[3], dec_3000_scsifast[3]; |
184 | #endif | | 184 | #endif |
185 | | | 185 | |
186 | struct platform platform; | | 186 | struct platform platform; |
187 | | | 187 | |
188 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 188 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
189 | /* start and end of kernel symbol table */ | | 189 | /* start and end of kernel symbol table */ |
190 | void *ksym_start, *ksym_end; | | 190 | void *ksym_start, *ksym_end; |
191 | #endif | | 191 | #endif |
192 | | | 192 | |
193 | /* for cpu_sysctl() */ | | 193 | /* for cpu_sysctl() */ |
194 | int alpha_unaligned_print = 1; /* warn about unaligned accesses */ | | 194 | int alpha_unaligned_print = 1; /* warn about unaligned accesses */ |
195 | int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ | | 195 | int alpha_unaligned_fix = 1; /* fix up unaligned accesses */ |
196 | int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ | | 196 | int alpha_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ |
197 | int alpha_fp_sync_complete = 0; /* fp fixup if sync even without /s */ | | 197 | int alpha_fp_sync_complete = 0; /* fp fixup if sync even without /s */ |
| | | 198 | int alpha_fp_complete_debug = 0; /* fp completion debug enabled */ |
198 | | | 199 | |
199 | /* | | 200 | /* |
200 | * XXX This should be dynamically sized, but we have the chicken-egg problem! | | 201 | * XXX This should be dynamically sized, but we have the chicken-egg problem! |
201 | * XXX it should also be larger than it is, because not all of the mddt | | 202 | * XXX it should also be larger than it is, because not all of the mddt |
202 | * XXX clusters end up being used for VM. | | 203 | * XXX clusters end up being used for VM. |
203 | */ | | 204 | */ |
204 | phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; /* low size bits overloaded */ | | 205 | phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; /* low size bits overloaded */ |
205 | int mem_cluster_cnt; | | 206 | int mem_cluster_cnt; |
206 | | | 207 | |
207 | int cpu_dump(void); | | 208 | int cpu_dump(void); |
208 | int cpu_dumpsize(void); | | 209 | int cpu_dumpsize(void); |
209 | u_long cpu_dump_mempagecnt(void); | | 210 | u_long cpu_dump_mempagecnt(void); |
210 | void dumpsys(void); | | 211 | void dumpsys(void); |
211 | void identifycpu(void); | | 212 | void identifycpu(void); |
212 | void printregs(struct reg *); | | 213 | void printregs(struct reg *); |
213 | | | 214 | |
214 | const pcu_ops_t fpu_ops = { | | 215 | const pcu_ops_t fpu_ops = { |
215 | .pcu_id = PCU_FPU, | | 216 | .pcu_id = PCU_FPU, |
216 | .pcu_state_load = fpu_state_load, | | 217 | .pcu_state_load = fpu_state_load, |
217 | .pcu_state_save = fpu_state_save, | | 218 | .pcu_state_save = fpu_state_save, |
218 | .pcu_state_release = fpu_state_release, | | 219 | .pcu_state_release = fpu_state_release, |
219 | }; | | 220 | }; |
220 | | | 221 | |
221 | const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = { | | 222 | const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = { |
222 | [PCU_FPU] = &fpu_ops, | | 223 | [PCU_FPU] = &fpu_ops, |
223 | }; | | 224 | }; |
224 | | | 225 | |
225 | static void | | 226 | static void |
226 | alpha_page_physload(unsigned long const start_pfn, unsigned long const end_pfn) | | 227 | alpha_page_physload(unsigned long const start_pfn, unsigned long const end_pfn) |
227 | { | | 228 | { |
228 | | | 229 | |
229 | /* | | 230 | /* |
230 | * Some Alpha platforms may have unique requirements about | | 231 | * Some Alpha platforms may have unique requirements about |
231 | * how physical memory is managed (e.g. reserving memory | | 232 | * how physical memory is managed (e.g. reserving memory |
232 | * ranges due to lack of SGMAP DMA). | | 233 | * ranges due to lack of SGMAP DMA). |
233 | */ | | 234 | */ |
234 | if (platform.page_physload != NULL) { | | 235 | if (platform.page_physload != NULL) { |
235 | (*platform.page_physload)(start_pfn, end_pfn); | | 236 | (*platform.page_physload)(start_pfn, end_pfn); |
236 | return; | | 237 | return; |
237 | } | | 238 | } |
238 | | | 239 | |
239 | uvm_page_physload(start_pfn, end_pfn, start_pfn, end_pfn, | | 240 | uvm_page_physload(start_pfn, end_pfn, start_pfn, end_pfn, |
240 | VM_FREELIST_DEFAULT); | | 241 | VM_FREELIST_DEFAULT); |
241 | } | | 242 | } |
242 | | | 243 | |
243 | void | | 244 | void |
244 | alpha_page_physload_sheltered(unsigned long const start_pfn, | | 245 | alpha_page_physload_sheltered(unsigned long const start_pfn, |
245 | unsigned long const end_pfn, unsigned long const shelter_start_pfn, | | 246 | unsigned long const end_pfn, unsigned long const shelter_start_pfn, |
246 | unsigned long const shelter_end_pfn) | | 247 | unsigned long const shelter_end_pfn) |
247 | { | | 248 | { |
248 | | | 249 | |
249 | /* | | 250 | /* |
250 | * If the added region ends before or starts after the sheltered | | 251 | * If the added region ends before or starts after the sheltered |
251 | * region, then it just goes on the default freelist. | | 252 | * region, then it just goes on the default freelist. |
252 | */ | | 253 | */ |
253 | if (end_pfn <= shelter_start_pfn || start_pfn >= shelter_end_pfn) { | | 254 | if (end_pfn <= shelter_start_pfn || start_pfn >= shelter_end_pfn) { |
254 | uvm_page_physload(start_pfn, end_pfn, | | 255 | uvm_page_physload(start_pfn, end_pfn, |
255 | start_pfn, end_pfn, VM_FREELIST_DEFAULT); | | 256 | start_pfn, end_pfn, VM_FREELIST_DEFAULT); |
256 | return; | | 257 | return; |
257 | } | | 258 | } |
258 | | | 259 | |
259 | /* | | 260 | /* |
260 | * Load any portion that comes before the sheltered region. | | 261 | * Load any portion that comes before the sheltered region. |
261 | */ | | 262 | */ |
262 | if (start_pfn < shelter_start_pfn) { | | 263 | if (start_pfn < shelter_start_pfn) { |
263 | KASSERT(end_pfn > shelter_start_pfn); | | 264 | KASSERT(end_pfn > shelter_start_pfn); |
264 | uvm_page_physload(start_pfn, shelter_start_pfn, | | 265 | uvm_page_physload(start_pfn, shelter_start_pfn, |
265 | start_pfn, shelter_start_pfn, VM_FREELIST_DEFAULT); | | 266 | start_pfn, shelter_start_pfn, VM_FREELIST_DEFAULT); |
266 | } | | 267 | } |
267 | | | 268 | |
268 | /* | | 269 | /* |
269 | * Load the portion that overlaps that sheltered region. | | 270 | * Load the portion that overlaps that sheltered region. |
270 | */ | | 271 | */ |
271 | const unsigned long ov_start = MAX(start_pfn, shelter_start_pfn); | | 272 | const unsigned long ov_start = MAX(start_pfn, shelter_start_pfn); |
272 | const unsigned long ov_end = MIN(end_pfn, shelter_end_pfn); | | 273 | const unsigned long ov_end = MIN(end_pfn, shelter_end_pfn); |
273 | KASSERT(ov_start >= shelter_start_pfn); | | 274 | KASSERT(ov_start >= shelter_start_pfn); |
274 | KASSERT(ov_end <= shelter_end_pfn); | | 275 | KASSERT(ov_end <= shelter_end_pfn); |
275 | uvm_page_physload(ov_start, ov_end, ov_start, ov_end, | | 276 | uvm_page_physload(ov_start, ov_end, ov_start, ov_end, |
276 | VM_FREELIST_SHELTERED); | | 277 | VM_FREELIST_SHELTERED); |
277 | | | 278 | |
278 | /* | | 279 | /* |
279 | * Load any portion that comes after the sheltered region. | | 280 | * Load any portion that comes after the sheltered region. |
280 | */ | | 281 | */ |
281 | if (end_pfn > shelter_end_pfn) { | | 282 | if (end_pfn > shelter_end_pfn) { |
282 | KASSERT(start_pfn < shelter_end_pfn); | | 283 | KASSERT(start_pfn < shelter_end_pfn); |
283 | uvm_page_physload(shelter_end_pfn, end_pfn, | | 284 | uvm_page_physload(shelter_end_pfn, end_pfn, |
284 | shelter_end_pfn, end_pfn, VM_FREELIST_DEFAULT); | | 285 | shelter_end_pfn, end_pfn, VM_FREELIST_DEFAULT); |
285 | } | | 286 | } |
286 | } | | 287 | } |
287 | | | 288 | |
288 | void | | 289 | void |
289 | alpha_init(u_long xxx_pfn __unused, u_long ptb, u_long bim, u_long bip, | | 290 | alpha_init(u_long xxx_pfn __unused, u_long ptb, u_long bim, u_long bip, |
290 | u_long biv) | | 291 | u_long biv) |
291 | /* pfn: first free PFN number (no longer used) */ | | 292 | /* pfn: first free PFN number (no longer used) */ |
292 | /* ptb: PFN of current level 1 page table */ | | 293 | /* ptb: PFN of current level 1 page table */ |
293 | /* bim: bootinfo magic */ | | 294 | /* bim: bootinfo magic */ |
294 | /* bip: bootinfo pointer */ | | 295 | /* bip: bootinfo pointer */ |
295 | /* biv: bootinfo version */ | | 296 | /* biv: bootinfo version */ |
296 | { | | 297 | { |
297 | extern char kernel_text[], _end[]; | | 298 | extern char kernel_text[], _end[]; |
298 | struct mddt *mddtp; | | 299 | struct mddt *mddtp; |
299 | struct mddt_cluster *memc; | | 300 | struct mddt_cluster *memc; |
300 | int i, mddtweird; | | 301 | int i, mddtweird; |
301 | struct pcb *pcb0; | | 302 | struct pcb *pcb0; |
302 | vaddr_t kernstart, kernend, v; | | 303 | vaddr_t kernstart, kernend, v; |
303 | paddr_t kernstartpfn, kernendpfn, pfn0, pfn1; | | 304 | paddr_t kernstartpfn, kernendpfn, pfn0, pfn1; |
304 | cpuid_t cpu_id; | | 305 | cpuid_t cpu_id; |
305 | struct cpu_info *ci; | | 306 | struct cpu_info *ci; |
306 | char *p; | | 307 | char *p; |
307 | const char *bootinfo_msg; | | 308 | const char *bootinfo_msg; |
308 | const struct cpuinit *c; | | 309 | const struct cpuinit *c; |
309 | | | 310 | |
310 | /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ | | 311 | /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ |
311 | | | 312 | |
312 | /* | | 313 | /* |
313 | * Turn off interrupts (not mchecks) and floating point. | | 314 | * Turn off interrupts (not mchecks) and floating point. |
314 | * Make sure the instruction and data streams are consistent. | | 315 | * Make sure the instruction and data streams are consistent. |
315 | */ | | 316 | */ |
316 | (void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); | | 317 | (void)alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); |
317 | alpha_pal_wrfen(0); | | 318 | alpha_pal_wrfen(0); |
318 | ALPHA_TBIA(); | | 319 | ALPHA_TBIA(); |
319 | alpha_pal_imb(); | | 320 | alpha_pal_imb(); |
320 | | | 321 | |
321 | /* Initialize the SCB. */ | | 322 | /* Initialize the SCB. */ |
322 | scb_init(); | | 323 | scb_init(); |
323 | | | 324 | |
324 | cpu_id = cpu_number(); | | 325 | cpu_id = cpu_number(); |
325 | | | 326 | |
326 | ci = &cpu_info_primary; | | 327 | ci = &cpu_info_primary; |
327 | ci->ci_cpuid = cpu_id; | | 328 | ci->ci_cpuid = cpu_id; |
328 | | | 329 | |
329 | #if defined(MULTIPROCESSOR) | | 330 | #if defined(MULTIPROCESSOR) |
330 | /* | | 331 | /* |
331 | * Set the SysValue to &lwp0, after making sure that lwp0 | | 332 | * Set the SysValue to &lwp0, after making sure that lwp0 |
332 | * is pointing at the primary CPU. Secondary processors do | | 333 | * is pointing at the primary CPU. Secondary processors do |
333 | * this in their spinup trampoline. | | 334 | * this in their spinup trampoline. |
334 | */ | | 335 | */ |
335 | lwp0.l_cpu = ci; | | 336 | lwp0.l_cpu = ci; |
336 | cpu_info[cpu_id] = ci; | | 337 | cpu_info[cpu_id] = ci; |
337 | alpha_pal_wrval((u_long)&lwp0); | | 338 | alpha_pal_wrval((u_long)&lwp0); |
338 | #endif | | 339 | #endif |
339 | | | 340 | |
340 | /* | | 341 | /* |
341 | * Get critical system information (if possible, from the | | 342 | * Get critical system information (if possible, from the |
342 | * information provided by the boot program). | | 343 | * information provided by the boot program). |
343 | */ | | 344 | */ |
344 | bootinfo_msg = NULL; | | 345 | bootinfo_msg = NULL; |
345 | if (bim == BOOTINFO_MAGIC) { | | 346 | if (bim == BOOTINFO_MAGIC) { |
346 | if (biv == 0) { /* backward compat */ | | 347 | if (biv == 0) { /* backward compat */ |
347 | biv = *(u_long *)bip; | | 348 | biv = *(u_long *)bip; |
348 | bip += 8; | | 349 | bip += 8; |
349 | } | | 350 | } |
350 | switch (biv) { | | 351 | switch (biv) { |
351 | case 1: { | | 352 | case 1: { |
352 | struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip; | | 353 | struct bootinfo_v1 *v1p = (struct bootinfo_v1 *)bip; |
353 | | | 354 | |
354 | bootinfo.ssym = v1p->ssym; | | 355 | bootinfo.ssym = v1p->ssym; |
355 | bootinfo.esym = v1p->esym; | | 356 | bootinfo.esym = v1p->esym; |
356 | /* hwrpb may not be provided by boot block in v1 */ | | 357 | /* hwrpb may not be provided by boot block in v1 */ |
357 | if (v1p->hwrpb != NULL) { | | 358 | if (v1p->hwrpb != NULL) { |
358 | bootinfo.hwrpb_phys = | | 359 | bootinfo.hwrpb_phys = |
359 | ((struct rpb *)v1p->hwrpb)->rpb_phys; | | 360 | ((struct rpb *)v1p->hwrpb)->rpb_phys; |
360 | bootinfo.hwrpb_size = v1p->hwrpbsize; | | 361 | bootinfo.hwrpb_size = v1p->hwrpbsize; |
361 | } else { | | 362 | } else { |
362 | bootinfo.hwrpb_phys = | | 363 | bootinfo.hwrpb_phys = |
363 | ((struct rpb *)HWRPB_ADDR)->rpb_phys; | | 364 | ((struct rpb *)HWRPB_ADDR)->rpb_phys; |
364 | bootinfo.hwrpb_size = | | 365 | bootinfo.hwrpb_size = |
365 | ((struct rpb *)HWRPB_ADDR)->rpb_size; | | 366 | ((struct rpb *)HWRPB_ADDR)->rpb_size; |
366 | } | | 367 | } |
367 | memcpy(bootinfo.boot_flags, v1p->boot_flags, | | 368 | memcpy(bootinfo.boot_flags, v1p->boot_flags, |
368 | uimin(sizeof v1p->boot_flags, | | 369 | uimin(sizeof v1p->boot_flags, |
369 | sizeof bootinfo.boot_flags)); | | 370 | sizeof bootinfo.boot_flags)); |
370 | memcpy(bootinfo.booted_kernel, v1p->booted_kernel, | | 371 | memcpy(bootinfo.booted_kernel, v1p->booted_kernel, |
371 | uimin(sizeof v1p->booted_kernel, | | 372 | uimin(sizeof v1p->booted_kernel, |
372 | sizeof bootinfo.booted_kernel)); | | 373 | sizeof bootinfo.booted_kernel)); |
373 | /* booted dev not provided in bootinfo */ | | 374 | /* booted dev not provided in bootinfo */ |
374 | init_prom_interface(ptb, (struct rpb *) | | 375 | init_prom_interface(ptb, (struct rpb *) |
375 | ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys)); | | 376 | ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys)); |
376 | prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, | | 377 | prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, |
377 | sizeof bootinfo.booted_dev); | | 378 | sizeof bootinfo.booted_dev); |
378 | break; | | 379 | break; |
379 | } | | 380 | } |
380 | default: | | 381 | default: |
381 | bootinfo_msg = "unknown bootinfo version"; | | 382 | bootinfo_msg = "unknown bootinfo version"; |
382 | goto nobootinfo; | | 383 | goto nobootinfo; |
383 | } | | 384 | } |
384 | } else { | | 385 | } else { |
385 | bootinfo_msg = "boot program did not pass bootinfo"; | | 386 | bootinfo_msg = "boot program did not pass bootinfo"; |
386 | nobootinfo: | | 387 | nobootinfo: |
387 | bootinfo.ssym = (u_long)_end; | | 388 | bootinfo.ssym = (u_long)_end; |
388 | bootinfo.esym = (u_long)_end; | | 389 | bootinfo.esym = (u_long)_end; |
389 | bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys; | | 390 | bootinfo.hwrpb_phys = ((struct rpb *)HWRPB_ADDR)->rpb_phys; |
390 | bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size; | | 391 | bootinfo.hwrpb_size = ((struct rpb *)HWRPB_ADDR)->rpb_size; |
391 | init_prom_interface(ptb, (struct rpb *)HWRPB_ADDR); | | 392 | init_prom_interface(ptb, (struct rpb *)HWRPB_ADDR); |
392 | if (alpha_is_qemu) { | | 393 | if (alpha_is_qemu) { |
393 | /* | | 394 | /* |
394 | * Grab boot flags from kernel command line. | | 395 | * Grab boot flags from kernel command line. |
395 | * Assume autoboot if not supplied. | | 396 | * Assume autoboot if not supplied. |
396 | */ | | 397 | */ |
397 | if (! prom_qemu_getenv("flags", bootinfo.boot_flags, | | 398 | if (! prom_qemu_getenv("flags", bootinfo.boot_flags, |
398 | sizeof(bootinfo.boot_flags))) { | | 399 | sizeof(bootinfo.boot_flags))) { |
399 | strlcpy(bootinfo.boot_flags, "A", | | 400 | strlcpy(bootinfo.boot_flags, "A", |
400 | sizeof(bootinfo.boot_flags)); | | 401 | sizeof(bootinfo.boot_flags)); |
401 | } | | 402 | } |
402 | } else { | | 403 | } else { |
403 | prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags, | | 404 | prom_getenv(PROM_E_BOOTED_OSFLAGS, bootinfo.boot_flags, |
404 | sizeof bootinfo.boot_flags); | | 405 | sizeof bootinfo.boot_flags); |
405 | prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel, | | 406 | prom_getenv(PROM_E_BOOTED_FILE, bootinfo.booted_kernel, |
406 | sizeof bootinfo.booted_kernel); | | 407 | sizeof bootinfo.booted_kernel); |
407 | prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, | | 408 | prom_getenv(PROM_E_BOOTED_DEV, bootinfo.booted_dev, |
408 | sizeof bootinfo.booted_dev); | | 409 | sizeof bootinfo.booted_dev); |
409 | } | | 410 | } |
410 | } | | 411 | } |
411 | | | 412 | |
412 | /* | | 413 | /* |
413 | * Initialize the kernel's mapping of the RPB. It's needed for | | 414 | * Initialize the kernel's mapping of the RPB. It's needed for |
414 | * lots of things. | | 415 | * lots of things. |
415 | */ | | 416 | */ |
416 | hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys); | | 417 | hwrpb = (struct rpb *)ALPHA_PHYS_TO_K0SEG(bootinfo.hwrpb_phys); |
417 | | | 418 | |
418 | #if defined(DEC_3000_300) || defined(DEC_3000_500) | | 419 | #if defined(DEC_3000_300) || defined(DEC_3000_500) |
419 | if (hwrpb->rpb_type == ST_DEC_3000_300 || | | 420 | if (hwrpb->rpb_type == ST_DEC_3000_300 || |
420 | hwrpb->rpb_type == ST_DEC_3000_500) { | | 421 | hwrpb->rpb_type == ST_DEC_3000_500) { |
421 | prom_getenv(PROM_E_SCSIID, dec_3000_scsiid, | | 422 | prom_getenv(PROM_E_SCSIID, dec_3000_scsiid, |
422 | sizeof(dec_3000_scsiid)); | | 423 | sizeof(dec_3000_scsiid)); |
423 | prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast, | | 424 | prom_getenv(PROM_E_SCSIFAST, dec_3000_scsifast, |
424 | sizeof(dec_3000_scsifast)); | | 425 | sizeof(dec_3000_scsifast)); |
425 | } | | 426 | } |
426 | #endif | | 427 | #endif |
427 | | | 428 | |
428 | /* | | 429 | /* |
429 | * Remember how many cycles there are per microsecond, | | 430 | * Remember how many cycles there are per microsecond, |
430 | * so that we can use delay(). Round up, for safety. | | 431 | * so that we can use delay(). Round up, for safety. |
431 | */ | | 432 | */ |
432 | cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000; | | 433 | cycles_per_usec = (hwrpb->rpb_cc_freq + 999999) / 1000000; |
433 | | | 434 | |
434 | /* | | 435 | /* |
435 | * Initialize the (temporary) bootstrap console interface, so | | 436 | * Initialize the (temporary) bootstrap console interface, so |
436 | * we can use printf until the VM system starts being setup. | | 437 | * we can use printf until the VM system starts being setup. |
437 | * The real console is initialized before then. | | 438 | * The real console is initialized before then. |
438 | */ | | 439 | */ |
439 | init_bootstrap_console(); | | 440 | init_bootstrap_console(); |
440 | | | 441 | |
441 | /* OUTPUT NOW ALLOWED */ | | 442 | /* OUTPUT NOW ALLOWED */ |
442 | | | 443 | |
443 | /* delayed from above */ | | 444 | /* delayed from above */ |
444 | if (bootinfo_msg) | | 445 | if (bootinfo_msg) |
445 | printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n", | | 446 | printf("WARNING: %s (0x%lx, 0x%lx, 0x%lx)\n", |
446 | bootinfo_msg, bim, bip, biv); | | 447 | bootinfo_msg, bim, bip, biv); |
447 | | | 448 | |
448 | /* Initialize the trap vectors on the primary processor. */ | | 449 | /* Initialize the trap vectors on the primary processor. */ |
449 | trap_init(); | | 450 | trap_init(); |
450 | | | 451 | |
451 | /* | | 452 | /* |
452 | * Find out this system's page size, and initialize | | 453 | * Find out this system's page size, and initialize |
453 | * PAGE_SIZE-dependent variables. | | 454 | * PAGE_SIZE-dependent variables. |
454 | */ | | 455 | */ |
455 | if (hwrpb->rpb_page_size != ALPHA_PGBYTES) | | 456 | if (hwrpb->rpb_page_size != ALPHA_PGBYTES) |
456 | panic("page size %lu != %d?!", hwrpb->rpb_page_size, | | 457 | panic("page size %lu != %d?!", hwrpb->rpb_page_size, |
457 | ALPHA_PGBYTES); | | 458 | ALPHA_PGBYTES); |
458 | uvmexp.pagesize = hwrpb->rpb_page_size; | | 459 | uvmexp.pagesize = hwrpb->rpb_page_size; |
459 | uvm_md_init(); | | 460 | uvm_md_init(); |
460 | | | 461 | |
461 | /* | | 462 | /* |
462 | * cputype has been initialized in init_prom_interface(). | | 463 | * cputype has been initialized in init_prom_interface(). |
463 | * Perform basic platform initialization using this info. | | 464 | * Perform basic platform initialization using this info. |
464 | */ | | 465 | */ |
465 | KASSERT(prom_interface_initialized); | | 466 | KASSERT(prom_interface_initialized); |
466 | c = platform_lookup(cputype); | | 467 | c = platform_lookup(cputype); |
467 | if (c == NULL) { | | 468 | if (c == NULL) { |
468 | platform_not_supported(); | | 469 | platform_not_supported(); |
469 | /* NOTREACHED */ | | 470 | /* NOTREACHED */ |
470 | } | | 471 | } |
471 | (*c->init)(); | | 472 | (*c->init)(); |
472 | cpu_setmodel("%s", platform.model); | | 473 | cpu_setmodel("%s", platform.model); |
473 | | | 474 | |
474 | /* | | 475 | /* |
475 | * Initialize the real console, so that the bootstrap console is | | 476 | * Initialize the real console, so that the bootstrap console is |
476 | * no longer necessary. | | 477 | * no longer necessary. |
477 | */ | | 478 | */ |
478 | (*platform.cons_init)(); | | 479 | (*platform.cons_init)(); |
479 | | | 480 | |
480 | #ifdef DIAGNOSTIC | | 481 | #ifdef DIAGNOSTIC |
481 | /* Paranoid sanity checking */ | | 482 | /* Paranoid sanity checking */ |
482 | | | 483 | |
483 | /* We should always be running on the primary. */ | | 484 | /* We should always be running on the primary. */ |
484 | assert(hwrpb->rpb_primary_cpu_id == cpu_id); | | 485 | assert(hwrpb->rpb_primary_cpu_id == cpu_id); |
485 | | | 486 | |
486 | /* | | 487 | /* |
487 | * On single-CPU systypes, the primary should always be CPU 0, | | 488 | * On single-CPU systypes, the primary should always be CPU 0, |
488 | * except on Alpha 8200 systems where the CPU id is related | | 489 | * except on Alpha 8200 systems where the CPU id is related |
489 | * to the VID, which is related to the Turbo Laser node id. | | 490 | * to the VID, which is related to the Turbo Laser node id. |
490 | */ | | 491 | */ |
491 | if (cputype != ST_DEC_21000) | | 492 | if (cputype != ST_DEC_21000) |
492 | assert(hwrpb->rpb_primary_cpu_id == 0); | | 493 | assert(hwrpb->rpb_primary_cpu_id == 0); |
493 | #endif | | 494 | #endif |
494 | | | 495 | |
495 | /* NO MORE FIRMWARE ACCESS ALLOWED */ | | 496 | /* NO MORE FIRMWARE ACCESS ALLOWED */ |
496 | /* XXX Unless prom_uses_prom_console() evaluates to non-zero.) */ | | 497 | /* XXX Unless prom_uses_prom_console() evaluates to non-zero.) */ |
497 | | | 498 | |
498 | /* | | 499 | /* |
499 | * Find the beginning and end of the kernel (and leave a | | 500 | * Find the beginning and end of the kernel (and leave a |
500 | * bit of space before the beginning for the bootstrap | | 501 | * bit of space before the beginning for the bootstrap |
501 | * stack). | | 502 | * stack). |
502 | */ | | 503 | */ |
503 | kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE; | | 504 | kernstart = trunc_page((vaddr_t)kernel_text) - 2 * PAGE_SIZE; |
504 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 505 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
505 | ksym_start = (void *)bootinfo.ssym; | | 506 | ksym_start = (void *)bootinfo.ssym; |
506 | ksym_end = (void *)bootinfo.esym; | | 507 | ksym_end = (void *)bootinfo.esym; |
507 | kernend = (vaddr_t)round_page((vaddr_t)ksym_end); | | 508 | kernend = (vaddr_t)round_page((vaddr_t)ksym_end); |
508 | #else | | 509 | #else |
509 | kernend = (vaddr_t)round_page((vaddr_t)_end); | | 510 | kernend = (vaddr_t)round_page((vaddr_t)_end); |
510 | #endif | | 511 | #endif |
511 | | | 512 | |
512 | kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart)); | | 513 | kernstartpfn = atop(ALPHA_K0SEG_TO_PHYS(kernstart)); |
513 | kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend)); | | 514 | kernendpfn = atop(ALPHA_K0SEG_TO_PHYS(kernend)); |
514 | | | 515 | |
515 | /* | | 516 | /* |
516 | * Find out how much memory is available, by looking at | | 517 | * Find out how much memory is available, by looking at |
517 | * the memory cluster descriptors. This also tries to do | | 518 | * the memory cluster descriptors. This also tries to do |
518 | * its best to detect things things that have never been seen | | 519 | * its best to detect things things that have never been seen |
519 | * before... | | 520 | * before... |
520 | */ | | 521 | */ |
521 | mddtp = (struct mddt *)(((char *)hwrpb) + hwrpb->rpb_memdat_off); | | 522 | mddtp = (struct mddt *)(((char *)hwrpb) + hwrpb->rpb_memdat_off); |
522 | | | 523 | |
523 | /* MDDT SANITY CHECKING */ | | 524 | /* MDDT SANITY CHECKING */ |
524 | mddtweird = 0; | | 525 | mddtweird = 0; |
525 | if (mddtp->mddt_cluster_cnt < 2) { | | 526 | if (mddtp->mddt_cluster_cnt < 2) { |
526 | mddtweird = 1; | | 527 | mddtweird = 1; |
527 | printf("WARNING: weird number of mem clusters: %lu\n", | | 528 | printf("WARNING: weird number of mem clusters: %lu\n", |
528 | mddtp->mddt_cluster_cnt); | | 529 | mddtp->mddt_cluster_cnt); |
529 | } | | 530 | } |
530 | | | 531 | |
531 | #if 0 | | 532 | #if 0 |
532 | printf("Memory cluster count: %" PRIu64 "\n", mddtp->mddt_cluster_cnt); | | 533 | printf("Memory cluster count: %" PRIu64 "\n", mddtp->mddt_cluster_cnt); |
533 | #endif | | 534 | #endif |
534 | | | 535 | |
535 | for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { | | 536 | for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { |
536 | memc = &mddtp->mddt_clusters[i]; | | 537 | memc = &mddtp->mddt_clusters[i]; |
537 | #if 0 | | 538 | #if 0 |
538 | printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i, | | 539 | printf("MEMC %d: pfn 0x%lx cnt 0x%lx usage 0x%lx\n", i, |
539 | memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage); | | 540 | memc->mddt_pfn, memc->mddt_pg_cnt, memc->mddt_usage); |
540 | #endif | | 541 | #endif |
541 | totalphysmem += memc->mddt_pg_cnt; | | 542 | totalphysmem += memc->mddt_pg_cnt; |
542 | if (mem_cluster_cnt < VM_PHYSSEG_MAX) { /* XXX */ | | 543 | if (mem_cluster_cnt < VM_PHYSSEG_MAX) { /* XXX */ |
543 | mem_clusters[mem_cluster_cnt].start = | | 544 | mem_clusters[mem_cluster_cnt].start = |
544 | ptoa(memc->mddt_pfn); | | 545 | ptoa(memc->mddt_pfn); |
545 | mem_clusters[mem_cluster_cnt].size = | | 546 | mem_clusters[mem_cluster_cnt].size = |
546 | ptoa(memc->mddt_pg_cnt); | | 547 | ptoa(memc->mddt_pg_cnt); |
547 | if (memc->mddt_usage & MDDT_mbz || | | 548 | if (memc->mddt_usage & MDDT_mbz || |
548 | memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */ | | 549 | memc->mddt_usage & MDDT_NONVOLATILE || /* XXX */ |
549 | memc->mddt_usage & MDDT_PALCODE) | | 550 | memc->mddt_usage & MDDT_PALCODE) |
550 | mem_clusters[mem_cluster_cnt].size |= | | 551 | mem_clusters[mem_cluster_cnt].size |= |
551 | PROT_READ; | | 552 | PROT_READ; |
552 | else | | 553 | else |
553 | mem_clusters[mem_cluster_cnt].size |= | | 554 | mem_clusters[mem_cluster_cnt].size |= |
554 | PROT_READ | PROT_WRITE | PROT_EXEC; | | 555 | PROT_READ | PROT_WRITE | PROT_EXEC; |
555 | mem_cluster_cnt++; | | 556 | mem_cluster_cnt++; |
556 | } | | 557 | } |
557 | | | 558 | |
558 | if (memc->mddt_usage & MDDT_mbz) { | | 559 | if (memc->mddt_usage & MDDT_mbz) { |
559 | mddtweird = 1; | | 560 | mddtweird = 1; |
560 | printf("WARNING: mem cluster %d has weird " | | 561 | printf("WARNING: mem cluster %d has weird " |
561 | "usage 0x%lx\n", i, memc->mddt_usage); | | 562 | "usage 0x%lx\n", i, memc->mddt_usage); |
562 | unknownmem += memc->mddt_pg_cnt; | | 563 | unknownmem += memc->mddt_pg_cnt; |
563 | continue; | | 564 | continue; |
564 | } | | 565 | } |
565 | if (memc->mddt_usage & MDDT_NONVOLATILE) { | | 566 | if (memc->mddt_usage & MDDT_NONVOLATILE) { |
566 | /* XXX should handle these... */ | | 567 | /* XXX should handle these... */ |
567 | printf("WARNING: skipping non-volatile mem " | | 568 | printf("WARNING: skipping non-volatile mem " |
568 | "cluster %d\n", i); | | 569 | "cluster %d\n", i); |
569 | unusedmem += memc->mddt_pg_cnt; | | 570 | unusedmem += memc->mddt_pg_cnt; |
570 | continue; | | 571 | continue; |
571 | } | | 572 | } |
572 | if (memc->mddt_usage & MDDT_PALCODE) { | | 573 | if (memc->mddt_usage & MDDT_PALCODE) { |
573 | resvmem += memc->mddt_pg_cnt; | | 574 | resvmem += memc->mddt_pg_cnt; |
574 | continue; | | 575 | continue; |
575 | } | | 576 | } |
576 | | | 577 | |
577 | /* | | 578 | /* |
578 | * We have a memory cluster available for system | | 579 | * We have a memory cluster available for system |
579 | * software use. We must determine if this cluster | | 580 | * software use. We must determine if this cluster |
580 | * holds the kernel. | | 581 | * holds the kernel. |
581 | */ | | 582 | */ |
582 | | | 583 | |
583 | /* | | 584 | /* |
584 | * XXX If the kernel uses the PROM console, we only use the | | 585 | * XXX If the kernel uses the PROM console, we only use the |
585 | * XXX memory after the kernel in the first system segment, | | 586 | * XXX memory after the kernel in the first system segment, |
586 | * XXX to avoid clobbering prom mapping, data, etc. | | 587 | * XXX to avoid clobbering prom mapping, data, etc. |
587 | */ | | 588 | */ |
588 | physmem += memc->mddt_pg_cnt; | | 589 | physmem += memc->mddt_pg_cnt; |
589 | pfn0 = memc->mddt_pfn; | | 590 | pfn0 = memc->mddt_pfn; |
590 | pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt; | | 591 | pfn1 = memc->mddt_pfn + memc->mddt_pg_cnt; |
591 | if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) { | | 592 | if (pfn0 <= kernstartpfn && kernendpfn <= pfn1) { |
592 | /* | | 593 | /* |
593 | * Must compute the location of the kernel | | 594 | * Must compute the location of the kernel |
594 | * within the segment. | | 595 | * within the segment. |
595 | */ | | 596 | */ |
596 | #if 0 | | 597 | #if 0 |
597 | printf("Cluster %d contains kernel\n", i); | | 598 | printf("Cluster %d contains kernel\n", i); |
598 | #endif | | 599 | #endif |
599 | if (pfn0 < kernstartpfn && !prom_uses_prom_console()) { | | 600 | if (pfn0 < kernstartpfn && !prom_uses_prom_console()) { |
600 | /* | | 601 | /* |
601 | * There is a chunk before the kernel. | | 602 | * There is a chunk before the kernel. |
602 | */ | | 603 | */ |
603 | #if 0 | | 604 | #if 0 |
604 | printf("Loading chunk before kernel: " | | 605 | printf("Loading chunk before kernel: " |
605 | "0x%lx / 0x%lx\n", pfn0, kernstartpfn); | | 606 | "0x%lx / 0x%lx\n", pfn0, kernstartpfn); |
606 | #endif | | 607 | #endif |
607 | alpha_page_physload(pfn0, kernstartpfn); | | 608 | alpha_page_physload(pfn0, kernstartpfn); |
608 | } | | 609 | } |
609 | if (kernendpfn < pfn1) { | | 610 | if (kernendpfn < pfn1) { |
610 | /* | | 611 | /* |
611 | * There is a chunk after the kernel. | | 612 | * There is a chunk after the kernel. |
612 | */ | | 613 | */ |
613 | #if 0 | | 614 | #if 0 |
614 | printf("Loading chunk after kernel: " | | 615 | printf("Loading chunk after kernel: " |
615 | "0x%lx / 0x%lx\n", kernendpfn, pfn1); | | 616 | "0x%lx / 0x%lx\n", kernendpfn, pfn1); |
616 | #endif | | 617 | #endif |
617 | alpha_page_physload(kernendpfn, pfn1); | | 618 | alpha_page_physload(kernendpfn, pfn1); |
618 | } | | 619 | } |
619 | } else { | | 620 | } else { |
620 | /* | | 621 | /* |
621 | * Just load this cluster as one chunk. | | 622 | * Just load this cluster as one chunk. |
622 | */ | | 623 | */ |
623 | #if 0 | | 624 | #if 0 |
624 | printf("Loading cluster %d: 0x%lx / 0x%lx\n", i, | | 625 | printf("Loading cluster %d: 0x%lx / 0x%lx\n", i, |
625 | pfn0, pfn1); | | 626 | pfn0, pfn1); |
626 | #endif | | 627 | #endif |
627 | alpha_page_physload(pfn0, pfn1); | | 628 | alpha_page_physload(pfn0, pfn1); |
628 | } | | 629 | } |
629 | } | | 630 | } |
630 | | | 631 | |
631 | /* | | 632 | /* |
632 | * Dump out the MDDT if it looks odd... | | 633 | * Dump out the MDDT if it looks odd... |
633 | */ | | 634 | */ |
634 | if (mddtweird) { | | 635 | if (mddtweird) { |
635 | printf("\n"); | | 636 | printf("\n"); |
636 | printf("complete memory cluster information:\n"); | | 637 | printf("complete memory cluster information:\n"); |
637 | for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { | | 638 | for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { |
638 | printf("mddt %d:\n", i); | | 639 | printf("mddt %d:\n", i); |
639 | printf("\tpfn %lx\n", | | 640 | printf("\tpfn %lx\n", |
640 | mddtp->mddt_clusters[i].mddt_pfn); | | 641 | mddtp->mddt_clusters[i].mddt_pfn); |
641 | printf("\tcnt %lx\n", | | 642 | printf("\tcnt %lx\n", |
642 | mddtp->mddt_clusters[i].mddt_pg_cnt); | | 643 | mddtp->mddt_clusters[i].mddt_pg_cnt); |
643 | printf("\ttest %lx\n", | | 644 | printf("\ttest %lx\n", |
644 | mddtp->mddt_clusters[i].mddt_pg_test); | | 645 | mddtp->mddt_clusters[i].mddt_pg_test); |
645 | printf("\tbva %lx\n", | | 646 | printf("\tbva %lx\n", |
646 | mddtp->mddt_clusters[i].mddt_v_bitaddr); | | 647 | mddtp->mddt_clusters[i].mddt_v_bitaddr); |
647 | printf("\tbpa %lx\n", | | 648 | printf("\tbpa %lx\n", |
648 | mddtp->mddt_clusters[i].mddt_p_bitaddr); | | 649 | mddtp->mddt_clusters[i].mddt_p_bitaddr); |
649 | printf("\tbcksum %lx\n", | | 650 | printf("\tbcksum %lx\n", |
650 | mddtp->mddt_clusters[i].mddt_bit_cksum); | | 651 | mddtp->mddt_clusters[i].mddt_bit_cksum); |
651 | printf("\tusage %lx\n", | | 652 | printf("\tusage %lx\n", |
652 | mddtp->mddt_clusters[i].mddt_usage); | | 653 | mddtp->mddt_clusters[i].mddt_usage); |
653 | } | | 654 | } |
654 | printf("\n"); | | 655 | printf("\n"); |
655 | } | | 656 | } |
656 | | | 657 | |
657 | if (totalphysmem == 0) | | 658 | if (totalphysmem == 0) |
658 | panic("can't happen: system seems to have no memory!"); | | 659 | panic("can't happen: system seems to have no memory!"); |
659 | maxmem = physmem; | | 660 | maxmem = physmem; |
660 | #if 0 | | 661 | #if 0 |
661 | printf("totalphysmem = %d\n", totalphysmem); | | 662 | printf("totalphysmem = %d\n", totalphysmem); |
662 | printf("physmem = %lu\n", physmem); | | 663 | printf("physmem = %lu\n", physmem); |
663 | printf("resvmem = %d\n", resvmem); | | 664 | printf("resvmem = %d\n", resvmem); |
664 | printf("unusedmem = %d\n", unusedmem); | | 665 | printf("unusedmem = %d\n", unusedmem); |
665 | printf("unknownmem = %d\n", unknownmem); | | 666 | printf("unknownmem = %d\n", unknownmem); |
666 | #endif | | 667 | #endif |
667 | | | 668 | |
668 | /* | | 669 | /* |
669 | * Initialize error message buffer (at end of core). | | 670 | * Initialize error message buffer (at end of core). |
670 | */ | | 671 | */ |
671 | { | | 672 | { |
672 | paddr_t end; | | 673 | paddr_t end; |
673 | vsize_t sz = (vsize_t)round_page(MSGBUFSIZE); | | 674 | vsize_t sz = (vsize_t)round_page(MSGBUFSIZE); |
674 | vsize_t reqsz = sz; | | 675 | vsize_t reqsz = sz; |
675 | uvm_physseg_t bank; | | 676 | uvm_physseg_t bank; |
676 | | | 677 | |
677 | bank = uvm_physseg_get_last(); | | 678 | bank = uvm_physseg_get_last(); |
678 | | | 679 | |
679 | /* shrink so that it'll fit in the last segment */ | | 680 | /* shrink so that it'll fit in the last segment */ |
680 | if (uvm_physseg_get_avail_end(bank) - uvm_physseg_get_avail_start(bank) < atop(sz)) | | 681 | if (uvm_physseg_get_avail_end(bank) - uvm_physseg_get_avail_start(bank) < atop(sz)) |
681 | sz = ptoa(uvm_physseg_get_avail_end(bank) - uvm_physseg_get_avail_start(bank)); | | 682 | sz = ptoa(uvm_physseg_get_avail_end(bank) - uvm_physseg_get_avail_start(bank)); |
682 | | | 683 | |
683 | end = uvm_physseg_get_end(bank); | | 684 | end = uvm_physseg_get_end(bank); |
684 | end -= atop(sz); | | 685 | end -= atop(sz); |
685 | | | 686 | |
686 | uvm_physseg_unplug(end, atop(sz)); | | 687 | uvm_physseg_unplug(end, atop(sz)); |
687 | msgbufaddr = (void *) ALPHA_PHYS_TO_K0SEG(ptoa(end)); | | 688 | msgbufaddr = (void *) ALPHA_PHYS_TO_K0SEG(ptoa(end)); |
688 | | | 689 | |
689 | initmsgbuf(msgbufaddr, sz); | | 690 | initmsgbuf(msgbufaddr, sz); |
690 | | | 691 | |
691 | /* warn if the message buffer had to be shrunk */ | | 692 | /* warn if the message buffer had to be shrunk */ |
692 | if (sz != reqsz) | | 693 | if (sz != reqsz) |
693 | printf("WARNING: %ld bytes not available for msgbuf " | | 694 | printf("WARNING: %ld bytes not available for msgbuf " |
694 | "in last cluster (%ld used)\n", reqsz, sz); | | 695 | "in last cluster (%ld used)\n", reqsz, sz); |
695 | | | 696 | |
696 | } | | 697 | } |
697 | | | 698 | |
698 | /* | | 699 | /* |
699 | * NOTE: It is safe to use uvm_pageboot_alloc() before | | 700 | * NOTE: It is safe to use uvm_pageboot_alloc() before |
700 | * pmap_bootstrap() because our pmap_virtual_space() | | 701 | * pmap_bootstrap() because our pmap_virtual_space() |
701 | * returns compile-time constants. | | 702 | * returns compile-time constants. |
702 | */ | | 703 | */ |
703 | | | 704 | |
704 | /* | | 705 | /* |
705 | * Allocate uarea page for lwp0 and set it. | | 706 | * Allocate uarea page for lwp0 and set it. |
706 | */ | | 707 | */ |
707 | v = uvm_pageboot_alloc(UPAGES * PAGE_SIZE); | | 708 | v = uvm_pageboot_alloc(UPAGES * PAGE_SIZE); |
708 | uvm_lwp_setuarea(&lwp0, v); | | 709 | uvm_lwp_setuarea(&lwp0, v); |
709 | | | 710 | |
710 | /* | | 711 | /* |
711 | * Initialize the virtual memory system, and set the | | 712 | * Initialize the virtual memory system, and set the |
712 | * page table base register in proc 0's PCB. | | 713 | * page table base register in proc 0's PCB. |
713 | */ | | 714 | */ |
714 | pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT), | | 715 | pmap_bootstrap(ALPHA_PHYS_TO_K0SEG(ptb << PGSHIFT), |
715 | hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt); | | 716 | hwrpb->rpb_max_asn, hwrpb->rpb_pcs_cnt); |
716 | | | 717 | |
717 | /* | | 718 | /* |
718 | * Initialize the rest of lwp0's PCB and cache its physical address. | | 719 | * Initialize the rest of lwp0's PCB and cache its physical address. |
719 | */ | | 720 | */ |
720 | pcb0 = lwp_getpcb(&lwp0); | | 721 | pcb0 = lwp_getpcb(&lwp0); |
721 | lwp0.l_md.md_pcbpaddr = (void *)ALPHA_K0SEG_TO_PHYS((vaddr_t)pcb0); | | 722 | lwp0.l_md.md_pcbpaddr = (void *)ALPHA_K0SEG_TO_PHYS((vaddr_t)pcb0); |
722 | | | 723 | |
723 | /* | | 724 | /* |
724 | * Set the kernel sp, reserving space for an (empty) trapframe, | | 725 | * Set the kernel sp, reserving space for an (empty) trapframe, |
725 | * and make lwp0's trapframe pointer point to it for sanity. | | 726 | * and make lwp0's trapframe pointer point to it for sanity. |
726 | */ | | 727 | */ |
727 | pcb0->pcb_hw.apcb_ksp = v + USPACE - sizeof(struct trapframe); | | 728 | pcb0->pcb_hw.apcb_ksp = v + USPACE - sizeof(struct trapframe); |
728 | lwp0.l_md.md_tf = (struct trapframe *)pcb0->pcb_hw.apcb_ksp; | | 729 | lwp0.l_md.md_tf = (struct trapframe *)pcb0->pcb_hw.apcb_ksp; |
729 | | | 730 | |
730 | /* Indicate that lwp0 has a CPU. */ | | 731 | /* Indicate that lwp0 has a CPU. */ |
731 | lwp0.l_cpu = ci; | | 732 | lwp0.l_cpu = ci; |
732 | | | 733 | |
733 | /* | | 734 | /* |
734 | * Look at arguments passed to us and compute boothowto. | | 735 | * Look at arguments passed to us and compute boothowto. |
735 | */ | | 736 | */ |
736 | | | 737 | |
737 | boothowto = RB_SINGLE; | | 738 | boothowto = RB_SINGLE; |
738 | #ifdef KADB | | 739 | #ifdef KADB |
739 | boothowto |= RB_KDB; | | 740 | boothowto |= RB_KDB; |
740 | #endif | | 741 | #endif |
741 | for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { | | 742 | for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { |
742 | /* | | 743 | /* |
743 | * Note that we'd really like to differentiate case here, | | 744 | * Note that we'd really like to differentiate case here, |
744 | * but the Alpha AXP Architecture Reference Manual | | 745 | * but the Alpha AXP Architecture Reference Manual |
745 | * says that we shouldn't. | | 746 | * says that we shouldn't. |
746 | */ | | 747 | */ |
747 | switch (*p) { | | 748 | switch (*p) { |
748 | case 'a': /* autoboot */ | | 749 | case 'a': /* autoboot */ |
749 | case 'A': | | 750 | case 'A': |
750 | boothowto &= ~RB_SINGLE; | | 751 | boothowto &= ~RB_SINGLE; |
751 | break; | | 752 | break; |
752 | | | 753 | |
753 | #ifdef DEBUG | | 754 | #ifdef DEBUG |
754 | case 'c': /* crash dump immediately after autoconfig */ | | 755 | case 'c': /* crash dump immediately after autoconfig */ |
755 | case 'C': | | 756 | case 'C': |
756 | boothowto |= RB_DUMP; | | 757 | boothowto |= RB_DUMP; |
757 | break; | | 758 | break; |
758 | #endif | | 759 | #endif |
759 | | | 760 | |
760 | #if defined(KGDB) || defined(DDB) | | 761 | #if defined(KGDB) || defined(DDB) |
761 | case 'd': /* break into the kernel debugger ASAP */ | | 762 | case 'd': /* break into the kernel debugger ASAP */ |
762 | case 'D': | | 763 | case 'D': |
763 | boothowto |= RB_KDB; | | 764 | boothowto |= RB_KDB; |
764 | break; | | 765 | break; |
765 | #endif | | 766 | #endif |
766 | | | 767 | |
767 | case 'h': /* always halt, never reboot */ | | 768 | case 'h': /* always halt, never reboot */ |
768 | case 'H': | | 769 | case 'H': |
769 | boothowto |= RB_HALT; | | 770 | boothowto |= RB_HALT; |
770 | break; | | 771 | break; |
771 | | | 772 | |
772 | #if 0 | | 773 | #if 0 |
773 | case 'm': /* mini root present in memory */ | | 774 | case 'm': /* mini root present in memory */ |
774 | case 'M': | | 775 | case 'M': |
775 | boothowto |= RB_MINIROOT; | | 776 | boothowto |= RB_MINIROOT; |
776 | break; | | 777 | break; |
777 | #endif | | 778 | #endif |
778 | | | 779 | |
779 | case 'n': /* askname */ | | 780 | case 'n': /* askname */ |
780 | case 'N': | | 781 | case 'N': |
781 | boothowto |= RB_ASKNAME; | | 782 | boothowto |= RB_ASKNAME; |
782 | break; | | 783 | break; |
783 | | | 784 | |
784 | case 's': /* single-user (default, supported for sanity) */ | | 785 | case 's': /* single-user (default, supported for sanity) */ |
785 | case 'S': | | 786 | case 'S': |
786 | boothowto |= RB_SINGLE; | | 787 | boothowto |= RB_SINGLE; |
787 | break; | | 788 | break; |
788 | | | 789 | |
789 | case 'q': /* quiet boot */ | | 790 | case 'q': /* quiet boot */ |
790 | case 'Q': | | 791 | case 'Q': |
791 | boothowto |= AB_QUIET; | | 792 | boothowto |= AB_QUIET; |
792 | break; | | 793 | break; |
793 | | | 794 | |
794 | case 'v': /* verbose boot */ | | 795 | case 'v': /* verbose boot */ |
795 | case 'V': | | 796 | case 'V': |
796 | boothowto |= AB_VERBOSE; | | 797 | boothowto |= AB_VERBOSE; |
797 | break; | | 798 | break; |
798 | | | 799 | |
799 | case '-': | | 800 | case '-': |
800 | /* | | 801 | /* |
801 | * Just ignore this. It's not required, but it's | | 802 | * Just ignore this. It's not required, but it's |
802 | * common for it to be passed regardless. | | 803 | * common for it to be passed regardless. |
803 | */ | | 804 | */ |
804 | break; | | 805 | break; |
805 | | | 806 | |
806 | default: | | 807 | default: |
807 | printf("Unrecognized boot flag '%c'.\n", *p); | | 808 | printf("Unrecognized boot flag '%c'.\n", *p); |
808 | break; | | 809 | break; |
809 | } | | 810 | } |
810 | } | | 811 | } |
811 | | | 812 | |
812 | /* | | 813 | /* |
813 | * Perform any initial kernel patches based on the running system. | | 814 | * Perform any initial kernel patches based on the running system. |
814 | * We may perform more later if we attach additional CPUs. | | 815 | * We may perform more later if we attach additional CPUs. |
815 | */ | | 816 | */ |
816 | alpha_patch(false); | | 817 | alpha_patch(false); |
817 | | | 818 | |
818 | /* | | 819 | /* |
819 | * Figure out the number of CPUs in the box, from RPB fields. | | 820 | * Figure out the number of CPUs in the box, from RPB fields. |
820 | * Really. We mean it. | | 821 | * Really. We mean it. |
821 | */ | | 822 | */ |
822 | for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { | | 823 | for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { |
823 | struct pcs *pcsp; | | 824 | struct pcs *pcsp; |
824 | | | 825 | |
825 | pcsp = LOCATE_PCS(hwrpb, i); | | 826 | pcsp = LOCATE_PCS(hwrpb, i); |
826 | if ((pcsp->pcs_flags & PCS_PP) != 0) | | 827 | if ((pcsp->pcs_flags & PCS_PP) != 0) |
827 | ncpus++; | | 828 | ncpus++; |
828 | } | | 829 | } |
829 | | | 830 | |
830 | /* | | 831 | /* |
831 | * Initialize debuggers, and break into them if appropriate. | | 832 | * Initialize debuggers, and break into them if appropriate. |
832 | */ | | 833 | */ |
833 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 834 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
834 | ksyms_addsyms_elf((int)((uint64_t)ksym_end - (uint64_t)ksym_start), | | 835 | ksyms_addsyms_elf((int)((uint64_t)ksym_end - (uint64_t)ksym_start), |
835 | ksym_start, ksym_end); | | 836 | ksym_start, ksym_end); |
836 | #endif | | 837 | #endif |
837 | | | 838 | |
838 | if (boothowto & RB_KDB) { | | 839 | if (boothowto & RB_KDB) { |
839 | #if defined(KGDB) | | 840 | #if defined(KGDB) |
840 | kgdb_debug_init = 1; | | 841 | kgdb_debug_init = 1; |
841 | kgdb_connect(1); | | 842 | kgdb_connect(1); |
842 | #elif defined(DDB) | | 843 | #elif defined(DDB) |
843 | Debugger(); | | 844 | Debugger(); |
844 | #endif | | 845 | #endif |
845 | } | | 846 | } |
846 | | | 847 | |
847 | #ifdef DIAGNOSTIC | | 848 | #ifdef DIAGNOSTIC |
848 | /* | | 849 | /* |
849 | * Check our clock frequency, from RPB fields. | | 850 | * Check our clock frequency, from RPB fields. |
850 | */ | | 851 | */ |
851 | if ((hwrpb->rpb_intr_freq >> 12) != 1024) | | 852 | if ((hwrpb->rpb_intr_freq >> 12) != 1024) |
852 | printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n", | | 853 | printf("WARNING: unbelievable rpb_intr_freq: %ld (%d hz)\n", |
853 | hwrpb->rpb_intr_freq, hz); | | 854 | hwrpb->rpb_intr_freq, hz); |
854 | #endif | | 855 | #endif |
855 | } | | 856 | } |
856 | | | 857 | |
857 | #ifdef MODULAR | | 858 | #ifdef MODULAR |
858 | /* Push any modules loaded by the boot loader */ | | 859 | /* Push any modules loaded by the boot loader */ |
859 | void | | 860 | void |
860 | module_init_md(void) | | 861 | module_init_md(void) |
861 | { | | 862 | { |
862 | /* nada. */ | | 863 | /* nada. */ |
863 | } | | 864 | } |
864 | #endif /* MODULAR */ | | 865 | #endif /* MODULAR */ |
865 | | | 866 | |
866 | void | | 867 | void |
867 | consinit(void) | | 868 | consinit(void) |
868 | { | | 869 | { |
869 | | | 870 | |
870 | /* | | 871 | /* |
871 | * Everything related to console initialization is done | | 872 | * Everything related to console initialization is done |
872 | * in alpha_init(). | | 873 | * in alpha_init(). |
873 | */ | | 874 | */ |
874 | #if defined(DIAGNOSTIC) && defined(_PROM_MAY_USE_PROM_CONSOLE) | | 875 | #if defined(DIAGNOSTIC) && defined(_PROM_MAY_USE_PROM_CONSOLE) |
875 | printf("consinit: %susing prom console\n", | | 876 | printf("consinit: %susing prom console\n", |
876 | prom_uses_prom_console() ? "" : "not "); | | 877 | prom_uses_prom_console() ? "" : "not "); |
877 | #endif | | 878 | #endif |
878 | } | | 879 | } |
879 | | | 880 | |
880 | void | | 881 | void |
881 | cpu_startup(void) | | 882 | cpu_startup(void) |
882 | { | | 883 | { |
883 | extern struct evcnt fpevent_use, fpevent_reuse; | | 884 | extern struct evcnt fpevent_use, fpevent_reuse; |
884 | vaddr_t minaddr, maxaddr; | | 885 | vaddr_t minaddr, maxaddr; |
885 | char pbuf[9]; | | 886 | char pbuf[9]; |
886 | #if defined(DEBUG) | | 887 | #if defined(DEBUG) |
887 | extern int pmapdebug; | | 888 | extern int pmapdebug; |
888 | int opmapdebug = pmapdebug; | | 889 | int opmapdebug = pmapdebug; |
889 | | | 890 | |
890 | pmapdebug = 0; | | 891 | pmapdebug = 0; |
891 | #endif | | 892 | #endif |
892 | | | 893 | |
893 | /* | | 894 | /* |
894 | * Good {morning,afternoon,evening,night}. | | 895 | * Good {morning,afternoon,evening,night}. |
895 | */ | | 896 | */ |
896 | printf("%s%s", copyright, version); | | 897 | printf("%s%s", copyright, version); |
897 | identifycpu(); | | 898 | identifycpu(); |
898 | format_bytes(pbuf, sizeof(pbuf), ptoa(totalphysmem)); | | 899 | format_bytes(pbuf, sizeof(pbuf), ptoa(totalphysmem)); |
899 | printf("total memory = %s\n", pbuf); | | 900 | printf("total memory = %s\n", pbuf); |
900 | format_bytes(pbuf, sizeof(pbuf), ptoa(resvmem)); | | 901 | format_bytes(pbuf, sizeof(pbuf), ptoa(resvmem)); |
901 | printf("(%s reserved for PROM, ", pbuf); | | 902 | printf("(%s reserved for PROM, ", pbuf); |
902 | format_bytes(pbuf, sizeof(pbuf), ptoa(physmem)); | | 903 | format_bytes(pbuf, sizeof(pbuf), ptoa(physmem)); |
903 | printf("%s used by NetBSD)\n", pbuf); | | 904 | printf("%s used by NetBSD)\n", pbuf); |
904 | if (unusedmem) { | | 905 | if (unusedmem) { |
905 | format_bytes(pbuf, sizeof(pbuf), ptoa(unusedmem)); | | 906 | format_bytes(pbuf, sizeof(pbuf), ptoa(unusedmem)); |
906 | printf("WARNING: unused memory = %s\n", pbuf); | | 907 | printf("WARNING: unused memory = %s\n", pbuf); |
907 | } | | 908 | } |
908 | if (unknownmem) { | | 909 | if (unknownmem) { |
909 | format_bytes(pbuf, sizeof(pbuf), ptoa(unknownmem)); | | 910 | format_bytes(pbuf, sizeof(pbuf), ptoa(unknownmem)); |
910 | printf("WARNING: %s of memory with unknown purpose\n", pbuf); | | 911 | printf("WARNING: %s of memory with unknown purpose\n", pbuf); |
911 | } | | 912 | } |
912 | | | 913 | |
913 | minaddr = 0; | | 914 | minaddr = 0; |
914 | | | 915 | |
915 | /* | | 916 | /* |
916 | * Allocate a submap for physio | | 917 | * Allocate a submap for physio |
917 | */ | | 918 | */ |
918 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 919 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
919 | VM_PHYS_SIZE, 0, false, NULL); | | 920 | VM_PHYS_SIZE, 0, false, NULL); |
920 | | | 921 | |
921 | /* | | 922 | /* |
922 | * No need to allocate an mbuf cluster submap. Mbuf clusters | | 923 | * No need to allocate an mbuf cluster submap. Mbuf clusters |
923 | * are allocated via the pool allocator, and we use K0SEG to | | 924 | * are allocated via the pool allocator, and we use K0SEG to |
924 | * map those pages. | | 925 | * map those pages. |
925 | */ | | 926 | */ |
926 | | | 927 | |
927 | #if defined(DEBUG) | | 928 | #if defined(DEBUG) |
928 | pmapdebug = opmapdebug; | | 929 | pmapdebug = opmapdebug; |
929 | #endif | | 930 | #endif |
930 | format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); | | 931 | format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); |
931 | printf("avail memory = %s\n", pbuf); | | 932 | printf("avail memory = %s\n", pbuf); |
932 | #if 0 | | 933 | #if 0 |
933 | { | | 934 | { |
934 | extern u_long pmap_pages_stolen; | | 935 | extern u_long pmap_pages_stolen; |
935 | | | 936 | |
936 | format_bytes(pbuf, sizeof(pbuf), pmap_pages_stolen * PAGE_SIZE); | | 937 | format_bytes(pbuf, sizeof(pbuf), pmap_pages_stolen * PAGE_SIZE); |
937 | printf("stolen memory for VM structures = %s\n", pbuf); | | 938 | printf("stolen memory for VM structures = %s\n", pbuf); |
938 | } | | 939 | } |
939 | #endif | | 940 | #endif |
940 | | | 941 | |
941 | /* | | 942 | /* |
942 | * Set up the HWPCB so that it's safe to configure secondary | | 943 | * Set up the HWPCB so that it's safe to configure secondary |
943 | * CPUs. | | 944 | * CPUs. |
944 | */ | | 945 | */ |
945 | hwrpb_primary_init(); | | 946 | hwrpb_primary_init(); |
946 | | | 947 | |
947 | /* | | 948 | /* |
948 | * Initialize some trap event counters. | | 949 | * Initialize some trap event counters. |
949 | */ | | 950 | */ |
950 | evcnt_attach_dynamic_nozero(&fpevent_use, EVCNT_TYPE_MISC, NULL, | | 951 | evcnt_attach_dynamic_nozero(&fpevent_use, EVCNT_TYPE_MISC, NULL, |
951 | "FP", "proc use"); | | 952 | "FP", "proc use"); |
952 | evcnt_attach_dynamic_nozero(&fpevent_reuse, EVCNT_TYPE_MISC, NULL, | | 953 | evcnt_attach_dynamic_nozero(&fpevent_reuse, EVCNT_TYPE_MISC, NULL, |
953 | "FP", "proc re-use"); | | 954 | "FP", "proc re-use"); |
954 | } | | 955 | } |
955 | | | 956 | |
956 | /* | | 957 | /* |
957 | * Retrieve the platform name from the DSR. | | 958 | * Retrieve the platform name from the DSR. |
958 | */ | | 959 | */ |
959 | const char * | | 960 | const char * |
960 | alpha_dsr_sysname(void) | | 961 | alpha_dsr_sysname(void) |
961 | { | | 962 | { |
962 | struct dsrdb *dsr; | | 963 | struct dsrdb *dsr; |
963 | const char *sysname; | | 964 | const char *sysname; |
964 | | | 965 | |
965 | /* | | 966 | /* |
966 | * DSR does not exist on early HWRPB versions. | | 967 | * DSR does not exist on early HWRPB versions. |
967 | */ | | 968 | */ |
968 | if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS) | | 969 | if (hwrpb->rpb_version < HWRPB_DSRDB_MINVERS) |
969 | return (NULL); | | 970 | return (NULL); |
970 | | | 971 | |
971 | dsr = (struct dsrdb *)(((char *)hwrpb) + hwrpb->rpb_dsrdb_off); | | 972 | dsr = (struct dsrdb *)(((char *)hwrpb) + hwrpb->rpb_dsrdb_off); |
972 | sysname = (const char *)((char *)dsr + (dsr->dsr_sysname_off + | | 973 | sysname = (const char *)((char *)dsr + (dsr->dsr_sysname_off + |
973 | sizeof(uint64_t))); | | 974 | sizeof(uint64_t))); |
974 | return (sysname); | | 975 | return (sysname); |
975 | } | | 976 | } |
976 | | | 977 | |
977 | /* | | 978 | /* |
978 | * Lookup the system specified system variation in the provided table, | | 979 | * Lookup the system specified system variation in the provided table, |
979 | * returning the model string on match. | | 980 | * returning the model string on match. |
980 | */ | | 981 | */ |
981 | const char * | | 982 | const char * |
982 | alpha_variation_name(uint64_t variation, const struct alpha_variation_table *avtp) | | 983 | alpha_variation_name(uint64_t variation, const struct alpha_variation_table *avtp) |
983 | { | | 984 | { |
984 | int i; | | 985 | int i; |
985 | | | 986 | |
986 | for (i = 0; avtp[i].avt_model != NULL; i++) | | 987 | for (i = 0; avtp[i].avt_model != NULL; i++) |
987 | if (avtp[i].avt_variation == variation) | | 988 | if (avtp[i].avt_variation == variation) |
988 | return (avtp[i].avt_model); | | 989 | return (avtp[i].avt_model); |
989 | return (NULL); | | 990 | return (NULL); |
990 | } | | 991 | } |
991 | | | 992 | |
992 | /* | | 993 | /* |
993 | * Generate a default platform name based for unknown system variations. | | 994 | * Generate a default platform name based for unknown system variations. |
994 | */ | | 995 | */ |
995 | const char * | | 996 | const char * |
996 | alpha_unknown_sysname(void) | | 997 | alpha_unknown_sysname(void) |
997 | { | | 998 | { |
998 | static char s[128]; /* safe size */ | | 999 | static char s[128]; /* safe size */ |
999 | | | 1000 | |
1000 | snprintf(s, sizeof(s), "%s family, unknown model variation 0x%lx", | | 1001 | snprintf(s, sizeof(s), "%s family, unknown model variation 0x%lx", |
1001 | platform.family, hwrpb->rpb_variation & SV_ST_MASK); | | 1002 | platform.family, hwrpb->rpb_variation & SV_ST_MASK); |
1002 | return ((const char *)s); | | 1003 | return ((const char *)s); |
1003 | } | | 1004 | } |
1004 | | | 1005 | |
1005 | void | | 1006 | void |
1006 | identifycpu(void) | | 1007 | identifycpu(void) |
1007 | { | | 1008 | { |
1008 | const char *s; | | 1009 | const char *s; |
1009 | int i; | | 1010 | int i; |
1010 | | | 1011 | |
1011 | /* | | 1012 | /* |
1012 | * print out CPU identification information. | | 1013 | * print out CPU identification information. |
1013 | */ | | 1014 | */ |
1014 | printf("%s", cpu_getmodel()); | | 1015 | printf("%s", cpu_getmodel()); |
1015 | for(s = cpu_getmodel(); *s; ++s) | | 1016 | for(s = cpu_getmodel(); *s; ++s) |
1016 | if(strncasecmp(s, "MHz", 3) == 0) | | 1017 | if(strncasecmp(s, "MHz", 3) == 0) |
1017 | goto skipMHz; | | 1018 | goto skipMHz; |
1018 | printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000); | | 1019 | printf(", %ldMHz", hwrpb->rpb_cc_freq / 1000000); |
1019 | skipMHz: | | 1020 | skipMHz: |
1020 | printf(", s/n "); | | 1021 | printf(", s/n "); |
1021 | for (i = 0; i < 10; i++) | | 1022 | for (i = 0; i < 10; i++) |
1022 | printf("%c", hwrpb->rpb_ssn[i]); | | 1023 | printf("%c", hwrpb->rpb_ssn[i]); |
1023 | printf("\n"); | | 1024 | printf("\n"); |
1024 | printf("%ld byte page size, %d processor%s.\n", | | 1025 | printf("%ld byte page size, %d processor%s.\n", |
1025 | hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s"); | | 1026 | hwrpb->rpb_page_size, ncpus, ncpus == 1 ? "" : "s"); |
1026 | } | | 1027 | } |
1027 | | | 1028 | |
1028 | int waittime = -1; | | 1029 | int waittime = -1; |
1029 | struct pcb dumppcb; | | 1030 | struct pcb dumppcb; |
1030 | | | 1031 | |
1031 | void | | 1032 | void |
1032 | cpu_reboot(int howto, char *bootstr) | | 1033 | cpu_reboot(int howto, char *bootstr) |
1033 | { | | 1034 | { |
1034 | #if defined(MULTIPROCESSOR) | | 1035 | #if defined(MULTIPROCESSOR) |
1035 | u_long cpu_id = cpu_number(); | | 1036 | u_long cpu_id = cpu_number(); |
1036 | u_long wait_mask; | | 1037 | u_long wait_mask; |
1037 | int i; | | 1038 | int i; |
1038 | #endif | | 1039 | #endif |
1039 | | | 1040 | |
1040 | /* If "always halt" was specified as a boot flag, obey. */ | | 1041 | /* If "always halt" was specified as a boot flag, obey. */ |
1041 | if ((boothowto & RB_HALT) != 0) | | 1042 | if ((boothowto & RB_HALT) != 0) |
1042 | howto |= RB_HALT; | | 1043 | howto |= RB_HALT; |
1043 | | | 1044 | |
1044 | boothowto = howto; | | 1045 | boothowto = howto; |
1045 | | | 1046 | |
1046 | /* If system is cold, just halt. */ | | 1047 | /* If system is cold, just halt. */ |
1047 | if (cold) { | | 1048 | if (cold) { |
1048 | boothowto |= RB_HALT; | | 1049 | boothowto |= RB_HALT; |
1049 | goto haltsys; | | 1050 | goto haltsys; |
1050 | } | | 1051 | } |
1051 | | | 1052 | |
1052 | if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { | | 1053 | if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { |
1053 | waittime = 0; | | 1054 | waittime = 0; |
1054 | vfs_shutdown(); | | 1055 | vfs_shutdown(); |
1055 | /* | | 1056 | /* |
1056 | * If we've been adjusting the clock, the todr | | 1057 | * If we've been adjusting the clock, the todr |
1057 | * will be out of synch; adjust it now. | | 1058 | * will be out of synch; adjust it now. |
1058 | */ | | 1059 | */ |
1059 | resettodr(); | | 1060 | resettodr(); |
1060 | } | | 1061 | } |
1061 | | | 1062 | |
1062 | /* Disable interrupts. */ | | 1063 | /* Disable interrupts. */ |
1063 | splhigh(); | | 1064 | splhigh(); |
1064 | | | 1065 | |
1065 | #if defined(MULTIPROCESSOR) | | 1066 | #if defined(MULTIPROCESSOR) |
1066 | /* | | 1067 | /* |
1067 | * Halt all other CPUs. If we're not the primary, the | | 1068 | * Halt all other CPUs. If we're not the primary, the |
1068 | * primary will spin, waiting for us to halt. | | 1069 | * primary will spin, waiting for us to halt. |
1069 | */ | | 1070 | */ |
1070 | cpu_id = cpu_number(); /* may have changed cpu */ | | 1071 | cpu_id = cpu_number(); /* may have changed cpu */ |
1071 | wait_mask = (1UL << cpu_id) | (1UL << hwrpb->rpb_primary_cpu_id); | | 1072 | wait_mask = (1UL << cpu_id) | (1UL << hwrpb->rpb_primary_cpu_id); |
1072 | | | 1073 | |
1073 | alpha_broadcast_ipi(ALPHA_IPI_HALT); | | 1074 | alpha_broadcast_ipi(ALPHA_IPI_HALT); |
1074 | | | 1075 | |
1075 | /* Ensure any CPUs paused by DDB resume execution so they can halt */ | | 1076 | /* Ensure any CPUs paused by DDB resume execution so they can halt */ |
1076 | cpus_paused = 0; | | 1077 | cpus_paused = 0; |
1077 | | | 1078 | |
1078 | for (i = 0; i < 10000; i++) { | | 1079 | for (i = 0; i < 10000; i++) { |
1079 | alpha_mb(); | | 1080 | alpha_mb(); |
1080 | if (cpus_running == wait_mask) | | 1081 | if (cpus_running == wait_mask) |
1081 | break; | | 1082 | break; |
1082 | delay(1000); | | 1083 | delay(1000); |
1083 | } | | 1084 | } |
1084 | alpha_mb(); | | 1085 | alpha_mb(); |
1085 | if (cpus_running != wait_mask) | | 1086 | if (cpus_running != wait_mask) |
1086 | printf("WARNING: Unable to halt secondary CPUs (0x%lx)\n", | | 1087 | printf("WARNING: Unable to halt secondary CPUs (0x%lx)\n", |
1087 | cpus_running); | | 1088 | cpus_running); |
1088 | #endif /* MULTIPROCESSOR */ | | 1089 | #endif /* MULTIPROCESSOR */ |
1089 | | | 1090 | |
1090 | /* If rebooting and a dump is requested do it. */ | | 1091 | /* If rebooting and a dump is requested do it. */ |
1091 | #if 0 | | 1092 | #if 0 |
1092 | if ((boothowto & (RB_DUMP | RB_HALT)) == RB_DUMP) | | 1093 | if ((boothowto & (RB_DUMP | RB_HALT)) == RB_DUMP) |
1093 | #else | | 1094 | #else |
1094 | if (boothowto & RB_DUMP) | | 1095 | if (boothowto & RB_DUMP) |
1095 | #endif | | 1096 | #endif |
1096 | dumpsys(); | | 1097 | dumpsys(); |
1097 | | | 1098 | |
1098 | haltsys: | | 1099 | haltsys: |
1099 | | | 1100 | |
1100 | /* run any shutdown hooks */ | | 1101 | /* run any shutdown hooks */ |
1101 | doshutdownhooks(); | | 1102 | doshutdownhooks(); |
1102 | | | 1103 | |
1103 | pmf_system_shutdown(boothowto); | | 1104 | pmf_system_shutdown(boothowto); |
1104 | | | 1105 | |
1105 | #ifdef BOOTKEY | | 1106 | #ifdef BOOTKEY |
1106 | printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot"); | | 1107 | printf("hit any key to %s...\n", howto & RB_HALT ? "halt" : "reboot"); |
1107 | cnpollc(1); /* for proper keyboard command handling */ | | 1108 | cnpollc(1); /* for proper keyboard command handling */ |
1108 | cngetc(); | | 1109 | cngetc(); |
1109 | cnpollc(0); | | 1110 | cnpollc(0); |
1110 | printf("\n"); | | 1111 | printf("\n"); |
1111 | #endif | | 1112 | #endif |
1112 | | | 1113 | |
1113 | /* Finally, powerdown/halt/reboot the system. */ | | 1114 | /* Finally, powerdown/halt/reboot the system. */ |
1114 | if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN && | | 1115 | if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN && |
1115 | platform.powerdown != NULL) { | | 1116 | platform.powerdown != NULL) { |
1116 | (*platform.powerdown)(); | | 1117 | (*platform.powerdown)(); |
1117 | printf("WARNING: powerdown failed!\n"); | | 1118 | printf("WARNING: powerdown failed!\n"); |
1118 | } | | 1119 | } |
1119 | printf("%s\n\n", (boothowto & RB_HALT) ? "halted." : "rebooting..."); | | 1120 | printf("%s\n\n", (boothowto & RB_HALT) ? "halted." : "rebooting..."); |
1120 | #if defined(MULTIPROCESSOR) | | 1121 | #if defined(MULTIPROCESSOR) |
1121 | if (cpu_id != hwrpb->rpb_primary_cpu_id) | | 1122 | if (cpu_id != hwrpb->rpb_primary_cpu_id) |
1122 | cpu_halt(); | | 1123 | cpu_halt(); |
1123 | else | | 1124 | else |
1124 | #endif | | 1125 | #endif |
1125 | prom_halt(boothowto & RB_HALT); | | 1126 | prom_halt(boothowto & RB_HALT); |
1126 | /*NOTREACHED*/ | | 1127 | /*NOTREACHED*/ |
1127 | } | | 1128 | } |
1128 | | | 1129 | |
1129 | /* | | 1130 | /* |
1130 | * These variables are needed by /sbin/savecore | | 1131 | * These variables are needed by /sbin/savecore |
1131 | */ | | 1132 | */ |
1132 | uint32_t dumpmag = 0x8fca0101; /* magic number */ | | 1133 | uint32_t dumpmag = 0x8fca0101; /* magic number */ |
1133 | int dumpsize = 0; /* pages */ | | 1134 | int dumpsize = 0; /* pages */ |
1134 | long dumplo = 0; /* blocks */ | | 1135 | long dumplo = 0; /* blocks */ |
1135 | | | 1136 | |
1136 | /* | | 1137 | /* |
1137 | * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. | | 1138 | * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. |
1138 | */ | | 1139 | */ |
1139 | int | | 1140 | int |
1140 | cpu_dumpsize(void) | | 1141 | cpu_dumpsize(void) |
1141 | { | | 1142 | { |
1142 | int size; | | 1143 | int size; |
1143 | | | 1144 | |
1144 | size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) + | | 1145 | size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) + |
1145 | ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); | | 1146 | ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); |
1146 | if (roundup(size, dbtob(1)) != dbtob(1)) | | 1147 | if (roundup(size, dbtob(1)) != dbtob(1)) |
1147 | return -1; | | 1148 | return -1; |
1148 | | | 1149 | |
1149 | return (1); | | 1150 | return (1); |
1150 | } | | 1151 | } |
1151 | | | 1152 | |
1152 | /* | | 1153 | /* |
1153 | * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped. | | 1154 | * cpu_dump_mempagecnt: calculate size of RAM (in pages) to be dumped. |
1154 | */ | | 1155 | */ |
1155 | u_long | | 1156 | u_long |
1156 | cpu_dump_mempagecnt(void) | | 1157 | cpu_dump_mempagecnt(void) |
1157 | { | | 1158 | { |
1158 | u_long i, n; | | 1159 | u_long i, n; |
1159 | | | 1160 | |
1160 | n = 0; | | 1161 | n = 0; |
1161 | for (i = 0; i < mem_cluster_cnt; i++) | | 1162 | for (i = 0; i < mem_cluster_cnt; i++) |
1162 | n += atop(mem_clusters[i].size); | | 1163 | n += atop(mem_clusters[i].size); |
1163 | return (n); | | 1164 | return (n); |
1164 | } | | 1165 | } |
1165 | | | 1166 | |
1166 | /* | | 1167 | /* |
1167 | * cpu_dump: dump machine-dependent kernel core dump headers. | | 1168 | * cpu_dump: dump machine-dependent kernel core dump headers. |
1168 | */ | | 1169 | */ |
1169 | int | | 1170 | int |
1170 | cpu_dump(void) | | 1171 | cpu_dump(void) |
1171 | { | | 1172 | { |
1172 | int (*dump)(dev_t, daddr_t, void *, size_t); | | 1173 | int (*dump)(dev_t, daddr_t, void *, size_t); |
1173 | char buf[dbtob(1)]; | | 1174 | char buf[dbtob(1)]; |
1174 | kcore_seg_t *segp; | | 1175 | kcore_seg_t *segp; |
1175 | cpu_kcore_hdr_t *cpuhdrp; | | 1176 | cpu_kcore_hdr_t *cpuhdrp; |
1176 | phys_ram_seg_t *memsegp; | | 1177 | phys_ram_seg_t *memsegp; |
1177 | const struct bdevsw *bdev; | | 1178 | const struct bdevsw *bdev; |
1178 | int i; | | 1179 | int i; |
1179 | | | 1180 | |
1180 | bdev = bdevsw_lookup(dumpdev); | | 1181 | bdev = bdevsw_lookup(dumpdev); |
1181 | if (bdev == NULL) | | 1182 | if (bdev == NULL) |
1182 | return (ENXIO); | | 1183 | return (ENXIO); |
1183 | dump = bdev->d_dump; | | 1184 | dump = bdev->d_dump; |
1184 | | | 1185 | |
1185 | memset(buf, 0, sizeof buf); | | 1186 | memset(buf, 0, sizeof buf); |
1186 | segp = (kcore_seg_t *)buf; | | 1187 | segp = (kcore_seg_t *)buf; |
1187 | cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))]; | | 1188 | cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))]; |
1188 | memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) + | | 1189 | memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) + |
1189 | ALIGN(sizeof(*cpuhdrp))]; | | 1190 | ALIGN(sizeof(*cpuhdrp))]; |
1190 | | | 1191 | |
1191 | /* | | 1192 | /* |
1192 | * Generate a segment header. | | 1193 | * Generate a segment header. |
1193 | */ | | 1194 | */ |
1194 | CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); | | 1195 | CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); |
1195 | segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); | | 1196 | segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); |
1196 | | | 1197 | |
1197 | /* | | 1198 | /* |
1198 | * Add the machine-dependent header info. | | 1199 | * Add the machine-dependent header info. |
1199 | */ | | 1200 | */ |
1200 | cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map); | | 1201 | cpuhdrp->lev1map_pa = ALPHA_K0SEG_TO_PHYS((vaddr_t)kernel_lev1map); |
1201 | cpuhdrp->page_size = PAGE_SIZE; | | 1202 | cpuhdrp->page_size = PAGE_SIZE; |
1202 | cpuhdrp->nmemsegs = mem_cluster_cnt; | | 1203 | cpuhdrp->nmemsegs = mem_cluster_cnt; |
1203 | | | 1204 | |
1204 | /* | | 1205 | /* |
1205 | * Fill in the memory segment descriptors. | | 1206 | * Fill in the memory segment descriptors. |
1206 | */ | | 1207 | */ |
1207 | for (i = 0; i < mem_cluster_cnt; i++) { | | 1208 | for (i = 0; i < mem_cluster_cnt; i++) { |
1208 | memsegp[i].start = mem_clusters[i].start; | | 1209 | memsegp[i].start = mem_clusters[i].start; |
1209 | memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK; | | 1210 | memsegp[i].size = mem_clusters[i].size & ~PAGE_MASK; |
1210 | } | | 1211 | } |
1211 | | | 1212 | |
1212 | return (dump(dumpdev, dumplo, (void *)buf, dbtob(1))); | | 1213 | return (dump(dumpdev, dumplo, (void *)buf, dbtob(1))); |
1213 | } | | 1214 | } |
1214 | | | 1215 | |
1215 | /* | | 1216 | /* |
1216 | * This is called by main to set dumplo and dumpsize. | | 1217 | * This is called by main to set dumplo and dumpsize. |
1217 | * Dumps always skip the first PAGE_SIZE of disk space | | 1218 | * Dumps always skip the first PAGE_SIZE of disk space |
1218 | * in case there might be a disk label stored there. | | 1219 | * in case there might be a disk label stored there. |
1219 | * If there is extra space, put dump at the end to | | 1220 | * If there is extra space, put dump at the end to |
1220 | * reduce the chance that swapping trashes it. | | 1221 | * reduce the chance that swapping trashes it. |
1221 | */ | | 1222 | */ |
1222 | void | | 1223 | void |
1223 | cpu_dumpconf(void) | | 1224 | cpu_dumpconf(void) |
1224 | { | | 1225 | { |
1225 | int nblks, dumpblks; /* size of dump area */ | | 1226 | int nblks, dumpblks; /* size of dump area */ |
1226 | | | 1227 | |
1227 | if (dumpdev == NODEV) | | 1228 | if (dumpdev == NODEV) |
1228 | goto bad; | | 1229 | goto bad; |
1229 | nblks = bdev_size(dumpdev); | | 1230 | nblks = bdev_size(dumpdev); |
1230 | if (nblks <= ctod(1)) | | 1231 | if (nblks <= ctod(1)) |
1231 | goto bad; | | 1232 | goto bad; |
1232 | | | 1233 | |
1233 | dumpblks = cpu_dumpsize(); | | 1234 | dumpblks = cpu_dumpsize(); |
1234 | if (dumpblks < 0) | | 1235 | if (dumpblks < 0) |
1235 | goto bad; | | 1236 | goto bad; |
1236 | dumpblks += ctod(cpu_dump_mempagecnt()); | | 1237 | dumpblks += ctod(cpu_dump_mempagecnt()); |
1237 | | | 1238 | |
1238 | /* If dump won't fit (incl. room for possible label), punt. */ | | 1239 | /* If dump won't fit (incl. room for possible label), punt. */ |
1239 | if (dumpblks > (nblks - ctod(1))) | | 1240 | if (dumpblks > (nblks - ctod(1))) |
1240 | goto bad; | | 1241 | goto bad; |
1241 | | | 1242 | |
1242 | /* Put dump at end of partition */ | | 1243 | /* Put dump at end of partition */ |
1243 | dumplo = nblks - dumpblks; | | 1244 | dumplo = nblks - dumpblks; |
1244 | | | 1245 | |
1245 | /* dumpsize is in page units, and doesn't include headers. */ | | 1246 | /* dumpsize is in page units, and doesn't include headers. */ |
1246 | dumpsize = cpu_dump_mempagecnt(); | | 1247 | dumpsize = cpu_dump_mempagecnt(); |
1247 | return; | | 1248 | return; |
1248 | | | 1249 | |
1249 | bad: | | 1250 | bad: |
1250 | dumpsize = 0; | | 1251 | dumpsize = 0; |
1251 | return; | | 1252 | return; |
1252 | } | | 1253 | } |
1253 | | | 1254 | |
1254 | /* | | 1255 | /* |
1255 | * Dump the kernel's image to the swap partition. | | 1256 | * Dump the kernel's image to the swap partition. |
1256 | */ | | 1257 | */ |
1257 | #define BYTES_PER_DUMP PAGE_SIZE | | 1258 | #define BYTES_PER_DUMP PAGE_SIZE |
1258 | | | 1259 | |
1259 | void | | 1260 | void |
1260 | dumpsys(void) | | 1261 | dumpsys(void) |
1261 | { | | 1262 | { |
1262 | const struct bdevsw *bdev; | | 1263 | const struct bdevsw *bdev; |
1263 | u_long totalbytesleft, bytes, i, n, memcl; | | 1264 | u_long totalbytesleft, bytes, i, n, memcl; |
1264 | u_long maddr; | | 1265 | u_long maddr; |
1265 | int psize; | | 1266 | int psize; |
1266 | daddr_t blkno; | | 1267 | daddr_t blkno; |
1267 | int (*dump)(dev_t, daddr_t, void *, size_t); | | 1268 | int (*dump)(dev_t, daddr_t, void *, size_t); |
1268 | int error; | | 1269 | int error; |
1269 | | | 1270 | |
1270 | /* Save registers. */ | | 1271 | /* Save registers. */ |
1271 | savectx(&dumppcb); | | 1272 | savectx(&dumppcb); |
1272 | | | 1273 | |
1273 | if (dumpdev == NODEV) | | 1274 | if (dumpdev == NODEV) |
1274 | return; | | 1275 | return; |
1275 | bdev = bdevsw_lookup(dumpdev); | | 1276 | bdev = bdevsw_lookup(dumpdev); |
1276 | if (bdev == NULL || bdev->d_psize == NULL) | | 1277 | if (bdev == NULL || bdev->d_psize == NULL) |
1277 | return; | | 1278 | return; |
1278 | | | 1279 | |
1279 | /* | | 1280 | /* |
1280 | * For dumps during autoconfiguration, | | 1281 | * For dumps during autoconfiguration, |
1281 | * if dump device has already configured... | | 1282 | * if dump device has already configured... |
1282 | */ | | 1283 | */ |
1283 | if (dumpsize == 0) | | 1284 | if (dumpsize == 0) |
1284 | cpu_dumpconf(); | | 1285 | cpu_dumpconf(); |
1285 | if (dumplo <= 0) { | | 1286 | if (dumplo <= 0) { |
1286 | printf("\ndump to dev %u,%u not possible\n", | | 1287 | printf("\ndump to dev %u,%u not possible\n", |
1287 | major(dumpdev), minor(dumpdev)); | | 1288 | major(dumpdev), minor(dumpdev)); |
1288 | return; | | 1289 | return; |
1289 | } | | 1290 | } |
1290 | printf("\ndumping to dev %u,%u offset %ld\n", | | 1291 | printf("\ndumping to dev %u,%u offset %ld\n", |
1291 | major(dumpdev), minor(dumpdev), dumplo); | | 1292 | major(dumpdev), minor(dumpdev), dumplo); |
1292 | | | 1293 | |
1293 | psize = bdev_size(dumpdev); | | 1294 | psize = bdev_size(dumpdev); |
1294 | printf("dump "); | | 1295 | printf("dump "); |
1295 | if (psize == -1) { | | 1296 | if (psize == -1) { |
1296 | printf("area unavailable\n"); | | 1297 | printf("area unavailable\n"); |
1297 | return; | | 1298 | return; |
1298 | } | | 1299 | } |
1299 | | | 1300 | |
1300 | /* XXX should purge all outstanding keystrokes. */ | | 1301 | /* XXX should purge all outstanding keystrokes. */ |
1301 | | | 1302 | |
1302 | if ((error = cpu_dump()) != 0) | | 1303 | if ((error = cpu_dump()) != 0) |
1303 | goto err; | | 1304 | goto err; |
1304 | | | 1305 | |
1305 | totalbytesleft = ptoa(cpu_dump_mempagecnt()); | | 1306 | totalbytesleft = ptoa(cpu_dump_mempagecnt()); |
1306 | blkno = dumplo + cpu_dumpsize(); | | 1307 | blkno = dumplo + cpu_dumpsize(); |
1307 | dump = bdev->d_dump; | | 1308 | dump = bdev->d_dump; |
1308 | error = 0; | | 1309 | error = 0; |
1309 | | | 1310 | |
1310 | for (memcl = 0; memcl < mem_cluster_cnt; memcl++) { | | 1311 | for (memcl = 0; memcl < mem_cluster_cnt; memcl++) { |
1311 | maddr = mem_clusters[memcl].start; | | 1312 | maddr = mem_clusters[memcl].start; |
1312 | bytes = mem_clusters[memcl].size & ~PAGE_MASK; | | 1313 | bytes = mem_clusters[memcl].size & ~PAGE_MASK; |
1313 | | | 1314 | |
1314 | for (i = 0; i < bytes; i += n, totalbytesleft -= n) { | | 1315 | for (i = 0; i < bytes; i += n, totalbytesleft -= n) { |
1315 | | | 1316 | |
1316 | /* Print out how many MBs we to go. */ | | 1317 | /* Print out how many MBs we to go. */ |
1317 | if ((totalbytesleft % (1024*1024)) == 0) | | 1318 | if ((totalbytesleft % (1024*1024)) == 0) |
1318 | printf_nolog("%ld ", | | 1319 | printf_nolog("%ld ", |
1319 | totalbytesleft / (1024 * 1024)); | | 1320 | totalbytesleft / (1024 * 1024)); |
1320 | | | 1321 | |
1321 | /* Limit size for next transfer. */ | | 1322 | /* Limit size for next transfer. */ |
1322 | n = bytes - i; | | 1323 | n = bytes - i; |
1323 | if (n > BYTES_PER_DUMP) | | 1324 | if (n > BYTES_PER_DUMP) |
1324 | n = BYTES_PER_DUMP; | | 1325 | n = BYTES_PER_DUMP; |
1325 | | | 1326 | |
1326 | error = (*dump)(dumpdev, blkno, | | 1327 | error = (*dump)(dumpdev, blkno, |
1327 | (void *)ALPHA_PHYS_TO_K0SEG(maddr), n); | | 1328 | (void *)ALPHA_PHYS_TO_K0SEG(maddr), n); |
1328 | if (error) | | 1329 | if (error) |
1329 | goto err; | | 1330 | goto err; |
1330 | maddr += n; | | 1331 | maddr += n; |
1331 | blkno += btodb(n); /* XXX? */ | | 1332 | blkno += btodb(n); /* XXX? */ |
1332 | | | 1333 | |
1333 | /* XXX should look for keystrokes, to cancel. */ | | 1334 | /* XXX should look for keystrokes, to cancel. */ |
1334 | } | | 1335 | } |
1335 | } | | 1336 | } |
1336 | | | 1337 | |
1337 | err: | | 1338 | err: |
1338 | switch (error) { | | 1339 | switch (error) { |
1339 | | | 1340 | |
1340 | case ENXIO: | | 1341 | case ENXIO: |
1341 | printf("device bad\n"); | | 1342 | printf("device bad\n"); |
1342 | break; | | 1343 | break; |
1343 | | | 1344 | |
1344 | case EFAULT: | | 1345 | case EFAULT: |
1345 | printf("device not ready\n"); | | 1346 | printf("device not ready\n"); |
1346 | break; | | 1347 | break; |
1347 | | | 1348 | |
1348 | case EINVAL: | | 1349 | case EINVAL: |
1349 | printf("area improper\n"); | | 1350 | printf("area improper\n"); |
1350 | break; | | 1351 | break; |
1351 | | | 1352 | |
1352 | case EIO: | | 1353 | case EIO: |
1353 | printf("i/o error\n"); | | 1354 | printf("i/o error\n"); |
1354 | break; | | 1355 | break; |
1355 | | | 1356 | |
1356 | case EINTR: | | 1357 | case EINTR: |
1357 | printf("aborted from console\n"); | | 1358 | printf("aborted from console\n"); |
1358 | break; | | 1359 | break; |
1359 | | | 1360 | |
1360 | case 0: | | 1361 | case 0: |
1361 | printf("succeeded\n"); | | 1362 | printf("succeeded\n"); |
1362 | break; | | 1363 | break; |
1363 | | | 1364 | |
1364 | default: | | 1365 | default: |
1365 | printf("error %d\n", error); | | 1366 | printf("error %d\n", error); |
1366 | break; | | 1367 | break; |
1367 | } | | 1368 | } |
1368 | printf("\n\n"); | | 1369 | printf("\n\n"); |
1369 | delay(1000); | | 1370 | delay(1000); |
1370 | } | | 1371 | } |
1371 | | | 1372 | |
1372 | void | | 1373 | void |
1373 | frametoreg(const struct trapframe *framep, struct reg *regp) | | 1374 | frametoreg(const struct trapframe *framep, struct reg *regp) |
1374 | { | | 1375 | { |
1375 | | | 1376 | |
1376 | regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0]; | | 1377 | regp->r_regs[R_V0] = framep->tf_regs[FRAME_V0]; |
1377 | regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0]; | | 1378 | regp->r_regs[R_T0] = framep->tf_regs[FRAME_T0]; |
1378 | regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1]; | | 1379 | regp->r_regs[R_T1] = framep->tf_regs[FRAME_T1]; |
1379 | regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2]; | | 1380 | regp->r_regs[R_T2] = framep->tf_regs[FRAME_T2]; |
1380 | regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3]; | | 1381 | regp->r_regs[R_T3] = framep->tf_regs[FRAME_T3]; |
1381 | regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4]; | | 1382 | regp->r_regs[R_T4] = framep->tf_regs[FRAME_T4]; |
1382 | regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5]; | | 1383 | regp->r_regs[R_T5] = framep->tf_regs[FRAME_T5]; |
1383 | regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6]; | | 1384 | regp->r_regs[R_T6] = framep->tf_regs[FRAME_T6]; |
1384 | regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7]; | | 1385 | regp->r_regs[R_T7] = framep->tf_regs[FRAME_T7]; |
1385 | regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0]; | | 1386 | regp->r_regs[R_S0] = framep->tf_regs[FRAME_S0]; |
1386 | regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1]; | | 1387 | regp->r_regs[R_S1] = framep->tf_regs[FRAME_S1]; |
1387 | regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2]; | | 1388 | regp->r_regs[R_S2] = framep->tf_regs[FRAME_S2]; |
1388 | regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3]; | | 1389 | regp->r_regs[R_S3] = framep->tf_regs[FRAME_S3]; |
1389 | regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4]; | | 1390 | regp->r_regs[R_S4] = framep->tf_regs[FRAME_S4]; |
1390 | regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5]; | | 1391 | regp->r_regs[R_S5] = framep->tf_regs[FRAME_S5]; |
1391 | regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6]; | | 1392 | regp->r_regs[R_S6] = framep->tf_regs[FRAME_S6]; |
1392 | regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0]; | | 1393 | regp->r_regs[R_A0] = framep->tf_regs[FRAME_A0]; |
1393 | regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1]; | | 1394 | regp->r_regs[R_A1] = framep->tf_regs[FRAME_A1]; |
1394 | regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2]; | | 1395 | regp->r_regs[R_A2] = framep->tf_regs[FRAME_A2]; |
1395 | regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3]; | | 1396 | regp->r_regs[R_A3] = framep->tf_regs[FRAME_A3]; |
1396 | regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4]; | | 1397 | regp->r_regs[R_A4] = framep->tf_regs[FRAME_A4]; |
1397 | regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5]; | | 1398 | regp->r_regs[R_A5] = framep->tf_regs[FRAME_A5]; |
1398 | regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8]; | | 1399 | regp->r_regs[R_T8] = framep->tf_regs[FRAME_T8]; |
1399 | regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9]; | | 1400 | regp->r_regs[R_T9] = framep->tf_regs[FRAME_T9]; |
1400 | regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10]; | | 1401 | regp->r_regs[R_T10] = framep->tf_regs[FRAME_T10]; |
1401 | regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11]; | | 1402 | regp->r_regs[R_T11] = framep->tf_regs[FRAME_T11]; |
1402 | regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA]; | | 1403 | regp->r_regs[R_RA] = framep->tf_regs[FRAME_RA]; |
1403 | regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12]; | | 1404 | regp->r_regs[R_T12] = framep->tf_regs[FRAME_T12]; |
1404 | regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT]; | | 1405 | regp->r_regs[R_AT] = framep->tf_regs[FRAME_AT]; |
1405 | regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP]; | | 1406 | regp->r_regs[R_GP] = framep->tf_regs[FRAME_GP]; |
1406 | /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */ | | 1407 | /* regp->r_regs[R_SP] = framep->tf_regs[FRAME_SP]; XXX */ |
1407 | regp->r_regs[R_ZERO] = 0; | | 1408 | regp->r_regs[R_ZERO] = 0; |
1408 | } | | 1409 | } |
1409 | | | 1410 | |
1410 | void | | 1411 | void |
1411 | regtoframe(const struct reg *regp, struct trapframe *framep) | | 1412 | regtoframe(const struct reg *regp, struct trapframe *framep) |
1412 | { | | 1413 | { |
1413 | | | 1414 | |
1414 | framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0]; | | 1415 | framep->tf_regs[FRAME_V0] = regp->r_regs[R_V0]; |
1415 | framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0]; | | 1416 | framep->tf_regs[FRAME_T0] = regp->r_regs[R_T0]; |
1416 | framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1]; | | 1417 | framep->tf_regs[FRAME_T1] = regp->r_regs[R_T1]; |
1417 | framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2]; | | 1418 | framep->tf_regs[FRAME_T2] = regp->r_regs[R_T2]; |
1418 | framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3]; | | 1419 | framep->tf_regs[FRAME_T3] = regp->r_regs[R_T3]; |
1419 | framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4]; | | 1420 | framep->tf_regs[FRAME_T4] = regp->r_regs[R_T4]; |
1420 | framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5]; | | 1421 | framep->tf_regs[FRAME_T5] = regp->r_regs[R_T5]; |
1421 | framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6]; | | 1422 | framep->tf_regs[FRAME_T6] = regp->r_regs[R_T6]; |
1422 | framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7]; | | 1423 | framep->tf_regs[FRAME_T7] = regp->r_regs[R_T7]; |
1423 | framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0]; | | 1424 | framep->tf_regs[FRAME_S0] = regp->r_regs[R_S0]; |
1424 | framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1]; | | 1425 | framep->tf_regs[FRAME_S1] = regp->r_regs[R_S1]; |
1425 | framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2]; | | 1426 | framep->tf_regs[FRAME_S2] = regp->r_regs[R_S2]; |
1426 | framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3]; | | 1427 | framep->tf_regs[FRAME_S3] = regp->r_regs[R_S3]; |
1427 | framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4]; | | 1428 | framep->tf_regs[FRAME_S4] = regp->r_regs[R_S4]; |
1428 | framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5]; | | 1429 | framep->tf_regs[FRAME_S5] = regp->r_regs[R_S5]; |
1429 | framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6]; | | 1430 | framep->tf_regs[FRAME_S6] = regp->r_regs[R_S6]; |
1430 | framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0]; | | 1431 | framep->tf_regs[FRAME_A0] = regp->r_regs[R_A0]; |
1431 | framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1]; | | 1432 | framep->tf_regs[FRAME_A1] = regp->r_regs[R_A1]; |
1432 | framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2]; | | 1433 | framep->tf_regs[FRAME_A2] = regp->r_regs[R_A2]; |
1433 | framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3]; | | 1434 | framep->tf_regs[FRAME_A3] = regp->r_regs[R_A3]; |
1434 | framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4]; | | 1435 | framep->tf_regs[FRAME_A4] = regp->r_regs[R_A4]; |
1435 | framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5]; | | 1436 | framep->tf_regs[FRAME_A5] = regp->r_regs[R_A5]; |
1436 | framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8]; | | 1437 | framep->tf_regs[FRAME_T8] = regp->r_regs[R_T8]; |
1437 | framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9]; | | 1438 | framep->tf_regs[FRAME_T9] = regp->r_regs[R_T9]; |
1438 | framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10]; | | 1439 | framep->tf_regs[FRAME_T10] = regp->r_regs[R_T10]; |
1439 | framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11]; | | 1440 | framep->tf_regs[FRAME_T11] = regp->r_regs[R_T11]; |
1440 | framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA]; | | 1441 | framep->tf_regs[FRAME_RA] = regp->r_regs[R_RA]; |
1441 | framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12]; | | 1442 | framep->tf_regs[FRAME_T12] = regp->r_regs[R_T12]; |
1442 | framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT]; | | 1443 | framep->tf_regs[FRAME_AT] = regp->r_regs[R_AT]; |
1443 | framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP]; | | 1444 | framep->tf_regs[FRAME_GP] = regp->r_regs[R_GP]; |
1444 | /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */ | | 1445 | /* framep->tf_regs[FRAME_SP] = regp->r_regs[R_SP]; XXX */ |
1445 | /* ??? = regp->r_regs[R_ZERO]; */ | | 1446 | /* ??? = regp->r_regs[R_ZERO]; */ |
1446 | } | | 1447 | } |
1447 | | | 1448 | |
1448 | void | | 1449 | void |
1449 | printregs(struct reg *regp) | | 1450 | printregs(struct reg *regp) |
1450 | { | | 1451 | { |
1451 | int i; | | 1452 | int i; |
1452 | | | 1453 | |
1453 | for (i = 0; i < 32; i++) | | 1454 | for (i = 0; i < 32; i++) |
1454 | printf("R%d:\t0x%016lx%s", i, regp->r_regs[i], | | 1455 | printf("R%d:\t0x%016lx%s", i, regp->r_regs[i], |
1455 | i & 1 ? "\n" : "\t"); | | 1456 | i & 1 ? "\n" : "\t"); |
1456 | } | | 1457 | } |
1457 | | | 1458 | |
1458 | void | | 1459 | void |
1459 | regdump(struct trapframe *framep) | | 1460 | regdump(struct trapframe *framep) |
1460 | { | | 1461 | { |
1461 | struct reg reg; | | 1462 | struct reg reg; |
1462 | | | 1463 | |
1463 | frametoreg(framep, ®); | | 1464 | frametoreg(framep, ®); |
1464 | reg.r_regs[R_SP] = alpha_pal_rdusp(); | | 1465 | reg.r_regs[R_SP] = alpha_pal_rdusp(); |
1465 | | | 1466 | |
1466 | printf("REGISTERS:\n"); | | 1467 | printf("REGISTERS:\n"); |
1467 | printregs(®); | | 1468 | printregs(®); |
1468 | } | | 1469 | } |
1469 | | | 1470 | |
1470 | | | 1471 | |
1471 | | | 1472 | |
1472 | void * | | 1473 | void * |
1473 | getframe(const struct lwp *l, int sig, int *onstack) | | 1474 | getframe(const struct lwp *l, int sig, int *onstack) |
1474 | { | | 1475 | { |
1475 | void *frame; | | 1476 | void *frame; |
1476 | | | 1477 | |
1477 | /* Do we need to jump onto the signal stack? */ | | 1478 | /* Do we need to jump onto the signal stack? */ |
1478 | *onstack = | | 1479 | *onstack = |
1479 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && | | 1480 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && |
1480 | (SIGACTION(l->l_proc, sig).sa_flags & SA_ONSTACK) != 0; | | 1481 | (SIGACTION(l->l_proc, sig).sa_flags & SA_ONSTACK) != 0; |
1481 | | | 1482 | |
1482 | if (*onstack) | | 1483 | if (*onstack) |
1483 | frame = (void *)((char *)l->l_sigstk.ss_sp + | | 1484 | frame = (void *)((char *)l->l_sigstk.ss_sp + |
1484 | l->l_sigstk.ss_size); | | 1485 | l->l_sigstk.ss_size); |
1485 | else | | 1486 | else |
1486 | frame = (void *)(alpha_pal_rdusp()); | | 1487 | frame = (void *)(alpha_pal_rdusp()); |
1487 | return (frame); | | 1488 | return (frame); |
1488 | } | | 1489 | } |
1489 | | | 1490 | |
1490 | void | | 1491 | void |
1491 | buildcontext(struct lwp *l, const void *catcher, const void *tramp, const void *fp) | | 1492 | buildcontext(struct lwp *l, const void *catcher, const void *tramp, const void *fp) |
1492 | { | | 1493 | { |
1493 | struct trapframe *tf = l->l_md.md_tf; | | 1494 | struct trapframe *tf = l->l_md.md_tf; |
1494 | | | 1495 | |
1495 | tf->tf_regs[FRAME_RA] = (uint64_t)tramp; | | 1496 | tf->tf_regs[FRAME_RA] = (uint64_t)tramp; |
1496 | tf->tf_regs[FRAME_PC] = (uint64_t)catcher; | | 1497 | tf->tf_regs[FRAME_PC] = (uint64_t)catcher; |
1497 | tf->tf_regs[FRAME_T12] = (uint64_t)catcher; | | 1498 | tf->tf_regs[FRAME_T12] = (uint64_t)catcher; |
1498 | alpha_pal_wrusp((unsigned long)fp); | | 1499 | alpha_pal_wrusp((unsigned long)fp); |
1499 | } | | 1500 | } |
1500 | | | 1501 | |
1501 | | | 1502 | |
1502 | /* | | 1503 | /* |
1503 | * Send an interrupt to process, new style | | 1504 | * Send an interrupt to process, new style |
1504 | */ | | 1505 | */ |
1505 | void | | 1506 | void |
1506 | sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | | 1507 | sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) |
1507 | { | | 1508 | { |
1508 | struct lwp *l = curlwp; | | 1509 | struct lwp *l = curlwp; |
1509 | struct proc *p = l->l_proc; | | 1510 | struct proc *p = l->l_proc; |
1510 | struct sigacts *ps = p->p_sigacts; | | 1511 | struct sigacts *ps = p->p_sigacts; |
1511 | int onstack, sig = ksi->ksi_signo, error; | | 1512 | int onstack, sig = ksi->ksi_signo, error; |
1512 | struct sigframe_siginfo *fp, frame; | | 1513 | struct sigframe_siginfo *fp, frame; |
1513 | struct trapframe *tf; | | 1514 | struct trapframe *tf; |
1514 | sig_t catcher = SIGACTION(p, ksi->ksi_signo).sa_handler; | | 1515 | sig_t catcher = SIGACTION(p, ksi->ksi_signo).sa_handler; |
1515 | | | 1516 | |
1516 | fp = (struct sigframe_siginfo *)getframe(l,ksi->ksi_signo,&onstack); | | 1517 | fp = (struct sigframe_siginfo *)getframe(l,ksi->ksi_signo,&onstack); |
1517 | tf = l->l_md.md_tf; | | 1518 | tf = l->l_md.md_tf; |
1518 | | | 1519 | |
1519 | /* Allocate space for the signal handler context. */ | | 1520 | /* Allocate space for the signal handler context. */ |
1520 | fp--; | | 1521 | fp--; |
1521 | | | 1522 | |
1522 | #ifdef DEBUG | | 1523 | #ifdef DEBUG |
1523 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) | | 1524 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) |
1524 | printf("sendsig_siginfo(%d): sig %d ssp %p usp %p\n", p->p_pid, | | 1525 | printf("sendsig_siginfo(%d): sig %d ssp %p usp %p\n", p->p_pid, |
1525 | sig, &onstack, fp); | | 1526 | sig, &onstack, fp); |
1526 | #endif | | 1527 | #endif |
1527 | | | 1528 | |
1528 | /* Build stack frame for signal trampoline. */ | | 1529 | /* Build stack frame for signal trampoline. */ |
1529 | memset(&frame, 0, sizeof(frame)); | | 1530 | memset(&frame, 0, sizeof(frame)); |
1530 | frame.sf_si._info = ksi->ksi_info; | | 1531 | frame.sf_si._info = ksi->ksi_info; |
1531 | frame.sf_uc.uc_flags = _UC_SIGMASK; | | 1532 | frame.sf_uc.uc_flags = _UC_SIGMASK; |
1532 | frame.sf_uc.uc_sigmask = *mask; | | 1533 | frame.sf_uc.uc_sigmask = *mask; |
1533 | frame.sf_uc.uc_link = l->l_ctxlink; | | 1534 | frame.sf_uc.uc_link = l->l_ctxlink; |
1534 | frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) | | 1535 | frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) |
1535 | ? _UC_SETSTACK : _UC_CLRSTACK; | | 1536 | ? _UC_SETSTACK : _UC_CLRSTACK; |
1536 | sendsig_reset(l, sig); | | 1537 | sendsig_reset(l, sig); |
1537 | mutex_exit(p->p_lock); | | 1538 | mutex_exit(p->p_lock); |
1538 | cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); | | 1539 | cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); |
1539 | error = copyout(&frame, fp, sizeof(frame)); | | 1540 | error = copyout(&frame, fp, sizeof(frame)); |
1540 | mutex_enter(p->p_lock); | | 1541 | mutex_enter(p->p_lock); |
1541 | | | 1542 | |
1542 | if (error != 0) { | | 1543 | if (error != 0) { |
1543 | /* | | 1544 | /* |
1544 | * Process has trashed its stack; give it an illegal | | 1545 | * Process has trashed its stack; give it an illegal |
1545 | * instruction to halt it in its tracks. | | 1546 | * instruction to halt it in its tracks. |
1546 | */ | | 1547 | */ |
1547 | #ifdef DEBUG | | 1548 | #ifdef DEBUG |
1548 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) | | 1549 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) |
1549 | printf("sendsig_siginfo(%d): copyout failed on sig %d\n", | | 1550 | printf("sendsig_siginfo(%d): copyout failed on sig %d\n", |
1550 | p->p_pid, sig); | | 1551 | p->p_pid, sig); |
1551 | #endif | | 1552 | #endif |
1552 | sigexit(l, SIGILL); | | 1553 | sigexit(l, SIGILL); |
1553 | /* NOTREACHED */ | | 1554 | /* NOTREACHED */ |
1554 | } | | 1555 | } |
1555 | | | 1556 | |
1556 | #ifdef DEBUG | | 1557 | #ifdef DEBUG |
1557 | if (sigdebug & SDB_FOLLOW) | | 1558 | if (sigdebug & SDB_FOLLOW) |
1558 | printf("sendsig_siginfo(%d): sig %d usp %p code %x\n", | | 1559 | printf("sendsig_siginfo(%d): sig %d usp %p code %x\n", |
1559 | p->p_pid, sig, fp, ksi->ksi_code); | | 1560 | p->p_pid, sig, fp, ksi->ksi_code); |
1560 | #endif | | 1561 | #endif |
1561 | | | 1562 | |
1562 | /* | | 1563 | /* |
1563 | * Set up the registers to directly invoke the signal handler. The | | 1564 | * Set up the registers to directly invoke the signal handler. The |
1564 | * signal trampoline is then used to return from the signal. Note | | 1565 | * signal trampoline is then used to return from the signal. Note |
1565 | * the trampoline version numbers are coordinated with machine- | | 1566 | * the trampoline version numbers are coordinated with machine- |
1566 | * dependent code in libc. | | 1567 | * dependent code in libc. |
1567 | */ | | 1568 | */ |
1568 | | | 1569 | |
1569 | tf->tf_regs[FRAME_A0] = sig; | | 1570 | tf->tf_regs[FRAME_A0] = sig; |
1570 | tf->tf_regs[FRAME_A1] = (uint64_t)&fp->sf_si; | | 1571 | tf->tf_regs[FRAME_A1] = (uint64_t)&fp->sf_si; |
1571 | tf->tf_regs[FRAME_A2] = (uint64_t)&fp->sf_uc; | | 1572 | tf->tf_regs[FRAME_A2] = (uint64_t)&fp->sf_uc; |
1572 | | | 1573 | |
1573 | buildcontext(l,catcher,ps->sa_sigdesc[sig].sd_tramp,fp); | | 1574 | buildcontext(l,catcher,ps->sa_sigdesc[sig].sd_tramp,fp); |
1574 | | | 1575 | |
1575 | /* Remember that we're now on the signal stack. */ | | 1576 | /* Remember that we're now on the signal stack. */ |
1576 | if (onstack) | | 1577 | if (onstack) |
1577 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 1578 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
1578 | | | 1579 | |
1579 | #ifdef DEBUG | | 1580 | #ifdef DEBUG |
1580 | if (sigdebug & SDB_FOLLOW) | | 1581 | if (sigdebug & SDB_FOLLOW) |
1581 | printf("sendsig_siginfo(%d): pc %lx, catcher %lx\n", p->p_pid, | | 1582 | printf("sendsig_siginfo(%d): pc %lx, catcher %lx\n", p->p_pid, |
1582 | tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]); | | 1583 | tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]); |
1583 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) | | 1584 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) |
1584 | printf("sendsig_siginfo(%d): sig %d returns\n", | | 1585 | printf("sendsig_siginfo(%d): sig %d returns\n", |
1585 | p->p_pid, sig); | | 1586 | p->p_pid, sig); |
1586 | #endif | | 1587 | #endif |
1587 | } | | 1588 | } |
1588 | | | 1589 | |
1589 | /* | | 1590 | /* |
1590 | * machine dependent system variables. | | 1591 | * machine dependent system variables. |
1591 | */ | | 1592 | */ |
1592 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") | | 1593 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") |
1593 | { | | 1594 | { |
1594 | | | 1595 | |
1595 | sysctl_createv(clog, 0, NULL, NULL, | | 1596 | sysctl_createv(clog, 0, NULL, NULL, |
1596 | CTLFLAG_PERMANENT, | | 1597 | CTLFLAG_PERMANENT, |
1597 | CTLTYPE_NODE, "machdep", NULL, | | 1598 | CTLTYPE_NODE, "machdep", NULL, |
1598 | NULL, 0, NULL, 0, | | 1599 | NULL, 0, NULL, 0, |
1599 | CTL_MACHDEP, CTL_EOL); | | 1600 | CTL_MACHDEP, CTL_EOL); |
1600 | | | 1601 | |
1601 | sysctl_createv(clog, 0, NULL, NULL, | | 1602 | sysctl_createv(clog, 0, NULL, NULL, |
1602 | CTLFLAG_PERMANENT, | | 1603 | CTLFLAG_PERMANENT, |
1603 | CTLTYPE_STRUCT, "console_device", NULL, | | 1604 | CTLTYPE_STRUCT, "console_device", NULL, |
1604 | sysctl_consdev, 0, NULL, sizeof(dev_t), | | 1605 | sysctl_consdev, 0, NULL, sizeof(dev_t), |
1605 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); | | 1606 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); |
1606 | sysctl_createv(clog, 0, NULL, NULL, | | 1607 | sysctl_createv(clog, 0, NULL, NULL, |
1607 | CTLFLAG_PERMANENT, | | 1608 | CTLFLAG_PERMANENT, |
1608 | CTLTYPE_STRING, "root_device", NULL, | | 1609 | CTLTYPE_STRING, "root_device", NULL, |
1609 | sysctl_root_device, 0, NULL, 0, | | 1610 | sysctl_root_device, 0, NULL, 0, |
1610 | CTL_MACHDEP, CPU_ROOT_DEVICE, CTL_EOL); | | 1611 | CTL_MACHDEP, CPU_ROOT_DEVICE, CTL_EOL); |
1611 | sysctl_createv(clog, 0, NULL, NULL, | | 1612 | sysctl_createv(clog, 0, NULL, NULL, |
1612 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1613 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1613 | CTLTYPE_INT, "unaligned_print", | | 1614 | CTLTYPE_INT, "unaligned_print", |
1614 | SYSCTL_DESCR("Warn about unaligned accesses"), | | 1615 | SYSCTL_DESCR("Warn about unaligned accesses"), |
1615 | NULL, 0, &alpha_unaligned_print, 0, | | 1616 | NULL, 0, &alpha_unaligned_print, 0, |
1616 | CTL_MACHDEP, CPU_UNALIGNED_PRINT, CTL_EOL); | | 1617 | CTL_MACHDEP, CPU_UNALIGNED_PRINT, CTL_EOL); |
1617 | sysctl_createv(clog, 0, NULL, NULL, | | 1618 | sysctl_createv(clog, 0, NULL, NULL, |
1618 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1619 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1619 | CTLTYPE_INT, "unaligned_fix", | | 1620 | CTLTYPE_INT, "unaligned_fix", |
1620 | SYSCTL_DESCR("Fix up unaligned accesses"), | | 1621 | SYSCTL_DESCR("Fix up unaligned accesses"), |
1621 | NULL, 0, &alpha_unaligned_fix, 0, | | 1622 | NULL, 0, &alpha_unaligned_fix, 0, |
1622 | CTL_MACHDEP, CPU_UNALIGNED_FIX, CTL_EOL); | | 1623 | CTL_MACHDEP, CPU_UNALIGNED_FIX, CTL_EOL); |
1623 | sysctl_createv(clog, 0, NULL, NULL, | | 1624 | sysctl_createv(clog, 0, NULL, NULL, |
1624 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1625 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1625 | CTLTYPE_INT, "unaligned_sigbus", | | 1626 | CTLTYPE_INT, "unaligned_sigbus", |
1626 | SYSCTL_DESCR("Do SIGBUS for fixed unaligned accesses"), | | 1627 | SYSCTL_DESCR("Do SIGBUS for fixed unaligned accesses"), |
1627 | NULL, 0, &alpha_unaligned_sigbus, 0, | | 1628 | NULL, 0, &alpha_unaligned_sigbus, 0, |
1628 | CTL_MACHDEP, CPU_UNALIGNED_SIGBUS, CTL_EOL); | | 1629 | CTL_MACHDEP, CPU_UNALIGNED_SIGBUS, CTL_EOL); |
1629 | sysctl_createv(clog, 0, NULL, NULL, | | 1630 | sysctl_createv(clog, 0, NULL, NULL, |
1630 | CTLFLAG_PERMANENT, | | 1631 | CTLFLAG_PERMANENT, |
1631 | CTLTYPE_STRING, "booted_kernel", NULL, | | 1632 | CTLTYPE_STRING, "booted_kernel", NULL, |
1632 | NULL, 0, bootinfo.booted_kernel, 0, | | 1633 | NULL, 0, bootinfo.booted_kernel, 0, |
1633 | CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); | | 1634 | CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); |
1634 | sysctl_createv(clog, 0, NULL, NULL, | | 1635 | sysctl_createv(clog, 0, NULL, NULL, |
1635 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1636 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1636 | CTLTYPE_INT, "fp_sync_complete", NULL, | | 1637 | CTLTYPE_INT, "fp_sync_complete", NULL, |
1637 | NULL, 0, &alpha_fp_sync_complete, 0, | | 1638 | NULL, 0, &alpha_fp_sync_complete, 0, |
1638 | CTL_MACHDEP, CPU_FP_SYNC_COMPLETE, CTL_EOL); | | 1639 | CTL_MACHDEP, CPU_FP_SYNC_COMPLETE, CTL_EOL); |
1639 | sysctl_createv(clog, 0, NULL, NULL, | | 1640 | sysctl_createv(clog, 0, NULL, NULL, |
1640 | CTLFLAG_PERMANENT, | | 1641 | CTLFLAG_PERMANENT, |
1641 | CTLTYPE_INT, "cctr", NULL, | | 1642 | CTLTYPE_INT, "cctr", NULL, |
1642 | NULL, 0, &alpha_use_cctr, 0, | | 1643 | NULL, 0, &alpha_use_cctr, 0, |
1643 | CTL_MACHDEP, CPU_CCTR, CTL_EOL); | | 1644 | CTL_MACHDEP, CPU_CCTR, CTL_EOL); |
1644 | sysctl_createv(clog, 0, NULL, NULL, | | 1645 | sysctl_createv(clog, 0, NULL, NULL, |
1645 | CTLFLAG_PERMANENT, | | 1646 | CTLFLAG_PERMANENT, |
1646 | CTLTYPE_BOOL, "is_qemu", NULL, | | 1647 | CTLTYPE_BOOL, "is_qemu", NULL, |
1647 | NULL, 0, &alpha_is_qemu, 0, | | 1648 | NULL, 0, &alpha_is_qemu, 0, |
1648 | CTL_MACHDEP, CPU_IS_QEMU, CTL_EOL); | | 1649 | CTL_MACHDEP, CPU_IS_QEMU, CTL_EOL); |
| | | 1650 | sysctl_createv(clog, 0, NULL, NULL, |
| | | 1651 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| | | 1652 | CTLTYPE_INT, "fp_complete_debug", NULL, |
| | | 1653 | NULL, 0, &alpha_fp_complete_debug, 0, |
| | | 1654 | CTL_MACHDEP, CPU_FP_COMPLETE_DEBUG, CTL_EOL); |
1649 | } | | 1655 | } |
1650 | | | 1656 | |
1651 | /* | | 1657 | /* |
1652 | * Set registers on exec. | | 1658 | * Set registers on exec. |
1653 | */ | | 1659 | */ |
1654 | void | | 1660 | void |
1655 | setregs(register struct lwp *l, struct exec_package *pack, vaddr_t stack) | | 1661 | setregs(register struct lwp *l, struct exec_package *pack, vaddr_t stack) |
1656 | { | | 1662 | { |
1657 | struct trapframe *tfp = l->l_md.md_tf; | | 1663 | struct trapframe *tfp = l->l_md.md_tf; |
1658 | struct pcb *pcb; | | 1664 | struct pcb *pcb; |
1659 | #ifdef DEBUG | | 1665 | #ifdef DEBUG |
1660 | int i; | | 1666 | int i; |
1661 | #endif | | 1667 | #endif |
1662 | | | 1668 | |
1663 | #ifdef DEBUG | | 1669 | #ifdef DEBUG |
1664 | /* | | 1670 | /* |
1665 | * Crash and dump, if the user requested it. | | 1671 | * Crash and dump, if the user requested it. |
1666 | */ | | 1672 | */ |
1667 | if (boothowto & RB_DUMP) | | 1673 | if (boothowto & RB_DUMP) |
1668 | panic("crash requested by boot flags"); | | 1674 | panic("crash requested by boot flags"); |
1669 | #endif | | 1675 | #endif |
1670 | | | 1676 | |
1671 | #ifdef DEBUG | | 1677 | #ifdef DEBUG |
1672 | for (i = 0; i < FRAME_SIZE; i++) | | 1678 | for (i = 0; i < FRAME_SIZE; i++) |
1673 | tfp->tf_regs[i] = 0xbabefacedeadbeef; | | 1679 | tfp->tf_regs[i] = 0xbabefacedeadbeef; |
1674 | #else | | 1680 | #else |
1675 | memset(tfp->tf_regs, 0, FRAME_SIZE * sizeof tfp->tf_regs[0]); | | 1681 | memset(tfp->tf_regs, 0, FRAME_SIZE * sizeof tfp->tf_regs[0]); |
1676 | #endif | | 1682 | #endif |
1677 | pcb = lwp_getpcb(l); | | 1683 | pcb = lwp_getpcb(l); |
1678 | memset(&pcb->pcb_fp, 0, sizeof(pcb->pcb_fp)); | | 1684 | memset(&pcb->pcb_fp, 0, sizeof(pcb->pcb_fp)); |
1679 | alpha_pal_wrusp(stack); | | 1685 | alpha_pal_wrusp(stack); |
1680 | tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET; | | 1686 | tfp->tf_regs[FRAME_PS] = ALPHA_PSL_USERSET; |
1681 | tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3; | | 1687 | tfp->tf_regs[FRAME_PC] = pack->ep_entry & ~3; |
1682 | | | 1688 | |
1683 | tfp->tf_regs[FRAME_A0] = stack; /* a0 = sp */ | | 1689 | tfp->tf_regs[FRAME_A0] = stack; /* a0 = sp */ |
1684 | tfp->tf_regs[FRAME_A1] = 0; /* a1 = rtld cleanup */ | | 1690 | tfp->tf_regs[FRAME_A1] = 0; /* a1 = rtld cleanup */ |
1685 | tfp->tf_regs[FRAME_A2] = 0; /* a2 = rtld object */ | | 1691 | tfp->tf_regs[FRAME_A2] = 0; /* a2 = rtld object */ |
1686 | tfp->tf_regs[FRAME_A3] = l->l_proc->p_psstrp; /* a3 = ps_strings */ | | 1692 | tfp->tf_regs[FRAME_A3] = l->l_proc->p_psstrp; /* a3 = ps_strings */ |
1687 | tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ | | 1693 | tfp->tf_regs[FRAME_T12] = tfp->tf_regs[FRAME_PC]; /* a.k.a. PV */ |
1688 | | | 1694 | |
1689 | if (__predict_true((l->l_md.md_flags & IEEE_INHERIT) == 0)) { | | 1695 | if (__predict_true((l->l_md.md_flags & IEEE_INHERIT) == 0)) { |
1690 | l->l_md.md_flags &= ~MDLWP_FP_C; | | 1696 | l->l_md.md_flags = |
1691 | pcb->pcb_fp.fpr_cr = FPCR_DYN(FP_RN); | | 1697 | (l->l_md.md_flags & ~(MDLWP_FP_C | MDLWP_FPACTIVE)) | |
| | | 1698 | FP_C_DEFAULT; |
| | | 1699 | pcb->pcb_fp.fpr_cr = FPCR_DEFAULT; |
1692 | } | | 1700 | } |
1693 | } | | 1701 | } |
1694 | | | 1702 | |
1695 | void (*alpha_delay_fn)(unsigned long); | | 1703 | void (*alpha_delay_fn)(unsigned long); |
1696 | | | 1704 | |
1697 | /* | | 1705 | /* |
1698 | * Wait "n" microseconds. | | 1706 | * Wait "n" microseconds. |
1699 | */ | | 1707 | */ |
1700 | void | | 1708 | void |
1701 | delay(unsigned long n) | | 1709 | delay(unsigned long n) |
1702 | { | | 1710 | { |
1703 | unsigned long pcc0, pcc1, curcycle, cycles, usec; | | 1711 | unsigned long pcc0, pcc1, curcycle, cycles, usec; |
1704 | | | 1712 | |
1705 | if (n == 0) | | 1713 | if (n == 0) |
1706 | return; | | 1714 | return; |
1707 | | | 1715 | |
1708 | /* | | 1716 | /* |
1709 | * If we have an alternative delay function, go ahead and | | 1717 | * If we have an alternative delay function, go ahead and |
1710 | * use it. | | 1718 | * use it. |
1711 | */ | | 1719 | */ |
1712 | if (alpha_delay_fn != NULL) { | | 1720 | if (alpha_delay_fn != NULL) { |
1713 | (*alpha_delay_fn)(n); | | 1721 | (*alpha_delay_fn)(n); |
1714 | return; | | 1722 | return; |
1715 | } | | 1723 | } |
1716 | | | 1724 | |
1717 | lwp_t * const l = curlwp; | | 1725 | lwp_t * const l = curlwp; |
1718 | KPREEMPT_DISABLE(l); | | 1726 | KPREEMPT_DISABLE(l); |
1719 | | | 1727 | |
1720 | pcc0 = alpha_rpcc() & 0xffffffffUL; | | 1728 | pcc0 = alpha_rpcc() & 0xffffffffUL; |
1721 | cycles = 0; | | 1729 | cycles = 0; |
1722 | usec = 0; | | 1730 | usec = 0; |
1723 | | | 1731 | |
1724 | while (usec <= n) { | | 1732 | while (usec <= n) { |
1725 | /* | | 1733 | /* |
1726 | * Get the next CPU cycle count- assumes that we cannot | | 1734 | * Get the next CPU cycle count- assumes that we cannot |
1727 | * have had more than one 32 bit overflow. | | 1735 | * have had more than one 32 bit overflow. |
1728 | */ | | 1736 | */ |
1729 | pcc1 = alpha_rpcc() & 0xffffffffUL; | | 1737 | pcc1 = alpha_rpcc() & 0xffffffffUL; |
1730 | if (pcc1 < pcc0) | | 1738 | if (pcc1 < pcc0) |
1731 | curcycle = (pcc1 + 0x100000000UL) - pcc0; | | 1739 | curcycle = (pcc1 + 0x100000000UL) - pcc0; |
1732 | else | | 1740 | else |
1733 | curcycle = pcc1 - pcc0; | | 1741 | curcycle = pcc1 - pcc0; |
1734 | | | 1742 | |
1735 | /* | | 1743 | /* |
1736 | * We now have the number of processor cycles since we | | 1744 | * We now have the number of processor cycles since we |
1737 | * last checked. Add the current cycle count to the | | 1745 | * last checked. Add the current cycle count to the |
1738 | * running total. If it's over cycles_per_usec, increment | | 1746 | * running total. If it's over cycles_per_usec, increment |
1739 | * the usec counter. | | 1747 | * the usec counter. |
1740 | */ | | 1748 | */ |
1741 | cycles += curcycle; | | 1749 | cycles += curcycle; |
1742 | while (cycles > cycles_per_usec) { | | 1750 | while (cycles > cycles_per_usec) { |
1743 | usec++; | | 1751 | usec++; |
1744 | cycles -= cycles_per_usec; | | 1752 | cycles -= cycles_per_usec; |
1745 | } | | 1753 | } |
1746 | pcc0 = pcc1; | | 1754 | pcc0 = pcc1; |
1747 | } | | 1755 | } |
1748 | | | 1756 | |
1749 | KPREEMPT_ENABLE(l); | | 1757 | KPREEMPT_ENABLE(l); |
1750 | } | | 1758 | } |
1751 | | | 1759 | |
1752 | #ifdef EXEC_ECOFF | | 1760 | #ifdef EXEC_ECOFF |
1753 | void | | 1761 | void |
1754 | cpu_exec_ecoff_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) | | 1762 | cpu_exec_ecoff_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) |
1755 | { | | 1763 | { |
1756 | struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; | | 1764 | struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; |
1757 | | | 1765 | |
1758 | l->l_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value; | | 1766 | l->l_md.md_tf->tf_regs[FRAME_GP] = execp->a.gp_value; |
1759 | } | | 1767 | } |
1760 | | | 1768 | |
1761 | /* | | 1769 | /* |
1762 | * cpu_exec_ecoff_hook(): | | 1770 | * cpu_exec_ecoff_hook(): |
1763 | * cpu-dependent ECOFF format hook for execve(). | | 1771 | * cpu-dependent ECOFF format hook for execve(). |
1764 | * | | 1772 | * |
1765 | * Do any machine-dependent diddling of the exec package when doing ECOFF. | | 1773 | * Do any machine-dependent diddling of the exec package when doing ECOFF. |
1766 | * | | 1774 | * |
1767 | */ | | 1775 | */ |
1768 | int | | 1776 | int |
1769 | cpu_exec_ecoff_probe(struct lwp *l, struct exec_package *epp) | | 1777 | cpu_exec_ecoff_probe(struct lwp *l, struct exec_package *epp) |
1770 | { | | 1778 | { |
1771 | struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; | | 1779 | struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; |
1772 | int error; | | 1780 | int error; |
1773 | | | 1781 | |
1774 | if (execp->f.f_magic == ECOFF_MAGIC_NETBSD_ALPHA) | | 1782 | if (execp->f.f_magic == ECOFF_MAGIC_NETBSD_ALPHA) |
1775 | error = 0; | | 1783 | error = 0; |
1776 | else | | 1784 | else |
1777 | error = ENOEXEC; | | 1785 | error = ENOEXEC; |
1778 | | | 1786 | |
1779 | return (error); | | 1787 | return (error); |
1780 | } | | 1788 | } |
1781 | #endif /* EXEC_ECOFF */ | | 1789 | #endif /* EXEC_ECOFF */ |
1782 | | | 1790 | |
1783 | int | | 1791 | int |
1784 | mm_md_physacc(paddr_t pa, vm_prot_t prot) | | 1792 | mm_md_physacc(paddr_t pa, vm_prot_t prot) |
1785 | { | | 1793 | { |
1786 | u_quad_t size; | | 1794 | u_quad_t size; |
1787 | int i; | | 1795 | int i; |
1788 | | | 1796 | |
1789 | for (i = 0; i < mem_cluster_cnt; i++) { | | 1797 | for (i = 0; i < mem_cluster_cnt; i++) { |
1790 | if (pa < mem_clusters[i].start) | | 1798 | if (pa < mem_clusters[i].start) |
1791 | continue; | | 1799 | continue; |
1792 | size = mem_clusters[i].size & ~PAGE_MASK; | | 1800 | size = mem_clusters[i].size & ~PAGE_MASK; |
1793 | if (pa >= (mem_clusters[i].start + size)) | | 1801 | if (pa >= (mem_clusters[i].start + size)) |
1794 | continue; | | 1802 | continue; |
1795 | if ((prot & mem_clusters[i].size & PAGE_MASK) == prot) | | 1803 | if ((prot & mem_clusters[i].size & PAGE_MASK) == prot) |
1796 | return 0; | | 1804 | return 0; |
1797 | } | | 1805 | } |
1798 | return EFAULT; | | 1806 | return EFAULT; |
1799 | } | | 1807 | } |
1800 | | | 1808 | |
1801 | bool | | 1809 | bool |
1802 | mm_md_direct_mapped_io(void *addr, paddr_t *paddr) | | 1810 | mm_md_direct_mapped_io(void *addr, paddr_t *paddr) |
1803 | { | | 1811 | { |
1804 | vaddr_t va = (vaddr_t)addr; | | 1812 | vaddr_t va = (vaddr_t)addr; |
1805 | | | 1813 | |
1806 | if (va >= ALPHA_K0SEG_BASE && va <= ALPHA_K0SEG_END) { | | 1814 | if (va >= ALPHA_K0SEG_BASE && va <= ALPHA_K0SEG_END) { |
1807 | *paddr = ALPHA_K0SEG_TO_PHYS(va); | | 1815 | *paddr = ALPHA_K0SEG_TO_PHYS(va); |
1808 | return true; | | 1816 | return true; |
1809 | } | | 1817 | } |
1810 | return false; | | 1818 | return false; |
1811 | } | | 1819 | } |
1812 | | | 1820 | |
1813 | bool | | 1821 | bool |
1814 | mm_md_direct_mapped_phys(paddr_t paddr, vaddr_t *vaddr) | | 1822 | mm_md_direct_mapped_phys(paddr_t paddr, vaddr_t *vaddr) |
1815 | { | | 1823 | { |
1816 | | | 1824 | |
1817 | *vaddr = ALPHA_PHYS_TO_K0SEG(paddr); | | 1825 | *vaddr = ALPHA_PHYS_TO_K0SEG(paddr); |
1818 | return true; | | 1826 | return true; |
1819 | } | | 1827 | } |
1820 | | | 1828 | |
1821 | void | | 1829 | void |
1822 | cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) | | 1830 | cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) |
1823 | { | | 1831 | { |
1824 | struct trapframe *frame = l->l_md.md_tf; | | 1832 | struct trapframe *frame = l->l_md.md_tf; |
1825 | struct pcb *pcb = lwp_getpcb(l); | | 1833 | struct pcb *pcb = lwp_getpcb(l); |
1826 | __greg_t *gr = mcp->__gregs; | | 1834 | __greg_t *gr = mcp->__gregs; |
1827 | __greg_t ras_pc; | | 1835 | __greg_t ras_pc; |
1828 | | | 1836 | |
1829 | /* Save register context. */ | | 1837 | /* Save register context. */ |
1830 | frametoreg(frame, (struct reg *)gr); | | 1838 | frametoreg(frame, (struct reg *)gr); |
1831 | /* XXX if there's a better, general way to get the USP of | | 1839 | /* XXX if there's a better, general way to get the USP of |
1832 | * an LWP that might or might not be curlwp, I'd like to know | | 1840 | * an LWP that might or might not be curlwp, I'd like to know |
1833 | * about it. | | 1841 | * about it. |
1834 | */ | | 1842 | */ |
1835 | if (l == curlwp) { | | 1843 | if (l == curlwp) { |
1836 | gr[_REG_SP] = alpha_pal_rdusp(); | | 1844 | gr[_REG_SP] = alpha_pal_rdusp(); |
1837 | gr[_REG_UNIQUE] = alpha_pal_rdunique(); | | 1845 | gr[_REG_UNIQUE] = alpha_pal_rdunique(); |
1838 | } else { | | 1846 | } else { |
1839 | gr[_REG_SP] = pcb->pcb_hw.apcb_usp; | | 1847 | gr[_REG_SP] = pcb->pcb_hw.apcb_usp; |
1840 | gr[_REG_UNIQUE] = pcb->pcb_hw.apcb_unique; | | 1848 | gr[_REG_UNIQUE] = pcb->pcb_hw.apcb_unique; |
1841 | } | | 1849 | } |
1842 | gr[_REG_PC] = frame->tf_regs[FRAME_PC]; | | 1850 | gr[_REG_PC] = frame->tf_regs[FRAME_PC]; |
1843 | gr[_REG_PS] = frame->tf_regs[FRAME_PS]; | | 1851 | gr[_REG_PS] = frame->tf_regs[FRAME_PS]; |
1844 | | | 1852 | |
1845 | if ((ras_pc = (__greg_t)ras_lookup(l->l_proc, | | 1853 | if ((ras_pc = (__greg_t)ras_lookup(l->l_proc, |
1846 | (void *) gr[_REG_PC])) != -1) | | 1854 | (void *) gr[_REG_PC])) != -1) |
1847 | gr[_REG_PC] = ras_pc; | | 1855 | gr[_REG_PC] = ras_pc; |
1848 | | | 1856 | |
1849 | *flags |= _UC_CPU | _UC_TLSBASE; | | 1857 | *flags |= _UC_CPU | _UC_TLSBASE; |
1850 | | | 1858 | |
1851 | /* Save floating point register context, if any, and copy it. */ | | 1859 | /* Save floating point register context, if any, and copy it. */ |
1852 | if (fpu_valid_p(l)) { | | 1860 | if (fpu_valid_p(l)) { |
1853 | fpu_save(l); | | 1861 | fpu_save(l); |
1854 | (void)memcpy(&mcp->__fpregs, &pcb->pcb_fp, | | 1862 | (void)memcpy(&mcp->__fpregs, &pcb->pcb_fp, |
1855 | sizeof (mcp->__fpregs)); | | 1863 | sizeof (mcp->__fpregs)); |
1856 | mcp->__fpregs.__fp_fpcr = alpha_read_fp_c(l); | | 1864 | mcp->__fpregs.__fp_fpcr = alpha_read_fp_c(l); |
1857 | *flags |= _UC_FPU; | | 1865 | *flags |= _UC_FPU; |
1858 | } | | 1866 | } |
1859 | } | | 1867 | } |
1860 | | | 1868 | |
1861 | int | | 1869 | int |
1862 | cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) | | 1870 | cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) |
1863 | { | | 1871 | { |
1864 | const __greg_t *gr = mcp->__gregs; | | 1872 | const __greg_t *gr = mcp->__gregs; |
1865 | | | 1873 | |
1866 | if ((gr[_REG_PS] & ALPHA_PSL_USERSET) != ALPHA_PSL_USERSET || | | 1874 | if ((gr[_REG_PS] & ALPHA_PSL_USERSET) != ALPHA_PSL_USERSET || |
1867 | (gr[_REG_PS] & ALPHA_PSL_USERCLR) != 0) | | 1875 | (gr[_REG_PS] & ALPHA_PSL_USERCLR) != 0) |
1868 | return EINVAL; | | 1876 | return EINVAL; |
1869 | | | 1877 | |
1870 | return 0; | | 1878 | return 0; |
1871 | } | | 1879 | } |
1872 | | | 1880 | |
1873 | int | | 1881 | int |
1874 | cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) | | 1882 | cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) |
1875 | { | | 1883 | { |
1876 | struct trapframe *frame = l->l_md.md_tf; | | 1884 | struct trapframe *frame = l->l_md.md_tf; |
1877 | struct pcb *pcb = lwp_getpcb(l); | | 1885 | struct pcb *pcb = lwp_getpcb(l); |
1878 | const __greg_t *gr = mcp->__gregs; | | 1886 | const __greg_t *gr = mcp->__gregs; |
1879 | int error; | | 1887 | int error; |
1880 | | | 1888 | |
1881 | /* Restore register context, if any. */ | | 1889 | /* Restore register context, if any. */ |
1882 | if (flags & _UC_CPU) { | | 1890 | if (flags & _UC_CPU) { |
1883 | /* Check for security violations first. */ | | 1891 | /* Check for security violations first. */ |
1884 | error = cpu_mcontext_validate(l, mcp); | | 1892 | error = cpu_mcontext_validate(l, mcp); |
1885 | if (error) | | 1893 | if (error) |
1886 | return error; | | 1894 | return error; |
1887 | | | 1895 | |
1888 | regtoframe((const struct reg *)gr, l->l_md.md_tf); | | 1896 | regtoframe((const struct reg *)gr, l->l_md.md_tf); |
1889 | if (l == curlwp) | | 1897 | if (l == curlwp) |
1890 | alpha_pal_wrusp(gr[_REG_SP]); | | 1898 | alpha_pal_wrusp(gr[_REG_SP]); |
1891 | else | | 1899 | else |
1892 | pcb->pcb_hw.apcb_usp = gr[_REG_SP]; | | 1900 | pcb->pcb_hw.apcb_usp = gr[_REG_SP]; |
1893 | frame->tf_regs[FRAME_PC] = gr[_REG_PC]; | | 1901 | frame->tf_regs[FRAME_PC] = gr[_REG_PC]; |
1894 | frame->tf_regs[FRAME_PS] = gr[_REG_PS]; | | 1902 | frame->tf_regs[FRAME_PS] = gr[_REG_PS]; |
1895 | } | | 1903 | } |
1896 | | | 1904 | |
1897 | if (flags & _UC_TLSBASE) | | 1905 | if (flags & _UC_TLSBASE) |
1898 | lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_UNIQUE]); | | 1906 | lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_UNIQUE]); |
1899 | | | 1907 | |
1900 | /* Restore floating point register context, if any. */ | | 1908 | /* Restore floating point register context, if any. */ |
1901 | if (flags & _UC_FPU) { | | 1909 | if (flags & _UC_FPU) { |
1902 | /* If we have an FP register context, get rid of it. */ | | 1910 | /* If we have an FP register context, get rid of it. */ |
1903 | fpu_discard(l, true); | | 1911 | fpu_discard(l, true); |
1904 | (void)memcpy(&pcb->pcb_fp, &mcp->__fpregs, | | 1912 | (void)memcpy(&pcb->pcb_fp, &mcp->__fpregs, |
1905 | sizeof (pcb->pcb_fp)); | | 1913 | sizeof (pcb->pcb_fp)); |
1906 | l->l_md.md_flags = mcp->__fpregs.__fp_fpcr & MDLWP_FP_C; | | 1914 | l->l_md.md_flags = mcp->__fpregs.__fp_fpcr & MDLWP_FP_C; |
1907 | } | | 1915 | } |
1908 | | | 1916 | |
1909 | mutex_enter(l->l_proc->p_lock); | | 1917 | mutex_enter(l->l_proc->p_lock); |
1910 | if (flags & _UC_SETSTACK) | | 1918 | if (flags & _UC_SETSTACK) |
1911 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 1919 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
1912 | if (flags & _UC_CLRSTACK) | | 1920 | if (flags & _UC_CLRSTACK) |
1913 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | | 1921 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; |
1914 | mutex_exit(l->l_proc->p_lock); | | 1922 | mutex_exit(l->l_proc->p_lock); |
1915 | | | 1923 | |
1916 | return (0); | | 1924 | return (0); |
1917 | } | | 1925 | } |
1918 | | | 1926 | |
1919 | static void | | 1927 | static void |
1920 | cpu_kick(struct cpu_info * const ci) | | 1928 | cpu_kick(struct cpu_info * const ci) |
1921 | { | | 1929 | { |
1922 | #if defined(MULTIPROCESSOR) | | 1930 | #if defined(MULTIPROCESSOR) |
1923 | alpha_send_ipi(ci->ci_cpuid, ALPHA_IPI_AST); | | 1931 | alpha_send_ipi(ci->ci_cpuid, ALPHA_IPI_AST); |
1924 | #endif /* MULTIPROCESSOR */ | | 1932 | #endif /* MULTIPROCESSOR */ |
1925 | } | | 1933 | } |
1926 | | | 1934 | |
1927 | /* | | 1935 | /* |
1928 | * Preempt the current process if in interrupt from user mode, | | 1936 | * Preempt the current process if in interrupt from user mode, |
1929 | * or after the current trap/syscall if in system mode. | | 1937 | * or after the current trap/syscall if in system mode. |
1930 | */ | | 1938 | */ |
1931 | void | | 1939 | void |
1932 | cpu_need_resched(struct cpu_info *ci, struct lwp *l, int flags) | | 1940 | cpu_need_resched(struct cpu_info *ci, struct lwp *l, int flags) |
1933 | { | | 1941 | { |
1934 | | | 1942 | |
1935 | KASSERT(kpreempt_disabled()); | | 1943 | KASSERT(kpreempt_disabled()); |
1936 | | | 1944 | |
1937 | if ((flags & RESCHED_IDLE) != 0) { | | 1945 | if ((flags & RESCHED_IDLE) != 0) { |
1938 | /* | | 1946 | /* |
1939 | * Nothing to do here; we are not currently using WTINT | | 1947 | * Nothing to do here; we are not currently using WTINT |
1940 | * in cpu_idle(). | | 1948 | * in cpu_idle(). |
1941 | */ | | 1949 | */ |
1942 | return; | | 1950 | return; |
1943 | } | | 1951 | } |
1944 | | | 1952 | |
1945 | /* XXX RESCHED_KPREEMPT XXX */ | | 1953 | /* XXX RESCHED_KPREEMPT XXX */ |
1946 | | | 1954 | |
1947 | KASSERT((flags & RESCHED_UPREEMPT) != 0); | | 1955 | KASSERT((flags & RESCHED_UPREEMPT) != 0); |
1948 | if ((flags & RESCHED_REMOTE) != 0) { | | 1956 | if ((flags & RESCHED_REMOTE) != 0) { |
1949 | cpu_kick(ci); | | 1957 | cpu_kick(ci); |
1950 | } else { | | 1958 | } else { |
1951 | aston(l); | | 1959 | aston(l); |
1952 | } | | 1960 | } |
1953 | } | | 1961 | } |
1954 | | | 1962 | |
1955 | /* | | 1963 | /* |
1956 | * Notify the current lwp (l) that it has a signal pending, | | 1964 | * Notify the current lwp (l) that it has a signal pending, |
1957 | * process as soon as possible. | | 1965 | * process as soon as possible. |
1958 | */ | | 1966 | */ |
1959 | void | | 1967 | void |
1960 | cpu_signotify(struct lwp *l) | | 1968 | cpu_signotify(struct lwp *l) |
1961 | { | | 1969 | { |
1962 | | | 1970 | |
1963 | KASSERT(kpreempt_disabled()); | | 1971 | KASSERT(kpreempt_disabled()); |
1964 | | | 1972 | |
1965 | if (l->l_cpu != curcpu()) { | | 1973 | if (l->l_cpu != curcpu()) { |
1966 | cpu_kick(l->l_cpu); | | 1974 | cpu_kick(l->l_cpu); |
1967 | } else { | | 1975 | } else { |
1968 | aston(l); | | 1976 | aston(l); |
1969 | } | | 1977 | } |
1970 | } | | 1978 | } |
1971 | | | 1979 | |
1972 | /* | | 1980 | /* |
1973 | * Give a profiling tick to the current process when the user profiling | | 1981 | * Give a profiling tick to the current process when the user profiling |
1974 | * buffer pages are invalid. On the alpha, request an AST to send us | | 1982 | * buffer pages are invalid. On the alpha, request an AST to send us |
1975 | * through trap, marking the proc as needing a profiling tick. | | 1983 | * through trap, marking the proc as needing a profiling tick. |
1976 | */ | | 1984 | */ |
1977 | void | | 1985 | void |
1978 | cpu_need_proftick(struct lwp *l) | | 1986 | cpu_need_proftick(struct lwp *l) |
1979 | { | | 1987 | { |
1980 | | | 1988 | |
1981 | KASSERT(kpreempt_disabled()); | | 1989 | KASSERT(kpreempt_disabled()); |
1982 | KASSERT(l->l_cpu == curcpu()); | | 1990 | KASSERT(l->l_cpu == curcpu()); |
1983 | | | 1991 | |
1984 | l->l_pflag |= LP_OWEUPC; | | 1992 | l->l_pflag |= LP_OWEUPC; |
1985 | aston(l); | | 1993 | aston(l); |
1986 | } | | 1994 | } |