kvm_ia64.c revision 85478
1/* $FreeBSD: head/lib/libkvm/kvm_ia64.c 85478 2001-10-25 09:08:21Z dfr $ */ 2/* $NetBSD: kvm_alpha.c,v 1.7.2.1 1997/11/02 20:34:26 mellon Exp $ */ 3 4/* 5 * Copyright (c) 1994, 1995 Carnegie-Mellon University. 6 * All rights reserved. 7 * 8 * Author: Chris G. Demetriou 9 * 10 * Permission to use, copy, modify and distribute this software and 11 * its documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31#include <sys/param.h> 32#include <sys/lock.h> 33#include <sys/mutex.h> 34#include <sys/user.h> 35#include <sys/proc.h> 36#include <sys/stat.h> 37#include <sys/types.h> 38#include <sys/uio.h> 39#include <unistd.h> 40#include <nlist.h> 41#include <kvm.h> 42 43#include <vm/vm.h> 44#include <vm/vm_param.h> 45 46#include <limits.h> 47#include <stdlib.h> 48#include <machine/pmap.h> 49#include "kvm_private.h" 50 51static off_t _kvm_pa2off(kvm_t *kd, u_long pa); 52 53struct vmstate { 54 u_int64_t kptdir; /* PA of page table directory */ 55 u_int64_t page_size; /* Page size */ 56}; 57 58void 59_kvm_freevtop(kvm_t *kd) 60{ 61 62 /* Not actually used for anything right now, but safe. */ 63 if (kd->vmst != 0) 64 free(kd->vmst); 65} 66 67int 68_kvm_initvtop(kvm_t *kd) 69{ 70 struct vmstate *vm; 71 struct nlist nlist[2]; 72 u_int64_t va; 73 74 vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); 75 if (vm == 0) { 76 _kvm_err(kd, kd->program, "cannot allocate vm"); 77 return (-1); 78 } 79 kd->vmst = vm; 80 vm->page_size = getpagesize(); /* XXX wrong for crashdumps */ 81 82 nlist[0].n_name = "kptdir"; 83 nlist[1].n_name = 0; 84 85 if (kvm_nlist(kd, nlist) != 0) { 86 _kvm_err(kd, kd->program, "bad namelist"); 87 return (-1); 88 } 89 90 if(!ISALIVE(kd)) { 91 if (kvm_read(kd, (nlist[0].n_value), &va, sizeof(va)) != sizeof(va)) { 92 _kvm_err(kd, kd->program, "cannot read kptdir"); 93 return (-1); 94 } 95 } else 96 if (kvm_read(kd, (nlist[0].n_value), &va, sizeof(va)) != sizeof(va)) { 97 _kvm_err(kd, kd->program, "cannot read kptdir"); 98 return (-1); 99 } 100 vm->kptdir = IA64_RR_MASK(va); 101 return (0); 102 103} 104 105int 106_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa) 107{ 108 u_int64_t kptdir; /* PA of kptdir */ 109 u_int64_t page_size; 110 int rv, page_off; 111 struct ia64_lpte pte; 112 off_t pteoff; 113 struct vmstate *vm; 114 115 vm = kd->vmst; 116 117 if (ISALIVE(kd)) { 118 _kvm_err(kd, 0, "vatop called in live kernel!"); 119 return(0); 120 } 121 kptdir = vm->kptdir; 122 page_size = vm->page_size; 123 124 page_off = va & (page_size - 1); 125 if (va >= IA64_RR_BASE(6) && va <= IA64_RR_BASE(7) + ((1L<<61)-1)) { 126 /* 127 * Direct-mapped address: just convert it. 128 */ 129 130 *pa = IA64_RR_MASK(va); 131 rv = page_size - page_off; 132 } else if (va >= IA64_RR_BASE(5) && va < IA64_RR_BASE(6)) { 133 /* 134 * Real kernel virtual address: do the translation. 135 */ 136#define KPTE_DIR_INDEX(va, ps) \ 137 (IA64_RR_MASK(va) / ((ps) * (ps) * sizeof(struct ia64_lpte))) 138#define KPTE_PTE_INDEX(va, ps) \ 139 (((va) / (ps)) % (ps / sizeof(struct ia64_lpte))) 140 141 int maxpt = page_size / sizeof(u_int64_t); 142 int ptno = KPTE_DIR_INDEX(va, page_size); 143 int pgno = KPTE_PTE_INDEX(va, page_size); 144 u_int64_t ptoff, pgoff; 145 146 if (ptno >= maxpt) { 147 _kvm_err(kd, 0, "invalid translation (va too large)"); 148 goto lose; 149 } 150 ptoff = kptdir + ptno * sizeof(u_int64_t); 151 if (lseek(kd->pmfd, _kvm_pa2off(kd, ptoff), 0) == -1 || 152 read(kd->pmfd, &pgoff, sizeof(pgoff)) != sizeof(pgoff)) { 153 _kvm_syserr(kd, 0, "could not read page table address"); 154 goto lose; 155 } 156 pgoff = IA64_RR_MASK(pgoff); 157 if (!pgoff) { 158 _kvm_err(kd, 0, "invalid translation (no page table)"); 159 goto lose; 160 } 161 if (lseek(kd->pmfd, _kvm_pa2off(kd, pgoff), 0) == -1 || 162 read(kd->pmfd, &pte, sizeof(pte)) != sizeof(pte)) { 163 _kvm_syserr(kd, 0, "could not read PTE"); 164 goto lose; 165 } 166 if (!pte.pte_p) { 167 _kvm_err(kd, 0, "invalid translation (invalid PTE)"); 168 goto lose; 169 } 170 *pa = pte.pte_ppn << 12; 171 rv = page_size - page_off; 172 } else { 173 /* 174 * Bogus address (not in KV space): punt. 175 */ 176 177 _kvm_err(kd, 0, "invalid kernel virtual address"); 178lose: 179 *pa = -1; 180 rv = 0; 181 } 182 183 return (rv); 184} 185 186/* 187 * Translate a physical address to a file-offset in the crash-dump. 188 */ 189off_t 190_kvm_pa2off(kd, pa) 191 kvm_t *kd; 192 u_long pa; 193{ 194 return IA64_PHYS_TO_RR7(pa); 195} 196 197