1 /* $NetBSD: kvm_mips.c,v 1.22 2014/02/19 20:21:22 dsl 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.22 2014/02/19 20:21:22 dsl 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/proc.h> 46 #include <sys/stat.h> 47 #include <sys/kcore.h> 48 #include <sys/types.h> 49 50 #include <machine/kcore.h> 51 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <nlist.h> 55 #include <kvm.h> 56 57 #include <uvm/uvm_extern.h> 58 59 #include <limits.h> 60 #include <db.h> 61 62 #include "kvm_private.h" 63 64 #include <mips/cpuregs.h> 65 #include <mips/vmparam.h> 66 67 void 68 _kvm_freevtop(kvm_t *kd) 69 { 70 71 /* Not actually used for anything right now, but safe. */ 72 if (kd->vmst != 0) 73 free(kd->vmst); 74 } 75 76 int 77 _kvm_initvtop(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(kvm_t *kd, vaddr_t va, paddr_t *pa) 88 { 89 cpu_kcore_hdr_t *cpu_kh; 90 int page_off; 91 u_int pte; 92 paddr_t pte_pa; 93 94 if (ISALIVE(kd)) { 95 _kvm_err(kd, 0, "vatop called in live kernel!"); 96 return((off_t)0); 97 } 98 99 cpu_kh = kd->cpu_data; 100 page_off = va & PGOFSET; 101 102 #ifdef _LP64 103 if (MIPS_XKPHYS_P(va)) { 104 /* 105 * Direct-mapped cached address: just convert it. 106 */ 107 *pa = MIPS_XKPHYS_TO_PHYS(va); 108 return (NBPG - page_off); 109 } 110 111 if (va < MIPS_XKPHYS_START) { 112 /* 113 * XUSEG (user virtual address space) - invalid. 114 */ 115 _kvm_err(kd, 0, "invalid kernel virtual address"); 116 goto lose; 117 } 118 #else 119 if (va < MIPS_KSEG0_START) { 120 /* 121 * KUSEG (user virtual address space) - invalid. 122 */ 123 _kvm_err(kd, 0, "invalid kernel virtual address"); 124 goto lose; 125 } 126 #endif 127 128 if (MIPS_KSEG0_P(va)) { 129 /* 130 * Direct-mapped cached address: just convert it. 131 */ 132 *pa = MIPS_KSEG0_TO_PHYS(va); 133 return (NBPG - page_off); 134 } 135 136 if (MIPS_KSEG1_P(va)) { 137 /* 138 * Direct-mapped uncached address: just convert it. 139 */ 140 *pa = MIPS_KSEG1_TO_PHYS(va); 141 return (NBPG - page_off); 142 } 143 144 #ifdef _LP64 145 if (va >= MIPS_KSEG2_START) { 146 /* 147 * KUSEG (user virtual address space) - invalid. 148 */ 149 _kvm_err(kd, 0, "invalid kernel virtual address"); 150 goto lose; 151 } 152 #endif 153 154 /* 155 * We now know that we're a KSEG2 (kernel virtually mapped) 156 * address. Translate the address using the pmap's kernel 157 * page table. 158 */ 159 160 /* 161 * Step 1: Make sure the kernel page table has a translation 162 * for the address. 163 */ 164 #ifdef _LP64 165 if (va >= (MIPS_XKSEG_START + (cpu_kh->sysmapsize * NBPG))) { 166 _kvm_err(kd, 0, "invalid XKSEG address"); 167 goto lose; 168 } 169 #else 170 if (va >= (MIPS_KSEG2_START + (cpu_kh->sysmapsize * NBPG))) { 171 _kvm_err(kd, 0, "invalid KSEG2 address"); 172 goto lose; 173 } 174 #endif 175 176 /* 177 * Step 2: Locate and read the PTE. 178 */ 179 pte_pa = cpu_kh->sysmappa + 180 (((va - MIPS_KSEG2_START) >> PGSHIFT) * sizeof(u_int)); 181 if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte), 182 _kvm_pa2off(kd, pte_pa)) != sizeof(pte)) { 183 _kvm_syserr(kd, 0, "could not read PTE"); 184 goto lose; 185 } 186 187 /* 188 * Step 3: Validate the PTE and return the physical address. 189 */ 190 if ((pte & cpu_kh->pg_v) == 0) { 191 _kvm_err(kd, 0, "invalid translation (invalid PTE)"); 192 goto lose; 193 } 194 *pa = (((pte & cpu_kh->pg_frame) >> cpu_kh->pg_shift) << PGSHIFT) + 195 page_off; 196 return (NBPG - page_off); 197 198 lose: 199 *pa = -1; 200 return (0); 201 } 202 203 /* 204 * Translate a physical address to a file-offset in the crash dump. 205 */ 206 off_t 207 _kvm_pa2off(kvm_t *kd, paddr_t pa) 208 { 209 cpu_kcore_hdr_t *cpu_kh; 210 phys_ram_seg_t *ramsegs; 211 off_t off; 212 int i; 213 214 cpu_kh = kd->cpu_data; 215 ramsegs = (phys_ram_seg_t *)((char *)cpu_kh + ALIGN(sizeof *cpu_kh)); 216 217 off = 0; 218 for (i = 0; i < cpu_kh->nmemsegs; i++) { 219 if (pa >= ramsegs[i].start && 220 (pa - ramsegs[i].start) < ramsegs[i].size) { 221 off += (pa - ramsegs[i].start); 222 break; 223 } 224 off += ramsegs[i].size; 225 } 226 227 return (kd->dump_off + off); 228 } 229 230 /* 231 * Machine-dependent initialization for ALL open kvm descriptors, 232 * not just those for a kernel crash dump. Some architectures 233 * have to deal with these NOT being constants! (i.e. m68k) 234 */ 235 int 236 _kvm_mdopen(kvm_t *kd) 237 { 238 239 kd->usrstack = USRSTACK; 240 kd->min_uva = VM_MIN_ADDRESS; 241 kd->max_uva = VM_MAXUSER_ADDRESS; 242 243 return (0); 244 } 245