1*104ea677Schristos /* $NetBSD: kvm_mips.c,v 1.23 2022/01/10 19:51:30 christos Exp $ */
2346e67f8Sthorpej
35af26b83Sthorpej /*
45af26b83Sthorpej * Copyright (c) 1994, 1995 Carnegie-Mellon University.
55af26b83Sthorpej * All rights reserved.
60215cc7dScgd *
75af26b83Sthorpej * Author: Chris G. Demetriou
80215cc7dScgd *
95af26b83Sthorpej * Permission to use, copy, modify and distribute this software and
105af26b83Sthorpej * its documentation is hereby granted, provided that both the copyright
115af26b83Sthorpej * notice and this permission notice appear in all copies of the
125af26b83Sthorpej * software, derivative works or modified versions, and any portions
135af26b83Sthorpej * thereof, and that both notices appear in supporting documentation.
140215cc7dScgd *
155af26b83Sthorpej * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
165af26b83Sthorpej * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
175af26b83Sthorpej * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
185af26b83Sthorpej *
195af26b83Sthorpej * Carnegie Mellon requests users of this software to return to
205af26b83Sthorpej *
215af26b83Sthorpej * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
225af26b83Sthorpej * School of Computer Science
235af26b83Sthorpej * Carnegie Mellon University
245af26b83Sthorpej * Pittsburgh PA 15213-3890
255af26b83Sthorpej *
265af26b83Sthorpej * any improvements or extensions that they make and grant Carnegie the
275af26b83Sthorpej * rights to redistribute these changes.
285af26b83Sthorpej */
295af26b83Sthorpej
305af26b83Sthorpej /*
315af26b83Sthorpej * Modified for NetBSD/mips by Jason R. Thorpe, Numerical Aerospace
325af26b83Sthorpej * Simulation Facility, NASA Ames Research Center.
330215cc7dScgd */
340215cc7dScgd
35b4119f6bSmikel #include <sys/cdefs.h>
360215cc7dScgd #if defined(LIBC_SCCS) && !defined(lint)
37*104ea677Schristos __RCSID("$NetBSD: kvm_mips.c,v 1.23 2022/01/10 19:51:30 christos Exp $");
380215cc7dScgd #endif /* LIBC_SCCS and not lint */
39346e67f8Sthorpej
400215cc7dScgd /*
415af26b83Sthorpej * MIPS machine dependent routines for kvm.
420215cc7dScgd */
430215cc7dScgd
440215cc7dScgd #include <sys/param.h>
450215cc7dScgd #include <sys/proc.h>
460215cc7dScgd #include <sys/stat.h>
475af26b83Sthorpej #include <sys/kcore.h>
48962a341dSjym #include <sys/types.h>
49962a341dSjym
505af26b83Sthorpej #include <machine/kcore.h>
51962a341dSjym
520841fc37Sjonathan #include <stdlib.h>
530215cc7dScgd #include <unistd.h>
540215cc7dScgd #include <nlist.h>
550215cc7dScgd #include <kvm.h>
560215cc7dScgd
573b8ac18dSmrg #include <uvm/uvm_extern.h>
580215cc7dScgd
590215cc7dScgd #include <limits.h>
600215cc7dScgd #include <db.h>
610215cc7dScgd
620215cc7dScgd #include "kvm_private.h"
630215cc7dScgd
64e3a95730Sjonathan #include <mips/cpuregs.h>
65cce919e0Smatt #include <mips/vmparam.h>
660215cc7dScgd
670215cc7dScgd void
_kvm_freevtop(kvm_t * kd)686dc46b92Sjym _kvm_freevtop(kvm_t *kd)
690215cc7dScgd {
705af26b83Sthorpej
715af26b83Sthorpej /* Not actually used for anything right now, but safe. */
720215cc7dScgd if (kd->vmst != 0)
730215cc7dScgd free(kd->vmst);
740215cc7dScgd }
750215cc7dScgd
760215cc7dScgd int
_kvm_initvtop(kvm_t * kd)776dc46b92Sjym _kvm_initvtop(kvm_t *kd)
780215cc7dScgd {
790215cc7dScgd
800215cc7dScgd return (0);
810215cc7dScgd }
820215cc7dScgd
830215cc7dScgd /*
840215cc7dScgd * Translate a kernel virtual address to a physical address.
850215cc7dScgd */
860215cc7dScgd int
_kvm_kvatop(kvm_t * kd,vaddr_t va,paddr_t * pa)87962a341dSjym _kvm_kvatop(kvm_t *kd, vaddr_t va, paddr_t *pa)
880215cc7dScgd {
895af26b83Sthorpej cpu_kcore_hdr_t *cpu_kh;
905af26b83Sthorpej int page_off;
915af26b83Sthorpej u_int pte;
92962a341dSjym paddr_t pte_pa;
93e3a95730Sjonathan
940215cc7dScgd if (ISALIVE(kd)) {
950215cc7dScgd _kvm_err(kd, 0, "vatop called in live kernel!");
960215cc7dScgd return((off_t)0);
970215cc7dScgd }
98e3a95730Sjonathan
995af26b83Sthorpej cpu_kh = kd->cpu_data;
1005af26b83Sthorpej page_off = va & PGOFSET;
101e3a95730Sjonathan
1026ab33485Smatt #ifdef _LP64
1036ab33485Smatt if (MIPS_XKPHYS_P(va)) {
1046ab33485Smatt /*
1056ab33485Smatt * Direct-mapped cached address: just convert it.
1066ab33485Smatt */
1076ab33485Smatt *pa = MIPS_XKPHYS_TO_PHYS(va);
1086ab33485Smatt return (NBPG - page_off);
1096ab33485Smatt }
1106ab33485Smatt
1116ab33485Smatt if (va < MIPS_XKPHYS_START) {
1126ab33485Smatt /*
1136ab33485Smatt * XUSEG (user virtual address space) - invalid.
1146ab33485Smatt */
1156ab33485Smatt _kvm_err(kd, 0, "invalid kernel virtual address");
1166ab33485Smatt goto lose;
1176ab33485Smatt }
1186ab33485Smatt #else
1195af26b83Sthorpej if (va < MIPS_KSEG0_START) {
1200215cc7dScgd /*
1215af26b83Sthorpej * KUSEG (user virtual address space) - invalid.
1220215cc7dScgd */
1235af26b83Sthorpej _kvm_err(kd, 0, "invalid kernel virtual address");
1245af26b83Sthorpej goto lose;
1250215cc7dScgd }
1266ab33485Smatt #endif
1275af26b83Sthorpej
1286ab33485Smatt if (MIPS_KSEG0_P(va)) {
1295af26b83Sthorpej /*
1305af26b83Sthorpej * Direct-mapped cached address: just convert it.
1315af26b83Sthorpej */
132e9661d76Sjonathan *pa = MIPS_KSEG0_TO_PHYS(va);
1335af26b83Sthorpej return (NBPG - page_off);
1340215cc7dScgd }
1355af26b83Sthorpej
1366ab33485Smatt if (MIPS_KSEG1_P(va)) {
1375af26b83Sthorpej /*
1385af26b83Sthorpej * Direct-mapped uncached address: just convert it.
1395af26b83Sthorpej */
1405af26b83Sthorpej *pa = MIPS_KSEG1_TO_PHYS(va);
1415af26b83Sthorpej return (NBPG - page_off);
1425af26b83Sthorpej }
143e3a95730Sjonathan
1446ab33485Smatt #ifdef _LP64
1456ab33485Smatt if (va >= MIPS_KSEG2_START) {
1466ab33485Smatt /*
1476ab33485Smatt * KUSEG (user virtual address space) - invalid.
1486ab33485Smatt */
1496ab33485Smatt _kvm_err(kd, 0, "invalid kernel virtual address");
1506ab33485Smatt goto lose;
1516ab33485Smatt }
1526ab33485Smatt #endif
1536ab33485Smatt
1540215cc7dScgd /*
1555af26b83Sthorpej * We now know that we're a KSEG2 (kernel virtually mapped)
1565af26b83Sthorpej * address. Translate the address using the pmap's kernel
1575af26b83Sthorpej * page table.
1580215cc7dScgd */
1590215cc7dScgd
1605af26b83Sthorpej /*
1615af26b83Sthorpej * Step 1: Make sure the kernel page table has a translation
1625af26b83Sthorpej * for the address.
1635af26b83Sthorpej */
1646ab33485Smatt #ifdef _LP64
1656ab33485Smatt if (va >= (MIPS_XKSEG_START + (cpu_kh->sysmapsize * NBPG))) {
1666ab33485Smatt _kvm_err(kd, 0, "invalid XKSEG address");
1676ab33485Smatt goto lose;
1686ab33485Smatt }
1696ab33485Smatt #else
1705af26b83Sthorpej if (va >= (MIPS_KSEG2_START + (cpu_kh->sysmapsize * NBPG))) {
1715af26b83Sthorpej _kvm_err(kd, 0, "invalid KSEG2 address");
1725af26b83Sthorpej goto lose;
1735af26b83Sthorpej }
1746ab33485Smatt #endif
1755af26b83Sthorpej
1765af26b83Sthorpej /*
1775af26b83Sthorpej * Step 2: Locate and read the PTE.
1785af26b83Sthorpej */
1795af26b83Sthorpej pte_pa = cpu_kh->sysmappa +
1805af26b83Sthorpej (((va - MIPS_KSEG2_START) >> PGSHIFT) * sizeof(u_int));
181a7a2d171Sad if (_kvm_pread(kd, kd->pmfd, &pte, sizeof(pte),
182a7a2d171Sad _kvm_pa2off(kd, pte_pa)) != sizeof(pte)) {
1835af26b83Sthorpej _kvm_syserr(kd, 0, "could not read PTE");
1845af26b83Sthorpej goto lose;
1855af26b83Sthorpej }
1865af26b83Sthorpej
1875af26b83Sthorpej /*
1885af26b83Sthorpej * Step 3: Validate the PTE and return the physical address.
1895af26b83Sthorpej */
1905af26b83Sthorpej if ((pte & cpu_kh->pg_v) == 0) {
1915af26b83Sthorpej _kvm_err(kd, 0, "invalid translation (invalid PTE)");
1925af26b83Sthorpej goto lose;
1935af26b83Sthorpej }
1945af26b83Sthorpej *pa = (((pte & cpu_kh->pg_frame) >> cpu_kh->pg_shift) << PGSHIFT) +
1955af26b83Sthorpej page_off;
1965af26b83Sthorpej return (NBPG - page_off);
1975af26b83Sthorpej
1985af26b83Sthorpej lose:
1995af26b83Sthorpej *pa = -1;
2000215cc7dScgd return (0);
2010215cc7dScgd }
2027739ce58Sgwr
2037739ce58Sgwr /*
204b976c559Swiz * Translate a physical address to a file-offset in the crash dump.
2055af26b83Sthorpej */
2065af26b83Sthorpej off_t
_kvm_pa2off(kvm_t * kd,paddr_t pa)207962a341dSjym _kvm_pa2off(kvm_t *kd, paddr_t pa)
2085af26b83Sthorpej {
2095af26b83Sthorpej cpu_kcore_hdr_t *cpu_kh;
2105af26b83Sthorpej phys_ram_seg_t *ramsegs;
2115af26b83Sthorpej off_t off;
2125af26b83Sthorpej int i;
2135af26b83Sthorpej
2145af26b83Sthorpej cpu_kh = kd->cpu_data;
2155af26b83Sthorpej ramsegs = (phys_ram_seg_t *)((char *)cpu_kh + ALIGN(sizeof *cpu_kh));
2165af26b83Sthorpej
2175af26b83Sthorpej off = 0;
2185af26b83Sthorpej for (i = 0; i < cpu_kh->nmemsegs; i++) {
2195af26b83Sthorpej if (pa >= ramsegs[i].start &&
2205af26b83Sthorpej (pa - ramsegs[i].start) < ramsegs[i].size) {
2215af26b83Sthorpej off += (pa - ramsegs[i].start);
2225af26b83Sthorpej break;
2235af26b83Sthorpej }
2245af26b83Sthorpej off += ramsegs[i].size;
2255af26b83Sthorpej }
2265af26b83Sthorpej
2275af26b83Sthorpej return (kd->dump_off + off);
2285af26b83Sthorpej }
2295af26b83Sthorpej
2305af26b83Sthorpej /*
2317739ce58Sgwr * Machine-dependent initialization for ALL open kvm descriptors,
2327739ce58Sgwr * not just those for a kernel crash dump. Some architectures
2337739ce58Sgwr * have to deal with these NOT being constants! (i.e. m68k)
2347739ce58Sgwr */
2357739ce58Sgwr int
_kvm_mdopen(kvm_t * kd)2366dc46b92Sjym _kvm_mdopen(kvm_t *kd)
2377739ce58Sgwr {
2387739ce58Sgwr
2397739ce58Sgwr kd->min_uva = VM_MIN_ADDRESS;
2407739ce58Sgwr kd->max_uva = VM_MAXUSER_ADDRESS;
2417739ce58Sgwr
2427739ce58Sgwr return (0);
2437739ce58Sgwr }
244