kvm_sparc.c revision 1.13 1 /* $NetBSD: kvm_sparc.c,v 1.13 1997/08/15 02:22:03 mikel Exp $ */
2
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software developed by the Computer Systems
8 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
9 * BG 91-66 and contributed to Berkeley.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 #if defined(LIBC_SCCS) && !defined(lint)
42 #if 0
43 static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93";
44 #else
45 __RCSID("$NetBSD: kvm_sparc.c,v 1.13 1997/08/15 02:22:03 mikel Exp $");
46 #endif
47 #endif /* LIBC_SCCS and not lint */
48
49 /*
50 * Sparc machine dependent routines for kvm. Hopefully, the forthcoming
51 * vm code will one day obsolete this module.
52 */
53
54 #include <sys/param.h>
55 #include <sys/user.h>
56 #include <sys/proc.h>
57 #include <sys/stat.h>
58 #include <sys/core.h>
59 #include <sys/kcore.h>
60 #include <unistd.h>
61 #include <nlist.h>
62 #include <kvm.h>
63
64 #include <vm/vm.h>
65 #include <vm/vm_param.h>
66 #include <machine/autoconf.h>
67 #include <machine/kcore.h>
68
69 #include <limits.h>
70 #include <db.h>
71
72 #include "kvm_private.h"
73
74
75 static int cputyp = -1;
76 static int pgshift;
77 static int nptesg; /* [sun4/sun4c] only */
78
79 #define VA_VPG(va) ((cputyp == CPU_SUN4C || cputyp == CPU_SUN4M) \
80 ? VA_SUN4C_VPG(va) \
81 : VA_SUN4_VPG(va))
82
83 #define VA_OFF(va) (va & (kd->nbpg - 1))
84
85
86 void
87 _kvm_freevtop(kd)
88 kvm_t *kd;
89 {
90 if (kd->vmst != 0) {
91 _kvm_err(kd, kd->program, "_kvm_freevtop: internal error");
92 kd->vmst = 0;
93 }
94 }
95
96 /*
97 * Prepare for translation of kernel virtual addresses into offsets
98 * into crash dump files. We use the MMU specific goop written at the
99 * front of the crash dump by pmap_dumpmmu().
100 */
101 int
102 _kvm_initvtop(kd)
103 kvm_t *kd;
104 {
105 cpu_kcore_hdr_t *cpup = kd->cpu_data;
106
107 switch (cputyp = cpup->cputype) {
108 case CPU_SUN4:
109 kd->nbpg = 8196;
110 pgshift = 13;
111 break;
112 case CPU_SUN4C:
113 case CPU_SUN4M:
114 kd->nbpg = 4096;
115 pgshift = 12;
116 break;
117 default:
118 _kvm_err(kd, kd->program, "Unsupported CPU type");
119 return (-1);
120 }
121 nptesg = NBPSG / kd->nbpg;
122 return (0);
123 }
124
125 /*
126 * Translate a kernel virtual address to a physical address using the
127 * mapping information in kd->vm. Returns the result in pa, and returns
128 * the number of bytes that are contiguously available from this
129 * physical address. This routine is used only for crashdumps.
130 */
131 int
132 _kvm_kvatop(kd, va, pa)
133 kvm_t *kd;
134 u_long va;
135 u_long *pa;
136 {
137 if (cputyp == -1)
138 if (_kvm_initvtop(kd) != 0)
139 return (-1);
140
141 return ((cputyp == CPU_SUN4M)
142 ? _kvm_kvatop4m(kd, va, pa)
143 : _kvm_kvatop44c(kd, va, pa));
144 }
145
146 /*
147 * (note: sun4 3-level MMU not yet supported)
148 */
149 int
150 _kvm_kvatop44c(kd, va, pa)
151 kvm_t *kd;
152 u_long va;
153 u_long *pa;
154 {
155 register int vr, vs, pte;
156 cpu_kcore_hdr_t *cpup = kd->cpu_data;
157 struct regmap *rp;
158 struct segmap *sp;
159 int *ptes;
160
161 if (va < KERNBASE)
162 goto err;
163
164 /*
165 * Layout of CPU segment:
166 * cpu_kcore_hdr_t;
167 * [alignment]
168 * phys_ram_seg_t[cpup->nmemseg];
169 * ptes[cpup->npmegs];
170 */
171 ptes = (int *)((int)kd->cpu_data + cpup->pmegoffset);
172
173 vr = VA_VREG(va);
174 vs = VA_VSEG(va);
175
176 sp = &cpup->segmap_store[(vr-NUREG)*NSEGRG + vs];
177 if (sp->sg_npte == 0)
178 goto err;
179 if (sp->sg_pmeg == cpup->npmeg - 1) /* =seginval */
180 goto err;
181 pte = ptes[sp->sg_pmeg * nptesg + VA_VPG(va)];
182 if ((pte & PG_V) != 0) {
183 register long p, off = VA_OFF(va);
184
185 p = (pte & PG_PFNUM) << pgshift;
186 *pa = p + off;
187 return (kd->nbpg - off);
188 }
189 err:
190 _kvm_err(kd, 0, "invalid address (%x)", va);
191 return (0);
192 }
193
194 int
195 _kvm_kvatop4m(kd, va, pa)
196 kvm_t *kd;
197 u_long va;
198 u_long *pa;
199 {
200 cpu_kcore_hdr_t *cpup = kd->cpu_data;
201 register int vr, vs;
202 int pte;
203 off_t foff;
204 struct regmap *rp;
205 struct segmap *sp;
206
207 if (va < KERNBASE)
208 goto err;
209
210 /*
211 * Layout of CPU segment:
212 * cpu_kcore_hdr_t;
213 * [alignment]
214 * phys_ram_seg_t[cpup->nmemseg];
215 */
216
217 vr = VA_VREG(va);
218 vs = VA_VSEG(va);
219
220 sp = &cpup->segmap_store[(vr-NUREG)*NSEGRG + vs];
221 if (sp->sg_npte == 0)
222 goto err;
223
224 /* XXX - assume page tables in initial kernel DATA or BSS. */
225 foff = _kvm_pa2off(kd, (u_long)&sp->sg_pte[VA_VPG(va)] - KERNBASE);
226 if (foff == (off_t)-1)
227 return (0);
228
229 if (lseek(kd->pmfd, foff, 0) == -1 ||
230 read(kd->pmfd, (void *)&pte, sizeof(pte)) < 0) {
231 _kvm_err(kd, kd->program, "cannot read pte for %x", va);
232 return (0);
233 }
234
235 if ((pte & SRMMU_TETYPE) == SRMMU_TEPTE) {
236 register long p, off = VA_OFF(va);
237
238 p = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT;
239 *pa = p + off;
240 return (kd->nbpg - off);
241 }
242 err:
243 _kvm_err(kd, 0, "invalid address (%x)", va);
244 return (0);
245 }
246
247 /*
248 * Translate a physical address to a file-offset in the crash-dump.
249 */
250 off_t
251 _kvm_pa2off(kd, pa)
252 kvm_t *kd;
253 u_long pa;
254 {
255 cpu_kcore_hdr_t *cpup = kd->cpu_data;
256 phys_ram_seg_t *mp;
257 off_t off;
258 int nmem;
259
260 /*
261 * Layout of CPU segment:
262 * cpu_kcore_hdr_t;
263 * [alignment]
264 * phys_ram_seg_t[cpup->nmemseg];
265 */
266 mp = (phys_ram_seg_t *)((int)kd->cpu_data + cpup->memsegoffset);
267 off = 0;
268
269 /* Translate (sparse) pfnum to (packed) dump offset */
270 for (nmem = cpup->nmemseg; --nmem >= 0; mp++) {
271 if (mp->start <= pa && pa < mp->start + mp->size)
272 break;
273 off += mp->size;
274 }
275 if (nmem < 0) {
276 _kvm_err(kd, 0, "invalid address (%x)", pa);
277 return (-1);
278 }
279
280 return (kd->dump_off + off + pa - mp->start);
281 }
282
283 /*
284 * Machine-dependent initialization for ALL open kvm descriptors,
285 * not just those for a kernel crash dump. Some architectures
286 * have to deal with these NOT being constants! (i.e. m68k)
287 */
288 int
289 _kvm_mdopen(kd)
290 kvm_t *kd;
291 {
292
293 kd->usrstack = USRSTACK;
294 kd->min_uva = VM_MIN_ADDRESS;
295 kd->max_uva = VM_MAXUSER_ADDRESS;
296
297 return (0);
298 }
299