1 /*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software developed by the Computer Systems 6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7 * BG 91-66 and contributed to Berkeley. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #if defined(LIBC_SCCS) && !defined(lint) 39 static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93"; 40 #endif /* LIBC_SCCS and not lint */ 41 42 /* 43 * Sparc machine dependent routines for kvm. Hopefully, the forthcoming 44 * vm code will one day obsolete this module. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/user.h> 49 #include <sys/proc.h> 50 #include <sys/stat.h> 51 #include <sys/sysctl.h> 52 #include <sys/device.h> 53 #include <unistd.h> 54 #include <nlist.h> 55 #include <kvm.h> 56 57 #include <vm/vm.h> 58 #include <vm/vm_param.h> 59 #include <machine/autoconf.h> 60 61 #include <limits.h> 62 #include <db.h> 63 64 #include "kvm_private.h" 65 66 #define MA_SIZE 32 /* XXX */ 67 struct vmstate { 68 struct { 69 int x_seginval; 70 int x_npmemarr; 71 struct memarr x_pmemarr[MA_SIZE]; 72 struct segmap x_segmap_store[NKREG*NSEGRG]; 73 } x; 74 #define seginval x.x_seginval 75 #define npmemarr x.x_npmemarr 76 #define pmemarr x.x_pmemarr 77 #define segmap_store x.x_segmap_store 78 int *pte; 79 }; 80 #define NPMEG(vm) ((vm)->seginval+1) 81 82 static int cputyp = -1; 83 84 static int pgshift, nptesg; 85 86 #define VA_VPG(va) (cputyp==CPU_SUN4C ? VA_SUN4C_VPG(va) : VA_SUN4_VPG(va)) 87 88 static void 89 _kvm_mustinit(kd) 90 kvm_t *kd; 91 { 92 if (cputyp != -1) 93 return; 94 for (pgshift = 12; (1 << pgshift) != kd->nbpg; pgshift++) 95 ; 96 nptesg = NBPSG / kd->nbpg; 97 98 #if 1 99 if (cputyp == -1) { 100 if (kd->nbpg == 8192) 101 cputyp = CPU_SUN4; 102 else 103 cputyp = CPU_SUN4C; 104 } 105 #endif 106 } 107 108 void 109 _kvm_freevtop(kd) 110 kvm_t *kd; 111 { 112 if (kd->vmst != 0) { 113 if (kd->vmst->pte != 0) 114 free(kd->vmst->pte); 115 free(kd->vmst); 116 kd->vmst = 0; 117 } 118 } 119 120 /* 121 * Prepare for translation of kernel virtual addresses into offsets 122 * into crash dump files. We use the MMU specific goop written at the 123 * and of crash dump by pmap_dumpmmu(). 124 * (note: sun4/sun4c 2-level MMU specific) 125 */ 126 int 127 _kvm_initvtop(kd) 128 kvm_t *kd; 129 { 130 register int i; 131 register int off; 132 register struct vmstate *vm; 133 struct stat st; 134 struct nlist nlist[5]; 135 136 _kvm_mustinit(kd); 137 138 if ((vm = kd->vmst) == 0) { 139 kd->vmst = vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 140 if (vm == 0) 141 return (-1); 142 } 143 144 if (fstat(kd->pmfd, &st) < 0) 145 return (-1); 146 /* 147 * Read segment table. 148 */ 149 150 off = st.st_size - roundup(sizeof(vm->x), kd->nbpg); 151 errno = 0; 152 if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 || 153 read(kd->pmfd, (char *)&vm->x, sizeof(vm->x)) < 0) { 154 _kvm_err(kd, kd->program, "cannot read segment map"); 155 return (-1); 156 } 157 158 vm->pte = (int *)_kvm_malloc(kd, NPMEG(vm) * nptesg * sizeof(int)); 159 if (vm->pte == 0) { 160 free(kd->vmst); 161 kd->vmst = 0; 162 return (-1); 163 } 164 165 /* 166 * Read PMEGs. 167 */ 168 off = st.st_size - roundup(sizeof(vm->x), kd->nbpg) - 169 roundup(NPMEG(vm) * nptesg * sizeof(int), kd->nbpg); 170 171 errno = 0; 172 if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 || 173 read(kd->pmfd, (char *)vm->pte, NPMEG(vm) * nptesg * sizeof(int)) < 0) { 174 _kvm_err(kd, kd->program, "cannot read PMEG table"); 175 return (-1); 176 } 177 178 return (0); 179 } 180 181 #define VA_OFF(va) (va & (kd->nbpg - 1)) 182 183 /* 184 * Translate a kernel virtual address to a physical address using the 185 * mapping information in kd->vm. Returns the result in pa, and returns 186 * the number of bytes that are contiguously available from this 187 * physical address. This routine is used only for crashdumps. 188 */ 189 int 190 _kvm_kvatop(kd, va, pa) 191 kvm_t *kd; 192 u_long va; 193 u_long *pa; 194 { 195 register int vr, vs, pte, off, nmem; 196 register struct vmstate *vm = kd->vmst; 197 struct regmap *rp; 198 struct segmap *sp; 199 struct memarr *mp; 200 201 _kvm_mustinit(kd); 202 203 if (va < KERNBASE) 204 goto err; 205 206 vr = VA_VREG(va); 207 vs = VA_VSEG(va); 208 209 sp = &vm->segmap_store[(vr-NUREG)*NSEGRG + vs]; 210 if (sp->sg_npte == 0) 211 goto err; 212 if (sp->sg_pmeg == vm->seginval) 213 goto err; 214 pte = vm->pte[sp->sg_pmeg * nptesg + VA_VPG(va)]; 215 if ((pte & PG_V) != 0) { 216 register long p, dumpoff = 0; 217 218 off = VA_OFF(va); 219 p = (pte & PG_PFNUM) << pgshift; 220 /* Translate (sparse) pfnum to (packed) dump offset */ 221 for (mp = vm->pmemarr, nmem = vm->npmemarr; --nmem >= 0; mp++) { 222 if (mp->addr <= p && p < mp->addr + mp->len) 223 break; 224 dumpoff += mp->len; 225 } 226 if (nmem < 0) 227 goto err; 228 *pa = (dumpoff + p - mp->addr) | off; 229 return (kd->nbpg - off); 230 } 231 err: 232 _kvm_err(kd, 0, "invalid address (%x)", va); 233 return (0); 234 } 235 236 #if 0 237 static int 238 getcputyp() 239 { 240 int mib[2]; 241 size_t size; 242 243 mib[0] = CTL_HW; 244 mib[1] = HW_CLASS; 245 size = sizeof cputyp; 246 if (sysctl(mib, 2, &cputyp, &size, NULL, 0) == -1) 247 return (-1); 248 } 249 #endif 250