1 /* $NetBSD: kvm_mips.c,v 1.16 2001/08/05 03:33:15 matt Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 /* 31 * Modified for NetBSD/mips by Jason R. Thorpe, Numerical Aerospace 32 * Simulation Facility, NASA Ames Research Center. 33 */ 34 35 #include <sys/cdefs.h> 36 #if defined(LIBC_SCCS) && !defined(lint) 37 __RCSID("$NetBSD: kvm_mips.c,v 1.16 2001/08/05 03:33:15 matt Exp $"); 38 #endif /* LIBC_SCCS and not lint */ 39 40 /* 41 * MIPS machine dependent routines for kvm. 42 */ 43 44 #include <sys/param.h> 45 #include <sys/user.h> 46 #include <sys/proc.h> 47 #include <sys/stat.h> 48 #include <sys/kcore.h> 49 #include <machine/kcore.h> 50 #include <stdlib.h> 51 #include <unistd.h> 52 #include <nlist.h> 53 #include <kvm.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #include <limits.h> 58 #include <db.h> 59 60 #include "kvm_private.h" 61 62 #include <mips/cpuregs.h> 63 #include <mips/vmparam.h> 64 65 void 66 _kvm_freevtop(kd) 67 kvm_t *kd; 68 { 69 70 /* Not actually used for anything right now, but safe. */ 71 if (kd->vmst != 0) 72 free(kd->vmst); 73 } 74 75 int 76 _kvm_initvtop(kd) 77 kvm_t *kd; 78 { 79 80 return (0); 81 } 82 83 /* 84 * Translate a kernel virtual address to a physical address. 85 */ 86 int 87 _kvm_kvatop(kd, va, pa) 88 kvm_t *kd; 89 u_long va; 90 u_long *pa; 91 { 92 cpu_kcore_hdr_t *cpu_kh; 93 int page_off; 94 u_int pte; 95 u_long pte_pa; 96 97 if (ISALIVE(kd)) { 98 _kvm_err(kd, 0, "vatop called in live kernel!"); 99 return((off_t)0); 100 } 101 102 cpu_kh = kd->cpu_data; 103 page_off = va & PGOFSET; 104 105 if (va < MIPS_KSEG0_START) { 106 /* 107 * KUSEG (user virtual address space) - invalid. 108 */ 109 _kvm_err(kd, 0, "invalid kernel virtual address"); 110 goto lose; 111 } 112 113 if (va >= MIPS_KSEG0_START && va < MIPS_KSEG1_START) { 114 /* 115 * Direct-mapped cached address: just convert it. 116 */ 117 *pa = MIPS_KSEG0_TO_PHYS(va); 118 return (NBPG - page_off); 119 } 120 121 if (va >= MIPS_KSEG1_START && va < MIPS_KSEG2_START) { 122 /* 123 * Direct-mapped uncached address: just convert it. 124 */ 125 *pa = MIPS_KSEG1_TO_PHYS(va); 126 return (NBPG - page_off); 127 } 128 129 /* 130 * We now know that we're a KSEG2 (kernel virtually mapped) 131 * address. Translate the address using the pmap's kernel 132 * page table. 133 */ 134 135 /* 136 * Step 1: Make sure the kernel page table has a translation 137 * for the address. 138 */ 139 if (va >= (MIPS_KSEG2_START + (cpu_kh->sysmapsize * NBPG))) { 140 _kvm_err(kd, 0, "invalid KSEG2 address"); 141 goto lose; 142 } 143 144 /* 145 * Step 2: Locate and read the PTE. 146 */ 147 pte_pa = cpu_kh->sysmappa + 148 (((va - MIPS_KSEG2_START) >> PGSHIFT) * sizeof(u_int)); 149 if (pread(kd->pmfd, &pte, sizeof(pte), _kvm_pa2off(kd, pte_pa)) != 150 sizeof(pte)) { 151 _kvm_syserr(kd, 0, "could not read PTE"); 152 goto lose; 153 } 154 155 /* 156 * Step 3: Validate the PTE and return the physical address. 157 */ 158 if ((pte & cpu_kh->pg_v) == 0) { 159 _kvm_err(kd, 0, "invalid translation (invalid PTE)"); 160 goto lose; 161 } 162 *pa = (((pte & cpu_kh->pg_frame) >> cpu_kh->pg_shift) << PGSHIFT) + 163 page_off; 164 return (NBPG - page_off); 165 166 lose: 167 *pa = -1; 168 return (0); 169 } 170 171 /* 172 * Translate a physical address to a file-offset in the crash-dump. 173 */ 174 off_t 175 _kvm_pa2off(kd, pa) 176 kvm_t *kd; 177 u_long pa; 178 { 179 cpu_kcore_hdr_t *cpu_kh; 180 phys_ram_seg_t *ramsegs; 181 off_t off; 182 int i; 183 184 cpu_kh = kd->cpu_data; 185 ramsegs = (phys_ram_seg_t *)((char *)cpu_kh + ALIGN(sizeof *cpu_kh)); 186 187 off = 0; 188 for (i = 0; i < cpu_kh->nmemsegs; i++) { 189 if (pa >= ramsegs[i].start && 190 (pa - ramsegs[i].start) < ramsegs[i].size) { 191 off += (pa - ramsegs[i].start); 192 break; 193 } 194 off += ramsegs[i].size; 195 } 196 197 return (kd->dump_off + off); 198 } 199 200 /* 201 * Machine-dependent initialization for ALL open kvm descriptors, 202 * not just those for a kernel crash dump. Some architectures 203 * have to deal with these NOT being constants! (i.e. m68k) 204 */ 205 int 206 _kvm_mdopen(kd) 207 kvm_t *kd; 208 { 209 210 kd->usrstack = USRSTACK; 211 kd->min_uva = VM_MIN_ADDRESS; 212 kd->max_uva = VM_MAXUSER_ADDRESS; 213 214 return (0); 215 } 216