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