Deleted Added
full compact
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 *

--- 13 unchanged lines hidden (view full) ---

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