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. Modified for MIPS by Ralph Campbell.
8 *
9 * %sccs.include.redist.c%
10 */
11
12 #if defined(LIBC_SCCS) && !defined(lint)
13 static char sccsid[] = "@(#)kvm_mips.c 8.1 (Berkeley) 06/04/93";
14 #endif /* LIBC_SCCS and not lint */
15 /*
16 * MIPS machine dependent routines for kvm. Hopefully, the forthcoming
17 * vm code will one day obsolete this module.
18 */
19
20 #include <sys/param.h>
21 #include <sys/user.h>
22 #include <sys/proc.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <nlist.h>
26 #include <kvm.h>
27
28 #include <vm/vm.h>
29 #include <vm/vm_param.h>
30
31 #include <limits.h>
32 #include <db.h>
33
34 #include "kvm_private.h"
35
36 #include <machine/machConst.h>
37 #include <machine/pte.h>
38 #include <machine/pmap.h>
39
40 struct vmstate {
41 pt_entry_t *Sysmap;
42 u_int Sysmapsize;
43 };
44
45 #define KREAD(kd, addr, p)\
46 (kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)))
47
48 void
_kvm_freevtop(kd)49 _kvm_freevtop(kd)
50 kvm_t *kd;
51 {
52 if (kd->vmst != 0)
53 free(kd->vmst);
54 }
55
56 int
_kvm_initvtop(kd)57 _kvm_initvtop(kd)
58 kvm_t *kd;
59 {
60 struct vmstate *vm;
61 struct nlist nlist[3];
62
63 vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
64 if (vm == 0)
65 return (-1);
66 kd->vmst = vm;
67
68 nlist[0].n_name = "Sysmap";
69 nlist[1].n_name = "Sysmapsize";
70 nlist[2].n_name = 0;
71
72 if (kvm_nlist(kd, nlist) != 0) {
73 _kvm_err(kd, kd->program, "bad namelist");
74 return (-1);
75 }
76 if (KREAD(kd, (u_long)nlist[0].n_value, &vm->Sysmap)) {
77 _kvm_err(kd, kd->program, "cannot read Sysmap");
78 return (-1);
79 }
80 if (KREAD(kd, (u_long)nlist[1].n_value, &vm->Sysmapsize)) {
81 _kvm_err(kd, kd->program, "cannot read mmutype");
82 return (-1);
83 }
84 return (0);
85 }
86
87 /*
88 * Translate a kernel virtual address to a physical address.
89 */
90 int
_kvm_kvatop(kd,va,pa)91 _kvm_kvatop(kd, va, pa)
92 kvm_t *kd;
93 u_long va;
94 u_long *pa;
95 {
96 register struct vmstate *vm;
97 u_long pte, addr, offset;
98
99 if (ISALIVE(kd)) {
100 _kvm_err(kd, 0, "vatop called in live kernel!");
101 return((off_t)0);
102 }
103 vm = kd->vmst;
104 offset = va & PGOFSET;
105 /*
106 * If we are initializing (kernel segment table pointer not yet set)
107 * then return pa == va to avoid infinite recursion.
108 */
109 if (vm->Sysmap == 0) {
110 *pa = va;
111 return (NBPG - offset);
112 }
113 if (va < KERNBASE ||
114 va >= VM_MIN_KERNEL_ADDRESS + vm->Sysmapsize * NBPG)
115 goto invalid;
116 if (va < VM_MIN_KERNEL_ADDRESS) {
117 *pa = MACH_CACHED_TO_PHYS(va);
118 return (NBPG - offset);
119 }
120 addr = (u_long)(vm->Sysmap + ((va - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT));
121 /*
122 * Can't use KREAD to read kernel segment table entries.
123 * Fortunately it is 1-to-1 mapped so we don't have to.
124 */
125 if (lseek(kd->pmfd, (off_t)addr, 0) < 0 ||
126 read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0)
127 goto invalid;
128 if (!(pte & PG_V))
129 goto invalid;
130 *pa = (pte & PG_FRAME) | offset;
131 return (NBPG - offset);
132
133 invalid:
134 _kvm_err(kd, 0, "invalid address (%x)", va);
135 return (0);
136 }
137
138 /*
139 * Translate a user virtual address to a physical address.
140 */
141 int
_kvm_uvatop(kd,p,va,pa)142 _kvm_uvatop(kd, p, va, pa)
143 kvm_t *kd;
144 const struct proc *p;
145 u_long va;
146 u_long *pa;
147 {
148 register struct vmspace *vms = p->p_vmspace;
149 u_long kva, offset;
150
151 if (va >= KERNBASE)
152 goto invalid;
153
154 /* read the address of the first level table */
155 kva = (u_long)&vms->vm_pmap.pm_segtab;
156 if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva))
157 goto invalid;
158 if (kva == 0)
159 goto invalid;
160
161 /* read the address of the second level table */
162 kva += (va >> SEGSHIFT) * sizeof(caddr_t);
163 if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva))
164 goto invalid;
165 if (kva == 0)
166 goto invalid;
167
168 /* read the pte from the second level table */
169 kva += (va >> PGSHIFT) & (NPTEPG - 1);
170 if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva))
171 goto invalid;
172 if (!(kva & PG_V))
173 goto invalid;
174 offset = va & PGOFSET;
175 *pa = (kva & PG_FRAME) | offset;
176 return (NBPG - offset);
177
178 invalid:
179 _kvm_err(kd, 0, "invalid address (%x)", va);
180 return (0);
181 }
182