| @@ -1,1796 +1,1795 @@ | | | @@ -1,1796 +1,1795 @@ |
1 | /* $NetBSD: machdep.c,v 1.66 2009/05/18 05:20:46 skrll Exp $ */ | | 1 | /* $NetBSD: machdep.c,v 1.67 2009/05/29 08:37:34 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.66 2009/05/18 05:20:46 skrll Exp $"); | | 61 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.67 2009/05/29 08:37:34 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/user.h> | | 85 | #include <sys/user.h> |
86 | #include <sys/exec.h> | | 86 | #include <sys/exec.h> |
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 user *proc0paddr; | | 244 | struct user *proc0paddr; |
245 | struct extent *hp700_io_extent; | | 245 | struct extent *hp700_io_extent; |
246 | static long hp700_io_extent_store[EXTENT_FIXED_STORAGE_SIZE(64) / sizeof(long)]; | | 246 | static long hp700_io_extent_store[EXTENT_FIXED_STORAGE_SIZE(64) / sizeof(long)]; |
247 | | | 247 | |
248 | /* Virtual page frame for /dev/mem (see mem.c) */ | | 248 | /* Virtual page frame for /dev/mem (see mem.c) */ |
249 | vaddr_t vmmap; | | 249 | vaddr_t vmmap; |
250 | | | 250 | |
251 | /* | | 251 | /* |
252 | * Certain devices need DMA'able memory below the 16MB boundary. | | 252 | * Certain devices need DMA'able memory below the 16MB boundary. |
253 | */ | | 253 | */ |
254 | #define DMA24_SIZE (128 * 1024) | | 254 | #define DMA24_SIZE (128 * 1024) |
255 | struct extent *dma24_ex; | | 255 | struct extent *dma24_ex; |
256 | long dma24_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; | | 256 | long dma24_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; |
257 | | | 257 | |
258 | /* Our exported CPU info; we can have only one. */ | | 258 | /* Our exported CPU info; we can have only one. */ |
259 | struct cpu_info cpu_info_store = { | | 259 | struct cpu_info cpu_info_store = { |
260 | #ifdef MULTIPROCESSOR | | 260 | #ifdef MULTIPROCESSOR |
261 | .ci_curlwp = &lwp0 | | 261 | .ci_curlwp = &lwp0 |
262 | #endif | | 262 | #endif |
263 | }; | | 263 | }; |
264 | | | 264 | |
265 | struct vm_map *mb_map = NULL; | | 265 | struct vm_map *mb_map = NULL; |
266 | struct vm_map *phys_map = NULL; | | 266 | struct vm_map *phys_map = NULL; |
267 | | | 267 | |
268 | void delay_init(void); | | 268 | void delay_init(void); |
269 | static inline void fall(int, int, int, int, int); | | 269 | static inline void fall(int, int, int, int, int); |
270 | void dumpsys(void); | | 270 | void dumpsys(void); |
271 | void cpuid(void); | | 271 | void cpuid(void); |
272 | enum hppa_cpu_type cpu_model_cpuid(int); | | 272 | enum hppa_cpu_type cpu_model_cpuid(int); |
273 | | | 273 | |
274 | /* | | 274 | /* |
275 | * wide used hardware params | | 275 | * wide used hardware params |
276 | */ | | 276 | */ |
277 | struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; | | 277 | struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; |
278 | struct pdc_coproc pdc_coproc PDC_ALIGNMENT; | | 278 | struct pdc_coproc pdc_coproc PDC_ALIGNMENT; |
279 | struct pdc_coherence pdc_coherence PDC_ALIGNMENT; | | 279 | struct pdc_coherence pdc_coherence PDC_ALIGNMENT; |
280 | struct pdc_spidb pdc_spidbits PDC_ALIGNMENT; | | 280 | struct pdc_spidb pdc_spidbits PDC_ALIGNMENT; |
281 | struct pdc_pim pdc_pim PDC_ALIGNMENT; | | 281 | struct pdc_pim pdc_pim PDC_ALIGNMENT; |
282 | struct pdc_model pdc_model PDC_ALIGNMENT; | | 282 | struct pdc_model pdc_model PDC_ALIGNMENT; |
283 | | | 283 | |
284 | /* | | 284 | /* |
285 | * Debugger info. | | 285 | * Debugger info. |
286 | */ | | 286 | */ |
287 | int hp700_kgdb_attached; | | 287 | int hp700_kgdb_attached; |
288 | | | 288 | |
289 | /* | | 289 | /* |
290 | * Whatever CPU types we support | | 290 | * Whatever CPU types we support |
291 | */ | | 291 | */ |
292 | extern const u_int itlb_x[], itlbna_x[], dtlb_x[], dtlbna_x[], tlbd_x[]; | | 292 | extern const u_int itlb_x[], itlbna_x[], dtlb_x[], dtlbna_x[], tlbd_x[]; |
293 | extern const u_int itlb_s[], itlbna_s[], dtlb_s[], dtlbna_s[], tlbd_s[]; | | 293 | extern const u_int itlb_s[], itlbna_s[], dtlb_s[], dtlbna_s[], tlbd_s[]; |
294 | extern const u_int itlb_t[], itlbna_t[], dtlb_t[], dtlbna_t[], tlbd_t[]; | | 294 | extern const u_int itlb_t[], itlbna_t[], dtlb_t[], dtlbna_t[], tlbd_t[]; |
295 | extern const u_int itlb_l[], itlbna_l[], dtlb_l[], dtlbna_l[], tlbd_l[]; | | 295 | extern const u_int itlb_l[], itlbna_l[], dtlb_l[], dtlbna_l[], tlbd_l[]; |
296 | extern const u_int itlb_u[], itlbna_u[], dtlb_u[], dtlbna_u[], tlbd_u[]; | | 296 | extern const u_int itlb_u[], itlbna_u[], dtlb_u[], dtlbna_u[], tlbd_u[]; |
297 | | | 297 | |
298 | int iibtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 298 | int iibtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
299 | int idbtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 299 | int idbtlb_s(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
300 | int ibtlb_t(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 300 | int ibtlb_t(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
301 | int ibtlb_l(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 301 | int ibtlb_l(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
302 | int ibtlb_u(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 302 | int ibtlb_u(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
303 | int ibtlb_g(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); | | 303 | int ibtlb_g(int, pa_space_t, vaddr_t, paddr_t, vsize_t, u_int); |
304 | int pbtlb_g(int); | | 304 | int pbtlb_g(int); |
305 | int pbtlb_u(int); | | 305 | int pbtlb_u(int); |
306 | int hpti_l(vaddr_t, vsize_t); | | 306 | int hpti_l(vaddr_t, vsize_t); |
307 | int hpti_u(vaddr_t, vsize_t); | | 307 | int hpti_u(vaddr_t, vsize_t); |
308 | int hpti_g(vaddr_t, vsize_t); | | 308 | int hpti_g(vaddr_t, vsize_t); |
309 | int desidhash_x(void); | | 309 | int desidhash_x(void); |
310 | int desidhash_s(void); | | 310 | int desidhash_s(void); |
311 | int desidhash_t(void); | | 311 | int desidhash_t(void); |
312 | int desidhash_l(void); | | 312 | int desidhash_l(void); |
313 | int desidhash_u(void); | | 313 | int desidhash_u(void); |
314 | | | 314 | |
315 | const struct hppa_cpu_info cpu_types[] = { | | 315 | const struct hppa_cpu_info cpu_types[] = { |
316 | #ifdef HP7000_CPU | | 316 | #ifdef HP7000_CPU |
317 | { "PA7000", NULL, "PCX", | | 317 | { "PA7000", NULL, "PCX", |
318 | hpcx, 0, 0, "1.0", | | 318 | hpcx, 0, 0, "1.0", |
319 | desidhash_x, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, | | 319 | desidhash_x, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, |
320 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ | | 320 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ |
321 | #endif | | 321 | #endif |
322 | #ifdef HP7000_CPU | | 322 | #ifdef HP7000_CPU |
323 | { "PA7000", NULL, "PCXS", | | 323 | { "PA7000", NULL, "PCXS", |
324 | hpcxs, 0, 0, "1.1a", | | 324 | hpcxs, 0, 0, "1.1a", |
325 | desidhash_s, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, | | 325 | desidhash_s, itlb_x, dtlb_x, itlbna_x, dtlbna_x, tlbd_x, |
326 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ | | 326 | ibtlb_g, NULL, pbtlb_g }, /* XXXNH check */ |
327 | #endif | | 327 | #endif |
328 | #ifdef HP7100_CPU | | 328 | #ifdef HP7100_CPU |
329 | { "PA7100", "T-Bird", "PCXT", | | 329 | { "PA7100", "T-Bird", "PCXT", |
330 | hpcxt, 0, HPPA_FTRS_BTLBU, "1.1b", | | 330 | hpcxt, 0, HPPA_FTRS_BTLBU, "1.1b", |
331 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, | | 331 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, |
332 | ibtlb_g, NULL, pbtlb_g }, | | 332 | ibtlb_g, NULL, pbtlb_g }, |
333 | #endif | | 333 | #endif |
334 | #ifdef HP7100LC_CPU | | 334 | #ifdef HP7100LC_CPU |
335 | { "PA7100LC", "Hummingbird", "PCXL", | | 335 | { "PA7100LC", "Hummingbird", "PCXL", |
336 | hpcxl, HPPA_CPU_PCXL, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1c", | | 336 | hpcxl, HPPA_CPU_PCXL, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1c", |
337 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, | | 337 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, |
338 | ibtlb_g, NULL, pbtlb_g, hpti_g }, | | 338 | ibtlb_g, NULL, pbtlb_g, hpti_g }, |
339 | #endif | | 339 | #endif |
340 | #ifdef HP7200_CPU | | 340 | #ifdef HP7200_CPU |
341 | { "PA7200", "T-Bird", "PCXT'", | | 341 | { "PA7200", "T-Bird", "PCXT'", |
342 | hpcxtp, HPPA_CPU_PCXT2, HPPA_FTRS_BTLBU, "1.1d", | | 342 | hpcxtp, HPPA_CPU_PCXT2, HPPA_FTRS_BTLBU, "1.1d", |
343 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, | | 343 | desidhash_t, itlb_t, dtlb_t, itlbna_t, dtlbna_t, tlbd_t, |
344 | ibtlb_g, NULL, pbtlb_g }, | | 344 | ibtlb_g, NULL, pbtlb_g }, |
345 | #endif | | 345 | #endif |
346 | #ifdef HP7300LC_CPU | | 346 | #ifdef HP7300LC_CPU |
347 | { "PA7300LC", "Velociraptor", "PCXL2", | | 347 | { "PA7300LC", "Velociraptor", "PCXL2", |
348 | hpcxl2, HPPA_CPU_PCXL2, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1e", | | 348 | hpcxl2, HPPA_CPU_PCXL2, HPPA_FTRS_BTLBU|HPPA_FTRS_HVT, "1.1e", |
349 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, | | 349 | desidhash_l, itlb_l, dtlb_l, itlbna_l, dtlbna_l, tlbd_l, |
350 | ibtlb_g, NULL, pbtlb_g, hpti_g }, | | 350 | ibtlb_g, NULL, pbtlb_g, hpti_g }, |
351 | #endif | | 351 | #endif |
352 | #ifdef HP8000_CPU | | 352 | #ifdef HP8000_CPU |
353 | { "PA8000", "Onyx", "PCXU", | | 353 | { "PA8000", "Onyx", "PCXU", |
354 | hpcxu, HPPA_CPU_PCXU, HPPA_FTRS_W32B, "2.0", | | 354 | hpcxu, HPPA_CPU_PCXU, HPPA_FTRS_W32B, "2.0", |
355 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 355 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
356 | ibtlb_u, NULL, pbtlb_u }, | | 356 | ibtlb_u, NULL, pbtlb_u }, |
357 | #endif | | 357 | #endif |
358 | #ifdef HP8200_CPU | | 358 | #ifdef HP8200_CPU |
359 | { "PA8200", "Vulcan", "PCXU+", | | 359 | { "PA8200", "Vulcan", "PCXU+", |
360 | hpcxup, HPPA_CPU_PCXUP, HPPA_FTRS_W32B, "2.0", | | 360 | hpcxup, HPPA_CPU_PCXUP, HPPA_FTRS_W32B, "2.0", |
361 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 361 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
362 | ibtlb_u, NULL, pbtlb_u }, | | 362 | ibtlb_u, NULL, pbtlb_u }, |
363 | #endif | | 363 | #endif |
364 | #ifdef HP8500_CPU | | 364 | #ifdef HP8500_CPU |
365 | { "PA8500", "Barra'Cuda", "PCXW", | | 365 | { "PA8500", "Barra'Cuda", "PCXW", |
366 | hpcxw, HPPA_CPU_PCXW, HPPA_FTRS_W32B, "2.0", | | 366 | hpcxw, HPPA_CPU_PCXW, HPPA_FTRS_W32B, "2.0", |
367 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 367 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
368 | ibtlb_u, NULL, pbtlb_u }, | | 368 | ibtlb_u, NULL, pbtlb_u }, |
369 | #endif | | 369 | #endif |
370 | #ifdef HP8600_CPU | | 370 | #ifdef HP8600_CPU |
371 | { "PA8600", "Landshark", "PCXW+", | | 371 | { "PA8600", "Landshark", "PCXW+", |
372 | hpcxwp, HPPA_CPU_PCXW2 /*XXX NH */, HPPA_FTRS_W32B, "2.0", | | 372 | hpcxwp, HPPA_CPU_PCXW2 /*XXX NH */, HPPA_FTRS_W32B, "2.0", |
373 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 373 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
374 | ibtlb_u, NULL, pbtlb_u }, | | 374 | ibtlb_u, NULL, pbtlb_u }, |
375 | #endif | | 375 | #endif |
376 | #ifdef HP8700_CPU | | 376 | #ifdef HP8700_CPU |
377 | { "PA8700", "Piranha", "PCXW2", | | 377 | { "PA8700", "Piranha", "PCXW2", |
378 | hpcxw2, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", | | 378 | hpcxw2, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", |
379 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 379 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
380 | ibtlb_u, NULL, pbtlb_u }, | | 380 | ibtlb_u, NULL, pbtlb_u }, |
381 | #endif | | 381 | #endif |
382 | #ifdef HP8800_CPU | | 382 | #ifdef HP8800_CPU |
383 | { "PA8800", "Mako", "Make", | | 383 | { "PA8800", "Mako", "Make", |
384 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", | | 384 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", |
385 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 385 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
386 | ibtlb_u, NULL, pbtlb_u }, | | 386 | ibtlb_u, NULL, pbtlb_u }, |
387 | #endif | | 387 | #endif |
388 | #ifdef HP8900_CPU | | 388 | #ifdef HP8900_CPU |
389 | { "PA8900", "Shortfin", "Shortfin", | | 389 | { "PA8900", "Shortfin", "Shortfin", |
390 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", | | 390 | mako, HPPA_CPU_PCXW2, HPPA_FTRS_W32B, "2.0", |
391 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, | | 391 | desidhash_u, itlb_u, dtlb_u, itlbna_u, dtlbna_u, tlbd_u, |
392 | ibtlb_u, NULL, pbtlb_u }, | | 392 | ibtlb_u, NULL, pbtlb_u }, |
393 | #endif | | 393 | #endif |
394 | { "" } | | 394 | { "" } |
395 | }; | | 395 | }; |
396 | | | 396 | |
397 | extern kmutex_t vmmap_lock; | | 397 | extern kmutex_t vmmap_lock; |
398 | | | 398 | |
399 | void | | 399 | void |
400 | hppa_init(paddr_t start, void *bi) | | 400 | hppa_init(paddr_t start, void *bi) |
401 | { | | 401 | { |
402 | vaddr_t vstart; | | 402 | vaddr_t vstart; |
403 | vaddr_t v; | | 403 | vaddr_t v; |
404 | int error; | | 404 | int error; |
405 | u_int *p, *q; | | 405 | u_int *p, *q; |
406 | struct btlb_slot *btlb_slot; | | 406 | struct btlb_slot *btlb_slot; |
407 | int btlb_slot_i; | | 407 | int btlb_slot_i; |
408 | struct btinfo_symtab *bi_sym; | | 408 | struct btinfo_symtab *bi_sym; |
409 | | | 409 | |
410 | #ifdef KGDB | | 410 | #ifdef KGDB |
411 | boothowto |= RB_KDB; /* go to kgdb early if compiled in. */ | | 411 | boothowto |= RB_KDB; /* go to kgdb early if compiled in. */ |
412 | #endif | | 412 | #endif |
413 | /* Setup curlwp early for LOCKDEBUG */ | | 413 | /* Setup curlwp early for LOCKDEBUG */ |
414 | mtctl(&lwp0, CR_CURLWP); | | 414 | mtctl(&lwp0, CR_CURLWP); |
415 | | | 415 | |
416 | /* Copy bootinfo */ | | 416 | /* Copy bootinfo */ |
417 | if (bi != NULL) | | 417 | if (bi != NULL) |
418 | memcpy(&bootinfo, bi, sizeof(struct bootinfo)); | | 418 | memcpy(&bootinfo, bi, sizeof(struct bootinfo)); |
419 | | | 419 | |
420 | pdc_init(); /* init PDC iface, so we can call em easy */ | | 420 | pdc_init(); /* init PDC iface, so we can call em easy */ |
421 | | | 421 | |
422 | cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; | | 422 | cpu_hzticks = (PAGE0->mem_10msec * 100) / hz; |
423 | delay_init(); /* calculate CPU clock ratio */ | | 423 | delay_init(); /* calculate CPU clock ratio */ |
424 | | | 424 | |
425 | /* cache parameters */ | | 425 | /* cache parameters */ |
426 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, | | 426 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, |
427 | &pdc_cache)) < 0) { | | 427 | &pdc_cache)) < 0) { |
428 | #ifdef DEBUG | | 428 | #ifdef DEBUG |
429 | printf("WARNING: PDC_CACHE error %d\n", error); | | 429 | printf("WARNING: PDC_CACHE error %d\n", error); |
430 | #endif | | 430 | #endif |
431 | } | | 431 | } |
432 | | | 432 | |
433 | dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; | | 433 | dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; |
434 | dcache_stride = pdc_cache.dc_stride; | | 434 | dcache_stride = pdc_cache.dc_stride; |
435 | icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1; | | 435 | icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1; |
436 | icache_stride = pdc_cache.ic_stride; | | 436 | icache_stride = pdc_cache.ic_stride; |
437 | | | 437 | |
438 | /* cache coherence params (pbably available for 8k only) */ | | 438 | /* cache coherence params (pbably available for 8k only) */ |
439 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS, | | 439 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS, |
440 | &pdc_coherence, 1, 1, 1, 1); | | 440 | &pdc_coherence, 1, 1, 1, 1); |
441 | #ifdef DEBUG | | 441 | #ifdef DEBUG |
442 | printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n", | | 442 | printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n", |
443 | pdc_coherence.ia_cst, pdc_coherence.da_cst, | | 443 | pdc_coherence.ia_cst, pdc_coherence.da_cst, |
444 | pdc_coherence.ita_cst, pdc_coherence.dta_cst, error); | | 444 | pdc_coherence.ita_cst, pdc_coherence.dta_cst, error); |
445 | #endif | | 445 | #endif |
446 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB, | | 446 | error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB, |
447 | &pdc_spidbits, 0, 0, 0, 0); | | 447 | &pdc_spidbits, 0, 0, 0, 0); |
448 | #ifdef DEBUG | | 448 | #ifdef DEBUG |
449 | printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error); | | 449 | printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error); |
450 | #endif | | 450 | #endif |
451 | | | 451 | |
452 | /* Calculate the OS_HPMC handler checksums. */ | | 452 | /* Calculate the OS_HPMC handler checksums. */ |
453 | p = &os_hpmc; | | 453 | p = &os_hpmc; |
454 | if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p)) | | 454 | if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p)) |
455 | *p = 0x08000240; | | 455 | *p = 0x08000240; |
456 | p[7] = ((char *) &os_hpmc_cont_end) - ((char *) &os_hpmc_cont); | | 456 | p[7] = ((char *) &os_hpmc_cont_end) - ((char *) &os_hpmc_cont); |
457 | p[6] = (u_int) &os_hpmc_cont; | | 457 | p[6] = (u_int) &os_hpmc_cont; |
458 | p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]); | | 458 | p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]); |
459 | p = &os_hpmc_cont; | | 459 | p = &os_hpmc_cont; |
460 | q = (&os_hpmc_cont_end - 1); | | 460 | q = (&os_hpmc_cont_end - 1); |
461 | for(*q = 0; p < q; *q -= *(p++)); | | 461 | for(*q = 0; p < q; *q -= *(p++)); |
462 | | | 462 | |
463 | /* Calculate the OS_TOC handler checksum. */ | | 463 | /* Calculate the OS_TOC handler checksum. */ |
464 | p = (u_int *) &os_toc; | | 464 | p = (u_int *) &os_toc; |
465 | q = (&os_toc_end - 1); | | 465 | q = (&os_toc_end - 1); |
466 | for (*q = 0; p < q; *q -= *(p++)); | | 466 | for (*q = 0; p < q; *q -= *(p++)); |
467 | | | 467 | |
468 | /* Install the OS_TOC handler. */ | | 468 | /* Install the OS_TOC handler. */ |
469 | PAGE0->ivec_toc = os_toc; | | 469 | PAGE0->ivec_toc = os_toc; |
470 | PAGE0->ivec_toclen = ((char *) &os_toc_end) - ((char *) &os_toc); | | 470 | PAGE0->ivec_toclen = ((char *) &os_toc_end) - ((char *) &os_toc); |
471 | | | 471 | |
472 | cpuid(); | | 472 | cpuid(); |
473 | ptlball(); | | 473 | ptlball(); |
474 | fcacheall(); | | 474 | fcacheall(); |
475 | | | 475 | |
476 | avail_end = trunc_page(PAGE0->imm_max_mem); | | 476 | avail_end = trunc_page(PAGE0->imm_max_mem); |
477 | totalphysmem = atop(avail_end); | | 477 | totalphysmem = atop(avail_end); |
478 | if (avail_end > SYSCALLGATE) | | 478 | if (avail_end > SYSCALLGATE) |
479 | avail_end = SYSCALLGATE; | | 479 | avail_end = SYSCALLGATE; |
480 | physmem = atop(avail_end); | | 480 | physmem = atop(avail_end); |
481 | resvmem = atop(resvmem); /* XXXNH */ | | 481 | resvmem = atop(resvmem); /* XXXNH */ |
482 | | | 482 | |
483 | /* we hope this won't fail */ | | 483 | /* we hope this won't fail */ |
484 | hp700_io_extent = extent_create("io", | | 484 | hp700_io_extent = extent_create("io", |
485 | HPPA_IOSPACE, 0xffffffff, M_DEVBUF, | | 485 | HPPA_IOSPACE, 0xffffffff, M_DEVBUF, |
486 | (void *)hp700_io_extent_store, sizeof(hp700_io_extent_store), | | 486 | (void *)hp700_io_extent_store, sizeof(hp700_io_extent_store), |
487 | EX_NOCOALESCE|EX_NOWAIT); | | 487 | EX_NOCOALESCE|EX_NOWAIT); |
488 | | | 488 | |
489 | vstart = round_page(start); | | 489 | vstart = round_page(start); |
490 | | | 490 | |
491 | /* | | 491 | /* |
492 | * Now allocate kernel dynamic variables | | 492 | * Now allocate kernel dynamic variables |
493 | */ | | 493 | */ |
494 | | | 494 | |
495 | /* Allocate the msgbuf. */ | | 495 | /* Allocate the msgbuf. */ |
496 | msgbufaddr = (void *) vstart; | | 496 | msgbufaddr = (void *) vstart; |
497 | vstart += MSGBUFSIZE; | | 497 | vstart += MSGBUFSIZE; |
498 | vstart = round_page(vstart); | | 498 | vstart = round_page(vstart); |
499 | | | 499 | |
500 | /* Allocate the 24-bit DMA region. */ | | 500 | /* Allocate the 24-bit DMA region. */ |
501 | dma24_ex = extent_create("dma24", vstart, vstart + DMA24_SIZE, M_DEVBUF, | | 501 | dma24_ex = extent_create("dma24", vstart, vstart + DMA24_SIZE, M_DEVBUF, |
502 | (void *)dma24_ex_storage, sizeof(dma24_ex_storage), | | 502 | (void *)dma24_ex_storage, sizeof(dma24_ex_storage), |
503 | EX_NOCOALESCE|EX_NOWAIT); | | 503 | EX_NOCOALESCE|EX_NOWAIT); |
504 | vstart += DMA24_SIZE; | | 504 | vstart += DMA24_SIZE; |
505 | vstart = round_page(vstart); | | 505 | vstart = round_page(vstart); |
506 | | | 506 | |
507 | | | 507 | |
508 | if (usebtlb) { | | 508 | if (usebtlb) { |
509 | /* Allocate and initialize the BTLB slots array. */ | | 509 | /* Allocate and initialize the BTLB slots array. */ |
510 | btlb_slots = (struct btlb_slot *) ALIGN(vstart); | | 510 | btlb_slots = (struct btlb_slot *) ALIGN(vstart); |
511 | btlb_slot = btlb_slots; | | 511 | btlb_slot = btlb_slots; |
512 | #define BTLB_SLOTS(count, flags) \ | | 512 | #define BTLB_SLOTS(count, flags) \ |
513 | do { \ | | 513 | do { \ |
514 | for (btlb_slot_i = 0; \ | | 514 | for (btlb_slot_i = 0; \ |
515 | btlb_slot_i < pdc_btlb.count; \ | | 515 | btlb_slot_i < pdc_btlb.count; \ |
516 | btlb_slot_i++) { \ | | 516 | btlb_slot_i++) { \ |
517 | btlb_slot->btlb_slot_number = (btlb_slot - btlb_slots); \ | | 517 | btlb_slot->btlb_slot_number = (btlb_slot - btlb_slots); \ |
518 | btlb_slot->btlb_slot_flags = flags; \ | | 518 | btlb_slot->btlb_slot_flags = flags; \ |
519 | btlb_slot->btlb_slot_frames = 0; \ | | 519 | btlb_slot->btlb_slot_frames = 0; \ |
520 | btlb_slot++; \ | | 520 | btlb_slot++; \ |
521 | } \ | | 521 | } \ |
522 | } while (/* CONSTCOND */ 0) | | 522 | } while (/* CONSTCOND */ 0) |
523 | | | 523 | |
524 | BTLB_SLOTS(finfo.num_i, BTLB_SLOT_IBTLB); | | 524 | BTLB_SLOTS(finfo.num_i, BTLB_SLOT_IBTLB); |
525 | BTLB_SLOTS(finfo.num_d, BTLB_SLOT_DBTLB); | | 525 | BTLB_SLOTS(finfo.num_d, BTLB_SLOT_DBTLB); |
526 | BTLB_SLOTS(finfo.num_c, BTLB_SLOT_CBTLB); | | 526 | BTLB_SLOTS(finfo.num_c, BTLB_SLOT_CBTLB); |
527 | BTLB_SLOTS(vinfo.num_i, BTLB_SLOT_IBTLB | BTLB_SLOT_VARIABLE_RANGE); | | 527 | BTLB_SLOTS(vinfo.num_i, BTLB_SLOT_IBTLB | BTLB_SLOT_VARIABLE_RANGE); |
528 | BTLB_SLOTS(vinfo.num_d, BTLB_SLOT_DBTLB | BTLB_SLOT_VARIABLE_RANGE); | | 528 | BTLB_SLOTS(vinfo.num_d, BTLB_SLOT_DBTLB | BTLB_SLOT_VARIABLE_RANGE); |
529 | BTLB_SLOTS(vinfo.num_c, BTLB_SLOT_CBTLB | BTLB_SLOT_VARIABLE_RANGE); | | 529 | BTLB_SLOTS(vinfo.num_c, BTLB_SLOT_CBTLB | BTLB_SLOT_VARIABLE_RANGE); |
530 | #undef BTLB_SLOTS | | 530 | #undef BTLB_SLOTS |
531 | | | 531 | |
532 | btlb_slots_count = (btlb_slot - btlb_slots); | | 532 | btlb_slots_count = (btlb_slot - btlb_slots); |
533 | vstart = round_page((vaddr_t) btlb_slot); | | 533 | vstart = round_page((vaddr_t) btlb_slot); |
534 | } | | 534 | } |
535 | | | 535 | |
536 | v = vstart; | | 536 | v = vstart; |
537 | | | 537 | |
538 | /* sets resvphysmem */ | | 538 | /* sets resvphysmem */ |
539 | pmap_bootstrap(v); | | 539 | pmap_bootstrap(v); |
540 | | | 540 | |
541 | /* | | 541 | /* |
542 | * BELOW THIS LINE REFERENCING PAGE0 AND OTHER LOW MEMORY | | 542 | * BELOW THIS LINE REFERENCING PAGE0 AND OTHER LOW MEMORY |
543 | * LOCATIONS, AND WRITING THE KERNEL TEXT ARE PROHIBITED | | 543 | * LOCATIONS, AND WRITING THE KERNEL TEXT ARE PROHIBITED |
544 | * WITHOUT TAKING SPECIAL MEASURES. | | 544 | * WITHOUT TAKING SPECIAL MEASURES. |
545 | */ | | 545 | */ |
546 | | | 546 | |
547 | #ifdef DEBUG | | 547 | #ifdef DEBUG |
548 | printf("%s: PDC_CHASSIS\n", __func__); | | 548 | printf("%s: PDC_CHASSIS\n", __func__); |
549 | #endif | | 549 | #endif |
550 | /* they say PDC_COPROC might turn fault light on */ | | 550 | /* they say PDC_COPROC might turn fault light on */ |
551 | pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP, | | 551 | pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP, |
552 | PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0); | | 552 | PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0); |
553 | | | 553 | |
554 | #ifdef DEBUG | | 554 | #ifdef DEBUG |
555 | printf("%s: intr bootstrap\n", __func__); | | 555 | printf("%s: intr bootstrap\n", __func__); |
556 | #endif | | 556 | #endif |
557 | /* Bootstrap interrupt masking and dispatching. */ | | 557 | /* Bootstrap interrupt masking and dispatching. */ |
558 | hp700_intr_bootstrap(); | | 558 | hp700_intr_bootstrap(); |
559 | | | 559 | |
560 | /* | | 560 | /* |
561 | * Initialize any debugger. | | 561 | * Initialize any debugger. |
562 | */ | | 562 | */ |
563 | #ifdef KGDB | | 563 | #ifdef KGDB |
564 | /* | | 564 | /* |
565 | * XXX note that we're not virtual yet, yet these | | 565 | * XXX note that we're not virtual yet, yet these |
566 | * KGDB attach functions will be using bus_space(9) | | 566 | * KGDB attach functions will be using bus_space(9) |
567 | * to map and manipulate their devices. This only | | 567 | * to map and manipulate their devices. This only |
568 | * works because, currently, the mainbus.c bus_space | | 568 | * works because, currently, the mainbus.c bus_space |
569 | * implementation directly-maps things in I/O space. | | 569 | * implementation directly-maps things in I/O space. |
570 | */ | | 570 | */ |
571 | hp700_kgdb_attached = false; | | 571 | hp700_kgdb_attached = false; |
572 | #if NCOM > 0 | | 572 | #if NCOM > 0 |
573 | if (!strcmp(KGDB_DEVNAME, "com")) { | | 573 | if (!strcmp(KGDB_DEVNAME, "com")) { |
574 | int com_gsc_kgdb_attach(void); | | 574 | int com_gsc_kgdb_attach(void); |
575 | if (com_gsc_kgdb_attach() == 0) | | 575 | if (com_gsc_kgdb_attach() == 0) |
576 | hp700_kgdb_attached = true; | | 576 | hp700_kgdb_attached = true; |
577 | } | | 577 | } |
578 | #endif /* NCOM > 0 */ | | 578 | #endif /* NCOM > 0 */ |
579 | #endif /* KGDB */ | | 579 | #endif /* KGDB */ |
580 | | | 580 | |
581 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 581 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
582 | if ((bi_sym = lookup_bootinfo(BTINFO_SYMTAB)) != NULL) | | 582 | if ((bi_sym = lookup_bootinfo(BTINFO_SYMTAB)) != NULL) |
583 | ksyms_addsyms_elf(bi_sym->nsym, (int *)bi_sym->ssym, | | 583 | ksyms_addsyms_elf(bi_sym->nsym, (int *)bi_sym->ssym, |
584 | (int *)bi_sym->esym); | | 584 | (int *)bi_sym->esym); |
585 | else { | | 585 | else { |
586 | extern int end; | | 586 | extern int end; |
587 | | | 587 | |
588 | ksyms_addsyms_elf(esym - (int)&end, &end, (int*)esym); | | 588 | ksyms_addsyms_elf(esym - (int)&end, &end, (int*)esym); |
589 | } | | 589 | } |
590 | #endif | | 590 | #endif |
591 | | | 591 | |
592 | /* We will shortly go virtual. */ | | 592 | /* We will shortly go virtual. */ |
593 | pagezero_mapped = 0; | | 593 | pagezero_mapped = 0; |
594 | fcacheall(); | | 594 | fcacheall(); |
595 | } | | 595 | } |
596 | | | 596 | |
597 | void | | 597 | void |
598 | cpuid(void) | | 598 | cpuid(void) |
599 | { | | 599 | { |
600 | /* | | 600 | /* |
601 | * XXX fredette - much of this TLB trap handler setup should | | 601 | * XXX fredette - much of this TLB trap handler setup should |
602 | * probably be moved here to hppa/hppa/hppa_machdep.c, seeing | | 602 | * probably be moved here to hppa/hppa/hppa_machdep.c, seeing |
603 | * that there's related code already in hppa/hppa/trap.S. | | 603 | * that there's related code already in hppa/hppa/trap.S. |
604 | */ | | 604 | */ |
605 | | | 605 | |
606 | /* | | 606 | /* |
607 | * Ptrs to various tlb handlers, to be filled | | 607 | * Ptrs to various tlb handlers, to be filled |
608 | * based on CPU features. | | 608 | * based on CPU features. |
609 | * from locore.S | | 609 | * from locore.S |
610 | */ | | 610 | */ |
611 | extern u_int trap_ep_T_TLB_DIRTY[]; | | 611 | extern u_int trap_ep_T_TLB_DIRTY[]; |
612 | extern u_int trap_ep_T_DTLBMISS[]; | | 612 | extern u_int trap_ep_T_DTLBMISS[]; |
613 | extern u_int trap_ep_T_DTLBMISSNA[]; | | 613 | extern u_int trap_ep_T_DTLBMISSNA[]; |
614 | extern u_int trap_ep_T_ITLBMISS[]; | | 614 | extern u_int trap_ep_T_ITLBMISS[]; |
615 | extern u_int trap_ep_T_ITLBMISSNA[]; | | 615 | extern u_int trap_ep_T_ITLBMISSNA[]; |
616 | | | 616 | |
617 | struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT; | | 617 | struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT; |
618 | const struct hppa_cpu_info *p = NULL; | | 618 | const struct hppa_cpu_info *p = NULL; |
619 | const char *model; | | 619 | const char *model; |
620 | u_int cpu_version, cpu_features; | | 620 | u_int cpu_version, cpu_features; |
621 | int error; | | 621 | int error; |
622 | extern int kpsw; | | 622 | extern int kpsw; |
623 | | | 623 | |
624 | /* may the scientific guessing begin */ | | 624 | /* may the scientific guessing begin */ |
625 | cpu_type = hpc_unknown; | | 625 | cpu_type = hpc_unknown; |
626 | cpu_features = 0; | | 626 | cpu_features = 0; |
627 | cpu_version = 0; | | 627 | cpu_version = 0; |
628 | | | 628 | |
629 | /* identify system type */ | | 629 | /* identify system type */ |
630 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, | | 630 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, |
631 | &pdc_model)) < 0) { | | 631 | &pdc_model)) < 0) { |
632 | #ifdef DEBUG | | 632 | #ifdef DEBUG |
633 | printf("WARNING: PDC_MODEL_INFO error %d\n", error); | | 633 | printf("WARNING: PDC_MODEL_INFO error %d\n", error); |
634 | #endif | | 634 | #endif |
635 | pdc_model.hvers = 0; | | 635 | pdc_model.hvers = 0; |
636 | } else { | | 636 | } else { |
637 | #ifdef DEBUG | | 637 | #ifdef DEBUG |
638 | printf("pdc_model.hvers %d\n", pdc_model.hvers); | | 638 | printf("pdc_model.hvers %d\n", pdc_model.hvers); |
639 | #endif | | 639 | #endif |
640 | } | | 640 | } |
641 | /* XXXNH - check */ | | 641 | /* XXXNH - check */ |
642 | cpu_hvers = pdc_model.hvers >> 4; | | 642 | cpu_hvers = pdc_model.hvers >> 4; |
643 | model = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers); | | 643 | model = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers); |
644 | #ifdef DEBUG | | 644 | #ifdef DEBUG |
645 | printf("%s: model %s\n", __func__, model); | | 645 | printf("%s: model %s\n", __func__, model); |
646 | #endif | | 646 | #endif |
647 | | | 647 | |
648 | memset(&pdc_cpuid, 0, sizeof(pdc_cpuid)); | | 648 | memset(&pdc_cpuid, 0, sizeof(pdc_cpuid)); |
649 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID, | | 649 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID, |
650 | &pdc_cpuid, 0, 0, 0, 0)) < 0) { | | 650 | &pdc_cpuid, 0, 0, 0, 0)) < 0) { |
651 | #ifdef DEBUG | | 651 | #ifdef DEBUG |
652 | printf("WARNING: PDC_MODEL_CPUID error %d. " | | 652 | printf("WARNING: PDC_MODEL_CPUID error %d. " |
653 | "Using cpu_hvers based cpu_type.\n", error); | | 653 | "Using cpu_hvers based cpu_type.\n", error); |
654 | #endif | | 654 | #endif |
655 | cpu_type = cpu_model_cpuid(cpu_hvers); | | 655 | cpu_type = cpu_model_cpuid(cpu_hvers); |
656 | } else { | | 656 | } else { |
657 | #ifdef DEBUG | | 657 | #ifdef DEBUG |
658 | printf("%s: cpuid.version = %x\n", __func__, | | 658 | printf("%s: cpuid.version = %x\n", __func__, |
659 | pdc_cpuid.version); | | 659 | pdc_cpuid.version); |
660 | printf("%s: cpuid.revision = %x\n", __func__, | | 660 | printf("%s: cpuid.revision = %x\n", __func__, |
661 | pdc_cpuid.revision); | | 661 | pdc_cpuid.revision); |
662 | #endif | | 662 | #endif |
663 | cpu_version = pdc_cpuid.version; | | 663 | cpu_version = pdc_cpuid.version; |
664 | | | 664 | |
665 | /* XXXNH why? */ | | 665 | /* XXXNH why? */ |
666 | /* patch for old 8200 */ | | 666 | /* patch for old 8200 */ |
667 | if (pdc_cpuid.version == HPPA_CPU_PCXU && | | 667 | if (pdc_cpuid.version == HPPA_CPU_PCXU && |
668 | pdc_cpuid.revision > 0x0d) | | 668 | pdc_cpuid.revision > 0x0d) |
669 | cpu_version = HPPA_CPU_PCXUP; | | 669 | cpu_version = HPPA_CPU_PCXUP; |
670 | } | | 670 | } |
671 | | | 671 | |
672 | /* locate coprocessors and SFUs */ | | 672 | /* locate coprocessors and SFUs */ |
673 | memset(&pdc_coproc, 0, sizeof(pdc_coproc)); | | 673 | memset(&pdc_coproc, 0, sizeof(pdc_coproc)); |
674 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, | | 674 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, |
675 | &pdc_coproc, 0, 0, 0, 0)) < 0) { /* XXXNH 0,0,0,0 ???*/ | | 675 | &pdc_coproc, 0, 0, 0, 0)) < 0) { /* XXXNH 0,0,0,0 ???*/ |
676 | printf("WARNING: PDC_COPROC error %d\n", error); | | 676 | printf("WARNING: PDC_COPROC error %d\n", error); |
677 | pdc_coproc.ccr_enable = 0; | | 677 | pdc_coproc.ccr_enable = 0; |
678 | } else { | | 678 | } else { |
679 | #ifdef DEBUG | | 679 | #ifdef DEBUG |
680 | printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n", | | 680 | printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n", |
681 | pdc_coproc.ccr_enable, pdc_coproc.ccr_present, | | 681 | pdc_coproc.ccr_enable, pdc_coproc.ccr_present, |
682 | pdc_coproc.fpu_model, pdc_coproc.fpu_revision); | | 682 | pdc_coproc.fpu_model, pdc_coproc.fpu_revision); |
683 | | | 683 | |
684 | #endif | | 684 | #endif |
685 | /* a kludge to detect PCXW */ | | 685 | /* a kludge to detect PCXW */ |
686 | if (pdc_coproc.fpu_model == HPPA_FPU_PCXW) | | 686 | if (pdc_coproc.fpu_model == HPPA_FPU_PCXW) |
687 | cpu_version = HPPA_CPU_PCXW; | | 687 | cpu_version = HPPA_CPU_PCXW; |
688 | } | | 688 | } |
689 | mtctl(pdc_coproc.ccr_enable & CCR_MASK, CR_CCR); | | 689 | mtctl(pdc_coproc.ccr_enable & CCR_MASK, CR_CCR); |
690 | #ifdef DEBUG | | 690 | #ifdef DEBUG |
691 | printf("%s: bootstrap fpu\n", __func__); | | 691 | printf("%s: bootstrap fpu\n", __func__); |
692 | #endif | | 692 | #endif |
693 | | | 693 | |
694 | usebtlb = 0; | | 694 | usebtlb = 0; |
695 | if (cpu_version == HPPA_CPU_PCXW || cpu_version > HPPA_CPU_PCXL2) { | | 695 | if (cpu_version == HPPA_CPU_PCXW || cpu_version > HPPA_CPU_PCXL2) { |
696 | printf("WARNING: BTLB no supported on cpu %d\n", cpu_version); | | 696 | printf("WARNING: BTLB no supported on cpu %d\n", cpu_version); |
697 | } else { | | 697 | } else { |
698 | | | 698 | |
699 | /* BTLB params */ | | 699 | /* BTLB params */ |
700 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, | | 700 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, |
701 | PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) { | | 701 | PDC_BTLB_DEFAULT, &pdc_btlb)) < 0) { |
702 | #ifdef DEBUG | | 702 | #ifdef DEBUG |
703 | printf("WARNING: PDC_BTLB error %d\n", error); | | 703 | printf("WARNING: PDC_BTLB error %d\n", error); |
704 | #endif | | 704 | #endif |
705 | } else { | | 705 | } else { |
706 | #define BTLBDEBUG 1 | | 706 | #define BTLBDEBUG 1 |
707 | | | 707 | |
708 | #ifdef BTLBDEBUG | | 708 | #ifdef BTLBDEBUG |
709 | printf("btlb info: minsz=%d, maxsz=%d\n", | | 709 | printf("btlb info: minsz=%d, maxsz=%d\n", |
710 | pdc_btlb.min_size, pdc_btlb.max_size); | | 710 | pdc_btlb.min_size, pdc_btlb.max_size); |
711 | printf("btlb fixed: i=%d, d=%d, c=%d\n", | | 711 | printf("btlb fixed: i=%d, d=%d, c=%d\n", |
712 | pdc_btlb.finfo.num_i, | | 712 | pdc_btlb.finfo.num_i, |
713 | pdc_btlb.finfo.num_d, | | 713 | pdc_btlb.finfo.num_d, |
714 | pdc_btlb.finfo.num_c); | | 714 | pdc_btlb.finfo.num_c); |
715 | printf("btlb varbl: i=%d, d=%d, c=%d\n", | | 715 | printf("btlb varbl: i=%d, d=%d, c=%d\n", |
716 | pdc_btlb.vinfo.num_i, | | 716 | pdc_btlb.vinfo.num_i, |
717 | pdc_btlb.vinfo.num_d, | | 717 | pdc_btlb.vinfo.num_d, |
718 | pdc_btlb.vinfo.num_c); | | 718 | pdc_btlb.vinfo.num_c); |
719 | #endif /* BTLBDEBUG */ | | 719 | #endif /* BTLBDEBUG */ |
720 | /* purge TLBs and caches */ | | 720 | /* purge TLBs and caches */ |
721 | if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, | | 721 | if (pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, |
722 | PDC_BTLB_PURGE_ALL) < 0) | | 722 | PDC_BTLB_PURGE_ALL) < 0) |
723 | printf("WARNING: BTLB purge failed\n"); | | 723 | printf("WARNING: BTLB purge failed\n"); |
724 | | | 724 | |
725 | hppa_btlb_size_min = pdc_btlb.min_size; | | 725 | hppa_btlb_size_min = pdc_btlb.min_size; |
726 | hppa_btlb_size_max = pdc_btlb.max_size; | | 726 | hppa_btlb_size_max = pdc_btlb.max_size; |
727 | #ifdef DEBUG | | 727 | #ifdef DEBUG |
728 | printf("hppa_btlb_size_min 0x%x\n", hppa_btlb_size_min); | | 728 | printf("hppa_btlb_size_min 0x%x\n", hppa_btlb_size_min); |
729 | printf("hppa_btlb_size_max 0x%x\n", hppa_btlb_size_max); | | 729 | printf("hppa_btlb_size_max 0x%x\n", hppa_btlb_size_max); |
730 | #endif | | 730 | #endif |
731 | | | 731 | |
732 | if (pdc_btlb.finfo.num_c) | | 732 | if (pdc_btlb.finfo.num_c) |
733 | cpu_features |= HPPA_FTRS_BTLBU; | | 733 | cpu_features |= HPPA_FTRS_BTLBU; |
734 | usebtlb = 1; | | 734 | usebtlb = 1; |
735 | } | | 735 | } |
736 | } | | 736 | } |
737 | usebtlb = 0; | | 737 | usebtlb = 0; |
738 | | | 738 | |
739 | error = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb); | | 739 | error = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdc_hwtlb); |
740 | if (error == 0 && pdc_hwtlb.min_size != 0 && pdc_hwtlb.max_size != 0) { | | 740 | if (error == 0 && pdc_hwtlb.min_size != 0 && pdc_hwtlb.max_size != 0) { |
741 | cpu_features |= HPPA_FTRS_HVT; | | 741 | cpu_features |= HPPA_FTRS_HVT; |
742 | if (pmap_hptsize > pdc_hwtlb.max_size) | | 742 | if (pmap_hptsize > pdc_hwtlb.max_size) |
743 | pmap_hptsize = pdc_hwtlb.max_size; | | 743 | pmap_hptsize = pdc_hwtlb.max_size; |
744 | else if (pmap_hptsize && pmap_hptsize < pdc_hwtlb.min_size) | | 744 | else if (pmap_hptsize && pmap_hptsize < pdc_hwtlb.min_size) |
745 | pmap_hptsize = pdc_hwtlb.min_size; | | 745 | pmap_hptsize = pdc_hwtlb.min_size; |
746 | #ifdef DEBUG | | 746 | #ifdef DEBUG |
747 | printf("%s: pmap_hptsize 0x%x\n", __func__, pmap_hptsize); | | 747 | printf("%s: pmap_hptsize 0x%x\n", __func__, pmap_hptsize); |
748 | #endif | | 748 | #endif |
749 | } else { | | 749 | } else { |
750 | #ifdef DEBUG | | 750 | #ifdef DEBUG |
751 | printf("WARNING: no HPT support, fine!\n"); | | 751 | printf("WARNING: no HPT support, fine!\n"); |
752 | #endif | | 752 | #endif |
753 | pmap_hptsize = 0; | | 753 | pmap_hptsize = 0; |
754 | } | | 754 | } |
755 | | | 755 | |
756 | if (cpu_version) | | 756 | if (cpu_version) |
757 | for (p = cpu_types; p->hci_chip_name; p++) { | | 757 | for (p = cpu_types; p->hci_chip_name; p++) { |
758 | if (p->hci_cpuversion == cpu_version) | | 758 | if (p->hci_cpuversion == cpu_version) |
759 | break; | | 759 | break; |
760 | } | | 760 | } |
761 | else if (cpu_type != hpc_unknown) | | 761 | else if (cpu_type != hpc_unknown) |
762 | for (p = cpu_types; p->hci_chip_name; p++) { | | 762 | for (p = cpu_types; p->hci_chip_name; p++) { |
763 | if (p->hci_cputype == cpu_type) | | 763 | if (p->hci_cputype == cpu_type) |
764 | break; | | 764 | break; |
765 | } | | 765 | } |
766 | else | | 766 | else |
767 | for (p = cpu_types; p->hci_chip_name; p++) { | | 767 | for (p = cpu_types; p->hci_chip_name; p++) { |
768 | if (p->hci_features == cpu_features) | | 768 | if (p->hci_features == cpu_features) |
769 | break; | | 769 | break; |
770 | } | | 770 | } |
771 | | | 771 | |
772 | hppa_cpu_info = p; | | 772 | hppa_cpu_info = p; |
773 | | | 773 | |
774 | if (hppa_cpu_info->hci_chip_name == NULL) | | 774 | if (hppa_cpu_info->hci_chip_name == NULL) |
775 | panic("bad model string for 0x%x", pdc_model.hvers >> 4); | | 775 | panic("bad model string for 0x%x", pdc_model.hvers >> 4); |
776 | else if (hppa_cpu_info->desidhash == NULL) | | 776 | else if (hppa_cpu_info->desidhash == NULL) |
777 | panic("no kernel support for %s", | | 777 | panic("no kernel support for %s", |
778 | hppa_cpu_info->hci_chip_name); | | 778 | hppa_cpu_info->hci_chip_name); |
779 | | | 779 | |
780 | /* | | 780 | /* |
781 | * TODO: HPT on 7200 is not currently supported | | 781 | * TODO: HPT on 7200 is not currently supported |
782 | */ | | 782 | */ |
783 | if (pmap_hptsize && p->hci_cputype != hpcxl && p->hci_cputype != hpcxl2) | | 783 | if (pmap_hptsize && p->hci_cputype != hpcxl && p->hci_cputype != hpcxl2) |
784 | pmap_hptsize = 0; | | 784 | pmap_hptsize = 0; |
785 | | | 785 | |
786 | cpu_type = hppa_cpu_info->hci_cputype; | | 786 | cpu_type = hppa_cpu_info->hci_cputype; |
787 | cpu_ibtlb_ins = hppa_cpu_info->ibtlbins; | | 787 | cpu_ibtlb_ins = hppa_cpu_info->ibtlbins; |
788 | cpu_dbtlb_ins = hppa_cpu_info->dbtlbins; | | 788 | cpu_dbtlb_ins = hppa_cpu_info->dbtlbins; |
789 | cpu_hpt_init = hppa_cpu_info->hptinit; | | 789 | cpu_hpt_init = hppa_cpu_info->hptinit; |
790 | cpu_desidhash = hppa_cpu_info->desidhash; | | 790 | cpu_desidhash = hppa_cpu_info->desidhash; |
791 | | | 791 | |
792 | cpu_revision = (*cpu_desidhash)(); | | 792 | cpu_revision = (*cpu_desidhash)(); |
793 | | | 793 | |
794 | /* force strong ordering for now */ | | 794 | /* force strong ordering for now */ |
795 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) { | | 795 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) |
796 | kpsw |= PSW_O; | | 796 | kpsw |= PSW_O; |
797 | } | | | |
798 | | | 797 | |
799 | snprintf(cpu_model, sizeof(cpu_model), "HP9000/%s", model); | | 798 | snprintf(cpu_model, sizeof(cpu_model), "HP9000/%s", model); |
800 | | | 799 | |
801 | #define LDILDO(t,f) ((t)[0] = (f)[0], (t)[1] = (f)[1]); | | 800 | #define LDILDO(t,f) ((t)[0] = (f)[0], (t)[1] = (f)[1]); |
802 | LDILDO(trap_ep_T_TLB_DIRTY , hppa_cpu_info->tlbdh); | | 801 | LDILDO(trap_ep_T_TLB_DIRTY , hppa_cpu_info->tlbdh); |
803 | LDILDO(trap_ep_T_DTLBMISS , hppa_cpu_info->dtlbh); | | 802 | LDILDO(trap_ep_T_DTLBMISS , hppa_cpu_info->dtlbh); |
804 | LDILDO(trap_ep_T_DTLBMISSNA, hppa_cpu_info->dtlbnah); | | 803 | LDILDO(trap_ep_T_DTLBMISSNA, hppa_cpu_info->dtlbnah); |
805 | LDILDO(trap_ep_T_ITLBMISS , hppa_cpu_info->itlbh); | | 804 | LDILDO(trap_ep_T_ITLBMISS , hppa_cpu_info->itlbh); |
806 | LDILDO(trap_ep_T_ITLBMISSNA, hppa_cpu_info->itlbnah); | | 805 | LDILDO(trap_ep_T_ITLBMISSNA, hppa_cpu_info->itlbnah); |
807 | #undef LDILDO | | 806 | #undef LDILDO |
808 | | | 807 | |
809 | /* Bootstrap any FPU. */ | | 808 | /* Bootstrap any FPU. */ |
810 | hppa_fpu_bootstrap(pdc_coproc.ccr_enable); | | 809 | hppa_fpu_bootstrap(pdc_coproc.ccr_enable); |
811 | } | | 810 | } |
812 | | | 811 | |
813 | enum hppa_cpu_type | | 812 | enum hppa_cpu_type |
814 | cpu_model_cpuid(int hvers) | | 813 | cpu_model_cpuid(int hvers) |
815 | { | | 814 | { |
816 | switch (hvers) { | | 815 | switch (hvers) { |
817 | /* no supported HP8xx/9xx models with pcx */ | | 816 | /* no supported HP8xx/9xx models with pcx */ |
818 | case HPPA_BOARD_HP720: | | 817 | case HPPA_BOARD_HP720: |
819 | case HPPA_BOARD_HP750_66: | | 818 | case HPPA_BOARD_HP750_66: |
820 | case HPPA_BOARD_HP730_66: | | 819 | case HPPA_BOARD_HP730_66: |
821 | case HPPA_BOARD_HP710: | | 820 | case HPPA_BOARD_HP710: |
822 | case HPPA_BOARD_HP705: | | 821 | case HPPA_BOARD_HP705: |
823 | return hpcxs; | | 822 | return hpcxs; |
824 | | | 823 | |
825 | case HPPA_BOARD_HP735_99: | | 824 | case HPPA_BOARD_HP735_99: |
826 | case HPPA_BOARD_HP755_99: | | 825 | case HPPA_BOARD_HP755_99: |
827 | case HPPA_BOARD_HP755_125: | | 826 | case HPPA_BOARD_HP755_125: |
828 | case HPPA_BOARD_HP735_130: | | 827 | case HPPA_BOARD_HP735_130: |
829 | case HPPA_BOARD_HP715_50: | | 828 | case HPPA_BOARD_HP715_50: |
830 | case HPPA_BOARD_HP715_33: | | 829 | case HPPA_BOARD_HP715_33: |
831 | case HPPA_BOARD_HP715S_50: | | 830 | case HPPA_BOARD_HP715S_50: |
832 | case HPPA_BOARD_HP715S_33: | | 831 | case HPPA_BOARD_HP715S_33: |
833 | case HPPA_BOARD_HP715T_50: | | 832 | case HPPA_BOARD_HP715T_50: |
834 | case HPPA_BOARD_HP715T_33: | | 833 | case HPPA_BOARD_HP715T_33: |
835 | case HPPA_BOARD_HP715_75: | | 834 | case HPPA_BOARD_HP715_75: |
836 | case HPPA_BOARD_HP715_99: | | 835 | case HPPA_BOARD_HP715_99: |
837 | case HPPA_BOARD_HP725_50: | | 836 | case HPPA_BOARD_HP725_50: |
838 | case HPPA_BOARD_HP725_75: | | 837 | case HPPA_BOARD_HP725_75: |
839 | case HPPA_BOARD_HP725_99: | | 838 | case HPPA_BOARD_HP725_99: |
840 | return hpcxt; | | 839 | return hpcxt; |
841 | } | | 840 | } |
842 | return hpc_unknown; | | 841 | return hpc_unknown; |
843 | } | | 842 | } |
844 | | | 843 | |
845 | void | | 844 | void |
846 | cpu_startup(void) | | 845 | cpu_startup(void) |
847 | { | | 846 | { |
848 | vaddr_t minaddr, maxaddr; | | 847 | vaddr_t minaddr, maxaddr; |
849 | char pbuf[3][9]; | | 848 | char pbuf[3][9]; |
850 | #ifdef PMAPDEBUG | | 849 | #ifdef PMAPDEBUG |
851 | extern int pmapdebug; | | 850 | extern int pmapdebug; |
852 | int opmapdebug = pmapdebug; | | 851 | int opmapdebug = pmapdebug; |
853 | | | 852 | |
854 | pmapdebug = 0; | | 853 | pmapdebug = 0; |
855 | #endif | | 854 | #endif |
856 | /* Initialize the message buffer. */ | | 855 | /* Initialize the message buffer. */ |
857 | initmsgbuf(msgbufaddr, MSGBUFSIZE); | | 856 | initmsgbuf(msgbufaddr, MSGBUFSIZE); |
858 | | | 857 | |
859 | /* | | 858 | /* |
860 | * i won't understand a friend of mine, | | 859 | * i won't understand a friend of mine, |
861 | * who sat in a room full of artificial ice, | | 860 | * who sat in a room full of artificial ice, |
862 | * fogging the air w/ humid cries -- | | 861 | * fogging the air w/ humid cries -- |
863 | * WELCOME TO SUMMER! | | 862 | * WELCOME TO SUMMER! |
864 | */ | | 863 | */ |
865 | printf("%s%s", copyright, version); | | 864 | printf("%s%s", copyright, version); |
866 | | | 865 | |
867 | /* identify system type */ | | 866 | /* identify system type */ |
868 | printf("%s\n", cpu_model); | | 867 | printf("%s\n", cpu_model); |
869 | | | 868 | |
870 | /* Display some memory usage information. */ | | 869 | /* Display some memory usage information. */ |
871 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(physmem)); | | 870 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(physmem)); |
872 | format_bytes(pbuf[1], sizeof(pbuf[1]), ptoa(resvmem)); | | 871 | format_bytes(pbuf[1], sizeof(pbuf[1]), ptoa(resvmem)); |
873 | format_bytes(pbuf[2], sizeof(pbuf[2]), ptoa(availphysmem)); | | 872 | format_bytes(pbuf[2], sizeof(pbuf[2]), ptoa(availphysmem)); |
874 | printf("real mem = %s (%s reserved for PROM, %s used by NetBSD)\n", | | 873 | printf("real mem = %s (%s reserved for PROM, %s used by NetBSD)\n", |
875 | pbuf[0], pbuf[1], pbuf[2]); | | 874 | pbuf[0], pbuf[1], pbuf[2]); |
876 | | | 875 | |
877 | #ifdef DEBUG | | 876 | #ifdef DEBUG |
878 | if (totalphysmem > physmem) { | | 877 | if (totalphysmem > physmem) { |
879 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(totalphysmem - physmem)); | | 878 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(totalphysmem - physmem)); |
880 | printf("lost mem = %s\n", pbuf[0]); | | 879 | printf("lost mem = %s\n", pbuf[0]); |
881 | } | | 880 | } |
882 | #endif | | 881 | #endif |
883 | | | 882 | |
884 | minaddr = 0; | | 883 | minaddr = 0; |
885 | | | 884 | |
886 | /* | | 885 | /* |
887 | * Allocate a submap for physio | | 886 | * Allocate a submap for physio |
888 | */ | | 887 | */ |
889 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 888 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
890 | VM_PHYS_SIZE, 0, false, NULL); | | 889 | VM_PHYS_SIZE, 0, false, NULL); |
891 | | | 890 | |
892 | mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 891 | mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
893 | nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); | | 892 | nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL); |
894 | | | 893 | |
895 | #ifdef PMAPDEBUG | | 894 | #ifdef PMAPDEBUG |
896 | pmapdebug = opmapdebug; | | 895 | pmapdebug = opmapdebug; |
897 | #endif | | 896 | #endif |
898 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(uvmexp.free)); | | 897 | format_bytes(pbuf[0], sizeof(pbuf[0]), ptoa(uvmexp.free)); |
899 | printf("avail mem = %s\n", pbuf[0]); | | 898 | printf("avail mem = %s\n", pbuf[0]); |
900 | | | 899 | |
901 | /* | | 900 | /* |
902 | * Allocate a virtual page (for use by /dev/mem) | | 901 | * Allocate a virtual page (for use by /dev/mem) |
903 | * This page is handed to pmap_enter() therefore | | 902 | * This page is handed to pmap_enter() therefore |
904 | * it has to be in the normal kernel VA range. | | 903 | * it has to be in the normal kernel VA range. |
905 | */ | | 904 | */ |
906 | vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | | 905 | vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, |
907 | UVM_KMF_VAONLY | UVM_KMF_WAITVA); | | 906 | UVM_KMF_VAONLY | UVM_KMF_WAITVA); |
908 | | | 907 | |
909 | mutex_init(&vmmap_lock, MUTEX_DEFAULT, IPL_NONE); | | 908 | mutex_init(&vmmap_lock, MUTEX_DEFAULT, IPL_NONE); |
910 | } | | 909 | } |
911 | | | 910 | |
912 | /* | | 911 | /* |
913 | * compute CPU clock ratio such as: | | 912 | * compute CPU clock ratio such as: |
914 | * cpu_ticksnum / cpu_ticksdenom = t + delta | | 913 | * cpu_ticksnum / cpu_ticksdenom = t + delta |
915 | * delta -> 0 | | 914 | * delta -> 0 |
916 | */ | | 915 | */ |
917 | void | | 916 | void |
918 | delay_init(void) | | 917 | delay_init(void) |
919 | { | | 918 | { |
920 | u_int num, denom, delta, mdelta; | | 919 | u_int num, denom, delta, mdelta; |
921 | | | 920 | |
922 | mdelta = UINT_MAX; | | 921 | mdelta = UINT_MAX; |
923 | for (denom = 1; denom < 1000; denom++) { | | 922 | for (denom = 1; denom < 1000; denom++) { |
924 | num = (PAGE0->mem_10msec * denom) / 10000; | | 923 | num = (PAGE0->mem_10msec * denom) / 10000; |
925 | delta = num * 10000 / denom - PAGE0->mem_10msec; | | 924 | delta = num * 10000 / denom - PAGE0->mem_10msec; |
926 | if (!delta) { | | 925 | if (!delta) { |
927 | cpu_ticksdenom = denom; | | 926 | cpu_ticksdenom = denom; |
928 | cpu_ticksnum = num; | | 927 | cpu_ticksnum = num; |
929 | break; | | 928 | break; |
930 | } else if (delta < mdelta) { | | 929 | } else if (delta < mdelta) { |
931 | cpu_ticksdenom = denom; | | 930 | cpu_ticksdenom = denom; |
932 | cpu_ticksnum = num; | | 931 | cpu_ticksnum = num; |
933 | mdelta = delta; | | 932 | mdelta = delta; |
934 | } | | 933 | } |
935 | } | | 934 | } |
936 | } | | 935 | } |
937 | | | 936 | |
938 | void | | 937 | void |
939 | delay(u_int us) | | 938 | delay(u_int us) |
940 | { | | 939 | { |
941 | u_int start, end, n; | | 940 | u_int start, end, n; |
942 | | | 941 | |
943 | mfctl(CR_ITMR, start); | | 942 | mfctl(CR_ITMR, start); |
944 | while (us) { | | 943 | while (us) { |
945 | n = min(1000, us); | | 944 | n = min(1000, us); |
946 | end = start + n * cpu_ticksnum / cpu_ticksdenom; | | 945 | end = start + n * cpu_ticksnum / cpu_ticksdenom; |
947 | | | 946 | |
948 | /* N.B. Interval Timer may wrap around */ | | 947 | /* N.B. Interval Timer may wrap around */ |
949 | if (end < start) | | 948 | if (end < start) |
950 | do | | 949 | do |
951 | mfctl(CR_ITMR, start); | | 950 | mfctl(CR_ITMR, start); |
952 | while (start > end); | | 951 | while (start > end); |
953 | | | 952 | |
954 | do | | 953 | do |
955 | mfctl(CR_ITMR, start); | | 954 | mfctl(CR_ITMR, start); |
956 | while (start < end); | | 955 | while (start < end); |
957 | | | 956 | |
958 | us -= n; | | 957 | us -= n; |
959 | mfctl(CR_ITMR, start); | | 958 | mfctl(CR_ITMR, start); |
960 | } | | 959 | } |
961 | } | | 960 | } |
962 | | | 961 | |
963 | static inline void | | 962 | static inline void |
964 | fall(int c_base, int c_count, int c_loop, int c_stride, int data) | | 963 | fall(int c_base, int c_count, int c_loop, int c_stride, int data) |
965 | { | | 964 | { |
966 | int loop; | | 965 | int loop; |
967 | | | 966 | |
968 | for (; c_count--; c_base += c_stride) | | 967 | for (; c_count--; c_base += c_stride) |
969 | for (loop = c_loop; loop--; ) | | 968 | for (loop = c_loop; loop--; ) |
970 | if (data) | | 969 | if (data) |
971 | fdce(0, c_base); | | 970 | fdce(0, c_base); |
972 | else | | 971 | else |
973 | fice(0, c_base); | | 972 | fice(0, c_base); |
974 | } | | 973 | } |
975 | | | 974 | |
976 | void | | 975 | void |
977 | fcacheall(void) | | 976 | fcacheall(void) |
978 | { | | 977 | { |
979 | /* | | 978 | /* |
980 | * Flush the instruction, then data cache. | | 979 | * Flush the instruction, then data cache. |
981 | */ | | 980 | */ |
982 | fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop, | | 981 | fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop, |
983 | pdc_cache.ic_stride, 0); | | 982 | pdc_cache.ic_stride, 0); |
984 | sync_caches(); | | 983 | sync_caches(); |
985 | fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop, | | 984 | fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop, |
986 | pdc_cache.dc_stride, 1); | | 985 | pdc_cache.dc_stride, 1); |
987 | sync_caches(); | | 986 | sync_caches(); |
988 | } | | 987 | } |
989 | | | 988 | |
990 | void | | 989 | void |
991 | ptlball(void) | | 990 | ptlball(void) |
992 | { | | 991 | { |
993 | pa_space_t sp; | | 992 | pa_space_t sp; |
994 | int i, j, k; | | 993 | int i, j, k; |
995 | | | 994 | |
996 | /* instruction TLB */ | | 995 | /* instruction TLB */ |
997 | sp = pdc_cache.it_sp_base; | | 996 | sp = pdc_cache.it_sp_base; |
998 | for (i = 0; i < pdc_cache.it_sp_count; i++) { | | 997 | for (i = 0; i < pdc_cache.it_sp_count; i++) { |
999 | vaddr_t off = pdc_cache.it_off_base; | | 998 | vaddr_t off = pdc_cache.it_off_base; |
1000 | for (j = 0; j < pdc_cache.it_off_count; j++) { | | 999 | for (j = 0; j < pdc_cache.it_off_count; j++) { |
1001 | for (k = 0; k < pdc_cache.it_loop; k++) | | 1000 | for (k = 0; k < pdc_cache.it_loop; k++) |
1002 | pitlbe(sp, off); | | 1001 | pitlbe(sp, off); |
1003 | off += pdc_cache.it_off_stride; | | 1002 | off += pdc_cache.it_off_stride; |
1004 | } | | 1003 | } |
1005 | sp += pdc_cache.it_sp_stride; | | 1004 | sp += pdc_cache.it_sp_stride; |
1006 | } | | 1005 | } |
1007 | | | 1006 | |
1008 | /* data TLB */ | | 1007 | /* data TLB */ |
1009 | sp = pdc_cache.dt_sp_base; | | 1008 | sp = pdc_cache.dt_sp_base; |
1010 | for (i = 0; i < pdc_cache.dt_sp_count; i++) { | | 1009 | for (i = 0; i < pdc_cache.dt_sp_count; i++) { |
1011 | vaddr_t off = pdc_cache.dt_off_base; | | 1010 | vaddr_t off = pdc_cache.dt_off_base; |
1012 | for (j = 0; j < pdc_cache.dt_off_count; j++) { | | 1011 | for (j = 0; j < pdc_cache.dt_off_count; j++) { |
1013 | for (k = 0; k < pdc_cache.dt_loop; k++) | | 1012 | for (k = 0; k < pdc_cache.dt_loop; k++) |
1014 | pdtlbe(sp, off); | | 1013 | pdtlbe(sp, off); |
1015 | off += pdc_cache.dt_off_stride; | | 1014 | off += pdc_cache.dt_off_stride; |
1016 | } | | 1015 | } |
1017 | sp += pdc_cache.dt_sp_stride; | | 1016 | sp += pdc_cache.dt_sp_stride; |
1018 | } | | 1017 | } |
1019 | } | | 1018 | } |
1020 | | | 1019 | |
1021 | int | | 1020 | int |
1022 | hpti_g(vaddr_t hpt, vsize_t hptsize) | | 1021 | hpti_g(vaddr_t hpt, vsize_t hptsize) |
1023 | { | | 1022 | { |
1024 | | | 1023 | |
1025 | return pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, | | 1024 | return pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, |
1026 | &pdc_hwtlb, hpt, hptsize, PDC_TLB_CURRPDE); | | 1025 | &pdc_hwtlb, hpt, hptsize, PDC_TLB_CURRPDE); |
1027 | } | | 1026 | } |
1028 | | | 1027 | |
1029 | int | | 1028 | int |
1030 | pbtlb_g(int i) | | 1029 | pbtlb_g(int i) |
1031 | { | | 1030 | { |
1032 | return -1; | | 1031 | return -1; |
1033 | } | | 1032 | } |
1034 | | | 1033 | |
1035 | int | | 1034 | int |
1036 | ibtlb_g(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, u_int prot) | | 1035 | ibtlb_g(int i, pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, u_int prot) |
1037 | { | | 1036 | { |
1038 | int error; | | 1037 | int error; |
1039 | | | 1038 | |
1040 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, | | 1039 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, |
1041 | sp, va, pa, sz, prot, i)) < 0) { | | 1040 | sp, va, pa, sz, prot, i)) < 0) { |
1042 | #ifdef BTLBDEBUG | | 1041 | #ifdef BTLBDEBUG |
1043 | printf("WARNING: BTLB insert failed (%d)\n", error); | | 1042 | printf("WARNING: BTLB insert failed (%d)\n", error); |
1044 | #endif | | 1043 | #endif |
1045 | } | | 1044 | } |
1046 | return error; | | 1045 | return error; |
1047 | } | | 1046 | } |
1048 | | | 1047 | |
1049 | | | 1048 | |
1050 | /* | | 1049 | /* |
1051 | * This inserts a recorded BTLB slot. | | 1050 | * This inserts a recorded BTLB slot. |
1052 | */ | | 1051 | */ |
1053 | static int _hp700_btlb_insert(struct btlb_slot *); | | 1052 | static int _hp700_btlb_insert(struct btlb_slot *); |
1054 | static int | | 1053 | static int |
1055 | _hp700_btlb_insert(struct btlb_slot *btlb_slot) | | 1054 | _hp700_btlb_insert(struct btlb_slot *btlb_slot) |
1056 | { | | 1055 | { |
1057 | int error; | | 1056 | int error; |
1058 | #ifdef DEBUG | | 1057 | #ifdef DEBUG |
1059 | const char *prot; | | 1058 | const char *prot; |
1060 | | | 1059 | |
1061 | /* Display the protection like a file protection. */ | | 1060 | /* Display the protection like a file protection. */ |
1062 | switch (btlb_slot->btlb_slot_tlbprot & TLB_AR_MASK) { | | 1061 | switch (btlb_slot->btlb_slot_tlbprot & TLB_AR_MASK) { |
1063 | case TLB_AR_NA: prot = "------"; break; | | 1062 | case TLB_AR_NA: prot = "------"; break; |
1064 | case TLB_AR_R: prot = "r-----"; break; | | 1063 | case TLB_AR_R: prot = "r-----"; break; |
1065 | case TLB_AR_RW: prot = "rw----"; break; | | 1064 | case TLB_AR_RW: prot = "rw----"; break; |
1066 | case TLB_AR_RX: prot = "r-x---"; break; | | 1065 | case TLB_AR_RX: prot = "r-x---"; break; |
1067 | case TLB_AR_RWX: prot = "rwx---"; break; | | 1066 | case TLB_AR_RWX: prot = "rwx---"; break; |
1068 | case TLB_AR_R | TLB_USER: prot = "r--r--"; break; | | 1067 | case TLB_AR_R | TLB_USER: prot = "r--r--"; break; |
1069 | case TLB_AR_RW | TLB_USER: prot = "rw-rw-"; break; | | 1068 | case TLB_AR_RW | TLB_USER: prot = "rw-rw-"; break; |
1070 | case TLB_AR_RX | TLB_USER: prot = "r--r-x"; break; | | 1069 | case TLB_AR_RX | TLB_USER: prot = "r--r-x"; break; |
1071 | case TLB_AR_RWX | TLB_USER: prot = "rw-rwx"; break; | | 1070 | case TLB_AR_RWX | TLB_USER: prot = "rw-rwx"; break; |
1072 | default: prot = "??????"; break; | | 1071 | default: prot = "??????"; break; |
1073 | } | | 1072 | } |
1074 | | | 1073 | |
1075 | printf(" [ BTLB slot %d: %s 0x%08x @ 0x%x:0x%08x len 0x%08x prot 0x%08x] ", | | 1074 | printf(" [ BTLB slot %d: %s 0x%08x @ 0x%x:0x%08x len 0x%08x prot 0x%08x] ", |
1076 | btlb_slot->btlb_slot_number, | | 1075 | btlb_slot->btlb_slot_number, |
1077 | prot, | | 1076 | prot, |
1078 | (u_int)btlb_slot->btlb_slot_pa_frame << PGSHIFT, | | 1077 | (u_int)btlb_slot->btlb_slot_pa_frame << PGSHIFT, |
1079 | btlb_slot->btlb_slot_va_space, | | 1078 | btlb_slot->btlb_slot_va_space, |
1080 | (u_int)btlb_slot->btlb_slot_va_frame << PGSHIFT, | | 1079 | (u_int)btlb_slot->btlb_slot_va_frame << PGSHIFT, |
1081 | (u_int)btlb_slot->btlb_slot_frames << PGSHIFT, | | 1080 | (u_int)btlb_slot->btlb_slot_frames << PGSHIFT, |
1082 | btlb_slot->btlb_slot_tlbprot); | | 1081 | btlb_slot->btlb_slot_tlbprot); |
1083 | | | 1082 | |
1084 | /* | | 1083 | /* |
1085 | * Non-I/O space mappings are entered by the pmap, | | 1084 | * Non-I/O space mappings are entered by the pmap, |
1086 | * so we do print a newline to make things look better. | | 1085 | * so we do print a newline to make things look better. |
1087 | */ | | 1086 | */ |
1088 | if (btlb_slot->btlb_slot_pa_frame < (HPPA_IOSPACE >> PGSHIFT)) | | 1087 | if (btlb_slot->btlb_slot_pa_frame < (HPPA_IOSPACE >> PGSHIFT)) |
1089 | printf("\n"); | | 1088 | printf("\n"); |
1090 | #endif | | 1089 | #endif |
1091 | | | 1090 | |
1092 | /* Insert this mapping. */ | | 1091 | /* Insert this mapping. */ |
1093 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, | | 1092 | if ((error = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, |
1094 | btlb_slot->btlb_slot_va_space, | | 1093 | btlb_slot->btlb_slot_va_space, |
1095 | btlb_slot->btlb_slot_va_frame, | | 1094 | btlb_slot->btlb_slot_va_frame, |
1096 | btlb_slot->btlb_slot_pa_frame, | | 1095 | btlb_slot->btlb_slot_pa_frame, |
1097 | btlb_slot->btlb_slot_frames, | | 1096 | btlb_slot->btlb_slot_frames, |
1098 | btlb_slot->btlb_slot_tlbprot, | | 1097 | btlb_slot->btlb_slot_tlbprot, |
1099 | btlb_slot->btlb_slot_number)) < 0) { | | 1098 | btlb_slot->btlb_slot_number)) < 0) { |
1100 | #ifdef BTLBDEBUG | | 1099 | #ifdef BTLBDEBUG |
1101 | printf("WARNING: BTLB insert failed (%d)\n", error); | | 1100 | printf("WARNING: BTLB insert failed (%d)\n", error); |
1102 | #endif | | 1101 | #endif |
1103 | } | | 1102 | } |
1104 | return (error ? EINVAL : 0); | | 1103 | return (error ? EINVAL : 0); |
1105 | } | | 1104 | } |
1106 | | | 1105 | |
1107 | /* | | 1106 | /* |
1108 | * This records and inserts a new BTLB entry. | | 1107 | * This records and inserts a new BTLB entry. |
1109 | */ | | 1108 | */ |
1110 | int | | 1109 | int |
1111 | hppa_btlb_insert(pa_space_t space, vaddr_t va, paddr_t pa, vsize_t *sizep, | | 1110 | hppa_btlb_insert(pa_space_t space, vaddr_t va, paddr_t pa, vsize_t *sizep, |
1112 | u_int tlbprot) | | 1111 | u_int tlbprot) |
1113 | { | | 1112 | { |
1114 | struct btlb_slot *btlb_slot, *btlb_slot_best, *btlb_slot_end; | | 1113 | struct btlb_slot *btlb_slot, *btlb_slot_best, *btlb_slot_end; |
1115 | vsize_t frames; | | 1114 | vsize_t frames; |
1116 | int error; | | 1115 | int error; |
1117 | int need_dbtlb, need_ibtlb, need_variable_range; | | 1116 | int need_dbtlb, need_ibtlb, need_variable_range; |
1118 | int btlb_slot_score, btlb_slot_best_score; | | 1117 | int btlb_slot_score, btlb_slot_best_score; |
1119 | vsize_t slot_mapped_frames, total_mapped_frames; | | 1118 | vsize_t slot_mapped_frames, total_mapped_frames; |
1120 | | | 1119 | |
1121 | /* | | 1120 | /* |
1122 | * All entries need data translation. Those that | | 1121 | * All entries need data translation. Those that |
1123 | * allow execution also need instruction translation. | | 1122 | * allow execution also need instruction translation. |
1124 | */ | | 1123 | */ |
1125 | switch (tlbprot & TLB_AR_MASK) { | | 1124 | switch (tlbprot & TLB_AR_MASK) { |
1126 | case TLB_AR_R: | | 1125 | case TLB_AR_R: |
1127 | case TLB_AR_RW: | | 1126 | case TLB_AR_RW: |
1128 | case TLB_AR_R | TLB_USER: | | 1127 | case TLB_AR_R | TLB_USER: |
1129 | case TLB_AR_RW | TLB_USER: | | 1128 | case TLB_AR_RW | TLB_USER: |
1130 | need_dbtlb = true; | | 1129 | need_dbtlb = true; |
1131 | need_ibtlb = false; | | 1130 | need_ibtlb = false; |
1132 | break; | | 1131 | break; |
1133 | case TLB_AR_RX: | | 1132 | case TLB_AR_RX: |
1134 | case TLB_AR_RWX: | | 1133 | case TLB_AR_RWX: |
1135 | case TLB_AR_RX | TLB_USER: | | 1134 | case TLB_AR_RX | TLB_USER: |
1136 | case TLB_AR_RWX | TLB_USER: | | 1135 | case TLB_AR_RWX | TLB_USER: |
1137 | need_dbtlb = true; | | 1136 | need_dbtlb = true; |
1138 | need_ibtlb = true; | | 1137 | need_ibtlb = true; |
1139 | break; | | 1138 | break; |
1140 | default: | | 1139 | default: |
1141 | panic("btlb_insert: bad tlbprot"); | | 1140 | panic("btlb_insert: bad tlbprot"); |
1142 | } | | 1141 | } |
1143 | | | 1142 | |
1144 | /* | | 1143 | /* |
1145 | * If this entry isn't aligned to the size required | | 1144 | * If this entry isn't aligned to the size required |
1146 | * for a fixed-range slot, it requires a variable-range | | 1145 | * for a fixed-range slot, it requires a variable-range |
1147 | * slot. This also converts pa and va to page frame | | 1146 | * slot. This also converts pa and va to page frame |
1148 | * numbers. | | 1147 | * numbers. |
1149 | */ | | 1148 | */ |
1150 | frames = pdc_btlb.min_size << PGSHIFT; | | 1149 | frames = pdc_btlb.min_size << PGSHIFT; |
1151 | while (frames < *sizep) | | 1150 | while (frames < *sizep) |
1152 | frames <<= 1; | | 1151 | frames <<= 1; |
1153 | frames >>= PGSHIFT; | | 1152 | frames >>= PGSHIFT; |
1154 | if (frames > pdc_btlb.max_size) { | | 1153 | if (frames > pdc_btlb.max_size) { |
1155 | #ifdef BTLBDEBUG | | 1154 | #ifdef BTLBDEBUG |
1156 | printf("btlb_insert: too big (%u < %u < %u)\n", | | 1155 | printf("btlb_insert: too big (%u < %u < %u)\n", |
1157 | pdc_btlb.min_size, (u_int) frames, pdc_btlb.max_size); | | 1156 | pdc_btlb.min_size, (u_int) frames, pdc_btlb.max_size); |
1158 | #endif | | 1157 | #endif |
1159 | return -(ENOMEM); | | 1158 | return -(ENOMEM); |
1160 | } | | 1159 | } |
1161 | pa >>= PGSHIFT; | | 1160 | pa >>= PGSHIFT; |
1162 | va >>= PGSHIFT; | | 1161 | va >>= PGSHIFT; |
1163 | need_variable_range = | | 1162 | need_variable_range = |
1164 | ((pa & (frames - 1)) != 0 || (va & (frames - 1)) != 0); | | 1163 | ((pa & (frames - 1)) != 0 || (va & (frames - 1)) != 0); |
1165 | | | 1164 | |
1166 | /* I/O space must be mapped uncached. */ | | 1165 | /* I/O space must be mapped uncached. */ |
1167 | if (pa >= HPPA_IOBEGIN) | | 1166 | if (pa >= HPPA_IOBEGIN) |
1168 | tlbprot |= TLB_UNCACHEABLE; | | 1167 | tlbprot |= TLB_UNCACHEABLE; |
1169 | | | 1168 | |
1170 | /* | | 1169 | /* |
1171 | * Loop while we still need slots. | | 1170 | * Loop while we still need slots. |
1172 | */ | | 1171 | */ |
1173 | btlb_slot_end = btlb_slots + btlb_slots_count; | | 1172 | btlb_slot_end = btlb_slots + btlb_slots_count; |
1174 | total_mapped_frames = 0; | | 1173 | total_mapped_frames = 0; |
1175 | btlb_slot_best_score = 0; | | 1174 | btlb_slot_best_score = 0; |
1176 | while (need_dbtlb || need_ibtlb) { | | 1175 | while (need_dbtlb || need_ibtlb) { |
1177 | | | 1176 | |
1178 | /* | | 1177 | /* |
1179 | * Find an applicable slot. | | 1178 | * Find an applicable slot. |
1180 | */ | | 1179 | */ |
1181 | btlb_slot_best = NULL; | | 1180 | btlb_slot_best = NULL; |
1182 | for (btlb_slot = btlb_slots; | | 1181 | for (btlb_slot = btlb_slots; |
1183 | btlb_slot < btlb_slot_end; | | 1182 | btlb_slot < btlb_slot_end; |
1184 | btlb_slot++) { | | 1183 | btlb_slot++) { |
1185 | | | 1184 | |
1186 | /* | | 1185 | /* |
1187 | * Skip this slot if it's in use, or if we need a | | 1186 | * Skip this slot if it's in use, or if we need a |
1188 | * variable-range slot and this isn't one. | | 1187 | * variable-range slot and this isn't one. |
1189 | */ | | 1188 | */ |
1190 | if (btlb_slot->btlb_slot_frames != 0 || | | 1189 | if (btlb_slot->btlb_slot_frames != 0 || |
1191 | (need_variable_range && | | 1190 | (need_variable_range && |
1192 | !(btlb_slot->btlb_slot_flags & | | 1191 | !(btlb_slot->btlb_slot_flags & |
1193 | BTLB_SLOT_VARIABLE_RANGE))) | | 1192 | BTLB_SLOT_VARIABLE_RANGE))) |
1194 | continue; | | 1193 | continue; |
1195 | | | 1194 | |
1196 | /* | | 1195 | /* |
1197 | * Score this slot. | | 1196 | * Score this slot. |
1198 | */ | | 1197 | */ |
1199 | btlb_slot_score = 0; | | 1198 | btlb_slot_score = 0; |
1200 | if (need_dbtlb && | | 1199 | if (need_dbtlb && |
1201 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB)) | | 1200 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB)) |
1202 | btlb_slot_score++; | | 1201 | btlb_slot_score++; |
1203 | if (need_ibtlb && | | 1202 | if (need_ibtlb && |
1204 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB)) | | 1203 | (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB)) |
1205 | btlb_slot_score++; | | 1204 | btlb_slot_score++; |
1206 | | | 1205 | |
1207 | /* | | 1206 | /* |
1208 | * Update the best slot. | | 1207 | * Update the best slot. |
1209 | */ | | 1208 | */ |
1210 | if (btlb_slot_score > 0 && | | 1209 | if (btlb_slot_score > 0 && |
1211 | (btlb_slot_best == NULL || | | 1210 | (btlb_slot_best == NULL || |
1212 | btlb_slot_score > btlb_slot_best_score)) { | | 1211 | btlb_slot_score > btlb_slot_best_score)) { |
1213 | btlb_slot_best = btlb_slot; | | 1212 | btlb_slot_best = btlb_slot; |
1214 | btlb_slot_best_score = btlb_slot_score; | | 1213 | btlb_slot_best_score = btlb_slot_score; |
1215 | } | | 1214 | } |
1216 | } | | 1215 | } |
1217 | | | 1216 | |
1218 | /* | | 1217 | /* |
1219 | * If there were no applicable slots. | | 1218 | * If there were no applicable slots. |
1220 | */ | | 1219 | */ |
1221 | if (btlb_slot_best == NULL) { | | 1220 | if (btlb_slot_best == NULL) { |
1222 | #ifdef BTLBDEBUG | | 1221 | #ifdef BTLBDEBUG |
1223 | printf("BTLB full\n"); | | 1222 | printf("BTLB full\n"); |
1224 | #endif | | 1223 | #endif |
1225 | return -(ENOMEM); | | 1224 | return -(ENOMEM); |
1226 | } | | 1225 | } |
1227 | | | 1226 | |
1228 | /* | | 1227 | /* |
1229 | * Now fill this BTLB slot record and insert the entry. | | 1228 | * Now fill this BTLB slot record and insert the entry. |
1230 | */ | | 1229 | */ |
1231 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_VARIABLE_RANGE) | | 1230 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_VARIABLE_RANGE) |
1232 | slot_mapped_frames = ((*sizep + PGOFSET) >> PGSHIFT); | | 1231 | slot_mapped_frames = ((*sizep + PGOFSET) >> PGSHIFT); |
1233 | else | | 1232 | else |
1234 | slot_mapped_frames = frames; | | 1233 | slot_mapped_frames = frames; |
1235 | if (slot_mapped_frames > total_mapped_frames) | | 1234 | if (slot_mapped_frames > total_mapped_frames) |
1236 | total_mapped_frames = slot_mapped_frames; | | 1235 | total_mapped_frames = slot_mapped_frames; |
1237 | btlb_slot = btlb_slot_best; | | 1236 | btlb_slot = btlb_slot_best; |
1238 | btlb_slot->btlb_slot_va_space = space; | | 1237 | btlb_slot->btlb_slot_va_space = space; |
1239 | btlb_slot->btlb_slot_va_frame = va; | | 1238 | btlb_slot->btlb_slot_va_frame = va; |
1240 | btlb_slot->btlb_slot_pa_frame = pa; | | 1239 | btlb_slot->btlb_slot_pa_frame = pa; |
1241 | btlb_slot->btlb_slot_tlbprot = tlbprot; | | 1240 | btlb_slot->btlb_slot_tlbprot = tlbprot; |
1242 | btlb_slot->btlb_slot_frames = slot_mapped_frames; | | 1241 | btlb_slot->btlb_slot_frames = slot_mapped_frames; |
1243 | error = _hp700_btlb_insert(btlb_slot); | | 1242 | error = _hp700_btlb_insert(btlb_slot); |
1244 | if (error) | | 1243 | if (error) |
1245 | return -error; | | 1244 | return -error; |
1246 | /* | | 1245 | /* |
1247 | * Note what slots we no longer need. | | 1246 | * Note what slots we no longer need. |
1248 | */ | | 1247 | */ |
1249 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB) | | 1248 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_DBTLB) |
1250 | need_dbtlb = false; | | 1249 | need_dbtlb = false; |
1251 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB) | | 1250 | if (btlb_slot->btlb_slot_flags & BTLB_SLOT_IBTLB) |
1252 | need_ibtlb = false; | | 1251 | need_ibtlb = false; |
1253 | } | | 1252 | } |
1254 | | | 1253 | |
1255 | /* Success. */ | | 1254 | /* Success. */ |
1256 | *sizep = (total_mapped_frames << PGSHIFT); | | 1255 | *sizep = (total_mapped_frames << PGSHIFT); |
1257 | return 0; | | 1256 | return 0; |
1258 | } | | 1257 | } |
1259 | | | 1258 | |
1260 | /* | | 1259 | /* |
1261 | * This reloads the BTLB in the event that it becomes invalidated. | | 1260 | * This reloads the BTLB in the event that it becomes invalidated. |
1262 | */ | | 1261 | */ |
1263 | int | | 1262 | int |
1264 | hppa_btlb_reload(void) | | 1263 | hppa_btlb_reload(void) |
1265 | { | | 1264 | { |
1266 | struct btlb_slot *btlb_slot, *btlb_slot_end; | | 1265 | struct btlb_slot *btlb_slot, *btlb_slot_end; |
1267 | int error; | | 1266 | int error; |
1268 | | | 1267 | |
1269 | /* Insert all recorded BTLB entries. */ | | 1268 | /* Insert all recorded BTLB entries. */ |
1270 | btlb_slot = btlb_slots; | | 1269 | btlb_slot = btlb_slots; |
1271 | btlb_slot_end = btlb_slots + btlb_slots_count; | | 1270 | btlb_slot_end = btlb_slots + btlb_slots_count; |
1272 | error = 0; | | 1271 | error = 0; |
1273 | while (error == 0 && btlb_slot < btlb_slot_end) { | | 1272 | while (error == 0 && btlb_slot < btlb_slot_end) { |
1274 | if (btlb_slot->btlb_slot_frames != 0) | | 1273 | if (btlb_slot->btlb_slot_frames != 0) |
1275 | error = _hp700_btlb_insert(btlb_slot); | | 1274 | error = _hp700_btlb_insert(btlb_slot); |
1276 | btlb_slot++; | | 1275 | btlb_slot++; |
1277 | } | | 1276 | } |
1278 | #ifdef DEBUG | | 1277 | #ifdef DEBUG |
1279 | printf("\n"); | | 1278 | printf("\n"); |
1280 | #endif | | 1279 | #endif |
1281 | return (error); | | 1280 | return (error); |
1282 | } | | 1281 | } |
1283 | | | 1282 | |
1284 | /* | | 1283 | /* |
1285 | * This purges a BTLB entry. | | 1284 | * This purges a BTLB entry. |
1286 | */ | | 1285 | */ |
1287 | int | | 1286 | int |
1288 | hppa_btlb_purge(pa_space_t space, vaddr_t va, vsize_t *sizep) | | 1287 | hppa_btlb_purge(pa_space_t space, vaddr_t va, vsize_t *sizep) |
1289 | { | | 1288 | { |
1290 | struct btlb_slot *btlb_slot, *btlb_slot_end; | | 1289 | struct btlb_slot *btlb_slot, *btlb_slot_end; |
1291 | int error; | | 1290 | int error; |
1292 | | | 1291 | |
1293 | /* | | 1292 | /* |
1294 | * Purge all slots that map this virtual address. | | 1293 | * Purge all slots that map this virtual address. |
1295 | */ | | 1294 | */ |
1296 | error = ENOENT; | | 1295 | error = ENOENT; |
1297 | va >>= PGSHIFT; | | 1296 | va >>= PGSHIFT; |
1298 | btlb_slot_end = btlb_slots + btlb_slots_count; | | 1297 | btlb_slot_end = btlb_slots + btlb_slots_count; |
1299 | for (btlb_slot = btlb_slots; | | 1298 | for (btlb_slot = btlb_slots; |
1300 | btlb_slot < btlb_slot_end; | | 1299 | btlb_slot < btlb_slot_end; |
1301 | btlb_slot++) { | | 1300 | btlb_slot++) { |
1302 | if (btlb_slot->btlb_slot_frames != 0 && | | 1301 | if (btlb_slot->btlb_slot_frames != 0 && |
1303 | btlb_slot->btlb_slot_va_space == space && | | 1302 | btlb_slot->btlb_slot_va_space == space && |
1304 | btlb_slot->btlb_slot_va_frame == va) { | | 1303 | btlb_slot->btlb_slot_va_frame == va) { |
1305 | if ((error = pdc_call((iodcio_t)pdc, 0, | | 1304 | if ((error = pdc_call((iodcio_t)pdc, 0, |
1306 | PDC_BLOCK_TLB, PDC_BTLB_PURGE, | | 1305 | PDC_BLOCK_TLB, PDC_BTLB_PURGE, |
1307 | btlb_slot->btlb_slot_va_space, | | 1306 | btlb_slot->btlb_slot_va_space, |
1308 | btlb_slot->btlb_slot_va_frame, | | 1307 | btlb_slot->btlb_slot_va_frame, |
1309 | btlb_slot->btlb_slot_number, | | 1308 | btlb_slot->btlb_slot_number, |
1310 | btlb_slot->btlb_slot_frames)) < 0) { | | 1309 | btlb_slot->btlb_slot_frames)) < 0) { |
1311 | #ifdef BTLBDEBUG | | 1310 | #ifdef BTLBDEBUG |
1312 | printf("WARNING: BTLB purge failed (%d)\n", | | 1311 | printf("WARNING: BTLB purge failed (%d)\n", |
1313 | error); | | 1312 | error); |
1314 | #endif | | 1313 | #endif |
1315 | return (error); | | 1314 | return (error); |
1316 | } | | 1315 | } |
1317 | | | 1316 | |
1318 | /* | | 1317 | /* |
1319 | * Tell our caller how many bytes were mapped | | 1318 | * Tell our caller how many bytes were mapped |
1320 | * by this slot, then free the slot. | | 1319 | * by this slot, then free the slot. |
1321 | */ | | 1320 | */ |
1322 | *sizep = (btlb_slot->btlb_slot_frames << PGSHIFT); | | 1321 | *sizep = (btlb_slot->btlb_slot_frames << PGSHIFT); |
1323 | btlb_slot->btlb_slot_frames = 0; | | 1322 | btlb_slot->btlb_slot_frames = 0; |
1324 | } | | 1323 | } |
1325 | } | | 1324 | } |
1326 | return (error); | | 1325 | return (error); |
1327 | } | | 1326 | } |
1328 | | | 1327 | |
1329 | /* | | 1328 | /* |
1330 | * This maps page zero if it isn't already mapped, and | | 1329 | * This maps page zero if it isn't already mapped, and |
1331 | * returns a cookie for hp700_pagezero_unmap. | | 1330 | * returns a cookie for hp700_pagezero_unmap. |
1332 | */ | | 1331 | */ |
1333 | int | | 1332 | int |
1334 | hp700_pagezero_map(void) | | 1333 | hp700_pagezero_map(void) |
1335 | { | | 1334 | { |
1336 | int was_mapped_before; | | 1335 | int was_mapped_before; |
1337 | int s; | | 1336 | int s; |
1338 | | | 1337 | |
1339 | was_mapped_before = pagezero_mapped; | | 1338 | was_mapped_before = pagezero_mapped; |
1340 | if (!was_mapped_before) { | | 1339 | if (!was_mapped_before) { |
1341 | s = splhigh(); | | 1340 | s = splhigh(); |
1342 | pmap_kenter_pa(0, 0, VM_PROT_ALL); | | 1341 | pmap_kenter_pa(0, 0, VM_PROT_ALL); |
1343 | pagezero_mapped = 1; | | 1342 | pagezero_mapped = 1; |
1344 | splx(s); | | 1343 | splx(s); |
1345 | } | | 1344 | } |
1346 | return (was_mapped_before); | | 1345 | return (was_mapped_before); |
1347 | } | | 1346 | } |
1348 | | | 1347 | |
1349 | /* | | 1348 | /* |
1350 | * This unmaps mape zero, given a cookie previously returned | | 1349 | * This unmaps mape zero, given a cookie previously returned |
1351 | * by hp700_pagezero_map. | | 1350 | * by hp700_pagezero_map. |
1352 | */ | | 1351 | */ |
1353 | void | | 1352 | void |
1354 | hp700_pagezero_unmap(int was_mapped_before) | | 1353 | hp700_pagezero_unmap(int was_mapped_before) |
1355 | { | | 1354 | { |
1356 | int s; | | 1355 | int s; |
1357 | | | 1356 | |
1358 | if (!was_mapped_before) { | | 1357 | if (!was_mapped_before) { |
1359 | s = splhigh(); | | 1358 | s = splhigh(); |
1360 | pmap_kremove(0, PAGE_SIZE); | | 1359 | pmap_kremove(0, PAGE_SIZE); |
1361 | pagezero_mapped = 0; | | 1360 | pagezero_mapped = 0; |
1362 | splx(s); | | 1361 | splx(s); |
1363 | } | | 1362 | } |
1364 | } | | 1363 | } |
1365 | | | 1364 | |
1366 | int waittime = -1; | | 1365 | int waittime = -1; |
1367 | | | 1366 | |
1368 | __dead void | | 1367 | __dead void |
1369 | cpu_reboot(int howto, char *user_boot_string) | | 1368 | cpu_reboot(int howto, char *user_boot_string) |
1370 | { | | 1369 | { |
1371 | boothowto = howto | (boothowto & RB_HALT); | | 1370 | boothowto = howto | (boothowto & RB_HALT); |
1372 | | | 1371 | |
1373 | if (!(howto & RB_NOSYNC) && waittime < 0) { | | 1372 | if (!(howto & RB_NOSYNC) && waittime < 0) { |
1374 | waittime = 0; | | 1373 | waittime = 0; |
1375 | vfs_shutdown(); | | 1374 | vfs_shutdown(); |
1376 | | | 1375 | |
1377 | /* | | 1376 | /* |
1378 | * If we've been adjusting the clock, the todr | | 1377 | * If we've been adjusting the clock, the todr |
1379 | * will be out of synch; adjust it now. | | 1378 | * will be out of synch; adjust it now. |
1380 | */ | | 1379 | */ |
1381 | resettodr(); | | 1380 | resettodr(); |
1382 | } | | 1381 | } |
1383 | | | 1382 | |
1384 | /* XXX probably save howto into stable storage */ | | 1383 | /* XXX probably save howto into stable storage */ |
1385 | | | 1384 | |
1386 | /* Disable interrupts. */ | | 1385 | /* Disable interrupts. */ |
1387 | splhigh(); | | 1386 | splhigh(); |
1388 | | | 1387 | |
1389 | /* Make a crash dump. */ | | 1388 | /* Make a crash dump. */ |
1390 | if (howto & RB_DUMP) | | 1389 | if (howto & RB_DUMP) |
1391 | dumpsys(); | | 1390 | dumpsys(); |
1392 | | | 1391 | |
1393 | /* Run any shutdown hooks. */ | | 1392 | /* Run any shutdown hooks. */ |
1394 | doshutdownhooks(); | | 1393 | doshutdownhooks(); |
1395 | | | 1394 | |
1396 | pmf_system_shutdown(boothowto); | | 1395 | pmf_system_shutdown(boothowto); |
1397 | | | 1396 | |
1398 | /* in case we came on powerfail interrupt */ | | 1397 | /* in case we came on powerfail interrupt */ |
1399 | if (cold_hook) | | 1398 | if (cold_hook) |
1400 | (*cold_hook)(HPPA_COLD_COLD); | | 1399 | (*cold_hook)(HPPA_COLD_COLD); |
1401 | | | 1400 | |
1402 | if (howto & RB_HALT) { | | 1401 | if (howto & RB_HALT) { |
1403 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN && cold_hook) { | | 1402 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN && cold_hook) { |
1404 | printf("Powering off..."); | | 1403 | printf("Powering off..."); |
1405 | DELAY(1000000); | | 1404 | DELAY(1000000); |
1406 | (*cold_hook)(HPPA_COLD_OFF); | | 1405 | (*cold_hook)(HPPA_COLD_OFF); |
1407 | DELAY(1000000); | | 1406 | DELAY(1000000); |
1408 | } | | 1407 | } |
1409 | | | 1408 | |
1410 | printf("System halted!\n"); | | 1409 | printf("System halted!\n"); |
1411 | DELAY(1000000); | | 1410 | DELAY(1000000); |
1412 | __asm volatile("stwas %0, 0(%1)" | | 1411 | __asm volatile("stwas %0, 0(%1)" |
1413 | :: "r" (CMD_STOP), "r" (LBCAST_ADDR + iomod_command)); | | 1412 | :: "r" (CMD_STOP), "r" (LBCAST_ADDR + iomod_command)); |
1414 | } else { | | 1413 | } else { |
1415 | printf("rebooting..."); | | 1414 | printf("rebooting..."); |
1416 | DELAY(1000000); | | 1415 | DELAY(1000000); |
1417 | __asm volatile("stwas %0, 0(%1)" | | 1416 | __asm volatile("stwas %0, 0(%1)" |
1418 | :: "r" (CMD_RESET), "r" (LBCAST_ADDR + iomod_command)); | | 1417 | :: "r" (CMD_RESET), "r" (LBCAST_ADDR + iomod_command)); |
1419 | | | 1418 | |
1420 | /* ask firmware to reset */ | | 1419 | /* ask firmware to reset */ |
1421 | pdc_call((iodcio_t)pdc, 0, PDC_BROADCAST_RESET, PDC_DO_RESET); | | 1420 | pdc_call((iodcio_t)pdc, 0, PDC_BROADCAST_RESET, PDC_DO_RESET); |
1422 | /* forcably reset module if that fails */ | | 1421 | /* forcably reset module if that fails */ |
1423 | __asm __volatile("stwas %0, 0(%1)" | | 1422 | __asm __volatile("stwas %0, 0(%1)" |
1424 | :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command)); | | 1423 | :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command)); |
1425 | } | | 1424 | } |
1426 | | | 1425 | |
1427 | for (;;) | | 1426 | for (;;) |
1428 | /* loop while bus reset is coming up */ ; | | 1427 | /* loop while bus reset is coming up */ ; |
1429 | /* NOTREACHED */ | | 1428 | /* NOTREACHED */ |
1430 | } | | 1429 | } |
1431 | | | 1430 | |
1432 | u_int32_t dumpmag = 0x8fca0101; /* magic number */ | | 1431 | u_int32_t dumpmag = 0x8fca0101; /* magic number */ |
1433 | int dumpsize = 0; /* pages */ | | 1432 | int dumpsize = 0; /* pages */ |
1434 | long dumplo = 0; /* blocks */ | | 1433 | long dumplo = 0; /* blocks */ |
1435 | | | 1434 | |
1436 | /* | | 1435 | /* |
1437 | * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. | | 1436 | * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. |
1438 | */ | | 1437 | */ |
1439 | int | | 1438 | int |
1440 | cpu_dumpsize(void) | | 1439 | cpu_dumpsize(void) |
1441 | { | | 1440 | { |
1442 | int size; | | 1441 | int size; |
1443 | | | 1442 | |
1444 | size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); | | 1443 | size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); |
1445 | if (roundup(size, dbtob(1)) != dbtob(1)) | | 1444 | if (roundup(size, dbtob(1)) != dbtob(1)) |
1446 | return -1; | | 1445 | return -1; |
1447 | | | 1446 | |
1448 | return 1; | | 1447 | return 1; |
1449 | } | | 1448 | } |
1450 | | | 1449 | |
1451 | /* | | 1450 | /* |
1452 | * This handles a machine check. This can be either an HPMC, | | 1451 | * This handles a machine check. This can be either an HPMC, |
1453 | * an LPMC, or a TOC. The check type is passed in as a trap | | 1452 | * an LPMC, or a TOC. The check type is passed in as a trap |
1454 | * type, one of T_HPMC, T_LPMC, or T_INTERRUPT (for TOC). | | 1453 | * type, one of T_HPMC, T_LPMC, or T_INTERRUPT (for TOC). |
1455 | */ | | 1454 | */ |
1456 | static char pim_data_buffer[896] __attribute__((__aligned__(8))); | | 1455 | static char pim_data_buffer[896] __attribute__((__aligned__(8))); |
1457 | static char in_check = 0; | | 1456 | static char in_check = 0; |
1458 | | | 1457 | |
1459 | #define PIM_WORD(name, word, bits) \ | | 1458 | #define PIM_WORD(name, word, bits) \ |
1460 | do { \ | | 1459 | do { \ |
1461 | snprintb(bitmask_buffer, sizeof(bitmask_buffer),\ | | 1460 | snprintb(bitmask_buffer, sizeof(bitmask_buffer),\ |
1462 | bits, word); \ | | 1461 | bits, word); \ |
1463 | printf("%s %s", name, bitmask_buffer); \ | | 1462 | printf("%s %s", name, bitmask_buffer); \ |
1464 | } while (/* CONSTCOND */ 0) | | 1463 | } while (/* CONSTCOND */ 0) |
1465 | | | 1464 | |
1466 | | | 1465 | |
1467 | static inline void | | 1466 | static inline void |
1468 | hppa_pim_dump(int check_type) | | 1467 | hppa_pim_dump(int check_type) |
1469 | { | | 1468 | { |
1470 | struct hp700_pim_hpmc *hpmc; | | 1469 | struct hp700_pim_hpmc *hpmc; |
1471 | struct hp700_pim_lpmc *lpmc; | | 1470 | struct hp700_pim_lpmc *lpmc; |
1472 | struct hp700_pim_toc *toc; | | 1471 | struct hp700_pim_toc *toc; |
1473 | struct hp700_pim_regs *regs; | | 1472 | struct hp700_pim_regs *regs; |
1474 | struct hp700_pim_checks *checks; | | 1473 | struct hp700_pim_checks *checks; |
1475 | u_int *regarray; | | 1474 | u_int *regarray; |
1476 | int reg_i, reg_j, reg_k; | | 1475 | int reg_i, reg_j, reg_k; |
1477 | char bitmask_buffer[64]; | | 1476 | char bitmask_buffer[64]; |
1478 | const char *name; | | 1477 | const char *name; |
1479 | | | 1478 | |
1480 | regs = NULL; | | 1479 | regs = NULL; |
1481 | checks = NULL; | | 1480 | checks = NULL; |
1482 | switch (check_type) { | | 1481 | switch (check_type) { |
1483 | case T_HPMC: | | 1482 | case T_HPMC: |
1484 | hpmc = (struct hp700_pim_hpmc *) pim_data_buffer; | | 1483 | hpmc = (struct hp700_pim_hpmc *) pim_data_buffer; |
1485 | regs = &hpmc->pim_hpmc_regs; | | 1484 | regs = &hpmc->pim_hpmc_regs; |
1486 | checks = &hpmc->pim_hpmc_checks; | | 1485 | checks = &hpmc->pim_hpmc_checks; |
1487 | break; | | 1486 | break; |
1488 | case T_LPMC: | | 1487 | case T_LPMC: |
1489 | lpmc = (struct hp700_pim_lpmc *) pim_data_buffer; | | 1488 | lpmc = (struct hp700_pim_lpmc *) pim_data_buffer; |
1490 | checks = &lpmc->pim_lpmc_checks; | | 1489 | checks = &lpmc->pim_lpmc_checks; |
1491 | break; | | 1490 | break; |
1492 | case T_INTERRUPT: | | 1491 | case T_INTERRUPT: |
1493 | toc = (struct hp700_pim_toc *) pim_data_buffer; | | 1492 | toc = (struct hp700_pim_toc *) pim_data_buffer; |
1494 | regs = &toc->pim_toc_regs; | | 1493 | regs = &toc->pim_toc_regs; |
1495 | break; | | 1494 | break; |
1496 | default: | | 1495 | default: |
1497 | panic("unknown machine check type"); | | 1496 | panic("unknown machine check type"); |
1498 | /* NOTREACHED */ | | 1497 | /* NOTREACHED */ |
1499 | } | | 1498 | } |
1500 | | | 1499 | |
1501 | /* If we have register arrays, display them. */ | | 1500 | /* If we have register arrays, display them. */ |
1502 | if (regs != NULL) { | | 1501 | if (regs != NULL) { |
1503 | for (reg_i = 0; reg_i < 3; reg_i++) { | | 1502 | for (reg_i = 0; reg_i < 3; reg_i++) { |
1504 | if (reg_i == 0) { | | 1503 | if (reg_i == 0) { |
1505 | name = "General"; | | 1504 | name = "General"; |
1506 | regarray = ®s->pim_regs_r0; | | 1505 | regarray = ®s->pim_regs_r0; |
1507 | reg_j = 32; | | 1506 | reg_j = 32; |
1508 | } else if (reg_i == 1) { | | 1507 | } else if (reg_i == 1) { |
1509 | name = "Control"; | | 1508 | name = "Control"; |
1510 | regarray = ®s->pim_regs_cr0; | | 1509 | regarray = ®s->pim_regs_cr0; |
1511 | reg_j = 32; | | 1510 | reg_j = 32; |
1512 | } else { | | 1511 | } else { |
1513 | name = "Space"; | | 1512 | name = "Space"; |
1514 | regarray = ®s->pim_regs_sr0; | | 1513 | regarray = ®s->pim_regs_sr0; |
1515 | reg_j = 8; | | 1514 | reg_j = 8; |
1516 | } | | 1515 | } |
1517 | printf("\n\n\t%s Registers:", name); | | 1516 | printf("\n\n\t%s Registers:", name); |
1518 | for (reg_k = 0; reg_k < reg_j; reg_k++) | | 1517 | for (reg_k = 0; reg_k < reg_j; reg_k++) |
1519 | printf("%s0x%08x", | | 1518 | printf("%s0x%08x", |
1520 | (reg_k & 3) ? " " : "\n\t", | | 1519 | (reg_k & 3) ? " " : "\n\t", |
1521 | regarray[reg_k]); | | 1520 | regarray[reg_k]); |
1522 | } | | 1521 | } |
1523 | | | 1522 | |
1524 | /* Print out some interesting registers. */ | | 1523 | /* Print out some interesting registers. */ |
1525 | printf("\n\n\tIIA head 0x%x:0x%08x\n" | | 1524 | printf("\n\n\tIIA head 0x%x:0x%08x\n" |
1526 | "\tIIA tail 0x%x:0x%08x", | | 1525 | "\tIIA tail 0x%x:0x%08x", |
1527 | regs->pim_regs_cr17, regs->pim_regs_cr18, | | 1526 | regs->pim_regs_cr17, regs->pim_regs_cr18, |
1528 | regs->pim_regs_iisq_tail, regs->pim_regs_iioq_tail); | | 1527 | regs->pim_regs_iisq_tail, regs->pim_regs_iioq_tail); |
1529 | PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS); | | 1528 | PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS); |
1530 | printf("\n\tSP 0x%x:0x%08x FP 0x%x:0x%08x", | | 1529 | printf("\n\tSP 0x%x:0x%08x FP 0x%x:0x%08x", |
1531 | regs->pim_regs_sr0, regs->pim_regs_r30, | | 1530 | regs->pim_regs_sr0, regs->pim_regs_r30, |
1532 | regs->pim_regs_sr0, regs->pim_regs_r3); | | 1531 | regs->pim_regs_sr0, regs->pim_regs_r3); |
1533 | } | | 1532 | } |
1534 | | | 1533 | |
1535 | /* If we have check words, display them. */ | | 1534 | /* If we have check words, display them. */ |
1536 | if (checks != NULL) { | | 1535 | if (checks != NULL) { |
1537 | PIM_WORD("\n\n\tCheck Type", checks->pim_check_type, | | 1536 | PIM_WORD("\n\n\tCheck Type", checks->pim_check_type, |
1538 | PIM_CHECK_BITS); | | 1537 | PIM_CHECK_BITS); |
1539 | PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state, | | 1538 | PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state, |
1540 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); | | 1539 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); |
1541 | PIM_WORD("\n\tCache Check", checks->pim_check_cache, | | 1540 | PIM_WORD("\n\tCache Check", checks->pim_check_cache, |
1542 | PIM_CACHE_BITS); | | 1541 | PIM_CACHE_BITS); |
1543 | PIM_WORD("\n\tTLB Check", checks->pim_check_tlb, | | 1542 | PIM_WORD("\n\tTLB Check", checks->pim_check_tlb, |
1544 | PIM_TLB_BITS); | | 1543 | PIM_TLB_BITS); |
1545 | PIM_WORD("\n\tBus Check", checks->pim_check_bus, | | 1544 | PIM_WORD("\n\tBus Check", checks->pim_check_bus, |
1546 | PIM_BUS_BITS); | | 1545 | PIM_BUS_BITS); |
1547 | PIM_WORD("\n\tAssist Check", checks->pim_check_assist, | | 1546 | PIM_WORD("\n\tAssist Check", checks->pim_check_assist, |
1548 | PIM_ASSIST_BITS); | | 1547 | PIM_ASSIST_BITS); |
1549 | printf("\tAssist State %u", checks->pim_check_assist_state); | | 1548 | printf("\tAssist State %u", checks->pim_check_assist_state); |
1550 | printf("\n\tSystem Responder 0x%08x", | | 1549 | printf("\n\tSystem Responder 0x%08x", |
1551 | checks->pim_check_responder); | | 1550 | checks->pim_check_responder); |
1552 | printf("\n\tSystem Requestor 0x%08x", | | 1551 | printf("\n\tSystem Requestor 0x%08x", |
1553 | checks->pim_check_requestor); | | 1552 | checks->pim_check_requestor); |
1554 | printf("\n\tPath Info 0x%08x", | | 1553 | printf("\n\tPath Info 0x%08x", |
1555 | checks->pim_check_path_info); | | 1554 | checks->pim_check_path_info); |
1556 | } | | 1555 | } |
1557 | } | | 1556 | } |
1558 | | | 1557 | |
1559 | static inline void | | 1558 | static inline void |
1560 | hppa_pim64_dump(int check_type) | | 1559 | hppa_pim64_dump(int check_type) |
1561 | { | | 1560 | { |
1562 | struct hp700_pim64_hpmc *hpmc; | | 1561 | struct hp700_pim64_hpmc *hpmc; |
1563 | struct hp700_pim64_lpmc *lpmc; | | 1562 | struct hp700_pim64_lpmc *lpmc; |
1564 | struct hp700_pim64_toc *toc; | | 1563 | struct hp700_pim64_toc *toc; |
1565 | struct hp700_pim64_regs *regs; | | 1564 | struct hp700_pim64_regs *regs; |
1566 | struct hp700_pim64_checks *checks; | | 1565 | struct hp700_pim64_checks *checks; |
1567 | int reg_i, reg_j, reg_k; | | 1566 | int reg_i, reg_j, reg_k; |
1568 | uint64_t *regarray; | | 1567 | uint64_t *regarray; |
1569 | char bitmask_buffer[64]; | | 1568 | char bitmask_buffer[64]; |
1570 | const char *name; | | 1569 | const char *name; |
1571 | | | 1570 | |
1572 | regs = NULL; | | 1571 | regs = NULL; |
1573 | checks = NULL; | | 1572 | checks = NULL; |
1574 | switch (check_type) { | | 1573 | switch (check_type) { |
1575 | case T_HPMC: | | 1574 | case T_HPMC: |
1576 | hpmc = (struct hp700_pim64_hpmc *) pim_data_buffer; | | 1575 | hpmc = (struct hp700_pim64_hpmc *) pim_data_buffer; |
1577 | regs = &hpmc->pim_hpmc_regs; | | 1576 | regs = &hpmc->pim_hpmc_regs; |
1578 | checks = &hpmc->pim_hpmc_checks; | | 1577 | checks = &hpmc->pim_hpmc_checks; |
1579 | break; | | 1578 | break; |
1580 | case T_LPMC: | | 1579 | case T_LPMC: |
1581 | lpmc = (struct hp700_pim64_lpmc *) pim_data_buffer; | | 1580 | lpmc = (struct hp700_pim64_lpmc *) pim_data_buffer; |
1582 | checks = &lpmc->pim_lpmc_checks; | | 1581 | checks = &lpmc->pim_lpmc_checks; |
1583 | break; | | 1582 | break; |
1584 | case T_INTERRUPT: | | 1583 | case T_INTERRUPT: |
1585 | toc = (struct hp700_pim64_toc *) pim_data_buffer; | | 1584 | toc = (struct hp700_pim64_toc *) pim_data_buffer; |
1586 | regs = &toc->pim_toc_regs; | | 1585 | regs = &toc->pim_toc_regs; |
1587 | break; | | 1586 | break; |
1588 | default: | | 1587 | default: |
1589 | panic("unknown machine check type"); | | 1588 | panic("unknown machine check type"); |
1590 | /* NOTREACHED */ | | 1589 | /* NOTREACHED */ |
1591 | } | | 1590 | } |
1592 | | | 1591 | |
1593 | /* If we have register arrays, display them. */ | | 1592 | /* If we have register arrays, display them. */ |
1594 | if (regs != NULL) { | | 1593 | if (regs != NULL) { |
1595 | for (reg_i = 0; reg_i < 3; reg_i++) { | | 1594 | for (reg_i = 0; reg_i < 3; reg_i++) { |
1596 | if (reg_i == 0) { | | 1595 | if (reg_i == 0) { |
1597 | name = "General"; | | 1596 | name = "General"; |
1598 | regarray = ®s->pim_regs_r0; | | 1597 | regarray = ®s->pim_regs_r0; |
1599 | reg_j = 32; | | 1598 | reg_j = 32; |
1600 | } else if (reg_i == 1) { | | 1599 | } else if (reg_i == 1) { |
1601 | name = "Control"; | | 1600 | name = "Control"; |
1602 | regarray = ®s->pim_regs_cr0; | | 1601 | regarray = ®s->pim_regs_cr0; |
1603 | reg_j = 32; | | 1602 | reg_j = 32; |
1604 | } else { | | 1603 | } else { |
1605 | name = "Space"; | | 1604 | name = "Space"; |
1606 | regarray = ®s->pim_regs_sr0; | | 1605 | regarray = ®s->pim_regs_sr0; |
1607 | reg_j = 8; | | 1606 | reg_j = 8; |
1608 | } | | 1607 | } |
1609 | printf("\n\n\t%s Registers:", name); | | 1608 | printf("\n\n\t%s Registers:", name); |
1610 | for (reg_k = 0; reg_k < reg_j; reg_k++) { | | 1609 | for (reg_k = 0; reg_k < reg_j; reg_k++) { |
1611 | printf("%s", | | 1610 | printf("%s", |
1612 | (reg_k & 1) ? " " : "\n\t"); | | 1611 | (reg_k & 1) ? " " : "\n\t"); |
1613 | if (!(reg_k & 1)) | | 1612 | if (!(reg_k & 1)) |
1614 | printf("%2d: ", reg_k); | | 1613 | printf("%2d: ", reg_k); |
1615 | printf("0x%016lx", | | 1614 | printf("0x%016lx", |
1616 | (unsigned long)regarray[reg_k]); | | 1615 | (unsigned long)regarray[reg_k]); |
1617 | } | | 1616 | } |
1618 | | | 1617 | |
1619 | } | | 1618 | } |
1620 | | | 1619 | |
1621 | /* Print out some interesting registers. */ | | 1620 | /* Print out some interesting registers. */ |
1622 | printf("\n\n\tIIA head 0x%lx:0x%016lx\n" | | 1621 | printf("\n\n\tIIA head 0x%lx:0x%016lx\n" |
1623 | "\tIIA tail 0x%lx:0x%016lx", | | 1622 | "\tIIA tail 0x%lx:0x%016lx", |
1624 | (unsigned long)regs->pim_regs_cr17, | | 1623 | (unsigned long)regs->pim_regs_cr17, |
1625 | (unsigned long)regs->pim_regs_cr18, | | 1624 | (unsigned long)regs->pim_regs_cr18, |
1626 | (unsigned long)regs->pim_regs_iisq_tail, | | 1625 | (unsigned long)regs->pim_regs_iisq_tail, |
1627 | (unsigned long)regs->pim_regs_iioq_tail); | | 1626 | (unsigned long)regs->pim_regs_iioq_tail); |
1628 | PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS); | | 1627 | PIM_WORD("\n\tIPSW", regs->pim_regs_cr22, PSW_BITS); |
1629 | printf("\n\tSP 0x%lx:0x%016lx\n\tFP 0x%lx:0x%016lx", | | 1628 | printf("\n\tSP 0x%lx:0x%016lx\n\tFP 0x%lx:0x%016lx", |
1630 | (unsigned long)regs->pim_regs_sr0, | | 1629 | (unsigned long)regs->pim_regs_sr0, |
1631 | (unsigned long)regs->pim_regs_r30, | | 1630 | (unsigned long)regs->pim_regs_r30, |
1632 | (unsigned long)regs->pim_regs_sr0, | | 1631 | (unsigned long)regs->pim_regs_sr0, |
1633 | (unsigned long)regs->pim_regs_r3); | | 1632 | (unsigned long)regs->pim_regs_r3); |
1634 | } | | 1633 | } |
1635 | | | 1634 | |
1636 | /* If we have check words, display them. */ | | 1635 | /* If we have check words, display them. */ |
1637 | if (checks != NULL) { | | 1636 | if (checks != NULL) { |
1638 | PIM_WORD("\n\n\tCheck Type", checks->pim_check_type, | | 1637 | PIM_WORD("\n\n\tCheck Type", checks->pim_check_type, |
1639 | PIM_CHECK_BITS); | | 1638 | PIM_CHECK_BITS); |
1640 | PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state, | | 1639 | PIM_WORD("\n\tCPU State", checks->pim_check_cpu_state, |
1641 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); | | 1640 | PIM_CPU_BITS PIM_CPU_HPMC_BITS); |
1642 | PIM_WORD("\n\tCache Check", checks->pim_check_cache, | | 1641 | PIM_WORD("\n\tCache Check", checks->pim_check_cache, |
1643 | PIM_CACHE_BITS); | | 1642 | PIM_CACHE_BITS); |
1644 | PIM_WORD("\n\tTLB Check", checks->pim_check_tlb, | | 1643 | PIM_WORD("\n\tTLB Check", checks->pim_check_tlb, |
1645 | PIM_TLB_BITS); | | 1644 | PIM_TLB_BITS); |
1646 | PIM_WORD("\n\tBus Check", checks->pim_check_bus, | | 1645 | PIM_WORD("\n\tBus Check", checks->pim_check_bus, |
1647 | PIM_BUS_BITS); | | 1646 | PIM_BUS_BITS); |
1648 | PIM_WORD("\n\tAssist Check", checks->pim_check_assist, | | 1647 | PIM_WORD("\n\tAssist Check", checks->pim_check_assist, |
1649 | PIM_ASSIST_BITS); | | 1648 | PIM_ASSIST_BITS); |
1650 | printf("\tAssist State %u", checks->pim_check_assist_state); | | 1649 | printf("\tAssist State %u", checks->pim_check_assist_state); |
1651 | printf("\n\tSystem Responder 0x%016lx", | | 1650 | printf("\n\tSystem Responder 0x%016lx", |
1652 | (unsigned long)checks->pim_check_responder); | | 1651 | (unsigned long)checks->pim_check_responder); |
1653 | printf("\n\tSystem Requestor 0x%016lx", | | 1652 | printf("\n\tSystem Requestor 0x%016lx", |
1654 | (unsigned long)checks->pim_check_requestor); | | 1653 | (unsigned long)checks->pim_check_requestor); |
1655 | printf("\n\tPath Info 0x%08x", | | 1654 | printf("\n\tPath Info 0x%08x", |
1656 | checks->pim_check_path_info); | | 1655 | checks->pim_check_path_info); |
1657 | } | | 1656 | } |
1658 | } | | 1657 | } |
1659 | | | 1658 | |
1660 | void | | 1659 | void |
1661 | hppa_machine_check(int check_type) | | 1660 | hppa_machine_check(int check_type) |
1662 | { | | 1661 | { |
1663 | int pdc_pim_type; | | 1662 | int pdc_pim_type; |
1664 | const char *name; | | 1663 | const char *name; |
1665 | int error; | | 1664 | int error; |
1666 | | | 1665 | |
1667 | /* Do an fcacheall(). */ | | 1666 | /* Do an fcacheall(). */ |
1668 | fcacheall(); | | 1667 | fcacheall(); |
1669 | | | 1668 | |
1670 | /* Dispatch on the check type. */ | | 1669 | /* Dispatch on the check type. */ |
1671 | switch (check_type) { | | 1670 | switch (check_type) { |
1672 | case T_HPMC: | | 1671 | case T_HPMC: |
1673 | name = "HPMC"; | | 1672 | name = "HPMC"; |
1674 | pdc_pim_type = PDC_PIM_HPMC; | | 1673 | pdc_pim_type = PDC_PIM_HPMC; |
1675 | break; | | 1674 | break; |
1676 | case T_LPMC: | | 1675 | case T_LPMC: |
1677 | name = "LPMC"; | | 1676 | name = "LPMC"; |
1678 | pdc_pim_type = PDC_PIM_LPMC; | | 1677 | pdc_pim_type = PDC_PIM_LPMC; |
1679 | break; | | 1678 | break; |
1680 | case T_INTERRUPT: | | 1679 | case T_INTERRUPT: |
1681 | name = "TOC"; | | 1680 | name = "TOC"; |
1682 | pdc_pim_type = PDC_PIM_TOC; | | 1681 | pdc_pim_type = PDC_PIM_TOC; |
1683 | break; | | 1682 | break; |
1684 | default: | | 1683 | default: |
1685 | panic("unknown machine check type"); | | 1684 | panic("unknown machine check type"); |
1686 | /* NOTREACHED */ | | 1685 | /* NOTREACHED */ |
1687 | } | | 1686 | } |
1688 | | | 1687 | |
1689 | error = pdc_call((iodcio_t)pdc, 0, PDC_PIM, pdc_pim_type, | | 1688 | error = pdc_call((iodcio_t)pdc, 0, PDC_PIM, pdc_pim_type, |
1690 | &pdc_pim, pim_data_buffer, sizeof(pim_data_buffer)); | | 1689 | &pdc_pim, pim_data_buffer, sizeof(pim_data_buffer)); |
1691 | if (error < 0) | | 1690 | if (error < 0) |
1692 | printf(" - WARNING: could not transfer PIM info (%d)", error); | | 1691 | printf(" - WARNING: could not transfer PIM info (%d)", error); |
1693 | | | 1692 | |
1694 | CTASSERT(pdc_pim.count <= sizeof(pim_data_buffer)); | | 1693 | CTASSERT(pdc_pim.count <= sizeof(pim_data_buffer)); |
1695 | | | 1694 | |
1696 | /* | | 1695 | /* |
1697 | * Reset IO and log errors. | | 1696 | * Reset IO and log errors. |
1698 | * | | 1697 | * |
1699 | * This seems to be needed in order to output to the console | | 1698 | * This seems to be needed in order to output to the console |
1700 | * if we take a HPMC interrupt. This PDC procedure may not be | | 1699 | * if we take a HPMC interrupt. This PDC procedure may not be |
1701 | * implemented by some machines. | | 1700 | * implemented by some machines. |
1702 | */ | | 1701 | */ |
1703 | error = pdc_call((iodcio_t)pdc, 0, PDC_IO, 0, 0, 0, 0); | | 1702 | error = pdc_call((iodcio_t)pdc, 0, PDC_IO, 0, 0, 0, 0); |
1704 | if (error != PDC_ERR_OK && error != PDC_ERR_NOPROC) | | 1703 | if (error != PDC_ERR_OK && error != PDC_ERR_NOPROC) |
1705 | /* This seems futile if we can't print to the console. */ | | 1704 | /* This seems futile if we can't print to the console. */ |
1706 | panic("PDC_IO failed"); | | 1705 | panic("PDC_IO failed"); |
1707 | | | 1706 | |
1708 | printf("\nmachine check: %s", name); | | 1707 | printf("\nmachine check: %s", name); |
1709 | | | 1708 | |
1710 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) | | 1709 | if (hppa_cpu_info->hci_features & HPPA_FTRS_W32B) |
1711 | hppa_pim64_dump(check_type); | | 1710 | hppa_pim64_dump(check_type); |
1712 | else | | 1711 | else |
1713 | hppa_pim_dump(check_type); | | 1712 | hppa_pim_dump(check_type); |
1714 | | | 1713 | |
1715 | printf("\n"); | | 1714 | printf("\n"); |
1716 | | | 1715 | |
1717 | /* If this is our first check, panic. */ | | 1716 | /* If this is our first check, panic. */ |
1718 | if (in_check == 0) { | | 1717 | if (in_check == 0) { |
1719 | in_check = 1; | | 1718 | in_check = 1; |
1720 | DELAY(250000); | | 1719 | DELAY(250000); |
1721 | panic("machine check"); | | 1720 | panic("machine check"); |
1722 | } | | 1721 | } |
1723 | | | 1722 | |
1724 | /* Reboot the machine. */ | | 1723 | /* Reboot the machine. */ |
1725 | printf("Rebooting...\n"); | | 1724 | printf("Rebooting...\n"); |
1726 | cpu_die(); | | 1725 | cpu_die(); |
1727 | } | | 1726 | } |
1728 | | | 1727 | |
1729 | int | | 1728 | int |
1730 | cpu_dump(void) | | 1729 | cpu_dump(void) |
1731 | { | | 1730 | { |
1732 | long buf[dbtob(1) / sizeof (long)]; | | 1731 | long buf[dbtob(1) / sizeof (long)]; |
1733 | kcore_seg_t *segp; | | 1732 | kcore_seg_t *segp; |
1734 | cpu_kcore_hdr_t *cpuhdrp; | | 1733 | cpu_kcore_hdr_t *cpuhdrp; |
1735 | const struct bdevsw *bdev; | | 1734 | const struct bdevsw *bdev; |
1736 | | | 1735 | |
1737 | segp = (kcore_seg_t *)buf; | | 1736 | segp = (kcore_seg_t *)buf; |
1738 | cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; | | 1737 | cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; |
1739 | | | 1738 | |
1740 | /* | | 1739 | /* |
1741 | * Generate a segment header. | | 1740 | * Generate a segment header. |
1742 | */ | | 1741 | */ |
1743 | CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); | | 1742 | CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); |
1744 | segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); | | 1743 | segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); |
1745 | | | 1744 | |
1746 | /* | | 1745 | /* |
1747 | * Add the machine-dependent header info | | 1746 | * Add the machine-dependent header info |
1748 | */ | | 1747 | */ |
1749 | /* nothing for now */ | | 1748 | /* nothing for now */ |
1750 | | | 1749 | |
1751 | bdev = bdevsw_lookup(dumpdev); | | 1750 | bdev = bdevsw_lookup(dumpdev); |
1752 | if (bdev == NULL) | | 1751 | if (bdev == NULL) |
1753 | return (-1); | | 1752 | return (-1); |
1754 | | | 1753 | |
1755 | return (*bdev->d_dump)(dumpdev, dumplo, (void *)buf, dbtob(1)); | | 1754 | return (*bdev->d_dump)(dumpdev, dumplo, (void *)buf, dbtob(1)); |
1756 | } | | 1755 | } |
1757 | | | 1756 | |
1758 | /* | | 1757 | /* |
1759 | * Dump the kernel's image to the swap partition. | | 1758 | * Dump the kernel's image to the swap partition. |
1760 | */ | | 1759 | */ |
1761 | #define BYTES_PER_DUMP PAGE_SIZE | | 1760 | #define BYTES_PER_DUMP PAGE_SIZE |
1762 | | | 1761 | |
1763 | void | | 1762 | void |
1764 | dumpsys(void) | | 1763 | dumpsys(void) |
1765 | { | | 1764 | { |
1766 | const struct bdevsw *bdev; | | 1765 | const struct bdevsw *bdev; |
1767 | int psize, bytes, i, n; | | 1766 | int psize, bytes, i, n; |
1768 | char *maddr; | | 1767 | char *maddr; |
1769 | daddr_t blkno; | | 1768 | daddr_t blkno; |
1770 | int (*dump)(dev_t, daddr_t, void *, size_t); | | 1769 | int (*dump)(dev_t, daddr_t, void *, size_t); |
1771 | int error; | | 1770 | int error; |
1772 | | | 1771 | |
1773 | if (dumpdev == NODEV) | | 1772 | if (dumpdev == NODEV) |
1774 | return; | | 1773 | return; |
1775 | bdev = bdevsw_lookup(dumpdev); | | 1774 | bdev = bdevsw_lookup(dumpdev); |
1776 | if (bdev == NULL) | | 1775 | if (bdev == NULL) |
1777 | return; | | 1776 | return; |
1778 | | | 1777 | |
1779 | /* Save registers | | 1778 | /* Save registers |
1780 | savectx(&dumppcb); */ | | 1779 | savectx(&dumppcb); */ |
1781 | | | 1780 | |
1782 | if (dumpsize == 0) | | 1781 | if (dumpsize == 0) |
1783 | cpu_dumpconf(); | | 1782 | cpu_dumpconf(); |
1784 | if (dumplo <= 0) { | | 1783 | if (dumplo <= 0) { |
1785 | printf("\ndump to dev %u,%u not possible\n", | | 1784 | printf("\ndump to dev %u,%u not possible\n", |
1786 | major(dumpdev), minor(dumpdev)); | | 1785 | major(dumpdev), minor(dumpdev)); |
1787 | return; | | 1786 | return; |
1788 | } | | 1787 | } |
1789 | printf("\ndumping to dev %u,%u offset %ld\n", | | 1788 | printf("\ndumping to dev %u,%u offset %ld\n", |
1790 | major(dumpdev), minor(dumpdev), dumplo); | | 1789 | major(dumpdev), minor(dumpdev), dumplo); |
1791 | | | 1790 | |
1792 | psize = (*bdev->d_psize)(dumpdev); | | 1791 | psize = (*bdev->d_psize)(dumpdev); |
1793 | printf("dump "); | | 1792 | printf("dump "); |
1794 | if (psize == -1) { | | 1793 | if (psize == -1) { |
1795 | printf("area unavailable\n"); | | 1794 | printf("area unavailable\n"); |
1796 | return; | | 1795 | return; |