kvm_alpha.c revision 1.18 1 /* $NetBSD: kvm_alpha.c,v 1.18 2000/06/29 06:34:23 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 (at) 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 #define __KVM_ALPHA_PRIVATE /* see <machine/pte.h> */
31
32 #include <sys/param.h>
33 #include <sys/user.h>
34 #include <sys/proc.h>
35 #include <sys/stat.h>
36 #include <sys/kcore.h>
37 #include <machine/kcore.h>
38 #include <unistd.h>
39 #include <nlist.h>
40 #include <kvm.h>
41
42 #include <uvm/uvm_extern.h>
43
44 #include <limits.h>
45 #include <db.h>
46 #include <stdlib.h>
47
48 #include "kvm_private.h"
49
50 struct vmstate {
51 vsize_t page_shift;
52 };
53
54 void
55 _kvm_freevtop(kd)
56 kvm_t *kd;
57 {
58
59 if (kd->vmst != 0)
60 free(kd->vmst);
61 }
62
63 int
64 _kvm_initvtop(kd)
65 kvm_t *kd;
66 {
67 cpu_kcore_hdr_t *cpu_kh;
68 struct vmstate *vm;
69
70 vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
71 if (vm == NULL)
72 return (-1);
73
74 cpu_kh = kd->cpu_data;
75
76 /* Compute page_shift. */
77 for (vm->page_shift = 0; (1L << vm->page_shift) < cpu_kh->page_size;
78 vm->page_shift++)
79 /* nothing */ ;
80 if ((1L << vm->page_shift) != cpu_kh->page_size) {
81 free(vm);
82 return (-1);
83 }
84
85 kd->vmst = vm;
86 return (0);
87 }
88
89 int
90 _kvm_kvatop(kd, va, pa)
91 kvm_t *kd;
92 u_long va;
93 u_long *pa;
94 {
95 cpu_kcore_hdr_t *cpu_kh;
96 struct vmstate *vm;
97 alpha_pt_entry_t pte;
98 u_long pteoff, page_off;
99 int rv;
100
101 if (ISALIVE(kd)) {
102 _kvm_err(kd, 0, "vatop called in live kernel!");
103 return(0);
104 }
105
106 cpu_kh = kd->cpu_data;
107 vm = kd->vmst;
108 page_off = va & (cpu_kh->page_size - 1);
109
110 #define PAGE_SHIFT vm->page_shift
111
112 if (va >= ALPHA_K0SEG_BASE && va <= ALPHA_K0SEG_END) {
113 /*
114 * Direct-mapped address: just convert it.
115 */
116
117 *pa = ALPHA_K0SEG_TO_PHYS(va);
118 rv = cpu_kh->page_size - page_off;
119 } else if (va >= ALPHA_K1SEG_BASE && va <= ALPHA_K1SEG_END) {
120 /*
121 * Real kernel virtual address: do the translation.
122 */
123
124 /* Find and read the L1 PTE. */
125 pteoff = cpu_kh->lev1map_pa +
126 l1pte_index(va) * sizeof(alpha_pt_entry_t);
127 if (pread(kd->pmfd, &pte, sizeof(pte),
128 _kvm_pa2off(kd, pteoff)) != sizeof(pte)) {
129 _kvm_syserr(kd, 0, "could not read L1 PTE");
130 goto lose;
131 }
132
133 /* Find and read the L2 PTE. */
134 if ((pte & ALPHA_PTE_VALID) == 0) {
135 _kvm_err(kd, 0, "invalid translation (invalid L1 PTE)");
136 goto lose;
137 }
138 pteoff = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size +
139 l2pte_index(va) * sizeof(alpha_pt_entry_t);
140 if (pread(kd->pmfd, &pte, sizeof(pte),
141 _kvm_pa2off(kd, pteoff)) != sizeof(pte)) {
142 _kvm_syserr(kd, 0, "could not read L2 PTE");
143 goto lose;
144 }
145
146 /* Find and read the L3 PTE. */
147 if ((pte & ALPHA_PTE_VALID) == 0) {
148 _kvm_err(kd, 0, "invalid translation (invalid L2 PTE)");
149 goto lose;
150 }
151 pteoff = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size +
152 l3pte_index(va) * sizeof(alpha_pt_entry_t);
153 if (pread(kd->pmfd, &pte, sizeof(pte),
154 _kvm_pa2off(kd, pteoff)) != sizeof(pte)) {
155 _kvm_syserr(kd, 0, "could not read L3 PTE");
156 goto lose;
157 }
158
159 /* Fill in the PA. */
160 if ((pte & ALPHA_PTE_VALID) == 0) {
161 _kvm_err(kd, 0, "invalid translation (invalid L3 PTE)");
162 goto lose;
163 }
164 *pa = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size + page_off;
165 rv = cpu_kh->page_size - page_off;
166 } else {
167 /*
168 * Bogus address (not in KV space): punt.
169 */
170
171 _kvm_err(kd, 0, "invalid kernel virtual address");
172 lose:
173 *pa = -1;
174 rv = 0;
175 }
176
177 #undef PAGE_SHIFT
178
179 return (rv);
180 }
181
182 /*
183 * Translate a physical address to a file-offset in the crash-dump.
184 */
185 off_t
186 _kvm_pa2off(kd, pa)
187 kvm_t *kd;
188 u_long pa;
189 {
190 cpu_kcore_hdr_t *cpu_kh;
191 phys_ram_seg_t *ramsegs;
192 off_t off;
193 int i;
194
195 cpu_kh = kd->cpu_data;
196 ramsegs = (phys_ram_seg_t *)((char *)cpu_kh + ALIGN(sizeof *cpu_kh));
197
198 off = 0;
199 for (i = 0; i < cpu_kh->nmemsegs; i++) {
200 if (pa >= ramsegs[i].start &&
201 (pa - ramsegs[i].start) < ramsegs[i].size) {
202 off += (pa - ramsegs[i].start);
203 break;
204 }
205 off += ramsegs[i].size;
206 }
207
208 return (kd->dump_off + off);
209 }
210
211 /*
212 * Machine-dependent initialization for ALL open kvm descriptors,
213 * not just those for a kernel crash dump. Some architectures
214 * have to deal with these NOT being constants! (i.e. m68k)
215 */
216 int
217 _kvm_mdopen(kd)
218 kvm_t *kd;
219 {
220
221 kd->usrstack = USRSTACK;
222 kd->min_uva = VM_MIN_ADDRESS;
223 kd->max_uva = VM_MAXUSER_ADDRESS;
224
225 return (0);
226 }
227