| @@ -1,1994 +1,1994 @@ | | | @@ -1,1994 +1,1994 @@ |
1 | /* $NetBSD: machdep.c,v 1.75 2009/11/27 03:23:09 rmind Exp $ */ | | 1 | /* $NetBSD: machdep.c,v 1.76 2009/12/01 16:20:52 skrll Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2001, 2002 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 Matthew Fredette. | | 8 | * by Matthew Fredette. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* $OpenBSD: machdep.c,v 1.40 2001/09/19 20:50:56 mickey Exp $ */ | | 32 | /* $OpenBSD: machdep.c,v 1.40 2001/09/19 20:50:56 mickey Exp $ */ |
33 | | | 33 | |
34 | /* | | 34 | /* |
35 | * Copyright (c) 1999-2003 Michael Shalayeff | | 35 | * Copyright (c) 1999-2003 Michael Shalayeff |
36 | * All rights reserved. | | 36 | * All rights reserved. |
37 | * | | 37 | * |
38 | * Redistribution and use in source and binary forms, with or without | | 38 | * Redistribution and use in source and binary forms, with or without |
39 | * modification, are permitted provided that the following conditions | | 39 | * modification, are permitted provided that the following conditions |
40 | * are met: | | 40 | * are met: |
41 | * 1. Redistributions of source code must retain the above copyright | | 41 | * 1. Redistributions of source code must retain the above copyright |
42 | * notice, this list of conditions and the following disclaimer. | | 42 | * notice, this list of conditions and the following disclaimer. |
43 | * 2. Redistributions in binary form must reproduce the above copyright | | 43 | * 2. Redistributions in binary form must reproduce the above copyright |
44 | * notice, this list of conditions and the following disclaimer in the | | 44 | * notice, this list of conditions and the following disclaimer in the |
45 | * documentation and/or other materials provided with the distribution. | | 45 | * documentation and/or other materials provided with the distribution. |
46 | * | | 46 | * |
47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
48 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 48 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
49 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 49 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
50 | * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, | | 50 | * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, |
51 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | | 51 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
52 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | | 52 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
53 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 53 | * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | | 54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
55 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | | 55 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
56 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 56 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
57 | * THE POSSIBILITY OF SUCH DAMAGE. | | 57 | * THE POSSIBILITY OF SUCH DAMAGE. |
58 | */ | | 58 | */ |
59 | | | 59 | |
60 | #include <sys/cdefs.h> | | 60 | #include <sys/cdefs.h> |
61 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.75 2009/11/27 03:23:09 rmind Exp $"); | | 61 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.76 2009/12/01 16:20:52 skrll Exp $"); |
62 | | | 62 | |
63 | #include "opt_cputype.h" | | 63 | #include "opt_cputype.h" |
64 | #include "opt_ddb.h" | | 64 | #include "opt_ddb.h" |
65 | #include "opt_kgdb.h" | | 65 | #include "opt_kgdb.h" |
66 | #include "opt_modular.h" | | 66 | #include "opt_modular.h" |
67 | #include "opt_useleds.h" | | 67 | #include "opt_useleds.h" |
68 | | | 68 | |
69 | #include <sys/param.h> | | 69 | #include <sys/param.h> |
70 | #include <sys/systm.h> | | 70 | #include <sys/systm.h> |
71 | #include <sys/signalvar.h> | | 71 | #include <sys/signalvar.h> |
72 | #include <sys/kernel.h> | | 72 | #include <sys/kernel.h> |
73 | #include <sys/proc.h> | | 73 | #include <sys/proc.h> |
74 | #include <sys/buf.h> | | 74 | #include <sys/buf.h> |
75 | #include <sys/reboot.h> | | 75 | #include <sys/reboot.h> |
76 | #include <sys/device.h> | | 76 | #include <sys/device.h> |
77 | #include <sys/conf.h> | | 77 | #include <sys/conf.h> |
78 | #include <sys/file.h> | | 78 | #include <sys/file.h> |
79 | #include <sys/callout.h> | | 79 | #include <sys/callout.h> |
80 | #include <sys/malloc.h> | | 80 | #include <sys/malloc.h> |
81 | #include <sys/mbuf.h> | | 81 | #include <sys/mbuf.h> |
82 | #include <sys/msgbuf.h> | | 82 | #include <sys/msgbuf.h> |
83 | #include <sys/ioctl.h> | | 83 | #include <sys/ioctl.h> |
84 | #include <sys/tty.h> | | 84 | #include <sys/tty.h> |
85 | #include <sys/exec.h> | | 85 | #include <sys/exec.h> |
86 | #include <sys/exec_aout.h> /* for MID_* */ | | 86 | #include <sys/exec_aout.h> /* for MID_* */ |
87 | #include <sys/sysctl.h> | | 87 | #include <sys/sysctl.h> |
88 | #include <sys/core.h> | | 88 | #include <sys/core.h> |
89 | #include <sys/kcore.h> | | 89 | #include <sys/kcore.h> |
90 | #include <sys/module.h> | | 90 | #include <sys/module.h> |
91 | #include <sys/extent.h> | | 91 | #include <sys/extent.h> |
92 | #include <sys/ksyms.h> | | 92 | #include <sys/ksyms.h> |
93 | #include <sys/mount.h> | | 93 | #include <sys/mount.h> |
94 | #include <sys/mutex.h> | | 94 | #include <sys/mutex.h> |
95 | #include <sys/syscallargs.h> | | 95 | #include <sys/syscallargs.h> |
96 | | | 96 | |
97 | #include <uvm/uvm_page.h> | | 97 | #include <uvm/uvm_page.h> |
98 | #include <uvm/uvm.h> | | 98 | #include <uvm/uvm.h> |
99 | | | 99 | |
100 | #include <dev/cons.h> | | 100 | #include <dev/cons.h> |
101 | | | 101 | |
102 | #include <machine/pdc.h> | | 102 | #include <machine/pdc.h> |
103 | #include <machine/iomod.h> | | 103 | #include <machine/iomod.h> |
104 | #include <machine/psl.h> | | 104 | #include <machine/psl.h> |
105 | #include <machine/reg.h> | | 105 | #include <machine/reg.h> |
106 | #include <machine/cpufunc.h> | | 106 | #include <machine/cpufunc.h> |
107 | #include <machine/autoconf.h> | | 107 | #include <machine/autoconf.h> |
108 | #include <machine/bootinfo.h> | | 108 | #include <machine/bootinfo.h> |
109 | #include <machine/kcore.h> | | 109 | #include <machine/kcore.h> |
110 | | | 110 | |
111 | #ifdef KGDB | | 111 | #ifdef KGDB |
112 | #include "com.h" | | 112 | #include "com.h" |
113 | #endif | | 113 | #endif |
114 | | | 114 | |
115 | #ifdef DDB | | 115 | #ifdef DDB |
116 | #include <machine/db_machdep.h> | | 116 | #include <machine/db_machdep.h> |
117 | #include <ddb/db_access.h> | | 117 | #include <ddb/db_access.h> |
118 | #include <ddb/db_sym.h> | | 118 | #include <ddb/db_sym.h> |
119 | #include <ddb/db_extern.h> | | 119 | #include <ddb/db_extern.h> |
120 | #endif | | 120 | #endif |
121 | | | 121 | |
122 | #include <hp700/hp700/intr.h> | | 122 | #include <hp700/hp700/intr.h> |
123 | #include <hp700/hp700/machdep.h> | | 123 | #include <hp700/hp700/machdep.h> |
124 | #include <hp700/hp700/pim.h> | | 124 | #include <hp700/hp700/pim.h> |
125 | #include <hp700/dev/cpudevs.h> | | 125 | #include <hp700/dev/cpudevs.h> |
126 | | | 126 | |
127 | #ifdef PMAPDEBUG | | 127 | #ifdef PMAPDEBUG |
128 | #include <hppa/hppa/hpt.h> | | 128 | #include <hppa/hppa/hpt.h> |
129 | #endif | | 129 | #endif |
130 | | | 130 | |
131 | #include "ksyms.h" | | 131 | #include "ksyms.h" |
132 | | | 132 | |
133 | /* | | 133 | /* |
134 | * Different kinds of flags used throughout the kernel. | | 134 | * Different kinds of flags used throughout the kernel. |
135 | */ | | 135 | */ |
136 | void *msgbufaddr; | | 136 | void *msgbufaddr; |
137 | | | 137 | |
138 | /* | | 138 | /* |
139 | * cache configuration, for most machines is the same | | 139 | * cache configuration, for most machines is the same |
140 | * numbers, so it makes sense to do defines w/ numbers depending | | 140 | * numbers, so it makes sense to do defines w/ numbers depending |
141 | * on configured CPU types in the kernel | | 141 | * on configured CPU types in the kernel |
142 | */ | | 142 | */ |
143 | int icache_stride, icache_line_mask; | | 143 | int icache_stride, icache_line_mask; |
144 | int dcache_stride, dcache_line_mask; | | 144 | int dcache_stride, dcache_line_mask; |
145 | | | 145 | |
146 | /* | | 146 | /* |
147 | * things to not kill | | 147 | * things to not kill |
148 | */ | | 148 | */ |
149 | volatile u_int8_t *machine_ledaddr; | | 149 | volatile u_int8_t *machine_ledaddr; |
150 | int machine_ledword, machine_leds; | | 150 | int machine_ledword, machine_leds; |
151 | | | 151 | |
152 | /* | | 152 | /* |
153 | * This flag is nonzero iff page zero is mapped. | | 153 | * This flag is nonzero iff page zero is mapped. |
154 | * It is initialized to 1, because before we go | | 154 | * It is initialized to 1, because before we go |
155 | * virtual, page zero *is* available. It is set | | 155 | * virtual, page zero *is* available. It is set |
156 | * to zero right before we go virtual. | | 156 | * to zero right before we go virtual. |
157 | */ | | 157 | */ |
158 | static int pagezero_mapped = 1; | | 158 | static int pagezero_mapped = 1; |
159 | | | 159 | |
160 | /* | | 160 | /* |
161 | * CPU params (should be the same for all cpus in the system) | | 161 | * CPU params (should be the same for all cpus in the system) |
162 | */ | | 162 | */ |
163 | struct pdc_cache pdc_cache PDC_ALIGNMENT; | | 163 | struct pdc_cache pdc_cache PDC_ALIGNMENT; |
164 | struct pdc_btlb pdc_btlb PDC_ALIGNMENT; | | 164 | struct pdc_btlb pdc_btlb PDC_ALIGNMENT; |
165 | struct pdc_model pdc_model PDC_ALIGNMENT; | | 165 | struct pdc_model pdc_model PDC_ALIGNMENT; |
166 | | | 166 | |
167 | int usebtlb; | | 167 | int usebtlb; |
168 | | | 168 | |
169 | /* | | 169 | /* |
170 | * The BTLB slots. | | 170 | * The BTLB slots. |
171 | */ | | 171 | */ |
172 | static struct btlb_slot { | | 172 | static struct btlb_slot { |
173 | | | 173 | |
174 | /* The number associated with this slot. */ | | 174 | /* The number associated with this slot. */ |
175 | int btlb_slot_number; | | 175 | int btlb_slot_number; |
176 | | | 176 | |
177 | /* The flags associated with this slot. */ | | 177 | /* The flags associated with this slot. */ |
178 | int btlb_slot_flags; | | 178 | int btlb_slot_flags; |
179 | #define BTLB_SLOT_IBTLB (1 << 0) | | 179 | #define BTLB_SLOT_IBTLB (1 << 0) |
180 | #define BTLB_SLOT_DBTLB (1 << 1) | | 180 | #define BTLB_SLOT_DBTLB (1 << 1) |
181 | #define BTLB_SLOT_CBTLB (BTLB_SLOT_IBTLB | BTLB_SLOT_DBTLB) | | 181 | #define BTLB_SLOT_CBTLB (BTLB_SLOT_IBTLB | BTLB_SLOT_DBTLB) |
182 | #define BTLB_SLOT_VARIABLE_RANGE (1 << 2) | | 182 | #define BTLB_SLOT_VARIABLE_RANGE (1 << 2) |
183 | | | 183 | |
184 | /* | | 184 | /* |
185 | * The mapping information. A mapping is free | | 185 | * The mapping information. A mapping is free |
186 | * if its btlb_slot_frames member is zero. | | 186 | * if its btlb_slot_frames member is zero. |
187 | */ | | 187 | */ |
188 | pa_space_t btlb_slot_va_space; | | 188 | pa_space_t btlb_slot_va_space; |
189 | vaddr_t btlb_slot_va_frame; | | 189 | vaddr_t btlb_slot_va_frame; |
190 | paddr_t btlb_slot_pa_frame; | | 190 | paddr_t btlb_slot_pa_frame; |
191 | vsize_t btlb_slot_frames; | | 191 | vsize_t btlb_slot_frames; |
192 | u_int btlb_slot_tlbprot; | | 192 | u_int btlb_slot_tlbprot; |
193 | } *btlb_slots; | | 193 | } *btlb_slots; |
194 | int btlb_slots_count; | | 194 | int btlb_slots_count; |
195 | | | 195 | |
196 | /* w/ a little deviation should be the same for all installed cpus */ | | 196 | /* w/ a little deviation should be the same for all installed cpus */ |
197 | u_int cpu_ticksnum, cpu_ticksdenom, cpu_hzticks; | | 197 | u_int cpu_ticksnum, cpu_ticksdenom, cpu_hzticks; |
198 | | | 198 | |
199 | /* exported info */ | | 199 | /* exported info */ |
200 | char machine[] = MACHINE; | | 200 | char machine[] = MACHINE; |
201 | char cpu_model[128]; | | 201 | char cpu_model[128]; |
202 | const struct hppa_cpu_info *hppa_cpu_info; | | 202 | const struct hppa_cpu_info *hppa_cpu_info; |
203 | enum hppa_cpu_type cpu_type; | | 203 | enum hppa_cpu_type cpu_type; |
204 | int cpu_hvers; | | 204 | int cpu_hvers; |
205 | int cpu_revision; | | 205 | int cpu_revision; |
206 | | | 206 | |
207 | /* | | 207 | /* |
208 | * exported methods for cpus | | 208 | * exported methods for cpus |
209 | */ | | 209 | */ |
210 | int (*cpu_desidhash)(void); | | 210 | int (*cpu_desidhash)(void); |
211 | int (*cpu_hpt_init)(vaddr_t, vsize_t); | | 211 | int (*cpu_hpt_init)(vaddr_t, vsize_t); |
212 | int (*cpu_ibtlb_ins)(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 212 | int (*cpu_ibtlb_ins)(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
213 | int (*cpu_dbtlb_ins)(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 213 | int (*cpu_dbtlb_ins)(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
214 | | | 214 | |
215 | dev_t bootdev; | | 215 | dev_t bootdev; |
216 | int physmem; /* # pages supported by pmap */ | | 216 | int physmem; /* # pages supported by pmap */ |
217 | int totalphysmem; /* # pages in system */ | | 217 | int totalphysmem; /* # pages in system */ |
218 | int availphysmem; /* # pages available to kernel */ | | 218 | int availphysmem; /* # pages available to kernel */ |
219 | int esym; | | 219 | int esym; |
220 | paddr_t avail_end; | | 220 | paddr_t avail_end; |
221 | | | 221 | |
222 | /* | | 222 | /* |
223 | * Our copy of the bootinfo struct passed to us by the boot loader. | | 223 | * Our copy of the bootinfo struct passed to us by the boot loader. |
224 | */ | | 224 | */ |
225 | struct bootinfo bootinfo; | | 225 | struct bootinfo bootinfo; |
226 | | | 226 | |
227 | /* | | 227 | /* |
228 | * XXX note that 0x12000 is the old kernel text start | | 228 | * XXX note that 0x12000 is the old kernel text start |
229 | * address. Memory below this is assumed to belong | | 229 | * address. Memory below this is assumed to belong |
230 | * to the firmware. This value is converted into pages | | 230 | * to the firmware. This value is converted into pages |
231 | * by hppa_init and used as pages in pmap_bootstrap(). | | 231 | * by hppa_init and used as pages in pmap_bootstrap(). |
232 | */ | | 232 | */ |
233 | int resvmem = 0x12000; | | 233 | int resvmem = 0x12000; |
234 | int resvphysmem; | | 234 | int resvphysmem; |
235 | | | 235 | |
236 | /* | | 236 | /* |
237 | * BTLB parameters, broken out for the MI hppa code. | | 237 | * BTLB parameters, broken out for the MI hppa code. |
238 | */ | | 238 | */ |
239 | u_int hppa_btlb_size_min, hppa_btlb_size_max; | | 239 | u_int hppa_btlb_size_min, hppa_btlb_size_max; |
240 | | | 240 | |
241 | /* | | 241 | /* |
242 | * Things for MI glue to stick on. | | 242 | * Things for MI glue to stick on. |
243 | */ | | 243 | */ |
244 | struct extent *hp700_io_extent; | | 244 | struct extent *hp700_io_extent; |
245 | static long hp700_io_extent_store[EXTENT_FIXED_STORAGE_SIZE(64) / sizeof(long)]; | | 245 | static long hp700_io_extent_store[EXTENT_FIXED_STORAGE_SIZE(64) / sizeof(long)]; |
246 | | | 246 | |
247 | /* Virtual page frame for /dev/mem (see mem.c) */ | | 247 | /* Virtual page frame for /dev/mem (see mem.c) */ |
248 | vaddr_t vmmap; | | 248 | vaddr_t vmmap; |
249 | | | 249 | |
250 | /* | | 250 | /* |
251 | * Certain devices need DMA'able memory below the 16MB boundary. | | 251 | * Certain devices need DMA'able memory below the 16MB boundary. |
252 | */ | | 252 | */ |
253 | #define DMA24_SIZE (128 * 1024) | | 253 | #define DMA24_SIZE (128 * 1024) |
254 | struct extent *dma24_ex; | | 254 | struct extent *dma24_ex; |
255 | long dma24_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; | | 255 | long dma24_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; |
256 | | | 256 | |
257 | /* Our exported CPU info; we can have only one. */ | | 257 | /* Our exported CPU info; we can have only one. */ |
258 | struct cpu_info cpu_info_store = { | | 258 | struct cpu_info cpu_info_store = { |
259 | #ifdef MULTIPROCESSOR | | 259 | #ifdef MULTIPROCESSOR |
260 | .ci_curlwp = &lwp0 | | 260 | .ci_curlwp = &lwp0 |
261 | #endif | | 261 | #endif |
262 | }; | | 262 | }; |
263 | | | 263 | |
264 | struct vm_map *mb_map = NULL; | | 264 | struct vm_map *mb_map = NULL; |
265 | struct vm_map *phys_map = NULL; | | 265 | struct vm_map *phys_map = NULL; |
266 | | | 266 | |
267 | void delay_init(void); | | 267 | void delay_init(void); |
268 | static inline void fall(int, int, int, int, int); | | 268 | static inline void fall(int, int, int, int, int); |
269 | void dumpsys(void); | | 269 | void dumpsys(void); |
270 | void cpuid(void); | | 270 | void cpuid(void); |
271 | enum hppa_cpu_type cpu_model_cpuid(int); | | 271 | enum hppa_cpu_type cpu_model_cpuid(int); |
272 | | | 272 | |
273 | /* | | 273 | /* |
274 | * wide used hardware params | | 274 | * wide used hardware params |
275 | */ | | 275 | */ |
276 | struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; | | 276 | struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; |
277 | struct pdc_coproc pdc_coproc PDC_ALIGNMENT; | | 277 | struct pdc_coproc pdc_coproc PDC_ALIGNMENT; |
278 | struct pdc_coherence pdc_coherence PDC_ALIGNMENT; | | 278 | struct pdc_coherence pdc_coherence PDC_ALIGNMENT; |
279 | struct pdc_spidb pdc_spidbits PDC_ALIGNMENT; | | 279 | struct pdc_spidb pdc_spidbits PDC_ALIGNMENT; |
280 | struct pdc_pim pdc_pim PDC_ALIGNMENT; | | 280 | struct pdc_pim pdc_pim PDC_ALIGNMENT; |
281 | struct pdc_model pdc_model PDC_ALIGNMENT; | | 281 | struct pdc_model pdc_model PDC_ALIGNMENT; |
282 | | | 282 | |
283 | /* | | 283 | /* |
284 | * Debugger info. | | 284 | * Debugger info. |
285 | */ | | 285 | */ |
286 | int hp700_kgdb_attached; | | 286 | int hp700_kgdb_attached; |
287 | | | 287 | |
288 | /* | | 288 | /* |
289 | * Whatever CPU types we support | | 289 | * Whatever CPU types we support |
290 | */ | | 290 | */ |
291 | extern const u_int itlb_x[], itlbna_x[], dtlb_x[], dtlbna_x[], tlbd_x[]; | | 291 | extern const u_int itlb_x[], itlbna_x[], dtlb_x[], dtlbna_x[], tlbd_x[]; |
292 | extern const u_int itlb_s[], itlbna_s[], dtlb_s[], dtlbna_s[], tlbd_s[]; | | 292 | extern const u_int itlb_s[], itlbna_s[], dtlb_s[], dtlbna_s[], tlbd_s[]; |
293 | extern const u_int itlb_t[], itlbna_t[], dtlb_t[], dtlbna_t[], tlbd_t[]; | | 293 | extern const u_int itlb_t[], itlbna_t[], dtlb_t[], dtlbna_t[], tlbd_t[]; |
294 | extern const u_int itlb_l[], itlbna_l[], dtlb_l[], dtlbna_l[], tlbd_l[]; | | 294 | extern const u_int itlb_l[], itlbna_l[], dtlb_l[], dtlbna_l[], tlbd_l[]; |
295 | extern const u_int itlb_u[], itlbna_u[], dtlb_u[], dtlbna_u[], tlbd_u[]; | | 295 | extern const u_int itlb_u[], itlbna_u[], dtlb_u[], dtlbna_u[], tlbd_u[]; |
296 | | | 296 | |
297 | int iibtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 297 | int iibtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
298 | int idbtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 298 | int idbtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
299 | int ibtlb_t(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 299 | int ibtlb_t(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
300 | int ibtlb_l(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 300 | int ibtlb_l(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
301 | int ibtlb_u(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 301 | int ibtlb_u(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
302 | int ibtlb_g(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 302 | int ibtlb_g(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
303 | int pbtlb_g(int); | | 303 | int pbtlb_g(int); |
304 | int pbtlb_u(int); | | 304 | int pbtlb_u(int); |
305 | int hpti_l(vaddr_t, vsize_t); | | 305 | int hpti_l(vaddr_t, vsize_t); |
306 | int hpti_u(vaddr_t, vsize_t); | | 306 | int hpti_u(vaddr_t, vsize_t); |
307 | int hpti_g(vaddr_t, vsize_t); | | 307 | int hpti_g(vaddr_t, vsize_t); |
308 | int desidhash_x(void); | | 308 | int desidhash_x(void); |
309 | int desidhash_s(void); | | 309 | int desidhash_s(void); |
310 | int desidhash_t(void); | | 310 | int desidhash_t(void); |
311 | int desidhash_l(void); | | 311 | int desidhash_l(void); |
312 | int desidhash_u(void); | | 312 | int desidhash_u(void); |
313 | | | 313 | |
314 | const struct hppa_cpu_info cpu_types[] = { | | 314 | const struct hppa_cpu_info cpu_types[] = { |
315 | #ifdef HP7000_CPU | | 315 | #ifdef HP7000_CPU |
316 | { "PA7000", NULL, "PCX", | | 316 | { "PA7000", NULL, "PCX", |
317 | hpcx, 0, 0, "1.0", | | 317 | hpcx, 0, 0, "1.0", |
318 | desidhash_x, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, | | 318 | desidhash_x, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, |
319 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ | | 319 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ |
320 | #endif | | 320 | #endif |
321 | #ifdef HP7000_CPU | | 321 | #ifdef HP7000_CPU |
322 | { "PA7000", NULL, "PCXS", | | 322 | { "PA7000", NULL, "PCXS", |
323 | hpcxs, 0, 0, "1.1a", | | 323 | hpcxs, 0, 0, "1.1a", |
324 | desidhash_s, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, | | 324 | desidhash_s, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, |
325 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ | | 325 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ |
326 | #endif | | 326 | #endif |
327 | #ifdef HP7100_CPU | | 327 | #ifdef HP7100_CPU |
328 | { "PA7100", "T-Bird", "PCXT", | | 328 | { "PA7100", "T-Bird", "PCXT", |
329 | hpcxt, 0, HPPA_FTRS_BTLBU, "1.1b", | | 329 | hpcxt, 0, HPPA_FTRS_BTLBU, "1.1b", |
330 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, | | 330 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, |
331 | ibtlb_g, NULL, pbtlb_g }, | | 331 | ibtlb_g, NULL, pbtlb_g }, |
332 | #endif | | 332 | #endif |
333 | #ifdef HP7100LC_CPU | | 333 | #ifdef HP7100LC_CPU |
334 | { "PA7100LC", "Hummingbird", "PCXL", | | 334 | { "PA7100LC", "Hummingbird", "PCXL", |
335 | hpcxl, HPPA_CPU_PCXL, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1c", | | 335 | hpcxl, HPPA_CPU_PCXL, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1c", |
336 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, | | 336 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, |
337 | ibtlb_g, NULL, pbtlb_g, hpti_g }, | | 337 | ibtlb_g, NULL, pbtlb_g, hpti_g }, |
338 | #endif | | 338 | #endif |
339 | #ifdef HP7200_CPU | | 339 | #ifdef HP7200_CPU |
340 | { "PA7200", "T-Bird", "PCXT'", | | 340 | { "PA7200", "T-Bird", "PCXT'", |
341 | hpcxtp, HPPA_CPU_PCXT2, HPPA_FTRS_BTLBU, "1.1d", | | 341 | hpcxtp, HPPA_CPU_PCXT2, HPPA_FTRS_BTLBU, "1.1d", |
342 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, | | 342 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, |
343 | ibtlb_g, NULL, pbtlb_g }, | | 343 | ibtlb_g, NULL, pbtlb_g }, |
344 | #endif | | 344 | #endif |
345 | #ifdef HP7300LC_CPU | | 345 | #ifdef HP7300LC_CPU |
346 | { "PA7300LC", "Velociraptor", "PCXL2", | | 346 | { "PA7300LC", "Velociraptor", "PCXL2", |
347 | hpcxl2, HPPA_CPU_PCXL2, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1e", | | 347 | hpcxl2, HPPA_CPU_PCXL2, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1e", |
348 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, | | 348 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, |
349 | ibtlb_g, NULL, pbtlb_g, hpti_g }, | | 349 | ibtlb_g, NULL, pbtlb_g, hpti_g }, |
350 | #endif | | 350 | #endif |
351 | #ifdef HP8000_CPU | | 351 | #ifdef HP8000_CPU |
352 | { "PA8000", "Onyx", "PCXU", | | 352 | { "PA8000", "Onyx", "PCXU", |
353 | hpcxu, HPPA_CPU_PCXU, HPPA_FTRS_W32B, "2.0", | | 353 | hpcxu, HPPA_CPU_PCXU, HPPA_FTRS_W32B, "2.0", |
354 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 354 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
355 | ibtlb_u, NULL, pbtlb_u }, | | 355 | ibtlb_u, NULL, pbtlb_u }, |
356 | #endif | | 356 | #endif |
357 | #ifdef HP8200_CPU | | 357 | #ifdef HP8200_CPU |
358 | { "PA8200", "Vulcan", "PCXU+", | | 358 | { "PA8200", "Vulcan", "PCXU+", |
359 | hpcxup, HPPA_CPU_PCXUP, HPPA_FTRS_W32B, "2.0", | | 359 | hpcxup, HPPA_CPU_PCXUP, HPPA_FTRS_W32B, "2.0", |
360 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 360 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
361 | ibtlb_u, NULL, pbtlb_u }, | | 361 | ibtlb_u, NULL, pbtlb_u }, |
362 | #endif | | 362 | #endif |
363 | #ifdef HP8500_CPU | | 363 | #ifdef HP8500_CPU |
364 | { "PA8500", "Barra'Cuda", "PCXW", | | 364 | { "PA8500", "Barra'Cuda", "PCXW", |
365 | hpcxw, HPPA_CPU_PCXW, HPPA_FTRS_W32B, "2.0", | | 365 | hpcxw, HPPA_CPU_PCXW, HPPA_FTRS_W32B, "2.0", |
366 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 366 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
367 | ibtlb_u, NULL, pbtlb_u }, | | 367 | ibtlb_u, NULL, pbtlb_u }, |
368 | #endif | | 368 | #endif |
369 | #ifdef HP8600_CPU | | 369 | #ifdef HP8600_CPU |
370 | { "PA8600", "Landshark", "PCXW+", | | 370 | { "PA8600", "Landshark", "PCXW+", |
371 | hpcxwp, HPPA_CPU_PCXW2 /*XXX NH */, HPPA_FTRS_W32B, "2.0", | | 371 | hpcxwp, HPPA_CPU_PCXW2 /*XXX NH */, HPPA_FTRS_W32B, "2.0", |
372 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 372 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
373 | ibtlb_u, NULL, pbtlb_u }, | | 373 | ibtlb_u, NULL, pbtlb_u }, |
374 | #endif | | 374 | #endif |
375 | #ifdef HP8700_CPU | | 375 | #ifdef HP8700_CPU |
376 | { "PA8700", "Piranha", "PCXW2", | | 376 | { "PA8700", "Piranha", "PCXW2", |
377 | hpcxw2, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", | | 377 | hpcxw2, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", |
378 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 378 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
379 | ibtlb_u, NULL, pbtlb_u }, | | 379 | ibtlb_u, NULL, pbtlb_u }, |
380 | #endif | | 380 | #endif |
381 | #ifdef HP8800_CPU | | 381 | #ifdef HP8800_CPU |
382 | { "PA8800", "Mako", "Make", | | 382 | { "PA8800", "Mako", "Make", |
383 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", | | 383 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", |
384 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 384 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
385 | ibtlb_u, NULL, pbtlb_u }, | | 385 | ibtlb_u, NULL, pbtlb_u }, |
386 | #endif | | 386 | #endif |
387 | #ifdef HP8900_CPU | | 387 | #ifdef HP8900_CPU |
388 | { "PA8900", "Shortfin", "Shortfin", | | 388 | { "PA8900", "Shortfin", "Shortfin", |
389 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", | | 389 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", |
390 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 390 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
391 | ibtlb_u, NULL, pbtlb_u }, | | 391 | ibtlb_u, NULL, pbtlb_u }, |
392 | #endif | | 392 | #endif |
393 | { "" } | | 393 | { "" } |
394 | }; | | 394 | }; |
395 | | | 395 | |
396 | extern kmutex_t vmmap_lock; | | 396 | extern kmutex_t vmmap_lock; |
397 | | | 397 | |
398 | void | | 398 | void |
399 | hppa_init(paddr_t start, void *bi) | | 399 | hppa_init(paddr_t start, void *bi) |
400 | { | | 400 | { |
401 | vaddr_t vstart; | | 401 | vaddr_t vstart; |
402 | vaddr_t v; | | 402 | vaddr_t v; |
403 | int error; | | 403 | int error; |
404 | u_int *p, *q; | | 404 | u_int *p, *q; |
405 | struct btlb_slot *btlb_slot; | | 405 | struct btlb_slot *btlb_slot; |
406 | int btlb_slot_i; | | 406 | int btlb_slot_i; |
407 | struct btinfo_symtab *bi_sym; | | 407 | struct btinfo_symtab *bi_sym; |
408 | | | 408 | |
409 | #ifdef KGDB | | 409 | #ifdef KGDB |
410 | boothowto |= RB_KDB; /* go to kgdb early if compiled in. */ | | 410 | boothowto |= RB_KDB; /* go to kgdb early if compiled in. */ |
411 | #endif | | 411 | #endif |
412 | /* Setup curlwp early for LOCKDEBUG */ | | 412 | /* Setup curlwp early for LOCKDEBUG */ |
413 | mtctl(&lwp0, CR_CURLWP); | | 413 | mtctl(&lwp0, CR_CURLWP); |
414 | | | 414 | |
415 | /* Copy bootinfo */ | | 415 | /* Copy bootinfo */ |
416 | if (bi != NULL) | | 416 | if (bi != NULL) |
417 | memcpy(&bootinfo, bi, sizeof(struct bootinfo)); | | 417 | memcpy(&bootinfo, bi, sizeof(struct bootinfo)); |
418 | | | 418 | |
419 | pdc_init(); /* init PDC iface, so we can call em easy */ | | 419 | pdc_init(); /* init PDC iface, so we can call em easy */ |
420 | | | 420 | |
421 | cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; | | 421 | cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; |
422 | delay_init(); /* calculate CPU clock ratio */ | | 422 | delay_init(); /* calculate CPU clock ratio */ |
423 | | | 423 | |
424 | /* cache parameters */ | | 424 | /* cache parameters */ |
425 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, | | 425 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, |
426 | &pdc_cache)) < 0) { | | 426 | &pdc_cache)) < 0) { |
427 | #ifdef DEBUG | | 427 | #ifdef DEBUG |
428 | printf("WARNING: PDC_CACHE error %d\n", error); | | 428 | printf("WARNING: PDC_CACHE error %d\n", error); |
429 | #endif | | 429 | #endif |
430 | } | | 430 | } |
431 | | | 431 | |
432 | dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; | | 432 | dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; |
433 | dcache_stride = pdc_cache.dc_stride; | | 433 | dcache_stride = pdc_cache.dc_stride; |
434 | icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1; | | 434 | icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1; |
435 | icache_stride = pdc_cache.ic_stride; | | 435 | icache_stride = pdc_cache.ic_stride; |
436 | | | 436 | |
437 | /* cache coherence params (pbably available for 8k only) */ | | 437 | /* cache coherence params (pbably available for 8k only) */ |
438 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS, | | 438 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS, |
439 | &pdc_coherence, 1, 1, 1, 1); | | 439 | &pdc_coherence, 1, 1, 1, 1); |
440 | #ifdef DEBUG | | 440 | #ifdef DEBUG |
441 | printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n", | | 441 | printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n", |
442 | pdc_coherence.ia_cst, pdc_coherence.da_cst, | | 442 | pdc_coherence.ia_cst, pdc_coherence.da_cst, |
443 | pdc_coherence.ita_cst, pdc_coherence.dta_cst, error); | | 443 | pdc_coherence.ita_cst, pdc_coherence.dta_cst, error); |
444 | #endif | | 444 | #endif |
445 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB, | | 445 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB, |
446 | &pdc_spidbits, 0, 0, 0, 0); | | 446 | &pdc_spidbits, 0, 0, 0, 0); |
447 | #ifdef DEBUG | | 447 | #ifdef DEBUG |
448 | printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error); | | 448 | printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error); |
449 | #endif | | 449 | #endif |
450 | | | 450 | |
451 | /* Calculate the OS_HPMC handler checksums. */ | | 451 | /* Calculate the OS_HPMC handler checksums. */ |
452 | p = &os_hpmc; | | 452 | p = &os_hpmc; |
453 | if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p)) | | 453 | if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p)) |
454 | *p = 0x08000240; | | 454 | *p = 0x08000240; |
455 | p[7] = ((char *) &os_hpmc_cont_end) - ((char *) &os_hpmc_cont); | | 455 | p[7] = ((char *) &os_hpmc_cont_end) - ((char *) &os_hpmc_cont); |
456 | p[6] = (u_int) &os_hpmc_cont; | | 456 | p[6] = (u_int) &os_hpmc_cont; |
457 | p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]); | | 457 | p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]); |
458 | p = &os_hpmc_cont; | | 458 | p = &os_hpmc_cont; |
459 | q = (&os_hpmc_cont_end - 1); | | 459 | q = (&os_hpmc_cont_end - 1); |
460 | for(*q = 0; p < q; *q -= *(p++)); | | 460 | for(*q = 0; p < q; *q -= *(p++)); |
461 | | | 461 | |
462 | /* Calculate the OS_TOC handler checksum. */ | | 462 | /* Calculate the OS_TOC handler checksum. */ |
463 | p = (u_int *) &os_toc; | | 463 | p = (u_int *) &os_toc; |
464 | q = (&os_toc_end - 1); | | 464 | q = (&os_toc_end - 1); |
465 | for (*q = 0; p < q; *q -= *(p++)); | | 465 | for (*q = 0; p < q; *q -= *(p++)); |
466 | | | 466 | |
467 | /* Install the OS_TOC handler. */ | | 467 | /* Install the OS_TOC handler. */ |
468 | PAGE0->ivec_toc = os_toc; | | 468 | PAGE0->ivec_toc = os_toc; |
469 | PAGE0->ivec_toclen = ((char *) &os_toc_end) - ((char *) &os_toc); | | 469 | PAGE0->ivec_toclen = ((char *) &os_toc_end) - ((char *) &os_toc); |
470 | | | 470 | |
471 | cpuid(); | | 471 | cpuid(); |
472 | ptlball(); | | 472 | ptlball(); |
473 | fcacheall(); | | 473 | fcacheall(); |
474 | | | 474 | |
475 | avail_end = trunc_page(PAGE0->imm_max_mem); | | 475 | avail_end = trunc_page(PAGE0->imm_max_mem); |
476 | totalphysmem = atop(avail_end); | | 476 | totalphysmem = atop(avail_end); |
477 | if (avail_end > SYSCALLGATE) | | 477 | if (avail_end > SYSCALLGATE) |
478 | avail_end = SYSCALLGATE; | | 478 | avail_end = SYSCALLGATE; |
479 | physmem = atop(avail_end); | | 479 | physmem = atop(avail_end); |
480 | resvmem = atop(resvmem); /* XXXNH */ | | 480 | resvmem = atop(resvmem); /* XXXNH */ |
481 | | | 481 | |
482 | /* we hope this won't fail */ | | 482 | /* we hope this won't fail */ |
483 | hp700_io_extent = extent_create("io", | | 483 | hp700_io_extent = extent_create("io", |
484 | HPPA_IOSPACE, 0xffffffff, M_DEVBUF, | | 484 | HPPA_IOSPACE, 0xffffffff, M_DEVBUF, |
485 | (void *)hp700_io_extent_store, sizeof(hp700_io_extent_store), | | 485 | (void *)hp700_io_extent_store, sizeof(hp700_io_extent_store), |
486 | EX_NOCOALESCE|EX_NOWAIT); | | 486 | EX_NOCOALESCE|EX_NOWAIT); |
487 | | | 487 | |
488 | vstart = round_page(start); | | 488 | vstart = round_page(start); |
489 | | | 489 | |
490 | /* | | 490 | /* |
491 | * Now allocate kernel dynamic variables | | 491 | * Now allocate kernel dynamic variables |
492 | */ | | 492 | */ |
493 | | | 493 | |
494 | /* Allocate the msgbuf. */ | | 494 | /* Allocate the msgbuf. */ |
495 | msgbufaddr = (void *) vstart; | | 495 | msgbufaddr = (void *) vstart; |
496 | vstart += MSGBUFSIZE; | | 496 | vstart += MSGBUFSIZE; |
497 | vstart = round_page(vstart); | | 497 | vstart = round_page(vstart); |
498 | | | 498 | |
499 | /* Allocate the 24-bit DMA region. */ | | 499 | /* Allocate the 24-bit DMA region. */ |
500 | dma24_ex = extent_create("dma24", vstart, vstart + DMA24_SIZE, M_DEVBUF, | | 500 | dma24_ex = extent_create("dma24", vstart, vstart + DMA24_SIZE, M_DEVBUF, |
501 | (void *)dma24_ex_storage, sizeof(dma24_ex_storage), | | 501 | (void *)dma24_ex_storage, sizeof(dma24_ex_storage), |
502 | EX_NOCOALESCE|EX_NOWAIT); | | 502 | EX_NOCOALESCE|EX_NOWAIT); |
503 | vstart += DMA24_SIZE; | | 503 | vstart += DMA24_SIZE; |
504 | vstart = round_page(vstart); | | 504 | vstart = round_page(vstart); |
505 | | | 505 | |
506 | | | 506 | |
507 | if (usebtlb) { | | 507 | if (usebtlb) { |
508 | /* Allocate and initialize the BTLB slots array. */ | | 508 | /* Allocate and initialize the BTLB slots array. */ |
509 | btlb_slots = (struct btlb_slot *) ALIGN(vstart); | | 509 | btlb_slots = (struct btlb_slot *) ALIGN(vstart); |
510 | btlb_slot = btlb_slots; | | 510 | btlb_slot = btlb_slots; |
511 | #define BTLB_SLOTS(count, flags) \ | | 511 | #define BTLB_SLOTS(count, flags) \ |
512 | do { \ | | 512 | do { \ |
513 | for (btlb_slot_i = 0; \ | | 513 | for (btlb_slot_i = 0; \ |
514 | btlb_slot_i < pdc_btlb.count; \ | | 514 | btlb_slot_i < pdc_btlb.count; \ |
515 | btlb_slot_i++) { \ | | 515 | btlb_slot_i++) { \ |
516 | btlb_slot->btlb_slot_number = (btlb_slot - btlb_slots); \ | | 516 | btlb_slot->btlb_slot_number = (btlb_slot - btlb_slots); \ |
517 | btlb_slot->btlb_slot_flags = flags; \ | | 517 | btlb_slot->btlb_slot_flags = flags; \ |
518 | btlb_slot->btlb_slot_frames = 0; \ | | 518 | btlb_slot->btlb_slot_frames = 0; \ |
519 | btlb_slot++; \ | | 519 | btlb_slot++; \ |
520 | } \ | | 520 | } \ |
521 | } while (/* CONSTCOND */ 0) | | 521 | } while (/* CONSTCOND */ 0) |
522 | | | 522 | |
523 | BTLB_SLOTS(finfo.num_i, BTLB_SLOT_IBTLB); | | 523 | BTLB_SLOTS(finfo.num_i, BTLB_SLOT_IBTLB); |
524 | BTLB_SLOTS(finfo.num_d, BTLB_SLOT_DBTLB); | | 524 | BTLB_SLOTS(finfo.num_d, BTLB_SLOT_DBTLB); |
525 | BTLB_SLOTS(finfo.num_c, BTLB_SLOT_CBTLB); | | 525 | BTLB_SLOTS(finfo.num_c, BTLB_SLOT_CBTLB); |
526 | BTLB_SLOTS(vinfo.num_i, BTLB_SLOT_IBTLB | BTLB_SLOT_VARIABLE_RANGE); | | 526 | BTLB_SLOTS(vinfo.num_i, BTLB_SLOT_IBTLB | BTLB_SLOT_VARIABLE_RANGE); |
527 | BTLB_SLOTS(vinfo.num_d, BTLB_SLOT_DBTLB | BTLB_SLOT_VARIABLE_RANGE); | | 527 | BTLB_SLOTS(vinfo.num_d, BTLB_SLOT_DBTLB | BTLB_SLOT_VARIABLE_RANGE); |
528 | BTLB_SLOTS(vinfo.num_c, BTLB_SLOT_CBTLB | BTLB_SLOT_VARIABLE_RANGE); | | 528 | BTLB_SLOTS(vinfo.num_c, BTLB_SLOT_CBTLB | BTLB_SLOT_VARIABLE_RANGE); |
529 | #undef BTLB_SLOTS | | 529 | #undef BTLB_SLOTS |
530 | | | 530 | |
531 | btlb_slots_count = (btlb_slot - btlb_slots); | | 531 | btlb_slots_count = (btlb_slot - btlb_slots); |
532 | vstart = round_page((vaddr_t) btlb_slot); | | 532 | vstart = round_page((vaddr_t) btlb_slot); |
533 | } | | 533 | } |
534 | | | 534 | |
535 | v = vstart; | | 535 | v = vstart; |
536 | | | 536 | |
537 | /* sets resvphysmem */ | | 537 | /* sets resvphysmem */ |
538 | pmap_bootstrap(v); | | 538 | pmap_bootstrap(v); |
539 | | | 539 | |
540 | /* | | 540 | /* |
541 | * BELOW THIS LINE REFERENCING PAGE0 AND OTHER LOW MEMORY | | 541 | * BELOW THIS LINE REFERENCING PAGE0 AND OTHER LOW MEMORY |
542 | * LOCATIONS, AND WRITING THE KERNEL TEXT ARE PROHIBITED | | 542 | * LOCATIONS, AND WRITING THE KERNEL TEXT ARE PROHIBITED |
543 | * WITHOUT TAKING SPECIAL MEASURES. | | 543 | * WITHOUT TAKING SPECIAL MEASURES. |
544 | */ | | 544 | */ |
545 | | | 545 | |
546 | #ifdef DEBUG | | 546 | #ifdef DEBUG |
547 | printf("%s: PDC_CHASSIS\n", __func__); | | 547 | printf("%s: PDC_CHASSIS\n", __func__); |
548 | #endif | | 548 | #endif |
549 | /* they say PDC_COPROC might turn fault light on */ | | 549 | /* they say PDC_COPROC might turn fault light on */ |
550 | pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP, | | 550 | pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP, |
551 | PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0); | | 551 | PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0); |
552 | | | 552 | |
553 | #ifdef DEBUG | | 553 | #ifdef DEBUG |
554 | printf("%s: intr bootstrap\n", __func__); | | 554 | printf("%s: intr bootstrap\n", __func__); |
555 | #endif | | 555 | #endif |
556 | /* Bootstrap interrupt masking and dispatching. */ | | 556 | /* Bootstrap interrupt masking and dispatching. */ |
557 | hp700_intr_bootstrap(); | | 557 | hp700_intr_bootstrap(); |
558 | | | 558 | |
559 | /* | | 559 | /* |
560 | * Initialize any debugger. | | 560 | * Initialize any debugger. |
561 | */ | | 561 | */ |
562 | #ifdef KGDB | | 562 | #ifdef KGDB |
563 | /* | | 563 | /* |
564 | * XXX note that we're not virtual yet, yet these | | 564 | * XXX note that we're not virtual yet, yet these |
565 | * KGDB attach functions will be using bus_space(9) | | 565 | * KGDB attach functions will be using bus_space(9) |
566 | * to map and manipulate their devices. This only | | 566 | * to map and manipulate their devices. This only |
567 | * works because, currently, the mainbus.c bus_space | | 567 | * works because, currently, the mainbus.c bus_space |
568 | * implementation directly-maps things in I/O space. | | 568 | * implementation directly-maps things in I/O space. |
569 | */ | | 569 | */ |
570 | hp700_kgdb_attached = false; | | 570 | hp700_kgdb_attached = false; |
571 | #if NCOM > 0 | | 571 | #if NCOM > 0 |
572 | if (!strcmp(KGDB_DEVNAME, "com")) { | | 572 | if (!strcmp(KGDB_DEVNAME, "com")) { |
573 | int com_gsc_kgdb_attach(void); | | 573 | int com_gsc_kgdb_attach(void); |
574 | if (com_gsc_kgdb_attach() == 0) | | 574 | if (com_gsc_kgdb_attach() == 0) |
575 | hp700_kgdb_attached = true; | | 575 | hp700_kgdb_attached = true; |
576 | } | | 576 | } |
577 | #endif /* NCOM > 0 */ | | 577 | #endif /* NCOM > 0 */ |
578 | #endif /* KGDB */ | | 578 | #endif /* KGDB */ |
579 | | | 579 | |
580 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 580 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
581 | if ((bi_sym = lookup_bootinfo(BTINFO_SYMTAB)) != NULL) | | 581 | if ((bi_sym = lookup_bootinfo(BTINFO_SYMTAB)) != NULL) |
582 | ksyms_addsyms_elf(bi_sym->nsym, (int *)bi_sym->ssym, | | 582 | ksyms_addsyms_elf(bi_sym->nsym, (int *)bi_sym->ssym, |
583 | (int *)bi_sym->esym); | | 583 | (int *)bi_sym->esym); |
584 | else { | | 584 | else { |
585 | extern int end; | | 585 | extern int end; |
586 | | | 586 | |
587 | ksyms_addsyms_elf(esym - (int)&end, &end, (int*)esym); | | 587 | ksyms_addsyms_elf(esym - (int)&end, &end, (int*)esym); |
588 | } | | 588 | } |
589 | #endif | | 589 | #endif |
590 | | | 590 | |
591 | /* We will shortly go virtual. */ | | 591 | /* We will shortly go virtual. */ |
592 | pagezero_mapped = 0; | | 592 | pagezero_mapped = 0; |
593 | fcacheall(); | | 593 | fcacheall(); |
594 | } | | 594 | } |
595 | | | 595 | |
596 | void | | 596 | void |
597 | cpuid(void) | | 597 | cpuid(void) |
598 | { | | 598 | { |
599 | /* | | 599 | /* |
600 | * XXX fredette - much of this TLB trap handler setup should | | 600 | * XXX fredette - much of this TLB trap handler setup should |
601 | * probably be moved here to hppa/hppa/hppa_machdep.c, seeing | | 601 | * probably be moved here to hppa/hppa/hppa_machdep.c, seeing |
602 | * that there's related code already in hppa/hppa/trap.S. | | 602 | * that there's related code already in hppa/hppa/trap.S. |
603 | */ | | 603 | */ |
604 | | | 604 | |
605 | /* | | 605 | /* |
606 | * Ptrs to various tlb handlers, to be filled | | 606 | * Ptrs to various tlb handlers, to be filled |
607 | * based on CPU features. | | 607 | * based on CPU features. |
608 | * from locore.S | | 608 | * from locore.S |
609 | */ | | 609 | */ |
610 | extern u_int trap_ep_T_TLB_DIRTY[]; | | 610 | extern u_int trap_ep_T_TLB_DIRTY[]; |
611 | extern u_int trap_ep_T_DTLBMISS[]; | | 611 | extern u_int trap_ep_T_DTLBMISS[]; |
612 | extern u_int trap_ep_T_DTLBMISSNA[]; | | 612 | extern u_int trap_ep_T_DTLBMISSNA[]; |
613 | extern u_int trap_ep_T_ITLBMISS[]; | | 613 | extern u_int trap_ep_T_ITLBMISS[]; |
614 | extern u_int trap_ep_T_ITLBMISSNA[]; | | 614 | extern u_int trap_ep_T_ITLBMISSNA[]; |
615 | | | 615 | |
616 | struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT; | | 616 | struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT; |
617 | const struct hppa_cpu_info *p = NULL; | | 617 | const struct hppa_cpu_info *p = NULL; |
618 | const char *model; | | 618 | const char *model; |
619 | u_int cpu_version, cpu_features; | | 619 | u_int cpu_version, cpu_features; |
620 | int error; | | 620 | int error; |
621 | extern int kpsw; | | 621 | extern int kpsw; |
622 | | | 622 | |
623 | /* may the scientific guessing begin */ | | 623 | /* may the scientific guessing begin */ |
624 | cpu_type = hpc_unknown; | | 624 | cpu_type = hpc_unknown; |
625 | cpu_features = 0; | | 625 | cpu_features = 0; |
626 | cpu_version = 0; | | 626 | cpu_version = 0; |
627 | | | 627 | |
628 | /* identify system type */ | | 628 | /* identify system type */ |
629 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, | | 629 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, |
630 | &pdc_model)) < 0) { | | 630 | &pdc_model)) < 0) { |
631 | #ifdef DEBUG | | 631 | #ifdef DEBUG |
632 | printf("WARNING: PDC_MODEL_INFO error %d\n", error); | | 632 | printf("WARNING: PDC_MODEL_INFO error %d\n", error); |
633 | #endif | | 633 | #endif |
634 | pdc_model.hvers = 0; | | 634 | pdc_model.hvers = 0; |
635 | } else { | | 635 | } else { |
636 | #ifdef DEBUG | | 636 | #ifdef DEBUG |
637 | printf("pdc_model.hvers %d\n", pdc_model.hvers); | | 637 | printf("pdc_model.hvers %d\n", pdc_model.hvers); |
638 | #endif | | 638 | #endif |
639 | } | | 639 | } |
640 | /* XXXNH - check */ | | 640 | /* XXXNH - check */ |
641 | cpu_hvers = pdc_model.hvers >> 4; | | 641 | cpu_hvers = pdc_model.hvers >> 4; |
642 | model = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers); | | 642 | model = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers); |
643 | #ifdef DEBUG | | 643 | #ifdef DEBUG |
644 | printf("%s: model %s\n", __func__, model); | | 644 | printf("%s: model %s\n", __func__, model); |
645 | #endif | | 645 | #endif |
646 | | | 646 | |
647 | memset(&pdc_cpuid, 0, sizeof(pdc_cpuid)); | | 647 | memset(&pdc_cpuid, 0, sizeof(pdc_cpuid)); |
648 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID, | | 648 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID, |
649 | &pdc_cpuid, 0, 0, 0, 0)) < 0) { | | 649 | &pdc_cpuid, 0, 0, 0, 0)) < 0) { |
650 | #ifdef DEBUG | | 650 | #ifdef DEBUG |
651 | printf("WARNING: PDC_MODEL_CPUID error %d. " | | 651 | printf("WARNING: PDC_MODEL_CPUID error %d. " |
652 | "Using cpu_hvers based cpu_type.\n", error); | | 652 | "Using cpu_hvers based cpu_type.\n", error); |
653 | #endif | | 653 | #endif |
654 | cpu_type = cpu_model_cpuid(cpu_hvers); | | 654 | cpu_type = cpu_model_cpuid(cpu_hvers); |
655 | } else { | | 655 | } else { |
656 | #ifdef DEBUG | | 656 | #ifdef DEBUG |
657 | printf("%s: cpuid.version = %x\n", __func__, | | 657 | printf("%s: cpuid.version = %x\n", __func__, |
658 | pdc_cpuid.version); | | 658 | pdc_cpuid.version); |
659 | printf("%s: cpuid.revision = %x\n", __func__, | | 659 | printf("%s: cpuid.revision = %x\n", __func__, |
660 | pdc_cpuid.revision); | | 660 | pdc_cpuid.revision); |
661 | #endif | | 661 | #endif |
662 | cpu_version = pdc_cpuid.version; | | 662 | cpu_version = pdc_cpuid.version; |
663 | | | 663 | |
664 | /* XXXNH why? */ | | 664 | /* XXXNH why? */ |
665 | /* patch for old 8200 */ | | 665 | /* patch for old 8200 */ |
666 | if (pdc_cpuid.version == HPPA_CPU_PCXU && | | 666 | if (pdc_cpuid.version == HPPA_CPU_PCXU && |
667 | pdc_cpuid.revision > 0x0d) | | 667 | pdc_cpuid.revision > 0x0d) |
668 | cpu_version = HPPA_CPU_PCXUP; | | 668 | cpu_version = HPPA_CPU_PCXUP; |
669 | } | | 669 | } |
670 | | | 670 | |
671 | /* locate coprocessors and SFUs */ | | 671 | /* locate coprocessors and SFUs */ |
672 | memset(&pdc_coproc, 0, sizeof(pdc_coproc)); | | 672 | memset(&pdc_coproc, 0, sizeof(pdc_coproc)); |
673 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, | | 673 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, |
674 | &pdc_coproc, 0, 0, 0, 0)) < 0) { /* XXXNH 0,0,0,0 ???*/ | | 674 | &pdc_coproc, 0, 0, 0, 0)) < 0) { /* XXXNH 0,0,0,0 ???*/ |
675 | printf("WARNING: PDC_COPROC error %d\n", error); | | 675 | printf("WARNING: PDC_COPROC error %d\n", error); |
676 | pdc_coproc.ccr_enable = 0; | | 676 | pdc_coproc.ccr_enable = 0; |
677 | } else { | | 677 | } else { |
678 | #ifdef DEBUG | | 678 | #ifdef DEBUG |
679 | printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n", | | 679 | printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n", |
680 | pdc_coproc.ccr_enable, pdc_coproc.ccr_present, | | 680 | pdc_coproc.ccr_enable, pdc_coproc.ccr_present, |
681 | pdc_coproc.fpu_model, pdc_coproc.fpu_revision); | | 681 | pdc_coproc.fpu_model, pdc_coproc.fpu_revision); |
682 | | | 682 | |
683 | #endif | | 683 | #endif |
684 | /* a kludge to detect PCXW */ | | 684 | /* a kludge to detect PCXW */ |
685 | if (pdc_coproc.fpu_model == HPPA_FPU_PCXW) | | 685 | if (pdc_coproc.fpu_model == HPPA_FPU_PCXW) |
686 | cpu_version = HPPA_CPU_PCXW; | | 686 | cpu_version = HPPA_CPU_PCXW; |
687 | } | | 687 | } |
688 | mtctl(pdc_coproc.ccr_enable & CCR_MASK, CR_CCR); | | 688 | mtctl(pdc_coproc.ccr_enable & CCR_MASK, CR_CCR); |
689 | #ifdef DEBUG | | 689 | #ifdef DEBUG |
690 | printf("%s: bootstrap fpu\n", __func__); | | 690 | printf("%s: bootstrap fpu\n", __func__); |
691 | #endif | | 691 | #endif |
692 | | | 692 | |
693 | usebtlb = 0; | | 693 | usebtlb = 0; |
694 | if (cpu_version == HPPA_CPU_PCXW || cpu_version > HPPA_CPU_PCXL2) { | | 694 | if (cpu_version == HPPA_CPU_PCXW || cpu_version > HPPA_CPU_PCXL2) { |
695 | printf("WARNING: BTLB no supported on cpu %d\n", cpu_version); | | 695 | printf("WARNING: BTLB no supported on cpu %d\n", cpu_version); |
696 | } else { | | 696 | } else { |
697 | | | 697 | |
698 | /* BTLB params */ | | 698 | /* BTLB params */ |
699 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, | | 699 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, |
700 | PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) { | | 700 | PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) { |
701 | #ifdef DEBUG | | 701 | #ifdef DEBUG |
702 | printf("WARNING: PDC_BTLB error %d\n", error); | | 702 | printf("WARNING: PDC_BTLB error %d\n", error); |
703 | #endif | | 703 | #endif |
704 | } else { | | 704 | } else { |
705 | #define BTLBDEBUG 1 | | 705 | #define BTLBDEBUG 1 |
706 | | | 706 | |
707 | #ifdef BTLBDEBUG | | 707 | #ifdef BTLBDEBUG |
708 | printf("btlb info: minsz=%d, maxsz=%d\n", | | 708 | printf("btlb info: minsz=%d, maxsz=%d\n", |
709 | pdc_btlb.min_size, pdc_btlb.max_size); | | 709 | pdc_btlb.min_size, pdc_btlb.max_size); |
710 | printf("btlb fixed: i=%d, d=%d, c=%d\n", | | 710 | printf("btlb fixed: i=%d, d=%d, c=%d\n", |
711 | pdc_btlb.finfo.num_i, | | 711 | pdc_btlb.finfo.num_i, |
712 | pdc_btlb.finfo.num_d, | | 712 | pdc_btlb.finfo.num_d, |
713 | pdc_btlb.finfo.num_c); | | 713 | pdc_btlb.finfo.num_c); |
714 | printf("btlb varbl: i=%d, d=%d, c=%d\n", | | 714 | printf("btlb varbl: i=%d, d=%d, c=%d\n", |
715 | pdc_btlb.vinfo.num_i, | | 715 | pdc_btlb.vinfo.num_i, |
716 | pdc_btlb.vinfo.num_d, | | 716 | pdc_btlb.vinfo.num_d, |
717 | pdc_btlb.vinfo.num_c); | | 717 | pdc_btlb.vinfo.num_c); |
718 | #endif /* BTLBDEBUG */ | | 718 | #endif /* BTLBDEBUG */ |
719 | /* purge TLBs and caches */ | | 719 | /* purge TLBs and caches */ |
720 | if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, | | 720 | if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, |
721 | PDC_BTLB_PURGE_ALL) < 0) | | 721 | PDC_BTLB_PURGE_ALL) < 0) |
722 | printf("WARNING: BTLB purge failed\n"); | | 722 | printf("WARNING: BTLB purge failed\n"); |
723 | | | 723 | |
724 | hppa_btlb_size_min = pdc_btlb.min_size; | | 724 | hppa_btlb_size_min = pdc_btlb.min_size; |
725 | hppa_btlb_size_max = pdc_btlb.max_size; | | 725 | hppa_btlb_size_max = pdc_btlb.max_size; |
726 | #ifdef DEBUG | | 726 | #ifdef DEBUG |
727 | printf("hppa_btlb_size_min 0x%x\n", hppa_btlb_size_min); | | 727 | printf("hppa_btlb_size_min 0x%x\n", hppa_btlb_size_min); |
728 | printf("hppa_btlb_size_max 0x%x\n", hppa_btlb_size_max); | | 728 | printf("hppa_btlb_size_max 0x%x\n", hppa_btlb_size_max); |
729 | #endif | | 729 | #endif |
730 | | | 730 | |
731 | if (pdc_btlb.finfo.num_c) | | 731 | if (pdc_btlb.finfo.num_c) |
732 | cpu_features |= HPPA_FTRS_BTLBU; | | 732 | cpu_features |= HPPA_FTRS_BTLBU; |
733 | usebtlb = 1; | | 733 | usebtlb = 1; |
734 | } | | 734 | } |
735 | } | | 735 | } |
736 | usebtlb = 0; | | 736 | usebtlb = 0; |
737 | | | 737 | |
738 | error = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb); | | 738 | error = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb); |
739 | if (error == 0 && pdc_hwtlb.min_size != 0 && pdc_hwtlb.max_size != 0) { | | 739 | if (error == 0 && pdc_hwtlb.min_size != 0 && pdc_hwtlb.max_size != 0) { |
740 | cpu_features |= HPPA_FTRS_HVT; | | 740 | cpu_features |= HPPA_FTRS_HVT; |
741 | if (pmap_hptsize > pdc_hwtlb.max_size) | | 741 | if (pmap_hptsize > pdc_hwtlb.max_size) |
742 | pmap_hptsize = pdc_hwtlb.max_size; | | 742 | pmap_hptsize = pdc_hwtlb.max_size; |
743 | else if (pmap_hptsize && pmap_hptsize < pdc_hwtlb.min_size) | | 743 | else if (pmap_hptsize && pmap_hptsize < pdc_hwtlb.min_size) |
744 | pmap_hptsize = pdc_hwtlb.min_size; | | 744 | pmap_hptsize = pdc_hwtlb.min_size; |
745 | #ifdef DEBUG | | 745 | #ifdef DEBUG |
746 | printf("%s: pmap_hptsize 0x%x\n", __func__, pmap_hptsize); | | 746 | printf("%s: pmap_hptsize 0x%x\n", __func__, pmap_hptsize); |
747 | #endif | | 747 | #endif |
748 | } else { | | 748 | } else { |
749 | #ifdef DEBUG | | 749 | #ifdef DEBUG |
750 | printf("WARNING: no HPT support, fine!\n"); | | 750 | printf("WARNING: no HPT support, fine!\n"); |
751 | #endif | | 751 | #endif |
752 | pmap_hptsize = 0; | | 752 | pmap_hptsize = 0; |
753 | } | | 753 | } |
754 | | | 754 | |
755 | if (cpu_version) | | 755 | if (cpu_version) |
756 | for (p = cpu_types; p->hci_chip_name; p++) { | | 756 | for (p = cpu_types; p->hci_chip_name; p++) { |
757 | if (p->hci_cpuversion == cpu_version) | | 757 | if (p->hci_cpuversion == cpu_version) |
758 | break; | | 758 | break; |
759 | } | | 759 | } |
760 | else if (cpu_type != hpc_unknown) | | 760 | else if (cpu_type != hpc_unknown) |
761 | for (p = cpu_types; p->hci_chip_name; p++) { | | 761 | for (p = cpu_types; p->hci_chip_name; p++) { |
762 | if (p->hci_cputype == cpu_type) | | 762 | if (p->hci_cputype == cpu_type) |
763 | break; | | 763 | break; |
764 | } | | 764 | } |
765 | else | | 765 | else |
766 | for (p = cpu_types; p->hci_chip_name; p++) { | | 766 | for (p = cpu_types; p->hci_chip_name; p++) { |
767 | if (p->hci_features == cpu_features) | | 767 | if (p->hci_features == cpu_features) |
768 | break; | | 768 | break; |
769 | } | | 769 | } |
770 | | | 770 | |
771 | hppa_cpu_info = p; | | 771 | hppa_cpu_info = p; |
772 | | | 772 | |
773 | if (hppa_cpu_info->hci_chip_name == NULL) | | 773 | if (hppa_cpu_info->hci_chip_name == NULL) |
774 | panic("bad model string for 0x%x", pdc_model.hvers >> 4); | | 774 | panic("bad model string for 0x%x", pdc_model.hvers >> 4); |
775 | else if (hppa_cpu_info->desidhash == NULL) | | 775 | else if (hppa_cpu_info->desidhash == NULL) |
776 | panic("no kernel support for %s", | | 776 | panic("no kernel support for %s", |
777 | hppa_cpu_info->hci_chip_name); | | 777 | hppa_cpu_info->hci_chip_name); |
778 | | | 778 | |
779 | /* | | 779 | /* |
780 | * TODO: HPT on 7200 is not currently supported | | 780 | * TODO: HPT on 7200 is not currently supported |
781 | */ | | 781 | */ |
782 | if (pmap_hptsize && p->hci_cputype != hpcxl && p->hci_cputype != hpcxl2) | | 782 | if (pmap_hptsize && p->hci_cputype != hpcxl && p->hci_cputype != hpcxl2) |
783 | pmap_hptsize = 0; | | 783 | pmap_hptsize = 0; |
784 | | | 784 | |
785 | cpu_type = hppa_cpu_info->hci_cputype; | | 785 | cpu_type = hppa_cpu_info->hci_cputype; |
786 | cpu_ibtlb_ins = hppa_cpu_info->ibtlbins; | | 786 | cpu_ibtlb_ins = hppa_cpu_info->ibtlbins; |
787 | cpu_dbtlb_ins = hppa_cpu_info->dbtlbins; | | 787 | cpu_dbtlb_ins = hppa_cpu_info->dbtlbins; |
788 | cpu_hpt_init = hppa_cpu_info->hptinit; | | 788 | cpu_hpt_init = hppa_cpu_info->hptinit; |
789 | cpu_desidhash = hppa_cpu_info->desidhash; | | 789 | cpu_desidhash = hppa_cpu_info->desidhash; |
790 | | | 790 | |
791 | cpu_revision = (*cpu_desidhash)(); | | 791 | cpu_revision = (*cpu_desidhash)(); |
792 | | | 792 | |
793 | /* force strong ordering for now */ | | 793 | /* force strong ordering for now */ |
794 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) | | 794 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) |
795 | kpsw |= PSW_O; | | 795 | kpsw |= PSW_O; |
796 | | | 796 | |
797 | snprintf(cpu_model, sizeof(cpu_model), "HP9000/%s", model); | | 797 | snprintf(cpu_model, sizeof(cpu_model), "HP9000/%s", model); |
798 | | | 798 | |
799 | #define LDILDO(t,f) ((t)[0] = (f)[0], (t)[1] = (f)[1]); | | 799 | #define LDILDO(t,f) ((t)[0] = (f)[0], (t)[1] = (f)[1]); |
800 | LDILDO(trap_ep_T_TLB_DIRTY , hppa_cpu_info->tlbdh); | | 800 | LDILDO(trap_ep_T_TLB_DIRTY , hppa_cpu_info->tlbdh); |
801 | LDILDO(trap_ep_T_DTLBMISS , hppa_cpu_info->dtlbh); | | 801 | LDILDO(trap_ep_T_DTLBMISS , hppa_cpu_info->dtlbh); |
802 | LDILDO(trap_ep_T_DTLBMISSNA, hppa_cpu_info->dtlbnah); | | 802 | LDILDO(trap_ep_T_DTLBMISSNA, hppa_cpu_info->dtlbnah); |
803 | LDILDO(trap_ep_T_ITLBMISS , hppa_cpu_info->itlbh); | | 803 | LDILDO(trap_ep_T_ITLBMISS , hppa_cpu_info->itlbh); |
804 | LDILDO(trap_ep_T_ITLBMISSNA, hppa_cpu_info->itlbnah); | | 804 | LDILDO(trap_ep_T_ITLBMISSNA, hppa_cpu_info->itlbnah); |
805 | #undef LDILDO | | 805 | #undef LDILDO |
806 | | | 806 | |
807 | /* Bootstrap any FPU. */ | | 807 | /* Bootstrap any FPU. */ |
808 | hppa_fpu_bootstrap(pdc_coproc.ccr_enable); | | 808 | hppa_fpu_bootstrap(pdc_coproc.ccr_enable); |
809 | } | | 809 | } |
810 | | | 810 | |
811 | enum hppa_cpu_type | | 811 | enum hppa_cpu_type |
812 | cpu_model_cpuid(int hvers) | | 812 | cpu_model_cpuid(int hvers) |
813 | { | | 813 | { |
814 | switch (hvers) { | | 814 | switch (hvers) { |
815 | /* no supported HP8xx/9xx models with pcx */ | | 815 | /* no supported HP8xx/9xx models with pcx */ |
816 | case HPPA_BOARD_HP720: | | 816 | case HPPA_BOARD_HP720: |
817 | case HPPA_BOARD_HP750_66: | | 817 | case HPPA_BOARD_HP750_66: |
818 | case HPPA_BOARD_HP730_66: | | 818 | case HPPA_BOARD_HP730_66: |
819 | case HPPA_BOARD_HP710: | | 819 | case HPPA_BOARD_HP710: |
820 | case HPPA_BOARD_HP705: | | 820 | case HPPA_BOARD_HP705: |
821 | return hpcxs; | | 821 | return hpcxs; |
822 | | | 822 | |
823 | case HPPA_BOARD_HP735_99: | | 823 | case HPPA_BOARD_HP735_99: |
824 | case HPPA_BOARD_HP755_99: | | 824 | case HPPA_BOARD_HP755_99: |
825 | case HPPA_BOARD_HP755_125: | | 825 | case HPPA_BOARD_HP755_125: |
826 | case HPPA_BOARD_HP735_130: | | 826 | case HPPA_BOARD_HP735_130: |
827 | case HPPA_BOARD_HP715_50: | | 827 | case HPPA_BOARD_HP715_50: |
828 | case HPPA_BOARD_HP715_33: | | 828 | case HPPA_BOARD_HP715_33: |
829 | case HPPA_BOARD_HP715S_50: | | 829 | case HPPA_BOARD_HP715S_50: |
830 | case HPPA_BOARD_HP715S_33: | | 830 | case HPPA_BOARD_HP715S_33: |
831 | case HPPA_BOARD_HP715T_50: | | 831 | case HPPA_BOARD_HP715T_50: |
832 | case HPPA_BOARD_HP715T_33: | | 832 | case HPPA_BOARD_HP715T_33: |
833 | case HPPA_BOARD_HP715_75: | | 833 | case HPPA_BOARD_HP715_75: |
834 | case HPPA_BOARD_HP715_99: | | 834 | case HPPA_BOARD_HP715_99: |
835 | case HPPA_BOARD_HP725_50: | | 835 | case HPPA_BOARD_HP725_50: |
836 | case HPPA_BOARD_HP725_75: | | 836 | case HPPA_BOARD_HP725_75: |
837 | case HPPA_BOARD_HP725_99: | | 837 | case HPPA_BOARD_HP725_99: |
838 | return hpcxt; | | 838 | return hpcxt; |
839 | } | | 839 | } |
840 | return hpc_unknown; | | 840 | return hpc_unknown; |
841 | } | | 841 | } |
842 | | | 842 | |
843 | void | | 843 | void |
844 | cpu_startup(void) | | 844 | cpu_startup(void) |
845 | { | | 845 | { |
846 | vaddr_t minaddr, maxaddr; | | 846 | vaddr_t minaddr, maxaddr; |
847 | char pbuf[3][9]; | | 847 | char pbuf[3][9]; |
848 | #ifdef PMAPDEBUG | | 848 | #ifdef PMAPDEBUG |
849 | extern int pmapdebug; | | 849 | extern int pmapdebug; |
850 | int opmapdebug = pmapdebug; | | 850 | int opmapdebug = pmapdebug; |
851 | | | 851 | |
852 | pmapdebug = 0; | | 852 | pmapdebug = 0; |
853 | #endif | | 853 | #endif |
854 | /* Initialize the message buffer. */ | | 854 | /* Initialize the message buffer. */ |
855 | initmsgbuf(msgbufaddr, MSGBUFSIZE); | | 855 | initmsgbuf(msgbufaddr, MSGBUFSIZE); |
856 | | | 856 | |
857 | /* | | 857 | /* |
858 | * i won't understand a friend of mine, | | 858 | * i won't understand a friend of mine, |
859 | * who sat in a room full of artificial ice, | | 859 | * who sat in a room full of artificial ice, |
860 | * fogging the air w/ humid cries -- | | 860 | * fogging the air w/ humid cries -- |
861 | * WELCOME TO SUMMER! | | 861 | * WELCOME TO SUMMER! |
862 | */ | | 862 | */ |
863 | printf("%s%s", copyright, version); | | 863 | printf("%s%s", copyright, version); |
864 | | | 864 | |
865 | /* identify system type */ | | 865 | /* identify system type */ |
866 | printf("%s\n", cpu_model); | | 866 | printf("%s\n", cpu_model); |
867 | | | 867 | |
868 | /* Display some memory usage information. */ | | 868 | /* Display some memory usage information. */ |
869 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(physmem)); | | 869 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(physmem)); |
870 | format_bytes(pbuf[1], sizeof(pbuf[1]), ptoa(resvmem)); | | 870 | format_bytes(pbuf[1], sizeof(pbuf[1]), ptoa(resvmem)); |
871 | format_bytes(pbuf[2], sizeof(pbuf[2]), ptoa(availphysmem)); | | 871 | format_bytes(pbuf[2], sizeof(pbuf[2]), ptoa(availphysmem)); |
872 | printf("real mem = %s (%s reserved for PROM, %s used by NetBSD)\n", | | 872 | printf("real mem = %s (%s reserved for PROM, %s used by NetBSD)\n", |
873 | pbuf[0], pbuf[1], pbuf[2]); | | 873 | pbuf[0], pbuf[1], pbuf[2]); |
874 | | | 874 | |
875 | #ifdef DEBUG | | 875 | #ifdef DEBUG |
876 | if (totalphysmem > physmem) { | | 876 | if (totalphysmem > physmem) { |
877 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(totalphysmem - physmem)); | | 877 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(totalphysmem - physmem)); |
878 | printf("lost mem = %s\n", pbuf[0]); | | 878 | printf("lost mem = %s\n", pbuf[0]); |
879 | } | | 879 | } |
880 | #endif | | 880 | #endif |
881 | | | 881 | |
882 | minaddr = 0; | | 882 | minaddr = 0; |
883 | | | 883 | |
884 | /* | | 884 | /* |
885 | * Allocate a submap for physio | | 885 | * Allocate a submap for physio |
886 | */ | | 886 | */ |
887 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 887 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
888 | VM_PHYS_SIZE, 0, false, NULL); | | 888 | VM_PHYS_SIZE, 0, false, NULL); |
889 | | | 889 | |
890 | mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 890 | mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
891 | nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); | | 891 | nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); |
892 | | | 892 | |
893 | #ifdef PMAPDEBUG | | 893 | #ifdef PMAPDEBUG |
894 | pmapdebug = opmapdebug; | | 894 | pmapdebug = opmapdebug; |
895 | #endif | | 895 | #endif |
896 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(uvmexp.free)); | | 896 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(uvmexp.free)); |
897 | printf("avail mem = %s\n", pbuf[0]); | | 897 | printf("avail mem = %s\n", pbuf[0]); |
898 | | | 898 | |
899 | /* | | 899 | /* |
900 | * Allocate a virtual page (for use by /dev/mem) | | 900 | * Allocate a virtual page (for use by /dev/mem) |
901 | * This page is handed to pmap_enter() therefore | | 901 | * This page is handed to pmap_enter() therefore |
902 | * it has to be in the normal kernel VA range. | | 902 | * it has to be in the normal kernel VA range. |
903 | */ | | 903 | */ |
904 | vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | | 904 | vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, |
905 | UVM_KMF_VAONLY | UVM_KMF_WAITVA); | | 905 | UVM_KMF_VAONLY | UVM_KMF_WAITVA); |
906 | | | 906 | |
907 | mutex_init(&vmmap_lock, MUTEX_DEFAULT, IPL_NONE); | | 907 | mutex_init(&vmmap_lock, MUTEX_DEFAULT, IPL_NONE); |
908 | } | | 908 | } |
909 | | | 909 | |
910 | /* | | 910 | /* |
911 | * compute CPU clock ratio such as: | | 911 | * compute CPU clock ratio such as: |
912 | * cpu_ticksnum / cpu_ticksdenom = t + delta | | 912 | * cpu_ticksnum / cpu_ticksdenom = t + delta |
913 | * delta -> 0 | | 913 | * delta -> 0 |
914 | */ | | 914 | */ |
915 | void | | 915 | void |
916 | delay_init(void) | | 916 | delay_init(void) |
917 | { | | 917 | { |
918 | u_int num, denom, delta, mdelta; | | 918 | u_int num, denom, delta, mdelta; |
919 | | | 919 | |
920 | mdelta = UINT_MAX; | | 920 | mdelta = UINT_MAX; |
921 | for (denom = 1; denom < 1000; denom++) { | | 921 | for (denom = 1; denom < 1000; denom++) { |
922 | num = (PAGE0->mem_10msec * denom) / 10000; | | 922 | num = (PAGE0->mem_10msec * denom) / 10000; |
923 | delta = num * 10000 / denom - PAGE0->mem_10msec; | | 923 | delta = num * 10000 / denom - PAGE0->mem_10msec; |
924 | if (!delta) { | | 924 | if (!delta) { |
925 | cpu_ticksdenom = denom; | | 925 | cpu_ticksdenom = denom; |
926 | cpu_ticksnum = num; | | 926 | cpu_ticksnum = num; |
927 | break; | | 927 | break; |
928 | } else if (delta < mdelta) { | | 928 | } else if (delta < mdelta) { |
929 | cpu_ticksdenom = denom; | | 929 | cpu_ticksdenom = denom; |
930 | cpu_ticksnum = num; | | 930 | cpu_ticksnum = num; |
931 | mdelta = delta; | | 931 | mdelta = delta; |
932 | } | | 932 | } |
933 | } | | 933 | } |
934 | } | | 934 | } |
935 | | | 935 | |
936 | void | | 936 | void |
937 | delay(u_int us) | | 937 | delay(u_int us) |
938 | { | | 938 | { |
939 | u_int start, end, n; | | 939 | u_int start, end, n; |
940 | | | 940 | |
941 | mfctl(CR_ITMR, start); | | 941 | mfctl(CR_ITMR, start); |
942 | while (us) { | | 942 | while (us) { |
943 | n = min(1000, us); | | 943 | n = min(1000, us); |
944 | end = start + n * cpu_ticksnum / cpu_ticksdenom; | | 944 | end = start + n * cpu_ticksnum / cpu_ticksdenom; |
945 | | | 945 | |
946 | /* N.B. Interval Timer may wrap around */ | | 946 | /* N.B. Interval Timer may wrap around */ |
947 | if (end < start) | | 947 | if (end < start) |
948 | do | | 948 | do |
949 | mfctl(CR_ITMR, start); | | 949 | mfctl(CR_ITMR, start); |
950 | while (start > end); | | 950 | while (start > end); |
951 | | | 951 | |
952 | do | | 952 | do |
953 | mfctl(CR_ITMR, start); | | 953 | mfctl(CR_ITMR, start); |
954 | while (start < end); | | 954 | while (start < end); |
955 | | | 955 | |
956 | us -= n; | | 956 | us -= n; |
957 | mfctl(CR_ITMR, start); | | 957 | mfctl(CR_ITMR, start); |
958 | } | | 958 | } |
959 | } | | 959 | } |
960 | | | 960 | |
961 | static inline void | | 961 | static inline void |
962 | fall(int c_base, int c_count, int c_loop, int c_stride, int data) | | 962 | fall(int c_base, int c_count, int c_loop, int c_stride, int data) |
963 | { | | 963 | { |
964 | int loop; | | 964 | int loop; |
965 | | | 965 | |
966 | for (; c_count--; c_base += c_stride) | | 966 | for (; c_count--; c_base += c_stride) |
967 | for (loop = c_loop; loop--; ) | | 967 | for (loop = c_loop; loop--; ) |
968 | if (data) | | 968 | if (data) |
969 | fdce(0, c_base); | | 969 | fdce(0, c_base); |
970 | else | | 970 | else |
971 | fice(0, c_base); | | 971 | fice(0, c_base); |
972 | } | | 972 | } |
973 | | | 973 | |
974 | void | | 974 | void |
975 | fcacheall(void) | | 975 | fcacheall(void) |
976 | { | | 976 | { |
977 | /* | | 977 | /* |
978 | * Flush the instruction, then data cache. | | 978 | * Flush the instruction, then data cache. |
979 | */ | | 979 | */ |
980 | fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop, | | 980 | fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop, |
981 | pdc_cache.ic_stride, 0); | | 981 | pdc_cache.ic_stride, 0); |
982 | sync_caches(); | | 982 | sync_caches(); |
983 | fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop, | | 983 | fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop, |
984 | pdc_cache.dc_stride, 1); | | 984 | pdc_cache.dc_stride, 1); |
985 | sync_caches(); | | 985 | sync_caches(); |
986 | } | | 986 | } |
987 | | | 987 | |
988 | void | | 988 | void |
989 | ptlball(void) | | 989 | ptlball(void) |
990 | { | | 990 | { |
991 | pa_space_t sp; | | 991 | pa_space_t sp; |
992 | int i, j, k; | | 992 | int i, j, k; |
993 | | | 993 | |
994 | /* instruction TLB */ | | 994 | /* instruction TLB */ |
995 | sp = pdc_cache.it_sp_base; | | 995 | sp = pdc_cache.it_sp_base; |
996 | for (i = 0; i < pdc_cache.it_sp_count; i++) { | | 996 | for (i = 0; i < pdc_cache.it_sp_count; i++) { |
997 | vaddr_t off = pdc_cache.it_off_base; | | 997 | vaddr_t off = pdc_cache.it_off_base; |
998 | for (j = 0; j < pdc_cache.it_off_count; j++) { | | 998 | for (j = 0; j < pdc_cache.it_off_count; j++) { |
999 | for (k = 0; k < pdc_cache.it_loop; k++) | | 999 | for (k = 0; k < pdc_cache.it_loop; k++) |
1000 | pitlbe(sp, off); | | 1000 | pitlbe(sp, off); |
1001 | off += pdc_cache.it_off_stride; | | 1001 | off += pdc_cache.it_off_stride; |
1002 | } | | 1002 | } |
1003 | sp += pdc_cache.it_sp_stride; | | 1003 | sp += pdc_cache.it_sp_stride; |
1004 | } | | 1004 | } |
1005 | | | 1005 | |
1006 | /* data TLB */ | | 1006 | /* data TLB */ |
1007 | sp = pdc_cache.dt_sp_base; | | 1007 | sp = pdc_cache.dt_sp_base; |
1008 | for (i = 0; i < pdc_cache.dt_sp_count; i++) { | | 1008 | for (i = 0; i < pdc_cache.dt_sp_count; i++) { |
1009 | vaddr_t off = pdc_cache.dt_off_base; | | 1009 | vaddr_t off = pdc_cache.dt_off_base; |
1010 | for (j = 0; j < pdc_cache.dt_off_count; j++) { | | 1010 | for (j = 0; j < pdc_cache.dt_off_count; j++) { |
1011 | for (k = 0; k < pdc_cache.dt_loop; k++) | | 1011 | for (k = 0; k < pdc_cache.dt_loop; k++) |
1012 | pdtlbe(sp, off); | | 1012 | pdtlbe(sp, off); |
1013 | off += pdc_cache.dt_off_stride; | | 1013 | off += pdc_cache.dt_off_stride; |
1014 | } | | 1014 | } |
1015 | sp += pdc_cache.dt_sp_stride; | | 1015 | sp += pdc_cache.dt_sp_stride; |
1016 | } | | 1016 | } |
1017 | } | | 1017 | } |
1018 | | | 1018 | |
1019 | int | | 1019 | int |
1020 | hpti_g(vaddr_t hpt, vsize_t hptsize) | | 1020 | hpti_g(vaddr_t hpt, vsize_t hptsize) |
1021 | { | | 1021 | { |
1022 | | | 1022 | |
1023 | return pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, | | 1023 | return pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, |
1024 | &pdc_hwtlb, hpt, hptsize, PDC_TLB_CURRPDE); | | 1024 | &pdc_hwtlb, hpt, hptsize, PDC_TLB_CURRPDE); |
1025 | } | | 1025 | } |
1026 | | | 1026 | |
1027 | int | | 1027 | int |
1028 | pbtlb_g(int i) | | 1028 | pbtlb_g(int i) |
1029 | { | | 1029 | { |
1030 | return -1; | | 1030 | return -1; |
1031 | } | | 1031 | } |
1032 | | | 1032 | |
1033 | int | | 1033 | int |
1034 | ibtlb_g(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, u_int prot) | | 1034 | ibtlb_g(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, u_int prot) |
1035 | { | | 1035 | { |
1036 | int error; | | 1036 | int error; |
1037 | | | 1037 | |
1038 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, | | 1038 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, |
1039 | sp, va, pa, sz, prot, i)) < 0) { | | 1039 | sp, va, pa, sz, prot, i)) < 0) { |
1040 | #ifdef BTLBDEBUG | | 1040 | #ifdef BTLBDEBUG |
1041 | printf("WARNING: BTLB insert failed (%d)\n", error); | | 1041 | printf("WARNING: BTLB insert failed (%d)\n", error); |
1042 | #endif | | 1042 | #endif |
1043 | } | | 1043 | } |
1044 | return error; | | 1044 | return error; |
1045 | } | | 1045 | } |
1046 | | | 1046 | |
1047 | | | 1047 | |
1048 | /* | | 1048 | /* |
1049 | * This inserts a recorded BTLB slot. | | 1049 | * This inserts a recorded BTLB slot. |
1050 | */ | | 1050 | */ |
1051 | static int _hp700_btlb_insert(struct btlb_slot *); | | 1051 | static int _hp700_btlb_insert(struct btlb_slot *); |
1052 | static int | | 1052 | static int |
1053 | _hp700_btlb_insert(struct btlb_slot *btlb_slot) | | 1053 | _hp700_btlb_insert(struct btlb_slot *btlb_slot) |
1054 | { | | 1054 | { |
1055 | int error; | | 1055 | int error; |
1056 | #ifdef DEBUG | | 1056 | #ifdef DEBUG |
1057 | const char *prot; | | 1057 | const char *prot; |
1058 | | | 1058 | |
1059 | /* Display the protection like a file protection. */ | | 1059 | /* Display the protection like a file protection. */ |
1060 | switch (btlb_slot->btlb_slot_tlbprot & TLB_AR_MASK) { | | 1060 | switch (btlb_slot->btlb_slot_tlbprot & TLB_AR_MASK) { |
1061 | case TLB_AR_NA: prot = "------"; break; | | 1061 | case TLB_AR_NA: prot = "------"; break; |
1062 | case TLB_AR_R: prot = "r-----"; break; | | 1062 | case TLB_AR_R: prot = "r-----"; break; |
1063 | case TLB_AR_RW: prot = "rw----"; break; | | 1063 | case TLB_AR_RW: prot = "rw----"; break; |
1064 | case TLB_AR_RX: prot = "r-x---"; break; | | 1064 | case TLB_AR_RX: prot = "r-x---"; break; |
1065 | case TLB_AR_RWX: prot = "rwx---"; break; | | 1065 | case TLB_AR_RWX: prot = "rwx---"; break; |
1066 | case TLB_AR_R | TLB_USER: prot = "r--r--"; break; | | 1066 | case TLB_AR_R | TLB_USER: prot = "r--r--"; break; |
1067 | case TLB_AR_RW | TLB_USER: prot = "rw-rw-"; break; | | 1067 | case TLB_AR_RW | TLB_USER: prot = "rw-rw-"; break; |
1068 | case TLB_AR_RX | TLB_USER: prot = "r--r-x"; break; | | 1068 | case TLB_AR_RX | TLB_USER: prot = "r--r-x"; break; |
1069 | case TLB_AR_RWX | TLB_USER: prot = "rw-rwx"; break; | | 1069 | case TLB_AR_RWX | TLB_USER: prot = "rw-rwx"; break; |
1070 | default: prot = "??????"; break; | | 1070 | default: prot = "??????"; break; |
1071 | } | | 1071 | } |
1072 | | | 1072 | |
1073 | printf(" [ BTLB slot %d: %s 0x%08x @ 0x%x:0x%08x len 0x%08x prot 0x%08x] ", | | 1073 | printf(" [ BTLB slot %d: %s 0x%08x @ 0x%x:0x%08x len 0x%08x prot 0x%08x] ", |
1074 | btlb_slot->btlb_slot_number, | | 1074 | btlb_slot->btlb_slot_number, |
1075 | prot, | | 1075 | prot, |
1076 | (u_int)btlb_slot->btlb_slot_pa_frame << PGSHIFT, | | 1076 | (u_int)btlb_slot->btlb_slot_pa_frame << PGSHIFT, |
1077 | btlb_slot->btlb_slot_va_space, | | 1077 | btlb_slot->btlb_slot_va_space, |
1078 | (u_int)btlb_slot->btlb_slot_va_frame << PGSHIFT, | | 1078 | (u_int)btlb_slot->btlb_slot_va_frame << PGSHIFT, |
1079 | (u_int)btlb_slot->btlb_slot_frames << PGSHIFT, | | 1079 | (u_int)btlb_slot->btlb_slot_frames << PGSHIFT, |
1080 | btlb_slot->btlb_slot_tlbprot); | | 1080 | btlb_slot->btlb_slot_tlbprot); |
1081 | | | 1081 | |
1082 | /* | | 1082 | /* |
1083 | * Non-I/O space mappings are entered by the pmap, | | 1083 | * Non-I/O space mappings are entered by the pmap, |
1084 | * so we do print a newline to make things look better. | | 1084 | * so we do print a newline to make things look better. |
1085 | */ | | 1085 | */ |
1086 | if (btlb_slot->btlb_slot_pa_frame < (HPPA_IOSPACE >> PGSHIFT)) | | 1086 | if (btlb_slot->btlb_slot_pa_frame < (HPPA_IOSPACE >> PGSHIFT)) |
1087 | printf("\n"); | | 1087 | printf("\n"); |
1088 | #endif | | 1088 | #endif |
1089 | | | 1089 | |
1090 | /* Insert this mapping. */ | | 1090 | /* Insert this mapping. */ |
1091 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, | | 1091 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, |
1092 | btlb_slot->btlb_slot_va_space, | | 1092 | btlb_slot->btlb_slot_va_space, |
1093 | btlb_slot->btlb_slot_va_frame, | | 1093 | btlb_slot->btlb_slot_va_frame, |
1094 | btlb_slot->btlb_slot_pa_frame, | | 1094 | btlb_slot->btlb_slot_pa_frame, |
1095 | btlb_slot->btlb_slot_frames, | | 1095 | btlb_slot->btlb_slot_frames, |
1096 | btlb_slot->btlb_slot_tlbprot, | | 1096 | btlb_slot->btlb_slot_tlbprot, |
1097 | btlb_slot->btlb_slot_number)) < 0) { | | 1097 | btlb_slot->btlb_slot_number)) < 0) { |
1098 | #ifdef BTLBDEBUG | | 1098 | #ifdef BTLBDEBUG |
1099 | printf("WARNING: BTLB insert failed (%d)\n", error); | | 1099 | printf("WARNING: BTLB insert failed (%d)\n", error); |
1100 | #endif | | 1100 | #endif |
1101 | } | | 1101 | } |
1102 | return (error ? EINVAL : 0); | | 1102 | return (error ? EINVAL : 0); |
1103 | } | | 1103 | } |
1104 | | | 1104 | |
1105 | /* | | 1105 | /* |
1106 | * This records and inserts a new BTLB entry. | | 1106 | * This records and inserts a new BTLB entry. |
1107 | */ | | 1107 | */ |
1108 | int | | 1108 | int |
1109 | hppa_btlb_insert(pa_space_t space, vaddr_t va, paddr_t pa, vsize_t *sizep, | | 1109 | hppa_btlb_insert(pa_space_t space, vaddr_t va, paddr_t pa, vsize_t *sizep, |
1110 | u_int tlbprot) | | 1110 | u_int tlbprot) |
1111 | { | | 1111 | { |
1112 | struct btlb_slot *btlb_slot, *btlb_slot_best, *btlb_slot_end; | | 1112 | struct btlb_slot *btlb_slot, *btlb_slot_best, *btlb_slot_end; |
1113 | vsize_t frames; | | 1113 | vsize_t frames; |
1114 | int error; | | 1114 | int error; |
1115 | int need_dbtlb, need_ibtlb, need_variable_range; | | 1115 | int need_dbtlb, need_ibtlb, need_variable_range; |
1116 | int btlb_slot_score, btlb_slot_best_score; | | 1116 | int btlb_slot_score, btlb_slot_best_score; |
1117 | vsize_t slot_mapped_frames, total_mapped_frames; | | 1117 | vsize_t slot_mapped_frames, total_mapped_frames; |
1118 | | | 1118 | |
1119 | /* | | 1119 | /* |
1120 | * All entries need data translation. Those that | | 1120 | * All entries need data translation. Those that |
1121 | * allow execution also need instruction translation. | | 1121 | * allow execution also need instruction translation. |
1122 | */ | | 1122 | */ |
1123 | switch (tlbprot & TLB_AR_MASK) { | | 1123 | switch (tlbprot & TLB_AR_MASK) { |
1124 | case TLB_AR_R: | | 1124 | case TLB_AR_R: |
1125 | case TLB_AR_RW: | | 1125 | case TLB_AR_RW: |
1126 | case TLB_AR_R | TLB_USER: | | 1126 | case TLB_AR_R | TLB_USER: |
1127 | case TLB_AR_RW | TLB_USER: | | 1127 | case TLB_AR_RW | TLB_USER: |
1128 | need_dbtlb = true; | | 1128 | need_dbtlb = true; |
1129 | need_ibtlb = false; | | 1129 | need_ibtlb = false; |
1130 | break; | | 1130 | break; |
1131 | case TLB_AR_RX: | | 1131 | case TLB_AR_RX: |
1132 | case TLB_AR_RWX: | | 1132 | case TLB_AR_RWX: |
1133 | case TLB_AR_RX | TLB_USER: | | 1133 | case TLB_AR_RX | TLB_USER: |
1134 | case TLB_AR_RWX | TLB_USER: | | 1134 | case TLB_AR_RWX | TLB_USER: |
1135 | need_dbtlb = true; | | 1135 | need_dbtlb = true; |
1136 | need_ibtlb = true; | | 1136 | need_ibtlb = true; |
1137 | break; | | 1137 | break; |
1138 | default: | | 1138 | default: |
1139 | panic("btlb_insert: bad tlbprot"); | | 1139 | panic("btlb_insert: bad tlbprot"); |
1140 | } | | 1140 | } |
1141 | | | 1141 | |
1142 | /* | | 1142 | /* |
1143 | * If this entry isn't aligned to the size required | | 1143 | * If this entry isn't aligned to the size required |
1144 | * for a fixed-range slot, it requires a variable-range | | 1144 | * for a fixed-range slot, it requires a variable-range |
1145 | * slot. This also converts pa and va to page frame | | 1145 | * slot. This also converts pa and va to page frame |
1146 | * numbers. | | 1146 | * numbers. |
1147 | */ | | 1147 | */ |
1148 | frames = pdc_btlb.min_size << PGSHIFT; | | 1148 | frames = pdc_btlb.min_size << PGSHIFT; |
1149 | while (frames < *sizep) | | 1149 | while (frames < *sizep) |
1150 | frames <<= 1; | | 1150 | frames <<= 1; |
1151 | frames >>= PGSHIFT; | | 1151 | frames >>= PGSHIFT; |
1152 | if (frames > pdc_btlb.max_size) { | | 1152 | if (frames > pdc_btlb.max_size) { |
1153 | #ifdef BTLBDEBUG | | 1153 | #ifdef BTLBDEBUG |
1154 | printf("btlb_insert: too big (%u < %u < %u)\n", | | 1154 | printf("btlb_insert: too big (%u < %u < %u)\n", |
1155 | pdc_btlb.min_size, (u_int) frames, pdc_btlb.max_size); | | 1155 | pdc_btlb.min_size, (u_int) frames, pdc_btlb.max_size); |
1156 | #endif | | 1156 | #endif |
1157 | return -(ENOMEM); | | 1157 | return -(ENOMEM); |
1158 | } | | 1158 | } |
1159 | pa >>= PGSHIFT; | | 1159 | pa >>= PGSHIFT; |
1160 | va >>= PGSHIFT; | | 1160 | va >>= PGSHIFT; |
1161 | need_variable_range = | | 1161 | need_variable_range = |
1162 | ((pa & (frames - 1)) != 0 || (va & (frames - 1)) != 0); | | 1162 | ((pa & (frames - 1)) != 0 || (va & (frames - 1)) != 0); |
1163 | | | 1163 | |
1164 | /* I/O space must be mapped uncached. */ | | 1164 | /* I/O space must be mapped uncached. */ |
1165 | if (pa >= HPPA_IOBEGIN) | | 1165 | if (pa >= HPPA_IOBEGIN) |
1166 | tlbprot |= TLB_UNCACHEABLE; | | 1166 | tlbprot |= TLB_UNCACHEABLE; |
1167 | | | 1167 | |
1168 | /* | | 1168 | /* |
1169 | * Loop while we still need slots. | | 1169 | * Loop while we still need slots. |
1170 | */ | | 1170 | */ |
1171 | btlb_slot_end = btlb_slots + btlb_slots_count; | | 1171 | btlb_slot_end = btlb_slots + btlb_slots_count; |
1172 | total_mapped_frames = 0; | | 1172 | total_mapped_frames = 0; |
1173 | btlb_slot_best_score = 0; | | 1173 | btlb_slot_best_score = 0; |
1174 | while (need_dbtlb || need_ibtlb) { | | 1174 | while (need_dbtlb || need_ibtlb) { |
1175 | | | 1175 | |
1176 | /* | | 1176 | /* |
1177 | * Find an applicable slot. | | 1177 | * Find an applicable slot. |
1178 | */ | | 1178 | */ |
1179 | btlb_slot_best = NULL; | | 1179 | btlb_slot_best = NULL; |
1180 | for (btlb_slot = btlb_slots; | | 1180 | for (btlb_slot = btlb_slots; |
1181 | btlb_slot < btlb_slot_end; | | 1181 | btlb_slot < btlb_slot_end; |
1182 | btlb_slot++) { | | 1182 | btlb_slot++) { |
1183 | | | 1183 | |
1184 | /* | | 1184 | /* |
1185 | * Skip this slot if it's in use, or if we need a | | 1185 | * Skip this slot if it's in use, or if we need a |
1186 | * variable-range slot and this isn't one. | | 1186 | * variable-range slot and this isn't one. |
1187 | */ | | 1187 | */ |
1188 | if (btlb_slot->btlb_slot_frames != 0 || | | 1188 | if (btlb_slot->btlb_slot_frames != 0 || |
1189 | (need_variable_range && | | 1189 | (need_variable_range && |
1190 | !(btlb_slot->btlb_slot_flags & | | 1190 | !(btlb_slot->btlb_slot_flags & |
1191 | BTLB_SLOT_VARIABLE_RANGE))) | | 1191 | BTLB_SLOT_VARIABLE_RANGE))) |
1192 | continue; | | 1192 | continue; |
1193 | | | 1193 | |
1194 | /* | | 1194 | /* |
1195 | * Score this slot. | | 1195 | * Score this slot. |
1196 | */ | | 1196 | */ |
1197 | btlb_slot_score = 0; | | 1197 | btlb_slot_score = 0; |
1198 | if (need_dbtlb && | | 1198 | if (need_dbtlb && |
1199 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB)) | | 1199 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB)) |
1200 | btlb_slot_score++; | | 1200 | btlb_slot_score++; |
1201 | if (need_ibtlb && | | 1201 | if (need_ibtlb && |
1202 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB)) | | 1202 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB)) |
1203 | btlb_slot_score++; | | 1203 | btlb_slot_score++; |
1204 | | | 1204 | |
1205 | /* | | 1205 | /* |
1206 | * Update the best slot. | | 1206 | * Update the best slot. |
1207 | */ | | 1207 | */ |
1208 | if (btlb_slot_score > 0 && | | 1208 | if (btlb_slot_score > 0 && |
1209 | (btlb_slot_best == NULL || | | 1209 | (btlb_slot_best == NULL || |
1210 | btlb_slot_score > btlb_slot_best_score)) { | | 1210 | btlb_slot_score > btlb_slot_best_score)) { |
1211 | btlb_slot_best = btlb_slot; | | 1211 | btlb_slot_best = btlb_slot; |
1212 | btlb_slot_best_score = btlb_slot_score; | | 1212 | btlb_slot_best_score = btlb_slot_score; |
1213 | } | | 1213 | } |
1214 | } | | 1214 | } |
1215 | | | 1215 | |
1216 | /* | | 1216 | /* |
1217 | * If there were no applicable slots. | | 1217 | * If there were no applicable slots. |
1218 | */ | | 1218 | */ |
1219 | if (btlb_slot_best == NULL) { | | 1219 | if (btlb_slot_best == NULL) { |
1220 | #ifdef BTLBDEBUG | | 1220 | #ifdef BTLBDEBUG |
1221 | printf("BTLB full\n"); | | 1221 | printf("BTLB full\n"); |
1222 | #endif | | 1222 | #endif |
1223 | return -(ENOMEM); | | 1223 | return -(ENOMEM); |
1224 | } | | 1224 | } |
1225 | | | 1225 | |
1226 | /* | | 1226 | /* |
1227 | * Now fill this BTLB slot record and insert the entry. | | 1227 | * Now fill this BTLB slot record and insert the entry. |
1228 | */ | | 1228 | */ |
1229 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_VARIABLE_RANGE) | | 1229 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_VARIABLE_RANGE) |
1230 | slot_mapped_frames = ((*sizep + PGOFSET) >> PGSHIFT); | | 1230 | slot_mapped_frames = ((*sizep + PGOFSET) >> PGSHIFT); |
1231 | else | | 1231 | else |
1232 | slot_mapped_frames = frames; | | 1232 | slot_mapped_frames = frames; |
1233 | if (slot_mapped_frames > total_mapped_frames) | | 1233 | if (slot_mapped_frames > total_mapped_frames) |
1234 | total_mapped_frames = slot_mapped_frames; | | 1234 | total_mapped_frames = slot_mapped_frames; |
1235 | btlb_slot = btlb_slot_best; | | 1235 | btlb_slot = btlb_slot_best; |
1236 | btlb_slot->btlb_slot_va_space = space; | | 1236 | btlb_slot->btlb_slot_va_space = space; |
1237 | btlb_slot->btlb_slot_va_frame = va; | | 1237 | btlb_slot->btlb_slot_va_frame = va; |
1238 | btlb_slot->btlb_slot_pa_frame = pa; | | 1238 | btlb_slot->btlb_slot_pa_frame = pa; |
1239 | btlb_slot->btlb_slot_tlbprot = tlbprot; | | 1239 | btlb_slot->btlb_slot_tlbprot = tlbprot; |
1240 | btlb_slot->btlb_slot_frames = slot_mapped_frames; | | 1240 | btlb_slot->btlb_slot_frames = slot_mapped_frames; |
1241 | error = _hp700_btlb_insert(btlb_slot); | | 1241 | error = _hp700_btlb_insert(btlb_slot); |
1242 | if (error) | | 1242 | if (error) |
1243 | return -error; | | 1243 | return -error; |
1244 | /* | | 1244 | /* |
1245 | * Note what slots we no longer need. | | 1245 | * Note what slots we no longer need. |
1246 | */ | | 1246 | */ |
1247 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB) | | 1247 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB) |
1248 | need_dbtlb = false; | | 1248 | need_dbtlb = false; |
1249 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB) | | 1249 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB) |
1250 | need_ibtlb = false; | | 1250 | need_ibtlb = false; |
1251 | } | | 1251 | } |
1252 | | | 1252 | |
1253 | /* Success. */ | | 1253 | /* Success. */ |
1254 | *sizep = (total_mapped_frames << PGSHIFT); | | 1254 | *sizep = (total_mapped_frames << PGSHIFT); |
1255 | return 0; | | 1255 | return 0; |
1256 | } | | 1256 | } |
1257 | | | 1257 | |
1258 | /* | | 1258 | /* |
1259 | * This reloads the BTLB in the event that it becomes invalidated. | | 1259 | * This reloads the BTLB in the event that it becomes invalidated. |
1260 | */ | | 1260 | */ |
1261 | int | | 1261 | int |
1262 | hppa_btlb_reload(void) | | 1262 | hppa_btlb_reload(void) |
1263 | { | | 1263 | { |
1264 | struct btlb_slot *btlb_slot, *btlb_slot_end; | | 1264 | struct btlb_slot *btlb_slot, *btlb_slot_end; |
1265 | int error; | | 1265 | int error; |
1266 | | | 1266 | |
1267 | /* Insert all recorded BTLB entries. */ | | 1267 | /* Insert all recorded BTLB entries. */ |
1268 | btlb_slot = btlb_slots; | | 1268 | btlb_slot = btlb_slots; |
1269 | btlb_slot_end = btlb_slots + btlb_slots_count; | | 1269 | btlb_slot_end = btlb_slots + btlb_slots_count; |
1270 | error = 0; | | 1270 | error = 0; |
1271 | while (error == 0 && btlb_slot < btlb_slot_end) { | | 1271 | while (error == 0 && btlb_slot < btlb_slot_end) { |
1272 | if (btlb_slot->btlb_slot_frames != 0) | | 1272 | if (btlb_slot->btlb_slot_frames != 0) |
1273 | error = _hp700_btlb_insert(btlb_slot); | | 1273 | error = _hp700_btlb_insert(btlb_slot); |
1274 | btlb_slot++; | | 1274 | btlb_slot++; |
1275 | } | | 1275 | } |
1276 | #ifdef DEBUG | | 1276 | #ifdef DEBUG |
1277 | printf("\n"); | | 1277 | printf("\n"); |
1278 | #endif | | 1278 | #endif |
1279 | return (error); | | 1279 | return (error); |
1280 | } | | 1280 | } |
1281 | | | 1281 | |
1282 | /* | | 1282 | /* |
1283 | * This purges a BTLB entry. | | 1283 | * This purges a BTLB entry. |
1284 | */ | | 1284 | */ |
1285 | int | | 1285 | int |
1286 | hppa_btlb_purge(pa_space_t space, vaddr_t va, vsize_t *sizep) | | 1286 | hppa_btlb_purge(pa_space_t space, vaddr_t va, vsize_t *sizep) |
1287 | { | | 1287 | { |
1288 | struct btlb_slot *btlb_slot, *btlb_slot_end; | | 1288 | struct btlb_slot *btlb_slot, *btlb_slot_end; |
1289 | int error; | | 1289 | int error; |
1290 | | | 1290 | |
1291 | /* | | 1291 | /* |
1292 | * Purge all slots that map this virtual address. | | 1292 | * Purge all slots that map this virtual address. |
1293 | */ | | 1293 | */ |
1294 | error = ENOENT; | | 1294 | error = ENOENT; |
1295 | va >>= PGSHIFT; | | 1295 | va >>= PGSHIFT; |
1296 | btlb_slot_end = btlb_slots + btlb_slots_count; | | 1296 | btlb_slot_end = btlb_slots + btlb_slots_count; |
1297 | for (btlb_slot = btlb_slots; | | 1297 | for (btlb_slot = btlb_slots; |
1298 | btlb_slot < btlb_slot_end; | | 1298 | btlb_slot < btlb_slot_end; |
1299 | btlb_slot++) { | | 1299 | btlb_slot++) { |
1300 | if (btlb_slot->btlb_slot_frames != 0 && | | 1300 | if (btlb_slot->btlb_slot_frames != 0 && |
1301 | btlb_slot->btlb_slot_va_space == space && | | 1301 | btlb_slot->btlb_slot_va_space == space && |
1302 | btlb_slot->btlb_slot_va_frame == va) { | | 1302 | btlb_slot->btlb_slot_va_frame == va) { |
1303 | if ((error = pdc_call((iodcio_t)pdc, 0, | | 1303 | if ((error = pdc_call((iodcio_t)pdc, 0, |
1304 | PDC_BLOCK_TLB, PDC_BTLB_PURGE, | | 1304 | PDC_BLOCK_TLB, PDC_BTLB_PURGE, |
1305 | btlb_slot->btlb_slot_va_space, | | 1305 | btlb_slot->btlb_slot_va_space, |
1306 | btlb_slot->btlb_slot_va_frame, | | 1306 | btlb_slot->btlb_slot_va_frame, |
1307 | btlb_slot->btlb_slot_number, | | 1307 | btlb_slot->btlb_slot_number, |
1308 | btlb_slot->btlb_slot_frames)) < 0) { | | 1308 | btlb_slot->btlb_slot_frames)) < 0) { |
1309 | #ifdef BTLBDEBUG | | 1309 | #ifdef BTLBDEBUG |
1310 | printf("WARNING: BTLB purge failed (%d)\n", | | 1310 | printf("WARNING: BTLB purge failed (%d)\n", |
1311 | error); | | 1311 | error); |
1312 | #endif | | 1312 | #endif |
1313 | return (error); | | 1313 | return (error); |
1314 | } | | 1314 | } |
1315 | | | 1315 | |
1316 | /* | | 1316 | /* |
1317 | * Tell our caller how many bytes were mapped | | 1317 | * Tell our caller how many bytes were mapped |
1318 | * by this slot, then free the slot. | | 1318 | * by this slot, then free the slot. |
1319 | */ | | 1319 | */ |
1320 | *sizep = (btlb_slot->btlb_slot_frames << PGSHIFT); | | 1320 | *sizep = (btlb_slot->btlb_slot_frames << PGSHIFT); |
1321 | btlb_slot->btlb_slot_frames = 0; | | 1321 | btlb_slot->btlb_slot_frames = 0; |
1322 | } | | 1322 | } |
1323 | } | | 1323 | } |
1324 | return (error); | | 1324 | return (error); |
1325 | } | | 1325 | } |
1326 | | | 1326 | |
1327 | /* | | 1327 | /* |
1328 | * This maps page zero if it isn't already mapped, and | | 1328 | * This maps page zero if it isn't already mapped, and |
1329 | * returns a cookie for hp700_pagezero_unmap. | | 1329 | * returns a cookie for hp700_pagezero_unmap. |
1330 | */ | | 1330 | */ |
1331 | int | | 1331 | int |
1332 | hp700_pagezero_map(void) | | 1332 | hp700_pagezero_map(void) |
1333 | { | | 1333 | { |
1334 | int was_mapped_before; | | 1334 | int was_mapped_before; |
1335 | int s; | | 1335 | int s; |
1336 | | | 1336 | |
1337 | was_mapped_before = pagezero_mapped; | | 1337 | was_mapped_before = pagezero_mapped; |
1338 | if (!was_mapped_before) { | | 1338 | if (!was_mapped_before) { |
1339 | s = splhigh(); | | 1339 | s = splhigh(); |
1340 | pmap_kenter_pa(0, 0, VM_PROT_ALL, 0); | | 1340 | pmap_kenter_pa(0, 0, VM_PROT_ALL, 0); |
1341 | pagezero_mapped = 1; | | 1341 | pagezero_mapped = 1; |
1342 | splx(s); | | 1342 | splx(s); |
1343 | } | | 1343 | } |
1344 | return (was_mapped_before); | | 1344 | return (was_mapped_before); |
1345 | } | | 1345 | } |
1346 | | | 1346 | |
1347 | /* | | 1347 | /* |
1348 | * This unmaps mape zero, given a cookie previously returned | | 1348 | * This unmaps mape zero, given a cookie previously returned |
1349 | * by hp700_pagezero_map. | | 1349 | * by hp700_pagezero_map. |
1350 | */ | | 1350 | */ |
1351 | void | | 1351 | void |
1352 | hp700_pagezero_unmap(int was_mapped_before) | | 1352 | hp700_pagezero_unmap(int was_mapped_before) |
1353 | { | | 1353 | { |
1354 | int s; | | 1354 | int s; |
1355 | | | 1355 | |
1356 | if (!was_mapped_before) { | | 1356 | if (!was_mapped_before) { |
1357 | s = splhigh(); | | 1357 | s = splhigh(); |
1358 | pmap_kremove(0, PAGE_SIZE); | | 1358 | pmap_kremove(0, PAGE_SIZE); |
1359 | pagezero_mapped = 0; | | 1359 | pagezero_mapped = 0; |
1360 | splx(s); | | 1360 | splx(s); |
1361 | } | | 1361 | } |
1362 | } | | 1362 | } |
1363 | | | 1363 | |
1364 | int waittime = -1; | | 1364 | int waittime = -1; |
1365 | | | 1365 | |
1366 | __dead void | | 1366 | __dead void |
1367 | cpu_reboot(int howto, char *user_boot_string) | | 1367 | cpu_reboot(int howto, char *user_boot_string) |
1368 | { | | 1368 | { |
1369 | boothowto = howto | (boothowto & RB_HALT); | | 1369 | boothowto = howto | (boothowto & RB_HALT); |
1370 | | | 1370 | |
1371 | if (!(howto & RB_NOSYNC) && waittime < 0) { | | 1371 | if (!(howto & RB_NOSYNC) && waittime < 0) { |
1372 | waittime = 0; | | 1372 | waittime = 0; |
1373 | vfs_shutdown(); | | 1373 | vfs_shutdown(); |
1374 | | | 1374 | |
1375 | /* | | 1375 | /* |
1376 | * If we've been adjusting the clock, the todr | | 1376 | * If we've been adjusting the clock, the todr |
1377 | * will be out of synch; adjust it now. | | 1377 | * will be out of synch; adjust it now. |
1378 | */ | | 1378 | */ |
1379 | resettodr(); | | 1379 | resettodr(); |
1380 | } | | 1380 | } |
1381 | | | 1381 | |
1382 | /* XXX probably save howto into stable storage */ | | 1382 | /* XXX probably save howto into stable storage */ |
1383 | | | 1383 | |
1384 | /* Disable interrupts. */ | | 1384 | /* Disable interrupts. */ |
1385 | splhigh(); | | 1385 | splhigh(); |
1386 | | | 1386 | |
1387 | /* Make a crash dump. */ | | 1387 | /* Make a crash dump. */ |
1388 | if (howto & RB_DUMP) | | 1388 | if (howto & RB_DUMP) |
1389 | dumpsys(); | | 1389 | dumpsys(); |
1390 | | | 1390 | |
1391 | /* Run any shutdown hooks. */ | | 1391 | /* Run any shutdown hooks. */ |
1392 | doshutdownhooks(); | | 1392 | doshutdownhooks(); |
1393 | | | 1393 | |
1394 | pmf_system_shutdown(boothowto); | | 1394 | pmf_system_shutdown(boothowto); |
1395 | | | 1395 | |
1396 | /* in case we came on powerfail interrupt */ | | 1396 | /* in case we came on powerfail interrupt */ |
1397 | if (cold_hook) | | 1397 | if (cold_hook) |
1398 | (*cold_hook)(HPPA_COLD_COLD); | | 1398 | (*cold_hook)(HPPA_COLD_COLD); |
1399 | | | 1399 | |
1400 | if (howto & RB_HALT) { | | 1400 | if (howto & RB_HALT) { |
1401 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN && cold_hook) { | | 1401 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN && cold_hook) { |
1402 | printf("Powering off..."); | | 1402 | printf("Powering off..."); |
1403 | DELAY(1000000); | | 1403 | DELAY(1000000); |
1404 | (*cold_hook)(HPPA_COLD_OFF); | | 1404 | (*cold_hook)(HPPA_COLD_OFF); |
1405 | DELAY(1000000); | | 1405 | DELAY(1000000); |
1406 | } | | 1406 | } |
1407 | | | 1407 | |
1408 | printf("System halted!\n"); | | 1408 | printf("System halted!\n"); |
1409 | DELAY(1000000); | | 1409 | DELAY(1000000); |
1410 | __asm volatile("stwas %0, 0(%1)" | | 1410 | __asm volatile("stwas %0, 0(%1)" |
1411 | :: "r" (CMD_STOP), "r" (LBCAST_ADDR + iomod_command)); | | 1411 | :: "r" (CMD_STOP), "r" (LBCAST_ADDR + iomod_command)); |
1412 | } else { | | 1412 | } else { |
1413 | printf("rebooting..."); | | 1413 | printf("rebooting..."); |
1414 | DELAY(1000000); | | 1414 | DELAY(1000000); |
1415 | __asm volatile("stwas %0, 0(%1)" | | 1415 | __asm volatile("stwas %0, 0(%1)" |
1416 | :: "r" (CMD_RESET), "r" (LBCAST_ADDR + iomod_command)); | | 1416 | :: "r" (CMD_RESET), "r" (LBCAST_ADDR + iomod_command)); |
1417 | | | 1417 | |
1418 | /* ask firmware to reset */ | | 1418 | /* ask firmware to reset */ |
1419 | pdc_call((iodcio_t)pdc, 0, PDC_BROADCAST_RESET, PDC_DO_RESET); | | 1419 | pdc_call((iodcio_t)pdc, 0, PDC_BROADCAST_RESET, PDC_DO_RESET); |
1420 | /* forcably reset module if that fails */ | | 1420 | /* forcably reset module if that fails */ |
1421 | __asm __volatile("stwas %0, 0(%1)" | | 1421 | __asm __volatile("stwas %0, 0(%1)" |
1422 | :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command)); | | 1422 | :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command)); |
1423 | } | | 1423 | } |
1424 | | | 1424 | |
1425 | for (;;) | | 1425 | for (;;) |
1426 | /* loop while bus reset is coming up */ ; | | 1426 | /* loop while bus reset is coming up */ ; |
1427 | /* NOTREACHED */ | | 1427 | /* NOTREACHED */ |
1428 | } | | 1428 | } |
1429 | | | 1429 | |
1430 | u_int32_t dumpmag = 0x8fca0101; /* magic number */ | | 1430 | u_int32_t dumpmag = 0x8fca0101; /* magic number */ |
1431 | int dumpsize = 0; /* pages */ | | 1431 | int dumpsize = 0; /* pages */ |
1432 | long dumplo = 0; /* blocks */ | | 1432 | long dumplo = 0; /* blocks */ |
1433 | | | 1433 | |
1434 | /* | | 1434 | /* |
1435 | * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. | | 1435 | * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. |
1436 | */ | | 1436 | */ |
1437 | int | | 1437 | int |
1438 | cpu_dumpsize(void) | | 1438 | cpu_dumpsize(void) |
1439 | { | | 1439 | { |
1440 | int size; | | 1440 | int size; |
1441 | | | 1441 | |
1442 | size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); | | 1442 | size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); |
1443 | if (roundup(size, dbtob(1)) != dbtob(1)) | | 1443 | if (roundup(size, dbtob(1)) != dbtob(1)) |
1444 | return -1; | | 1444 | return -1; |
1445 | | | 1445 | |
1446 | return 1; | | 1446 | return 1; |
1447 | } | | 1447 | } |
1448 | | | 1448 | |
1449 | /* | | 1449 | /* |
1450 | * This handles a machine check. This can be either an HPMC, | | 1450 | * This handles a machine check. This can be either an HPMC, |
1451 | * an LPMC, or a TOC. The check type is passed in as a trap | | 1451 | * an LPMC, or a TOC. The check type is passed in as a trap |
1452 | * type, one of T_HPMC, T_LPMC, or T_INTERRUPT (for TOC). | | 1452 | * type, one of T_HPMC, T_LPMC, or T_INTERRUPT (for TOC). |
1453 | */ | | 1453 | */ |
1454 | static char pim_data_buffer[896] __attribute__((__aligned__(8))); | | 1454 | static char pim_data_buffer[896] __attribute__((__aligned__(8))); |
1455 | static char in_check = 0; | | 1455 | static char in_check = 0; |
1456 | | | 1456 | |
1457 | #define PIM_WORD(name, word, bits) \ | | 1457 | #define PIM_WORD(name, word, bits) \ |
1458 | do { \ | | 1458 | do { \ |
1459 | snprintb(bitmask_buffer, sizeof(bitmask_buffer),\ | | 1459 | snprintb(bitmask_buffer, sizeof(bitmask_buffer),\ |
1460 | bits, word); \ | | 1460 | bits, word); \ |
1461 | printf("%s %s", name, bitmask_buffer); \ | | 1461 | printf("%s %s", name, bitmask_buffer); \ |
1462 | } while (/* CONSTCOND */ 0) | | 1462 | } while (/* CONSTCOND */ 0) |
1463 | | | 1463 | |
1464 | | | 1464 | |
1465 | static inline void | | 1465 | static inline void |
1466 | hppa_pim_dump(int check_type) | | 1466 | hppa_pim_dump(int check_type) |
1467 | { | | 1467 | { |
1468 | struct hp700_pim_hpmc *hpmc; | | 1468 | struct hp700_pim_hpmc *hpmc; |
1469 | struct hp700_pim_lpmc *lpmc; | | 1469 | struct hp700_pim_lpmc *lpmc; |
1470 | struct hp700_pim_toc *toc; | | 1470 | struct hp700_pim_toc *toc; |
1471 | struct hp700_pim_regs *regs; | | 1471 | struct hp700_pim_regs *regs; |
1472 | struct hp700_pim_checks *checks; | | 1472 | struct hp700_pim_checks *checks; |
1473 | u_int *regarray; | | 1473 | u_int *regarray; |
1474 | int reg_i, reg_j, reg_k; | | 1474 | int reg_i, reg_j, reg_k; |
1475 | char bitmask_buffer[64]; | | 1475 | char bitmask_buffer[64]; |
1476 | const char *name; | | 1476 | const char *name; |
1477 | | | 1477 | |
1478 | regs = NULL; | | 1478 | regs = NULL; |
1479 | checks = NULL; | | 1479 | checks = NULL; |
1480 | switch (check_type) { | | 1480 | switch (check_type) { |
1481 | case T_HPMC: | | 1481 | case T_HPMC: |
1482 | hpmc = (struct hp700_pim_hpmc *) pim_data_buffer; | | 1482 | hpmc = (struct hp700_pim_hpmc *) pim_data_buffer; |
1483 | regs = &hpmc->pim_hpmc_regs; | | 1483 | regs = &hpmc->pim_hpmc_regs; |
1484 | checks = &hpmc->pim_hpmc_checks; | | 1484 | checks = &hpmc->pim_hpmc_checks; |
1485 | break; | | 1485 | break; |
1486 | case T_LPMC: | | 1486 | case T_LPMC: |
1487 | lpmc = (struct hp700_pim_lpmc *) pim_data_buffer; | | 1487 | lpmc = (struct hp700_pim_lpmc *) pim_data_buffer; |
1488 | checks = &lpmc->pim_lpmc_checks; | | 1488 | checks = &lpmc->pim_lpmc_checks; |
1489 | break; | | 1489 | break; |
1490 | case T_INTERRUPT: | | 1490 | case T_INTERRUPT: |
1491 | toc = (struct hp700_pim_toc *) pim_data_buffer; | | 1491 | toc = (struct hp700_pim_toc *) pim_data_buffer; |
1492 | regs = &toc->pim_toc_regs; | | 1492 | regs = &toc->pim_toc_regs; |
1493 | break; | | 1493 | break; |
1494 | default: | | 1494 | default: |
1495 | panic("unknown machine check type"); | | 1495 | panic("unknown machine check type"); |
1496 | /* NOTREACHED */ | | 1496 | /* NOTREACHED */ |
1497 | } | | 1497 | } |
1498 | | | 1498 | |
1499 | /* If we have register arrays, display them. */ | | 1499 | /* If we have register arrays, display them. */ |
1500 | if (regs != NULL) { | | 1500 | if (regs != NULL) { |
1501 | for (reg_i = 0; reg_i < 3; reg_i++) { | | 1501 | for (reg_i = 0; reg_i < 3; reg_i++) { |
1502 | if (reg_i == 0) { | | 1502 | if (reg_i == 0) { |
1503 | name = "General"; | | 1503 | name = "General"; |
1504 | regarray = ®s->pim_regs_r0; | | 1504 | regarray = ®s->pim_regs_r0; |
1505 | reg_j = 32; | | 1505 | reg_j = 32; |
1506 | } else if (reg_i == 1) { | | 1506 | } else if (reg_i == 1) { |
1507 | name = "Control"; | | 1507 | name = "Control"; |
1508 | regarray = ®s->pim_regs_cr0; | | 1508 | regarray = ®s->pim_regs_cr0; |
1509 | reg_j = 32; | | 1509 | reg_j = 32; |
1510 | } else { | | 1510 | } else { |
1511 | name = "Space"; | | 1511 | name = "Space"; |
1512 | regarray = ®s->pim_regs_sr0; | | 1512 | regarray = ®s->pim_regs_sr0; |
1513 | reg_j = 8; | | 1513 | reg_j = 8; |
1514 | } | | 1514 | } |
1515 | printf("\n\n\t%s Registers:", name); | | 1515 | printf("\n\n\t%s Registers:", name); |
1516 | for (reg_k = 0; reg_k < reg_j; reg_k++) | | 1516 | for (reg_k = 0; reg_k < reg_j; reg_k++) |
1517 | printf("%s0x%08x", | | 1517 | printf("%s0x%08x", |
1518 | (reg_k & 3) ? " " : "\n", | | 1518 | (reg_k & 3) ? " " : "\n", |
1519 | regarray[reg_k]); | | 1519 | regarray[reg_k]); |
1520 | } | | 1520 | } |
1521 | | | 1521 | |
1522 | /* Print out some interesting registers. */ | | 1522 | /* Print out some interesting registers. */ |
1523 | printf("\n\n\tIIA head 0x%x:0x%08x\n" | | 1523 | printf("\n\n\tIIA head 0x%x:0x%08x\n" |
1524 | "\tIIA tail 0x%x:0x%08x", | | 1524 | "\tIIA tail 0x%x:0x%08x", |
1525 | regs->pim_regs_cr17, regs->pim_regs_cr18, | | 1525 | regs->pim_regs_cr17, regs->pim_regs_cr18, |
1526 | regs->pim_regs_iisq_tail, regs->pim_regs_iioq_tail); | | 1526 | regs->pim_regs_iisq_tail, regs->pim_regs_iioq_tail); |
1527 | PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS); | | 1527 | PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS); |
1528 | printf("\n\tSP 0x%x:0x%08x FP 0x%x:0x%08x", | | 1528 | printf("\n\tSP 0x%x:0x%08x FP 0x%x:0x%08x", |
1529 | regs->pim_regs_sr0, regs->pim_regs_r30, | | 1529 | regs->pim_regs_sr0, regs->pim_regs_r30, |
1530 | regs->pim_regs_sr0, regs->pim_regs_r3); | | 1530 | regs->pim_regs_sr0, regs->pim_regs_r3); |
1531 | } | | 1531 | } |
1532 | | | 1532 | |
1533 | /* If we have check words, display them. */ | | 1533 | /* If we have check words, display them. */ |
1534 | if (checks != NULL) { | | 1534 | if (checks != NULL) { |
1535 | PIM_WORD("\n\n\tCheck Type", checks->pim_check_type, | | 1535 | PIM_WORD("\n\n\tCheck Type", checks->pim_check_type, |
1536 | PIM_CHECK_BITS); | | 1536 | PIM_CHECK_BITS); |
1537 | PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state, | | 1537 | PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state, |
1538 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); | | 1538 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); |
1539 | PIM_WORD("\n\tCache Check", checks->pim_check_cache, | | 1539 | PIM_WORD("\n\tCache Check", checks->pim_check_cache, |
1540 | PIM_CACHE_BITS); | | 1540 | PIM_CACHE_BITS); |
1541 | PIM_WORD("\n\tTLB Check", checks->pim_check_tlb, | | 1541 | PIM_WORD("\n\tTLB Check", checks->pim_check_tlb, |
1542 | PIM_TLB_BITS); | | 1542 | PIM_TLB_BITS); |
1543 | PIM_WORD("\n\tBus Check", checks->pim_check_bus, | | 1543 | PIM_WORD("\n\tBus Check", checks->pim_check_bus, |
1544 | PIM_BUS_BITS); | | 1544 | PIM_BUS_BITS); |
1545 | PIM_WORD("\n\tAssist Check", checks->pim_check_assist, | | 1545 | PIM_WORD("\n\tAssist Check", checks->pim_check_assist, |
1546 | PIM_ASSIST_BITS); | | 1546 | PIM_ASSIST_BITS); |
1547 | printf("\tAssist State %u", checks->pim_check_assist_state); | | 1547 | printf("\tAssist State %u", checks->pim_check_assist_state); |
1548 | printf("\n\tSystem Responder 0x%08x", | | 1548 | printf("\n\tSystem Responder 0x%08x", |
1549 | checks->pim_check_responder); | | 1549 | checks->pim_check_responder); |
1550 | printf("\n\tSystem Requestor 0x%08x", | | 1550 | printf("\n\tSystem Requestor 0x%08x", |
1551 | checks->pim_check_requestor); | | 1551 | checks->pim_check_requestor); |
1552 | printf("\n\tPath Info 0x%08x", | | 1552 | printf("\n\tPath Info 0x%08x", |
1553 | checks->pim_check_path_info); | | 1553 | checks->pim_check_path_info); |
1554 | } | | 1554 | } |
1555 | } | | 1555 | } |
1556 | | | 1556 | |
1557 | static inline void | | 1557 | static inline void |
1558 | hppa_pim64_dump(int check_type) | | 1558 | hppa_pim64_dump(int check_type) |
1559 | { | | 1559 | { |
1560 | struct hp700_pim64_hpmc *hpmc; | | 1560 | struct hp700_pim64_hpmc *hpmc; |
1561 | struct hp700_pim64_lpmc *lpmc; | | 1561 | struct hp700_pim64_lpmc *lpmc; |
1562 | struct hp700_pim64_toc *toc; | | 1562 | struct hp700_pim64_toc *toc; |
1563 | struct hp700_pim64_regs *regs; | | 1563 | struct hp700_pim64_regs *regs; |
1564 | struct hp700_pim64_checks *checks; | | 1564 | struct hp700_pim64_checks *checks; |
1565 | int reg_i, reg_j, reg_k; | | 1565 | int reg_i, reg_j, reg_k; |
1566 | uint64_t *regarray; | | 1566 | uint64_t *regarray; |
1567 | char bitmask_buffer[64]; | | 1567 | char bitmask_buffer[64]; |
1568 | const char *name; | | 1568 | const char *name; |
1569 | | | 1569 | |
1570 | regs = NULL; | | 1570 | regs = NULL; |
1571 | checks = NULL; | | 1571 | checks = NULL; |
1572 | switch (check_type) { | | 1572 | switch (check_type) { |
1573 | case T_HPMC: | | 1573 | case T_HPMC: |
1574 | hpmc = (struct hp700_pim64_hpmc *) pim_data_buffer; | | 1574 | hpmc = (struct hp700_pim64_hpmc *) pim_data_buffer; |
1575 | regs = &hpmc->pim_hpmc_regs; | | 1575 | regs = &hpmc->pim_hpmc_regs; |
1576 | checks = &hpmc->pim_hpmc_checks; | | 1576 | checks = &hpmc->pim_hpmc_checks; |
1577 | break; | | 1577 | break; |
1578 | case T_LPMC: | | 1578 | case T_LPMC: |
1579 | lpmc = (struct hp700_pim64_lpmc *) pim_data_buffer; | | 1579 | lpmc = (struct hp700_pim64_lpmc *) pim_data_buffer; |
1580 | checks = &lpmc->pim_lpmc_checks; | | 1580 | checks = &lpmc->pim_lpmc_checks; |
1581 | break; | | 1581 | break; |
1582 | case T_INTERRUPT: | | 1582 | case T_INTERRUPT: |
1583 | toc = (struct hp700_pim64_toc *) pim_data_buffer; | | 1583 | toc = (struct hp700_pim64_toc *) pim_data_buffer; |
1584 | regs = &toc->pim_toc_regs; | | 1584 | regs = &toc->pim_toc_regs; |
1585 | break; | | 1585 | break; |
1586 | default: | | 1586 | default: |
1587 | panic("unknown machine check type"); | | 1587 | panic("unknown machine check type"); |
1588 | /* NOTREACHED */ | | 1588 | /* NOTREACHED */ |
1589 | } | | 1589 | } |
1590 | | | 1590 | |
1591 | /* If we have register arrays, display them. */ | | 1591 | /* If we have register arrays, display them. */ |
1592 | if (regs != NULL) { | | 1592 | if (regs != NULL) { |
1593 | for (reg_i = 0; reg_i < 3; reg_i++) { | | 1593 | for (reg_i = 0; reg_i < 3; reg_i++) { |
1594 | if (reg_i == 0) { | | 1594 | if (reg_i == 0) { |
1595 | name = "General"; | | 1595 | name = "General"; |
1596 | regarray = ®s->pim_regs_r0; | | 1596 | regarray = ®s->pim_regs_r0; |
1597 | reg_j = 32; | | 1597 | reg_j = 32; |
1598 | } else if (reg_i == 1) { | | 1598 | } else if (reg_i == 1) { |
1599 | name = "Control"; | | 1599 | name = "Control"; |
1600 | regarray = ®s->pim_regs_cr0; | | 1600 | regarray = ®s->pim_regs_cr0; |
1601 | reg_j = 32; | | 1601 | reg_j = 32; |
1602 | } else { | | 1602 | } else { |
1603 | name = "Space"; | | 1603 | name = "Space"; |
1604 | regarray = ®s->pim_regs_sr0; | | 1604 | regarray = ®s->pim_regs_sr0; |
1605 | reg_j = 8; | | 1605 | reg_j = 8; |
1606 | } | | 1606 | } |
1607 | printf("\n\n%s Registers:", name); | | 1607 | printf("\n\n%s Registers:", name); |
1608 | for (reg_k = 0; reg_k < reg_j; reg_k++) | | 1608 | for (reg_k = 0; reg_k < reg_j; reg_k++) |
1609 | printf("%s0x%016lx", | | 1609 | printf("%s0x%016lx", |
1610 | (reg_k & 3) ? " " : "\n", | | 1610 | (reg_k & 3) ? " " : "\n", |
1611 | (unsigned long)regarray[reg_k]); | | 1611 | (unsigned long)regarray[reg_k]); |
1612 | } | | 1612 | } |
1613 | | | 1613 | |
1614 | /* Print out some interesting registers. */ | | 1614 | /* Print out some interesting registers. */ |
1615 | printf("\n\nIIA head 0x%lx:0x%016lx\n" | | 1615 | printf("\n\nIIA head 0x%lx:0x%016lx\n" |
1616 | "IIA tail 0x%lx:0x%016lx", | | 1616 | "IIA tail 0x%lx:0x%016lx", |
1617 | (unsigned long)regs->pim_regs_cr17, | | 1617 | (unsigned long)regs->pim_regs_cr17, |
1618 | (unsigned long)regs->pim_regs_cr18, | | 1618 | (unsigned long)regs->pim_regs_cr18, |
1619 | (unsigned long)regs->pim_regs_iisq_tail, | | 1619 | (unsigned long)regs->pim_regs_iisq_tail, |
1620 | (unsigned long)regs->pim_regs_iioq_tail); | | 1620 | (unsigned long)regs->pim_regs_iioq_tail); |
1621 | PIM_WORD("\nIPSW", regs->pim_regs_cr22, PSW_BITS); | | 1621 | PIM_WORD("\nIPSW", regs->pim_regs_cr22, PSW_BITS); |
1622 | printf("\nSP 0x%lx:0x%016lx\nFP 0x%lx:0x%016lx", | | 1622 | printf("\nSP 0x%lx:0x%016lx\nFP 0x%lx:0x%016lx", |
1623 | (unsigned long)regs->pim_regs_sr0, | | 1623 | (unsigned long)regs->pim_regs_sr0, |
1624 | (unsigned long)regs->pim_regs_r30, | | 1624 | (unsigned long)regs->pim_regs_r30, |
1625 | (unsigned long)regs->pim_regs_sr0, | | 1625 | (unsigned long)regs->pim_regs_sr0, |
1626 | (unsigned long)regs->pim_regs_r3); | | 1626 | (unsigned long)regs->pim_regs_r3); |
1627 | } | | 1627 | } |
1628 | | | 1628 | |
1629 | /* If we have check words, display them. */ | | 1629 | /* If we have check words, display them. */ |
1630 | if (checks != NULL) { | | 1630 | if (checks != NULL) { |
1631 | PIM_WORD("\n\nCheck Type", checks->pim_check_type, | | 1631 | PIM_WORD("\n\nCheck Type", checks->pim_check_type, |
1632 | PIM_CHECK_BITS); | | 1632 | PIM_CHECK_BITS); |
1633 | PIM_WORD("\nCPU State", checks->pim_check_cpu_state, | | 1633 | PIM_WORD("\nCPU State", checks->pim_check_cpu_state, |
1634 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); | | 1634 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); |
1635 | PIM_WORD("\nCache Check", checks->pim_check_cache, | | 1635 | PIM_WORD("\nCache Check", checks->pim_check_cache, |
1636 | PIM_CACHE_BITS); | | 1636 | PIM_CACHE_BITS); |
1637 | PIM_WORD("\nTLB Check", checks->pim_check_tlb, | | 1637 | PIM_WORD("\nTLB Check", checks->pim_check_tlb, |
1638 | PIM_TLB_BITS); | | 1638 | PIM_TLB_BITS); |
1639 | PIM_WORD("\nBus Check", checks->pim_check_bus, | | 1639 | PIM_WORD("\nBus Check", checks->pim_check_bus, |
1640 | PIM_BUS_BITS); | | 1640 | PIM_BUS_BITS); |
1641 | PIM_WORD("\nAssist Check", checks->pim_check_assist, | | 1641 | PIM_WORD("\nAssist Check", checks->pim_check_assist, |
1642 | PIM_ASSIST_BITS); | | 1642 | PIM_ASSIST_BITS); |
1643 | printf("Assist State %u", checks->pim_check_assist_state); | | 1643 | printf("\nAssist State %u", checks->pim_check_assist_state); |
1644 | printf("\nSystem Responder 0x%016lx", | | 1644 | printf("\nSystem Responder 0x%016lx", |
1645 | (unsigned long)checks->pim_check_responder); | | 1645 | (unsigned long)checks->pim_check_responder); |
1646 | printf("\nSystem Requestor 0x%016lx", | | 1646 | printf("\nSystem Requestor 0x%016lx", |
1647 | (unsigned long)checks->pim_check_requestor); | | 1647 | (unsigned long)checks->pim_check_requestor); |
1648 | printf("\nPath Info 0x%08x", | | 1648 | printf("\nPath Info 0x%08x", |
1649 | checks->pim_check_path_info); | | 1649 | checks->pim_check_path_info); |
1650 | } | | 1650 | } |
1651 | } | | 1651 | } |
1652 | | | 1652 | |
1653 | void | | 1653 | void |
1654 | hppa_machine_check(int check_type) | | 1654 | hppa_machine_check(int check_type) |
1655 | { | | 1655 | { |
1656 | int pdc_pim_type; | | 1656 | int pdc_pim_type; |
1657 | const char *name; | | 1657 | const char *name; |
1658 | int pimerror, error; | | 1658 | int pimerror, error; |
1659 | | | 1659 | |
1660 | /* Do an fcacheall(). */ | | 1660 | /* Do an fcacheall(). */ |
1661 | fcacheall(); | | 1661 | fcacheall(); |
1662 | | | 1662 | |
1663 | /* Dispatch on the check type. */ | | 1663 | /* Dispatch on the check type. */ |
1664 | switch (check_type) { | | 1664 | switch (check_type) { |
1665 | case T_HPMC: | | 1665 | case T_HPMC: |
1666 | name = "HPMC"; | | 1666 | name = "HPMC"; |
1667 | pdc_pim_type = PDC_PIM_HPMC; | | 1667 | pdc_pim_type = PDC_PIM_HPMC; |
1668 | break; | | 1668 | break; |
1669 | case T_LPMC: | | 1669 | case T_LPMC: |
1670 | name = "LPMC"; | | 1670 | name = "LPMC"; |
1671 | pdc_pim_type = PDC_PIM_LPMC; | | 1671 | pdc_pim_type = PDC_PIM_LPMC; |
1672 | break; | | 1672 | break; |
1673 | case T_INTERRUPT: | | 1673 | case T_INTERRUPT: |
1674 | name = "TOC"; | | 1674 | name = "TOC"; |
1675 | pdc_pim_type = PDC_PIM_TOC; | | 1675 | pdc_pim_type = PDC_PIM_TOC; |
1676 | break; | | 1676 | break; |
1677 | default: | | 1677 | default: |
1678 | panic("unknown machine check type"); | | 1678 | panic("unknown machine check type"); |
1679 | /* NOTREACHED */ | | 1679 | /* NOTREACHED */ |
1680 | } | | 1680 | } |
1681 | | | 1681 | |
1682 | pimerror = pdc_call((iodcio_t)pdc, 0, PDC_PIM, pdc_pim_type, | | 1682 | pimerror = pdc_call((iodcio_t)pdc, 0, PDC_PIM, pdc_pim_type, |
1683 | &pdc_pim, pim_data_buffer, sizeof(pim_data_buffer)); | | 1683 | &pdc_pim, pim_data_buffer, sizeof(pim_data_buffer)); |
1684 | | | 1684 | |
1685 | KASSERT(pdc_pim.count <= sizeof(pim_data_buffer)); | | 1685 | KASSERT(pdc_pim.count <= sizeof(pim_data_buffer)); |
1686 | | | 1686 | |
1687 | /* | | 1687 | /* |
1688 | * Reset IO and log errors. | | 1688 | * Reset IO and log errors. |
1689 | * | | 1689 | * |
1690 | * This seems to be needed in order to output to the console | | 1690 | * This seems to be needed in order to output to the console |
1691 | * if we take a HPMC interrupt. This PDC procedure may not be | | 1691 | * if we take a HPMC interrupt. This PDC procedure may not be |
1692 | * implemented by some machines. | | 1692 | * implemented by some machines. |
1693 | */ | | 1693 | */ |
1694 | error = pdc_call((iodcio_t)pdc, 0, PDC_IO, 0, 0, 0, 0); | | 1694 | error = pdc_call((iodcio_t)pdc, 0, PDC_IO, 0, 0, 0, 0); |
1695 | if (error != PDC_ERR_OK && error != PDC_ERR_NOPROC) | | 1695 | if (error != PDC_ERR_OK && error != PDC_ERR_NOPROC) |
1696 | /* This seems futile if we can't print to the console. */ | | 1696 | /* This seems futile if we can't print to the console. */ |
1697 | panic("PDC_IO failed"); | | 1697 | panic("PDC_IO failed"); |
1698 | | | 1698 | |
1699 | printf("\nmachine check: %s", name); | | 1699 | printf("\nmachine check: %s", name); |
1700 | | | 1700 | |
1701 | if (pimerror < 0) { | | 1701 | if (pimerror < 0) { |
1702 | printf(" - WARNING: could not transfer PIM info (%d)", pimerror); | | 1702 | printf(" - WARNING: could not transfer PIM info (%d)", pimerror); |
1703 | } else { | | 1703 | } else { |
1704 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) | | 1704 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) |
1705 | hppa_pim64_dump(check_type); | | 1705 | hppa_pim64_dump(check_type); |
1706 | else | | 1706 | else |
1707 | hppa_pim_dump(check_type); | | 1707 | hppa_pim_dump(check_type); |
1708 | } | | 1708 | } |
1709 | | | 1709 | |
1710 | printf("\n"); | | 1710 | printf("\n"); |
1711 | | | 1711 | |
1712 | /* If this is our first check, panic. */ | | 1712 | /* If this is our first check, panic. */ |
1713 | if (in_check == 0) { | | 1713 | if (in_check == 0) { |
1714 | in_check = 1; | | 1714 | in_check = 1; |
1715 | DELAY(250000); | | 1715 | DELAY(250000); |
1716 | panic("machine check"); | | 1716 | panic("machine check"); |
1717 | } | | 1717 | } |
1718 | | | 1718 | |
1719 | /* Reboot the machine. */ | | 1719 | /* Reboot the machine. */ |
1720 | printf("Rebooting...\n"); | | 1720 | printf("Rebooting...\n"); |
1721 | cpu_die(); | | 1721 | cpu_die(); |
1722 | } | | 1722 | } |
1723 | | | 1723 | |
1724 | int | | 1724 | int |
1725 | cpu_dump(void) | | 1725 | cpu_dump(void) |
1726 | { | | 1726 | { |
1727 | long buf[dbtob(1) / sizeof (long)]; | | 1727 | long buf[dbtob(1) / sizeof (long)]; |
1728 | kcore_seg_t *segp; | | 1728 | kcore_seg_t *segp; |
1729 | cpu_kcore_hdr_t *cpuhdrp; | | 1729 | cpu_kcore_hdr_t *cpuhdrp; |
1730 | const struct bdevsw *bdev; | | 1730 | const struct bdevsw *bdev; |
1731 | | | 1731 | |
1732 | segp = (kcore_seg_t *)buf; | | 1732 | segp = (kcore_seg_t *)buf; |
1733 | cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; | | 1733 | cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; |
1734 | | | 1734 | |
1735 | /* | | 1735 | /* |
1736 | * Generate a segment header. | | 1736 | * Generate a segment header. |
1737 | */ | | 1737 | */ |
1738 | CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); | | 1738 | CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); |
1739 | segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); | | 1739 | segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); |
1740 | | | 1740 | |
1741 | /* | | 1741 | /* |
1742 | * Add the machine-dependent header info | | 1742 | * Add the machine-dependent header info |
1743 | */ | | 1743 | */ |
1744 | /* nothing for now */ | | 1744 | /* nothing for now */ |
1745 | | | 1745 | |
1746 | bdev = bdevsw_lookup(dumpdev); | | 1746 | bdev = bdevsw_lookup(dumpdev); |
1747 | if (bdev == NULL) | | 1747 | if (bdev == NULL) |
1748 | return (-1); | | 1748 | return (-1); |
1749 | | | 1749 | |
1750 | return (*bdev->d_dump)(dumpdev, dumplo, (void *)buf, dbtob(1)); | | 1750 | return (*bdev->d_dump)(dumpdev, dumplo, (void *)buf, dbtob(1)); |
1751 | } | | 1751 | } |
1752 | | | 1752 | |
1753 | /* | | 1753 | /* |
1754 | * Dump the kernel's image to the swap partition. | | 1754 | * Dump the kernel's image to the swap partition. |
1755 | */ | | 1755 | */ |
1756 | #define BYTES_PER_DUMP PAGE_SIZE | | 1756 | #define BYTES_PER_DUMP PAGE_SIZE |
1757 | | | 1757 | |
1758 | void | | 1758 | void |
1759 | dumpsys(void) | | 1759 | dumpsys(void) |
1760 | { | | 1760 | { |
1761 | const struct bdevsw *bdev; | | 1761 | const struct bdevsw *bdev; |
1762 | int psize, bytes, i, n; | | 1762 | int psize, bytes, i, n; |
1763 | char *maddr; | | 1763 | char *maddr; |
1764 | daddr_t blkno; | | 1764 | daddr_t blkno; |
1765 | int (*dump)(dev_t, daddr_t, void *, size_t); | | 1765 | int (*dump)(dev_t, daddr_t, void *, size_t); |
1766 | int error; | | 1766 | int error; |
1767 | | | 1767 | |
1768 | if (dumpdev == NODEV) | | 1768 | if (dumpdev == NODEV) |
1769 | return; | | 1769 | return; |
1770 | bdev = bdevsw_lookup(dumpdev); | | 1770 | bdev = bdevsw_lookup(dumpdev); |
1771 | if (bdev == NULL) | | 1771 | if (bdev == NULL) |
1772 | return; | | 1772 | return; |
1773 | | | 1773 | |
1774 | /* Save registers | | 1774 | /* Save registers |
1775 | savectx(&dumppcb); */ | | 1775 | savectx(&dumppcb); */ |
1776 | | | 1776 | |
1777 | if (dumpsize == 0) | | 1777 | if (dumpsize == 0) |
1778 | cpu_dumpconf(); | | 1778 | cpu_dumpconf(); |
1779 | if (dumplo <= 0) { | | 1779 | if (dumplo <= 0) { |
1780 | printf("\ndump to dev %u,%u not possible\n", | | 1780 | printf("\ndump to dev %u,%u not possible\n", |
1781 | major(dumpdev), minor(dumpdev)); | | 1781 | major(dumpdev), minor(dumpdev)); |
1782 | return; | | 1782 | return; |
1783 | } | | 1783 | } |
1784 | printf("\ndumping to dev %u,%u offset %ld\n", | | 1784 | printf("\ndumping to dev %u,%u offset %ld\n", |
1785 | major(dumpdev), minor(dumpdev), dumplo); | | 1785 | major(dumpdev), minor(dumpdev), dumplo); |
1786 | | | 1786 | |
1787 | psize = (*bdev->d_psize)(dumpdev); | | 1787 | psize = (*bdev->d_psize)(dumpdev); |
1788 | printf("dump "); | | 1788 | printf("dump "); |
1789 | if (psize == -1) { | | 1789 | if (psize == -1) { |
1790 | printf("area unavailable\n"); | | 1790 | printf("area unavailable\n"); |
1791 | return; | | 1791 | return; |
1792 | } | | 1792 | } |
1793 | | | 1793 | |
1794 | if (!(error = cpu_dump())) { | | 1794 | if (!(error = cpu_dump())) { |
1795 | | | 1795 | |
1796 | /* XXX fredette - this is way broken: */ | | 1796 | /* XXX fredette - this is way broken: */ |
1797 | bytes = ctob(physmem); | | 1797 | bytes = ctob(physmem); |
1798 | maddr = NULL; | | 1798 | maddr = NULL; |
1799 | blkno = dumplo + cpu_dumpsize(); | | 1799 | blkno = dumplo + cpu_dumpsize(); |
1800 | dump = bdev->d_dump; | | 1800 | dump = bdev->d_dump; |
1801 | /* TODO block map the whole physical memory */ | | 1801 | /* TODO block map the whole physical memory */ |
1802 | for (i = 0; i < bytes; i += n) { | | 1802 | for (i = 0; i < bytes; i += n) { |
1803 | | | 1803 | |
1804 | /* Print out how many MBs we are to go. */ | | 1804 | /* Print out how many MBs we are to go. */ |
1805 | n = bytes - i; | | 1805 | n = bytes - i; |
1806 | if (n && (n % (1024*1024)) == 0) | | 1806 | if (n && (n % (1024*1024)) == 0) |
1807 | printf_nolog("%d ", n / (1024 * 1024)); | | 1807 | printf_nolog("%d ", n / (1024 * 1024)); |
1808 | | | 1808 | |
1809 | /* Limit size for next transfer. */ | | 1809 | /* Limit size for next transfer. */ |
1810 | | | 1810 | |
1811 | if (n > BYTES_PER_DUMP) | | 1811 | if (n > BYTES_PER_DUMP) |
1812 | n = BYTES_PER_DUMP; | | 1812 | n = BYTES_PER_DUMP; |
1813 | | | 1813 | |
1814 | if ((error = (*dump)(dumpdev, blkno, maddr, n))) | | 1814 | if ((error = (*dump)(dumpdev, blkno, maddr, n))) |
1815 | break; | | 1815 | break; |
1816 | maddr += n; | | 1816 | maddr += n; |
1817 | blkno += btodb(n); | | 1817 | blkno += btodb(n); |
1818 | } | | 1818 | } |
1819 | } | | 1819 | } |
1820 | | | 1820 | |
1821 | switch (error) { | | 1821 | switch (error) { |
1822 | case ENXIO: printf("device bad\n"); break; | | 1822 | case ENXIO: printf("device bad\n"); break; |
1823 | case EFAULT: printf("device not ready\n"); break; | | 1823 | case EFAULT: printf("device not ready\n"); break; |
1824 | case EINVAL: printf("area improper\n"); break; | | 1824 | case EINVAL: printf("area improper\n"); break; |
1825 | case EIO: printf("i/o error\n"); break; | | 1825 | case EIO: printf("i/o error\n"); break; |
1826 | case EINTR: printf("aborted from console\n"); break; | | 1826 | case EINTR: printf("aborted from console\n"); break; |
1827 | case 0: printf("succeeded\n"); break; | | 1827 | case 0: printf("succeeded\n"); break; |
1828 | default: printf("error %d\n", error); break; | | 1828 | default: printf("error %d\n", error); break; |
1829 | } | | 1829 | } |
1830 | } | | 1830 | } |
1831 | | | 1831 | |
1832 | /* bcopy(), error on fault */ | | 1832 | /* bcopy(), error on fault */ |
1833 | int | | 1833 | int |
1834 | kcopy(const void *from, void *to, size_t size) | | 1834 | kcopy(const void *from, void *to, size_t size) |
1835 | { | | 1835 | { |
1836 | struct pcb *pcb = lwp_getpcb(curlwp); | | 1836 | struct pcb *pcb = lwp_getpcb(curlwp); |
1837 | u_int oldh = pcb->pcb_onfault; | | 1837 | u_int oldh = pcb->pcb_onfault; |
1838 | | | 1838 | |
1839 | pcb->pcb_onfault = (u_int)©_on_fault; | | 1839 | pcb->pcb_onfault = (u_int)©_on_fault; |
1840 | memcpy(to, from, size); | | 1840 | memcpy(to, from, size); |
1841 | pcb->pcb_onfault = oldh; | | 1841 | pcb->pcb_onfault = oldh; |
1842 | | | 1842 | |
1843 | return 0; | | 1843 | return 0; |
1844 | } | | 1844 | } |
1845 | | | 1845 | |
1846 | /* | | 1846 | /* |
1847 | * Set registers on exec. | | 1847 | * Set registers on exec. |
1848 | */ | | 1848 | */ |
1849 | void | | 1849 | void |
1850 | setregs(struct lwp *l, struct exec_package *pack, u_long stack) | | 1850 | setregs(struct lwp *l, struct exec_package *pack, u_long stack) |
1851 | { | | 1851 | { |
1852 | struct proc *p = l->l_proc; | | 1852 | struct proc *p = l->l_proc; |
1853 | struct trapframe *tf = l->l_md.md_regs; | | 1853 | struct trapframe *tf = l->l_md.md_regs; |
1854 | pmap_t pmap = p->p_vmspace->vm_map.pmap; | | 1854 | pmap_t pmap = p->p_vmspace->vm_map.pmap; |
1855 | pa_space_t space = pmap->pm_space; | | 1855 | pa_space_t space = pmap->pm_space; |
1856 | struct pcb *pcb = lwp_getpcb(l); | | 1856 | struct pcb *pcb = lwp_getpcb(l); |
1857 | | | 1857 | |
1858 | tf->tf_flags = TFF_SYS|TFF_LAST; | | 1858 | tf->tf_flags = TFF_SYS|TFF_LAST; |
1859 | tf->tf_iioq_tail = 4 + | | 1859 | tf->tf_iioq_tail = 4 + |
1860 | (tf->tf_iioq_head = pack->ep_entry | HPPA_PC_PRIV_USER); | | 1860 | (tf->tf_iioq_head = pack->ep_entry | HPPA_PC_PRIV_USER); |
1861 | tf->tf_rp = 0; | | 1861 | tf->tf_rp = 0; |
1862 | tf->tf_arg0 = (u_long)p->p_psstr; | | 1862 | tf->tf_arg0 = (u_long)p->p_psstr; |
1863 | tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */ | | 1863 | tf->tf_arg1 = tf->tf_arg2 = 0; /* XXX dynload stuff */ |
1864 | | | 1864 | |
1865 | tf->tf_sr7 = HPPA_SID_KERNEL; | | 1865 | tf->tf_sr7 = HPPA_SID_KERNEL; |
1866 | | | 1866 | |
1867 | /* Load all of the user's space registers. */ | | 1867 | /* Load all of the user's space registers. */ |
1868 | tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 = | | 1868 | tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 = |
1869 | tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 = space; | | 1869 | tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 = space; |
1870 | | | 1870 | |
1871 | tf->tf_iisq_head = tf->tf_iisq_tail = space; | | 1871 | tf->tf_iisq_head = tf->tf_iisq_tail = space; |
1872 | | | 1872 | |
1873 | /* Load the protection regsiters. */ | | 1873 | /* Load the protection regsiters. */ |
1874 | tf->tf_pidr1 = tf->tf_pidr2 = pmap->pm_pid; | | 1874 | tf->tf_pidr1 = tf->tf_pidr2 = pmap->pm_pid; |
1875 | | | 1875 | |
1876 | /* reset any of the pending FPU exceptions */ | | 1876 | /* reset any of the pending FPU exceptions */ |
1877 | hppa_fpu_flush(l); | | 1877 | hppa_fpu_flush(l); |
1878 | pcb->pcb_fpregs[0] = ((uint64_t)HPPA_FPU_INIT) << 32; | | 1878 | pcb->pcb_fpregs[0] = ((uint64_t)HPPA_FPU_INIT) << 32; |
1879 | pcb->pcb_fpregs[1] = 0; | | 1879 | pcb->pcb_fpregs[1] = 0; |
1880 | pcb->pcb_fpregs[2] = 0; | | 1880 | pcb->pcb_fpregs[2] = 0; |
1881 | pcb->pcb_fpregs[3] = 0; | | 1881 | pcb->pcb_fpregs[3] = 0; |
1882 | fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4); | | 1882 | fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4); |
1883 | | | 1883 | |
1884 | /* setup terminal stack frame */ | | 1884 | /* setup terminal stack frame */ |
1885 | stack = (u_long)STACK_ALIGN(stack, 63); | | 1885 | stack = (u_long)STACK_ALIGN(stack, 63); |
1886 | tf->tf_r3 = stack; | | 1886 | tf->tf_r3 = stack; |
1887 | suword((void *)(stack), 0); | | 1887 | suword((void *)(stack), 0); |
1888 | stack += HPPA_FRAME_SIZE; | | 1888 | stack += HPPA_FRAME_SIZE; |
1889 | suword((void *)(stack + HPPA_FRAME_PSP), 0); | | 1889 | suword((void *)(stack + HPPA_FRAME_PSP), 0); |
1890 | tf->tf_sp = stack; | | 1890 | tf->tf_sp = stack; |
1891 | } | | 1891 | } |
1892 | | | 1892 | |
1893 | /* | | 1893 | /* |
1894 | * machine dependent system variables. | | 1894 | * machine dependent system variables. |
1895 | */ | | 1895 | */ |
1896 | static int | | 1896 | static int |
1897 | sysctl_machdep_boot(SYSCTLFN_ARGS) | | 1897 | sysctl_machdep_boot(SYSCTLFN_ARGS) |
1898 | { | | 1898 | { |
1899 | struct sysctlnode node = *rnode; | | 1899 | struct sysctlnode node = *rnode; |
1900 | struct btinfo_kernelfile *bi_file; | | 1900 | struct btinfo_kernelfile *bi_file; |
1901 | const char *cp = NULL; | | 1901 | const char *cp = NULL; |
1902 | | | 1902 | |
1903 | switch (node.sysctl_num) { | | 1903 | switch (node.sysctl_num) { |
1904 | case CPU_BOOTED_KERNEL: | | 1904 | case CPU_BOOTED_KERNEL: |
1905 | if ((bi_file = lookup_bootinfo(BTINFO_KERNELFILE)) != NULL) | | 1905 | if ((bi_file = lookup_bootinfo(BTINFO_KERNELFILE)) != NULL) |
1906 | cp = bi_file->name; | | 1906 | cp = bi_file->name; |
1907 | if (cp != NULL && cp[0] == '\0') | | 1907 | if (cp != NULL && cp[0] == '\0') |
1908 | cp = "netbsd"; | | 1908 | cp = "netbsd"; |
1909 | break; | | 1909 | break; |
1910 | default: | | 1910 | default: |
1911 | return (EINVAL); | | 1911 | return (EINVAL); |
1912 | } | | 1912 | } |
1913 | | | 1913 | |
1914 | if (cp == NULL || cp[0] == '\0') | | 1914 | if (cp == NULL || cp[0] == '\0') |
1915 | return (ENOENT); | | 1915 | return (ENOENT); |
1916 | | | 1916 | |
1917 | node.sysctl_data = __UNCONST(cp); | | 1917 | node.sysctl_data = __UNCONST(cp); |
1918 | node.sysctl_size = strlen(cp) + 1; | | 1918 | node.sysctl_size = strlen(cp) + 1; |
1919 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); | | 1919 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); |
1920 | } | | 1920 | } |
1921 | | | 1921 | |
1922 | /* | | 1922 | /* |
1923 | * machine dependent system variables. | | 1923 | * machine dependent system variables. |
1924 | */ | | 1924 | */ |
1925 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") | | 1925 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") |
1926 | { | | 1926 | { |
1927 | | | 1927 | |
1928 | sysctl_createv(clog, 0, NULL, NULL, | | 1928 | sysctl_createv(clog, 0, NULL, NULL, |
1929 | CTLFLAG_PERMANENT, | | 1929 | CTLFLAG_PERMANENT, |
1930 | CTLTYPE_NODE, "machdep", NULL, | | 1930 | CTLTYPE_NODE, "machdep", NULL, |
1931 | NULL, 0, NULL, 0, | | 1931 | NULL, 0, NULL, 0, |
1932 | CTL_MACHDEP, CTL_EOL); | | 1932 | CTL_MACHDEP, CTL_EOL); |
1933 | | | 1933 | |
1934 | sysctl_createv(clog, 0, NULL, NULL, | | 1934 | sysctl_createv(clog, 0, NULL, NULL, |
1935 | CTLFLAG_PERMANENT, | | 1935 | CTLFLAG_PERMANENT, |
1936 | CTLTYPE_STRUCT, "console_device", NULL, | | 1936 | CTLTYPE_STRUCT, "console_device", NULL, |
1937 | sysctl_consdev, 0, NULL, sizeof(dev_t), | | 1937 | sysctl_consdev, 0, NULL, sizeof(dev_t), |
1938 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); | | 1938 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); |
1939 | | | 1939 | |
1940 | sysctl_createv(clog, 0, NULL, NULL, | | 1940 | sysctl_createv(clog, 0, NULL, NULL, |
1941 | CTLFLAG_PERMANENT, | | 1941 | CTLFLAG_PERMANENT, |
1942 | CTLTYPE_STRING, "booted_kernel", NULL, | | 1942 | CTLTYPE_STRING, "booted_kernel", NULL, |
1943 | sysctl_machdep_boot, 0, NULL, 0, | | 1943 | sysctl_machdep_boot, 0, NULL, 0, |
1944 | CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); | | 1944 | CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); |
1945 | } | | 1945 | } |
1946 | | | 1946 | |
1947 | /* | | 1947 | /* |
1948 | * Given the type of a bootinfo entry, looks for a matching item inside | | 1948 | * Given the type of a bootinfo entry, looks for a matching item inside |
1949 | * the bootinfo structure. If found, returns a pointer to it (which must | | 1949 | * the bootinfo structure. If found, returns a pointer to it (which must |
1950 | * then be casted to the appropriate bootinfo_* type); otherwise, returns | | 1950 | * then be casted to the appropriate bootinfo_* type); otherwise, returns |
1951 | * NULL. | | 1951 | * NULL. |
1952 | */ | | 1952 | */ |
1953 | void * | | 1953 | void * |
1954 | lookup_bootinfo(int type) | | 1954 | lookup_bootinfo(int type) |
1955 | { | | 1955 | { |
1956 | struct btinfo_common *bic; | | 1956 | struct btinfo_common *bic; |
1957 | int i; | | 1957 | int i; |
1958 | | | 1958 | |
1959 | bic = (struct btinfo_common *)(&bootinfo.bi_data[0]); | | 1959 | bic = (struct btinfo_common *)(&bootinfo.bi_data[0]); |
1960 | for (i = 0; i < bootinfo.bi_nentries; i++) | | 1960 | for (i = 0; i < bootinfo.bi_nentries; i++) |
1961 | if (bic->type == type) | | 1961 | if (bic->type == type) |
1962 | return bic; | | 1962 | return bic; |
1963 | else | | 1963 | else |
1964 | bic = (struct btinfo_common *) | | 1964 | bic = (struct btinfo_common *) |
1965 | ((uint8_t *)bic + bic->len); | | 1965 | ((uint8_t *)bic + bic->len); |
1966 | | | 1966 | |
1967 | return NULL; | | 1967 | return NULL; |
1968 | } | | 1968 | } |
1969 | | | 1969 | |
1970 | /* | | 1970 | /* |
1971 | * consinit: | | 1971 | * consinit: |
1972 | * initialize the system console. | | 1972 | * initialize the system console. |
1973 | */ | | 1973 | */ |
1974 | void | | 1974 | void |
1975 | consinit(void) | | 1975 | consinit(void) |
1976 | { | | 1976 | { |
1977 | static int initted = 0; | | 1977 | static int initted = 0; |
1978 | | | 1978 | |
1979 | if (!initted) { | | 1979 | if (!initted) { |
1980 | initted++; | | 1980 | initted++; |
1981 | cninit(); | | 1981 | cninit(); |
1982 | } | | 1982 | } |
1983 | } | | 1983 | } |
1984 | | | 1984 | |
1985 | #ifdef MODULAR | | 1985 | #ifdef MODULAR |
1986 | /* | | 1986 | /* |
1987 | * Push any modules loaded by the boot loader. | | 1987 | * Push any modules loaded by the boot loader. |
1988 | */ | | 1988 | */ |
1989 | void | | 1989 | void |
1990 | module_init_md(void) | | 1990 | module_init_md(void) |
1991 | { | | 1991 | { |
1992 | } | | 1992 | } |
1993 | #endif /* MODULAR */ | | 1993 | #endif /* MODULAR */ |
1994 | | | 1994 | |