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