1*0e64ee4cSderaadt /* $OpenBSD: kvm_mips64.c,v 1.17 2021/12/01 16:53:28 deraadt Exp $ */
2b618256dSderaadt /* $NetBSD: kvm_mips.c,v 1.3 1996/03/18 22:33:44 thorpej Exp $ */
3b618256dSderaadt
4b618256dSderaadt /*-
5b618256dSderaadt * Copyright (c) 1989, 1992, 1993
6b618256dSderaadt * The Regents of the University of California. All rights reserved.
7b618256dSderaadt *
8b618256dSderaadt * This code is derived from software developed by the Computer Systems
9b618256dSderaadt * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
10b618256dSderaadt * BG 91-66 and contributed to Berkeley. Modified for MIPS by Ralph Campbell.
11b618256dSderaadt *
12b618256dSderaadt * Redistribution and use in source and binary forms, with or without
13b618256dSderaadt * modification, are permitted provided that the following conditions
14b618256dSderaadt * are met:
15b618256dSderaadt * 1. Redistributions of source code must retain the above copyright
16b618256dSderaadt * notice, this list of conditions and the following disclaimer.
17b618256dSderaadt * 2. Redistributions in binary form must reproduce the above copyright
18b618256dSderaadt * notice, this list of conditions and the following disclaimer in the
19b618256dSderaadt * documentation and/or other materials provided with the distribution.
20ee74afa0Sderaadt * 3. Neither the name of the University nor the names of its contributors
21b618256dSderaadt * may be used to endorse or promote products derived from this software
22b618256dSderaadt * without specific prior written permission.
23b618256dSderaadt *
24b618256dSderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25b618256dSderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26b618256dSderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27b618256dSderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28b618256dSderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29b618256dSderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30b618256dSderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31b618256dSderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32b618256dSderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33b618256dSderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34b618256dSderaadt * SUCH DAMAGE.
35b618256dSderaadt */
36b618256dSderaadt
37b618256dSderaadt /*
38b618256dSderaadt * MIPS machine dependent routines for kvm. Hopefully, the forthcoming
39b618256dSderaadt * vm code will one day obsolete this module.
40b618256dSderaadt */
41b618256dSderaadt
42*0e64ee4cSderaadt #include <sys/types.h>
43*0e64ee4cSderaadt #include <sys/signal.h>
44b618256dSderaadt #include <sys/proc.h>
45b618256dSderaadt #include <sys/stat.h>
4624c56fd5Sderaadt #include <sys/sysctl.h>
47b618256dSderaadt #include <unistd.h>
48b7e5637aSmiod #include <stdlib.h>
49b618256dSderaadt #include <nlist.h>
50b618256dSderaadt #include <kvm.h>
51b618256dSderaadt
52b618256dSderaadt #include <limits.h>
53b618256dSderaadt #include <db.h>
54b618256dSderaadt
55b618256dSderaadt #include "kvm_private.h"
56b618256dSderaadt
57b618256dSderaadt #include <machine/cpu.h>
58b618256dSderaadt #include <machine/pte.h>
59b618256dSderaadt #include <machine/pmap.h>
60b618256dSderaadt
618371f9d0Smiod #include <uvm/uvm_extern.h>
628371f9d0Smiod
63b618256dSderaadt struct vmstate {
64b618256dSderaadt pt_entry_t *Sysmap;
65b618256dSderaadt u_int Sysmapsize;
668608c891Smiod vaddr_t Sysmapbase;
678371f9d0Smiod int pagesize;
688371f9d0Smiod int pagemask;
698371f9d0Smiod int pageshift;
70b618256dSderaadt };
71b618256dSderaadt
72b618256dSderaadt void
_kvm_freevtop(kvm_t * kd)73b618256dSderaadt _kvm_freevtop(kvm_t *kd)
74b618256dSderaadt {
75b618256dSderaadt free(kd->vmst);
7632ac5daaSzhuk kd->vmst = NULL;
77b618256dSderaadt }
78b618256dSderaadt
79b618256dSderaadt int
_kvm_initvtop(kvm_t * kd)80b618256dSderaadt _kvm_initvtop(kvm_t *kd)
81b618256dSderaadt {
82b618256dSderaadt struct vmstate *vm;
838371f9d0Smiod struct nlist nl[4];
848371f9d0Smiod struct uvmexp uvmexp;
85b618256dSderaadt
86b618256dSderaadt vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
87b618256dSderaadt if (vm == 0)
88b618256dSderaadt return (-1);
89b618256dSderaadt kd->vmst = vm;
90b618256dSderaadt
918371f9d0Smiod nl[0].n_name = "Sysmap";
928371f9d0Smiod nl[1].n_name = "Sysmapsize";
938371f9d0Smiod nl[2].n_name = "uvmexp";
948371f9d0Smiod nl[3].n_name = 0;
95b618256dSderaadt
968371f9d0Smiod if (kvm_nlist(kd, nl) != 0) {
97b618256dSderaadt _kvm_err(kd, kd->program, "bad namelist");
98b618256dSderaadt return (-1);
99b618256dSderaadt }
1008371f9d0Smiod if (KREAD(kd, (u_long)nl[0].n_value, &vm->Sysmap)) {
101b618256dSderaadt _kvm_err(kd, kd->program, "cannot read Sysmap");
102b618256dSderaadt return (-1);
103b618256dSderaadt }
1048371f9d0Smiod if (KREAD(kd, (u_long)nl[1].n_value, &vm->Sysmapsize)) {
1052f1ad4c7Smiod _kvm_err(kd, kd->program, "cannot read Sysmapsize");
106b618256dSderaadt return (-1);
107b618256dSderaadt }
1088371f9d0Smiod /*
1098371f9d0Smiod * We are only interested in the first three fields of struct
1108371f9d0Smiod * uvmexp, so do not try to read more than necessary (especially
1118371f9d0Smiod * in case the layout changes).
1128371f9d0Smiod */
1138371f9d0Smiod if (kvm_read(kd, (u_long)nl[2].n_value, &uvmexp,
1148371f9d0Smiod 3 * sizeof(int)) != 3 * sizeof(int)) {
1158371f9d0Smiod _kvm_err(kd, kd->program, "cannot read uvmexp");
1168371f9d0Smiod return (-1);
1178371f9d0Smiod }
1188371f9d0Smiod vm->pagesize = uvmexp.pagesize;
1198371f9d0Smiod vm->pagemask = uvmexp.pagemask;
1208371f9d0Smiod vm->pageshift = uvmexp.pageshift;
1218608c891Smiod
1228608c891Smiod /*
1238608c891Smiod * Older kernels might not have this symbol; in which case
1244da2d91aSmiod * we use the value of VM_MIN_KERNEL_ADDRESS they must have.
1258608c891Smiod */
1268371f9d0Smiod
1278371f9d0Smiod nl[0].n_name = "Sysmapbase";
1288371f9d0Smiod nl[1].n_name = 0;
1298371f9d0Smiod if (kvm_nlist(kd, nl) != 0 ||
1308371f9d0Smiod KREAD(kd, (u_long)nl[0].n_value, &vm->Sysmapbase))
131f0a1824eSmiod vm->Sysmapbase = (vaddr_t)CKSSEG_BASE;
1328608c891Smiod
133b618256dSderaadt return (0);
134b618256dSderaadt }
135b618256dSderaadt
136b618256dSderaadt /*
137b618256dSderaadt * Translate a kernel virtual address to a physical address.
138b618256dSderaadt */
139b618256dSderaadt int
_kvm_kvatop(kvm_t * kd,u_long va,paddr_t * pa)140fdd3f45bSmickey _kvm_kvatop(kvm_t *kd, u_long va, paddr_t *pa)
141b618256dSderaadt {
142b618256dSderaadt struct vmstate *vm;
14322899553Smiod pt_entry_t pte;
1448371f9d0Smiod u_long idx, addr;
1458371f9d0Smiod int offset;
146b618256dSderaadt
147b618256dSderaadt if (ISALIVE(kd)) {
148b618256dSderaadt _kvm_err(kd, 0, "vatop called in live kernel!");
149b618256dSderaadt return((off_t)0);
150b618256dSderaadt }
151b618256dSderaadt vm = kd->vmst;
1528371f9d0Smiod offset = (int)va & vm->pagemask;
153b618256dSderaadt /*
154b618256dSderaadt * If we are initializing (kernel segment table pointer not yet set)
155b618256dSderaadt * then return pa == va to avoid infinite recursion.
156b618256dSderaadt */
157b618256dSderaadt if (vm->Sysmap == 0) {
158b618256dSderaadt *pa = va;
1598371f9d0Smiod return vm->pagesize - offset;
160b618256dSderaadt }
161edb45030Smiod /*
162edb45030Smiod * Check for direct-mapped segments
163edb45030Smiod */
164edb45030Smiod if (IS_XKPHYS(va)) {
165edb45030Smiod *pa = XKPHYS_TO_PHYS(va);
1668371f9d0Smiod return vm->pagesize - offset;
167edb45030Smiod }
168f0a1824eSmiod if (va >= (vaddr_t)CKSEG0_BASE && va < (vaddr_t)CKSSEG_BASE) {
169f0a1824eSmiod *pa = CKSEG0_TO_PHYS(va);
1708371f9d0Smiod return vm->pagesize - offset;
171b618256dSderaadt }
1728608c891Smiod if (va < vm->Sysmapbase)
173edb45030Smiod goto invalid;
1748371f9d0Smiod idx = (va - vm->Sysmapbase) >> vm->pageshift;
175edb45030Smiod if (idx >= vm->Sysmapsize)
176edb45030Smiod goto invalid;
1778371f9d0Smiod addr = (u_long)vm->Sysmap + idx;
178b618256dSderaadt /*
179b618256dSderaadt * Can't use KREAD to read kernel segment table entries.
180b618256dSderaadt * Fortunately it is 1-to-1 mapped so we don't have to.
181b618256dSderaadt */
182edb45030Smiod if (_kvm_pread(kd, kd->pmfd, (char *)&pte, sizeof(pte),
183edb45030Smiod (off_t)addr) < 0)
184b618256dSderaadt goto invalid;
185b618256dSderaadt if (!(pte & PG_V))
186b618256dSderaadt goto invalid;
1878371f9d0Smiod *pa = (pte & PG_FRAME) | (paddr_t)offset;
1888371f9d0Smiod return vm->pagesize - offset;
189b618256dSderaadt
190b618256dSderaadt invalid:
191b618256dSderaadt _kvm_err(kd, 0, "invalid address (%lx)", va);
192b618256dSderaadt return (0);
193b618256dSderaadt }
194b618256dSderaadt
195b618256dSderaadt off_t
_kvm_pa2off(kvm_t * kd,paddr_t pa)196fdd3f45bSmickey _kvm_pa2off(kvm_t *kd, paddr_t pa)
197b618256dSderaadt {
198b618256dSderaadt _kvm_err(kd, 0, "pa2off going to be implemented!");
199b618256dSderaadt return 0;
200b618256dSderaadt }
201