1 /* $NetBSD: kvm_sparc.c,v 1.19 1999/01/30 16:57:25 eeh 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.19 1999/01/30 16:57:25 eeh 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/exec.h> 56 #include <sys/user.h> 57 #include <sys/proc.h> 58 #include <sys/stat.h> 59 #include <sys/core.h> 60 #include <sys/kcore.h> 61 #include <unistd.h> 62 #include <nlist.h> 63 #include <kvm.h> 64 65 #include <vm/vm.h> 66 #include <vm/vm_param.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 int _kvm_kvatop44c __P((kvm_t *, u_long, u_long *)); 86 int _kvm_kvatop4m __P((kvm_t *, u_long, u_long *)); 87 88 void 89 _kvm_freevtop(kd) 90 kvm_t *kd; 91 { 92 if (kd->vmst != 0) { 93 _kvm_err(kd, kd->program, "_kvm_freevtop: internal error"); 94 kd->vmst = 0; 95 } 96 } 97 98 /* 99 * Prepare for translation of kernel virtual addresses into offsets 100 * into crash dump files. We use the MMU specific goop written at the 101 * front of the crash dump by pmap_dumpmmu(). 102 */ 103 int 104 _kvm_initvtop(kd) 105 kvm_t *kd; 106 { 107 cpu_kcore_hdr_t *cpup = kd->cpu_data; 108 109 switch (cputyp = cpup->cputype) { 110 case CPU_SUN4: 111 case CPU_SUN4U: 112 kd->nbpg = 8196; 113 pgshift = 13; 114 break; 115 case CPU_SUN4C: 116 case CPU_SUN4M: 117 kd->nbpg = 4096; 118 pgshift = 12; 119 break; 120 default: 121 _kvm_err(kd, kd->program, "Unsupported CPU type"); 122 return (-1); 123 } 124 nptesg = NBPSG / kd->nbpg; 125 return (0); 126 } 127 128 /* 129 * Translate a kernel virtual address to a physical address using the 130 * mapping information in kd->vm. Returns the result in pa, and returns 131 * the number of bytes that are contiguously available from this 132 * physical address. This routine is used only for crashdumps. 133 */ 134 int 135 _kvm_kvatop(kd, va, pa) 136 kvm_t *kd; 137 u_long va; 138 u_long *pa; 139 { 140 if (cputyp == -1) 141 if (_kvm_initvtop(kd) != 0) 142 return (-1); 143 144 switch (cputyp) { 145 case CPU_SUN4: 146 case CPU_SUN4C: 147 return _kvm_kvatop44c(kd, va, pa); 148 break; 149 case CPU_SUN4M: 150 return _kvm_kvatop4m(kd, va, pa); 151 break; 152 case CPU_SUN4U: 153 default: 154 return _kvm_kvatop4u(kd, va, pa); 155 } 156 } 157 158 /* 159 * (note: sun4 3-level MMU not yet supported) 160 */ 161 int 162 _kvm_kvatop44c(kd, va, pa) 163 kvm_t *kd; 164 u_long va; 165 u_long *pa; 166 { 167 int vr, vs, pte; 168 cpu_kcore_hdr_t *cpup = kd->cpu_data; 169 struct segmap *sp, *segmaps; 170 int *ptes; 171 int nkreg, nureg; 172 u_long kernbase = cpup->kernbase; 173 174 if (va < kernbase) 175 goto err; 176 177 /* 178 * Layout of CPU segment: 179 * cpu_kcore_hdr_t; 180 * [alignment] 181 * phys_ram_seg_t[cpup->nmemseg]; 182 * segmap[cpup->nsegmap]; 183 * ptes[cpup->npmegs]; 184 */ 185 segmaps = (struct segmap *)((long)kd->cpu_data + cpup->segmapoffset); 186 ptes = (int *)((int)kd->cpu_data + cpup->pmegoffset); 187 nkreg = ((int)((-(unsigned)kernbase) / NBPRG)); 188 nureg = 256 - nkreg; 189 190 vr = VA_VREG(va); 191 vs = VA_VSEG(va); 192 193 sp = &segmaps[(vr-nureg)*NSEGRG + vs]; 194 if (sp->sg_npte == 0) 195 goto err; 196 if (sp->sg_pmeg == cpup->npmeg - 1) /* =seginval */ 197 goto err; 198 pte = ptes[sp->sg_pmeg * nptesg + VA_VPG(va)]; 199 if ((pte & PG_V) != 0) { 200 long p, off = VA_OFF(va); 201 202 p = (pte & PG_PFNUM) << pgshift; 203 *pa = p + off; 204 return (kd->nbpg - off); 205 } 206 err: 207 _kvm_err(kd, 0, "invalid address (%x)", va); 208 return (0); 209 } 210 211 int 212 _kvm_kvatop4m(kd, va, pa) 213 kvm_t *kd; 214 u_long va; 215 u_long *pa; 216 { 217 cpu_kcore_hdr_t *cpup = kd->cpu_data; 218 int vr, vs; 219 int pte; 220 off_t foff; 221 struct segmap *sp, *segmaps; 222 int nkreg, nureg; 223 u_long kernbase = cpup->kernbase; 224 225 if (va < kernbase) 226 goto err; 227 228 /* 229 * Layout of CPU segment: 230 * cpu_kcore_hdr_t; 231 * [alignment] 232 * phys_ram_seg_t[cpup->nmemseg]; 233 * segmap[cpup->nsegmap]; 234 */ 235 segmaps = (struct segmap *)((long)kd->cpu_data + cpup->segmapoffset); 236 nkreg = ((int)((-(unsigned)kernbase) / NBPRG)); 237 nureg = 256 - nkreg; 238 239 vr = VA_VREG(va); 240 vs = VA_VSEG(va); 241 242 sp = &segmaps[(vr-nureg)*NSEGRG + vs]; 243 if (sp->sg_npte == 0) 244 goto err; 245 246 /* XXX - assume page tables in initial kernel DATA or BSS. */ 247 foff = _kvm_pa2off(kd, (u_long)&sp->sg_pte[VA_VPG(va)] - kernbase); 248 if (foff == (off_t)-1) 249 return (0); 250 251 if (pread(kd->pmfd, &pte, sizeof(pte), foff) != sizeof(pte)) { 252 _kvm_syserr(kd, kd->program, "cannot read pte for %x", va); 253 return (0); 254 } 255 256 if ((pte & SRMMU_TETYPE) == SRMMU_TEPTE) { 257 long p, off = VA_OFF(va); 258 259 p = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT; 260 *pa = p + off; 261 return (kd->nbpg - off); 262 } 263 err: 264 _kvm_err(kd, 0, "invalid address (%x)", va); 265 return (0); 266 } 267 268 /* 269 * pmap's 32-bit page table format 270 */ 271 int 272 _kvm_kvatop4u(kd, va, pa) 273 kvm_t *kd; 274 u_long va; 275 u_long *pa; 276 { 277 int vr, vs; 278 cpu_kcore_hdr_t *cpup = kd->cpu_data; 279 int64_t **segmaps; 280 int64_t *ptes; 281 int64_t pte; 282 int nkreg, nureg; 283 u_long kernbase = cpup->kernbase; 284 int64_t kphys = cpup->kphys; 285 286 if (va < kernbase) 287 goto err; 288 289 /* 290 * Kernel layout: 291 * 292 * kernbase: 293 * 4MB locked TLB (text+data+BSS) 294 * Random other stuff. 295 */ 296 if (va >= kernbase && va < kernbase + 4*MEG) 297 return (va - kernbase) + kphys; 298 299 /* 300 * Layout of CPU segment: 301 * cpu_kcore_hdr_t; 302 * [alignment] 303 * phys_ram_seg_t[cpup->nmemseg]; 304 * segmap[cpup->nsegmap]; 305 */ 306 segmaps = ((long)kd->cpu_data + cpup->segmapoffset); 307 ptes = (int64_t *)_kvm_pa2off(kd, segmaps[va_to_seg(va)]); 308 pte = ptes[va_to_pte(va)]; 309 if ((pte & TLB_V) != 0) { 310 return ((pte & TLB_PA_MASK) | (va & PGOFSET); 311 } 312 err: 313 _kvm_err(kd, 0, "invalid address (%x)", va); 314 return (0); 315 } 316 317 318 /* 319 * Translate a physical address to a file-offset in the crash-dump. 320 */ 321 off_t 322 _kvm_pa2off(kd, pa) 323 kvm_t *kd; 324 u_long pa; 325 { 326 cpu_kcore_hdr_t *cpup = kd->cpu_data; 327 phys_ram_seg_t *mp; 328 off_t off; 329 int nmem; 330 331 /* 332 * Layout of CPU segment: 333 * cpu_kcore_hdr_t; 334 * [alignment] 335 * phys_ram_seg_t[cpup->nmemseg]; 336 */ 337 mp = (phys_ram_seg_t *)((int)kd->cpu_data + cpup->memsegoffset); 338 off = 0; 339 340 /* Translate (sparse) pfnum to (packed) dump offset */ 341 for (nmem = cpup->nmemseg; --nmem >= 0; mp++) { 342 if (mp->start <= pa && pa < mp->start + mp->size) 343 break; 344 off += mp->size; 345 } 346 if (nmem < 0) { 347 _kvm_err(kd, 0, "invalid address (%x)", pa); 348 return (-1); 349 } 350 351 return (kd->dump_off + off + pa - mp->start); 352 } 353 354 /* 355 * Machine-dependent initialization for ALL open kvm descriptors, 356 * not just those for a kernel crash dump. Some architectures 357 * have to deal with these NOT being constants! (i.e. m68k) 358 */ 359 int 360 _kvm_mdopen(kd) 361 kvm_t *kd; 362 { 363 u_long max_uva; 364 extern struct ps_strings *__ps_strings; 365 366 max_uva = (u_long) (__ps_strings + 1); 367 kd->usrstack = max_uva; 368 kd->max_uva = max_uva; 369 kd->min_uva = 0; 370 371 return (0); 372 } 373