* Removed the __P macros from lib/
[dragonfly.git] / lib / libkvm / kvm_alpha.c
1 /* $FreeBSD: src/lib/libkvm/kvm_alpha.c,v 1.4 1999/12/27 07:14:56 peter Exp $ */
2 /* $DragonFly: src/lib/libkvm/Attic/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