1 /* $NetBSD: kvm_mips.c,v 1.15 2000/06/29 06:34:24 mrg 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.15 2000/06/29 06:34:24 mrg 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 64 void 65 _kvm_freevtop(kd) 66 kvm_t *kd; 67 { 68 69 /* Not actually used for anything right now, but safe. */ 70 if (kd->vmst != 0) 71 free(kd->vmst); 72 } 73 74 int 75 _kvm_initvtop(kd) 76 kvm_t *kd; 77 { 78 79 return (0); 80 } 81 82 /* 83 * Translate a kernel virtual address to a physical address. 84 */ 85 int 86 _kvm_kvatop(kd, va, pa) 87 kvm_t *kd; 88 u_long va; 89 u_long *pa; 90 { 91 cpu_kcore_hdr_t *cpu_kh; 92 int page_off; 93 u_int pte; 94 u_long pte_pa; 95 96 if (ISALIVE(kd)) { 97 _kvm_err(kd, 0, "vatop called in live kernel!"); 98 return((off_t)0); 99 } 100 101 cpu_kh = kd->cpu_data; 102 page_off = va & PGOFSET; 103 104 if (va < MIPS_KSEG0_START) { 105 /* 106 * KUSEG (user virtual address space) - invalid. 107 */ 108 _kvm_err(kd, 0, "invalid kernel virtual address"); 109 goto lose; 110 } 111 112 if (va >= MIPS_KSEG0_START && va < MIPS_KSEG1_START) { 113 /* 114 * Direct-mapped cached address: just convert it. 115 */ 116 *pa = MIPS_KSEG0_TO_PHYS(va); 117 return (NBPG - page_off); 118 } 119 120 if (va >= MIPS_KSEG1_START && va < MIPS_KSEG2_START) { 121 /* 122 * Direct-mapped uncached address: just convert it. 123 */ 124 *pa = MIPS_KSEG1_TO_PHYS(va); 125 return (NBPG - page_off); 126 } 127 128 /* 129 * We now know that we're a KSEG2 (kernel virtually mapped) 130 * address. Translate the address using the pmap's kernel 131 * page table. 132 */ 133 134 /* 135 * Step 1: Make sure the kernel page table has a translation 136 * for the address. 137 */ 138 if (va >= (MIPS_KSEG2_START + (cpu_kh->sysmapsize * NBPG))) { 139 _kvm_err(kd, 0, "invalid KSEG2 address"); 140 goto lose; 141 } 142 143 /* 144 * Step 2: Locate and read the PTE. 145 */ 146 pte_pa = cpu_kh->sysmappa + 147 (((va - MIPS_KSEG2_START) >> PGSHIFT) * sizeof(u_int)); 148 if (pread(kd->pmfd, &pte, sizeof(pte), _kvm_pa2off(kd, pte_pa)) != 149 sizeof(pte)) { 150 _kvm_syserr(kd, 0, "could not read PTE"); 151 goto lose; 152 } 153 154 /* 155 * Step 3: Validate the PTE and return the physical address. 156 */ 157 if ((pte & cpu_kh->pg_v) == 0) { 158 _kvm_err(kd, 0, "invalid translation (invalid PTE)"); 159 goto lose; 160 } 161 *pa = (((pte & cpu_kh->pg_frame) >> cpu_kh->pg_shift) << PGSHIFT) + 162 page_off; 163 return (NBPG - page_off); 164 165 lose: 166 *pa = -1; 167 return (0); 168 } 169 170 /* 171 * Translate a physical address to a file-offset in the crash-dump. 172 */ 173 off_t 174 _kvm_pa2off(kd, pa) 175 kvm_t *kd; 176 u_long pa; 177 { 178 cpu_kcore_hdr_t *cpu_kh; 179 phys_ram_seg_t *ramsegs; 180 off_t off; 181 int i; 182 183 cpu_kh = kd->cpu_data; 184 ramsegs = (phys_ram_seg_t *)((char *)cpu_kh + ALIGN(sizeof *cpu_kh)); 185 186 off = 0; 187 for (i = 0; i < cpu_kh->nmemsegs; i++) { 188 if (pa >= ramsegs[i].start && 189 (pa - ramsegs[i].start) < ramsegs[i].size) { 190 off += (pa - ramsegs[i].start); 191 break; 192 } 193 off += ramsegs[i].size; 194 } 195 196 return (kd->dump_off + off); 197 } 198 199 /* 200 * Machine-dependent initialization for ALL open kvm descriptors, 201 * not just those for a kernel crash dump. Some architectures 202 * have to deal with these NOT being constants! (i.e. m68k) 203 */ 204 int 205 _kvm_mdopen(kd) 206 kvm_t *kd; 207 { 208 209 kd->usrstack = USRSTACK; 210 kd->min_uva = VM_MIN_ADDRESS; 211 kd->max_uva = VM_MAXUSER_ADDRESS; 212 213 return (0); 214 } 215