xref: /netbsd-src/lib/libkvm/kvm_mips.c (revision 104ea677951e7b2cca90d7e254308b7992ac0050)
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