1 /*-
2 * Copyright (c) 1989, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software developed by the Computer Systems
6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7 * BG 91-66 and contributed to Berkeley.
8 *
9 * %sccs.include.redist.c%
10 */
11
12 #if defined(LIBC_SCCS) && !defined(lint)
13 static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 06/04/93";
14 #endif /* LIBC_SCCS and not lint */
15
16 /*
17 * Hp300 machine dependent routines for kvm. Hopefully, the forthcoming
18 * vm code will one day obsolete this module.
19 */
20
21 #include <sys/param.h>
22 #include <sys/user.h>
23 #include <sys/proc.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <nlist.h>
27 #include <kvm.h>
28
29 #include <vm/vm.h>
30 #include <vm/vm_param.h>
31
32 #include <limits.h>
33 #include <db.h>
34
35 #include "kvm_private.h"
36
37 #if defined(hp300)
38 #include <hp300/hp300/pte.h>
39 #endif
40
41 #if defined(luna68k)
42 #include <luna68k/luna68k/pte.h>
43 #endif
44
45 #ifndef btop
46 #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */
47 #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */
48 #endif
49
50 struct vmstate {
51 u_long lowram;
52 int mmutype;
53 struct ste *Sysseg;
54 };
55
56 #define KREAD(kd, addr, p)\
57 (kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)))
58
59 void
_kvm_freevtop(kd)60 _kvm_freevtop(kd)
61 kvm_t *kd;
62 {
63 if (kd->vmst != 0)
64 free(kd->vmst);
65 }
66
67 int
_kvm_initvtop(kd)68 _kvm_initvtop(kd)
69 kvm_t *kd;
70 {
71 struct vmstate *vm;
72 struct nlist nlist[4];
73
74 vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
75 if (vm == 0)
76 return (-1);
77 kd->vmst = vm;
78
79 nlist[0].n_name = "_lowram";
80 nlist[1].n_name = "_mmutype";
81 nlist[2].n_name = "_Sysseg";
82 nlist[3].n_name = 0;
83
84 if (kvm_nlist(kd, nlist) != 0) {
85 _kvm_err(kd, kd->program, "bad namelist");
86 return (-1);
87 }
88 vm->Sysseg = 0;
89 if (KREAD(kd, (u_long)nlist[0].n_value, &vm->lowram)) {
90 _kvm_err(kd, kd->program, "cannot read lowram");
91 return (-1);
92 }
93 if (KREAD(kd, (u_long)nlist[1].n_value, &vm->mmutype)) {
94 _kvm_err(kd, kd->program, "cannot read mmutype");
95 return (-1);
96 }
97 if (KREAD(kd, (u_long)nlist[2].n_value, &vm->Sysseg)) {
98 _kvm_err(kd, kd->program, "cannot read segment table");
99 return (-1);
100 }
101 return (0);
102 }
103
104 static int
_kvm_vatop(kd,sta,va,pa)105 _kvm_vatop(kd, sta, va, pa)
106 kvm_t *kd;
107 struct ste *sta;
108 u_long va;
109 u_long *pa;
110 {
111 register struct vmstate *vm;
112 register u_long lowram;
113 register u_long addr;
114 int p, ste, pte;
115 int offset;
116
117 if (ISALIVE(kd)) {
118 _kvm_err(kd, 0, "vatop called in live kernel!");
119 return((off_t)0);
120 }
121 vm = kd->vmst;
122 offset = va & PGOFSET;
123 /*
124 * If we are initializing (kernel segment table pointer not yet set)
125 * then return pa == va to avoid infinite recursion.
126 */
127 if (vm->Sysseg == 0) {
128 *pa = va;
129 return (NBPG - offset);
130 }
131 lowram = vm->lowram;
132 if (vm->mmutype == -2) {
133 struct ste *sta2;
134
135 addr = (u_long)&sta[va >> SG4_SHIFT1];
136 /*
137 * Can't use KREAD to read kernel segment table entries.
138 * Fortunately it is 1-to-1 mapped so we don't have to.
139 */
140 if (sta == vm->Sysseg) {
141 if (lseek(kd->pmfd, (off_t)addr, 0) == -1 ||
142 read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
143 goto invalid;
144 } else if (KREAD(kd, addr, &ste))
145 goto invalid;
146 if ((ste & SG_V) == 0) {
147 _kvm_err(kd, 0, "invalid level 1 descriptor (%x)",
148 ste);
149 return((off_t)0);
150 }
151 sta2 = (struct ste *)(ste & SG4_ADDR1);
152 addr = (u_long)&sta2[(va & SG4_MASK2) >> SG4_SHIFT2];
153 /*
154 * Address from level 1 STE is a physical address,
155 * so don't use kvm_read.
156 */
157 if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
158 read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
159 goto invalid;
160 if ((ste & SG_V) == 0) {
161 _kvm_err(kd, 0, "invalid level 2 descriptor (%x)",
162 ste);
163 return((off_t)0);
164 }
165 sta2 = (struct ste *)(ste & SG4_ADDR2);
166 addr = (u_long)&sta2[(va & SG4_MASK3) >> SG4_SHIFT3];
167 } else {
168 addr = (u_long)&sta[va >> SEGSHIFT];
169 /*
170 * Can't use KREAD to read kernel segment table entries.
171 * Fortunately it is 1-to-1 mapped so we don't have to.
172 */
173 if (sta == vm->Sysseg) {
174 if (lseek(kd->pmfd, (off_t)addr, 0) == -1 ||
175 read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
176 goto invalid;
177 } else if (KREAD(kd, addr, &ste))
178 goto invalid;
179 if ((ste & SG_V) == 0) {
180 _kvm_err(kd, 0, "invalid segment (%x)", ste);
181 return((off_t)0);
182 }
183 p = btop(va & SG_PMASK);
184 addr = (ste & SG_FRAME) + (p * sizeof(struct pte));
185 }
186 /*
187 * Address from STE is a physical address so don't use kvm_read.
188 */
189 if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
190 read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0)
191 goto invalid;
192 addr = pte & PG_FRAME;
193 if (pte == PG_NV) {
194 _kvm_err(kd, 0, "page not valid");
195 return (0);
196 }
197 *pa = addr - lowram + offset;
198
199 return (NBPG - offset);
200 invalid:
201 _kvm_err(kd, 0, "invalid address (%x)", va);
202 return (0);
203 }
204
205 int
_kvm_kvatop(kd,va,pa)206 _kvm_kvatop(kd, va, pa)
207 kvm_t *kd;
208 u_long va;
209 u_long *pa;
210 {
211 return (_kvm_vatop(kd, (u_long)kd->vmst->Sysseg, va, pa));
212 }
213
214 /*
215 * Translate a user virtual address to a physical address.
216 */
217 int
_kvm_uvatop(kd,p,va,pa)218 _kvm_uvatop(kd, p, va, pa)
219 kvm_t *kd;
220 const struct proc *p;
221 u_long va;
222 u_long *pa;
223 {
224 register struct vmspace *vms = p->p_vmspace;
225 int kva;
226
227 /*
228 * If this is a live kernel we just look it up in the kernel
229 * virtually allocated flat 4mb page table (i.e. let the kernel
230 * do the table walk). In this way, we avoid needing to know
231 * the MMU type.
232 */
233 if (ISALIVE(kd)) {
234 struct pte *ptab;
235 int pte, offset;
236
237 kva = (int)&vms->vm_pmap.pm_ptab;
238 if (KREAD(kd, kva, &ptab)) {
239 _kvm_err(kd, 0, "invalid address (%x)", va);
240 return (0);
241 }
242 kva = (int)&ptab[btop(va)];
243 if (KREAD(kd, kva, &pte) || (pte & PG_V) == 0) {
244 _kvm_err(kd, 0, "invalid address (%x)", va);
245 return (0);
246 }
247 offset = va & PGOFSET;
248 *pa = (pte & PG_FRAME) | offset;
249 return (NBPG - offset);
250 }
251 /*
252 * Otherwise, we just walk the table ourself.
253 */
254 kva = (int)&vms->vm_pmap.pm_stab;
255 if (KREAD(kd, kva, &kva)) {
256 _kvm_err(kd, 0, "invalid address (%x)", va);
257 return (0);
258 }
259 return (_kvm_vatop(kd, kva, va, pa));
260 }
261