xref: /csrg-svn/lib/libkvm/kvm_mips.c (revision 61278)
157862Sralph /*-
2*61278Sbostic  * Copyright (c) 1989, 1992, 1993
3*61278Sbostic  *	The Regents of the University of California.  All rights reserved.
457862Sralph  *
557862Sralph  * This code is derived from software developed by the Computer Systems
657862Sralph  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
757862Sralph  * BG 91-66 and contributed to Berkeley. Modified for MIPS by Ralph Campbell.
857862Sralph  *
957862Sralph  * %sccs.include.redist.c%
1057862Sralph  */
1157862Sralph 
1257862Sralph #if defined(LIBC_SCCS) && !defined(lint)
13*61278Sbostic static char sccsid[] = "@(#)kvm_mips.c	8.1 (Berkeley) 06/04/93";
1457862Sralph #endif /* LIBC_SCCS and not lint */
1557862Sralph /*
1657862Sralph  * MIPS machine dependent routines for kvm.  Hopefully, the forthcoming
1757862Sralph  * vm code will one day obsolete this module.
1857862Sralph  */
1957862Sralph 
2057862Sralph #include <sys/param.h>
2157862Sralph #include <sys/user.h>
2257862Sralph #include <sys/proc.h>
2357862Sralph #include <sys/stat.h>
2457862Sralph #include <unistd.h>
2557862Sralph #include <nlist.h>
2657862Sralph #include <kvm.h>
2757862Sralph 
2857862Sralph #include <vm/vm.h>
2957862Sralph #include <vm/vm_param.h>
3057862Sralph 
3157862Sralph #include <limits.h>
3257862Sralph #include <db.h>
3357862Sralph 
3457862Sralph #include "kvm_private.h"
3557862Sralph 
3657862Sralph #include <machine/machConst.h>
3757862Sralph #include <machine/pte.h>
3857862Sralph #include <machine/pmap.h>
3957862Sralph 
4060020Sralph struct vmstate {
4160020Sralph 	pt_entry_t	*Sysmap;
4260020Sralph 	u_int		Sysmapsize;
4360020Sralph };
4460020Sralph 
4557862Sralph #define KREAD(kd, addr, p)\
4657862Sralph 	(kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)))
4757862Sralph 
4857862Sralph void
_kvm_freevtop(kd)4957862Sralph _kvm_freevtop(kd)
5057862Sralph 	kvm_t *kd;
5157862Sralph {
5260020Sralph 	if (kd->vmst != 0)
5360020Sralph 		free(kd->vmst);
5457862Sralph }
5557862Sralph 
5657862Sralph int
_kvm_initvtop(kd)5757862Sralph _kvm_initvtop(kd)
5857862Sralph 	kvm_t *kd;
5957862Sralph {
6060020Sralph 	struct vmstate *vm;
6160020Sralph 	struct nlist nlist[3];
6257862Sralph 
6360020Sralph 	vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
6460020Sralph 	if (vm == 0)
6560020Sralph 		return (-1);
6660020Sralph 	kd->vmst = vm;
6760020Sralph 
6860020Sralph 	nlist[0].n_name = "Sysmap";
6960020Sralph 	nlist[1].n_name = "Sysmapsize";
7060020Sralph 	nlist[2].n_name = 0;
7160020Sralph 
7260020Sralph 	if (kvm_nlist(kd, nlist) != 0) {
7360020Sralph 		_kvm_err(kd, kd->program, "bad namelist");
7460020Sralph 		return (-1);
7560020Sralph 	}
7660020Sralph 	if (KREAD(kd, (u_long)nlist[0].n_value, &vm->Sysmap)) {
7760020Sralph 		_kvm_err(kd, kd->program, "cannot read Sysmap");
7860020Sralph 		return (-1);
7960020Sralph 	}
8060020Sralph 	if (KREAD(kd, (u_long)nlist[1].n_value, &vm->Sysmapsize)) {
8160020Sralph 		_kvm_err(kd, kd->program, "cannot read mmutype");
8260020Sralph 		return (-1);
8360020Sralph 	}
8457862Sralph 	return (0);
8557862Sralph }
8657862Sralph 
8757862Sralph /*
8857862Sralph  * Translate a kernel virtual address to a physical address.
8957862Sralph  */
9057862Sralph int
_kvm_kvatop(kd,va,pa)9157862Sralph _kvm_kvatop(kd, va, pa)
9257862Sralph 	kvm_t *kd;
9357862Sralph 	u_long va;
9457862Sralph 	u_long *pa;
9557862Sralph {
9660020Sralph 	register struct vmstate *vm;
9757862Sralph 	u_long pte, addr, offset;
9857862Sralph 
9960020Sralph 	if (ISALIVE(kd)) {
10060020Sralph 		_kvm_err(kd, 0, "vatop called in live kernel!");
10160020Sralph 		return((off_t)0);
10260020Sralph 	}
10360020Sralph 	vm = kd->vmst;
10460020Sralph 	offset = va & PGOFSET;
10560020Sralph 	/*
10660020Sralph 	 * If we are initializing (kernel segment table pointer not yet set)
10760020Sralph 	 * then return pa == va to avoid infinite recursion.
10860020Sralph 	 */
10960020Sralph 	if (vm->Sysmap == 0) {
11060020Sralph 		*pa = va;
11160020Sralph 		return (NBPG - offset);
11260020Sralph 	}
11357862Sralph 	if (va < KERNBASE ||
11460020Sralph 	    va >= VM_MIN_KERNEL_ADDRESS + vm->Sysmapsize * NBPG)
11557862Sralph 		goto invalid;
11657862Sralph 	if (va < VM_MIN_KERNEL_ADDRESS) {
11757862Sralph 		*pa = MACH_CACHED_TO_PHYS(va);
11860020Sralph 		return (NBPG - offset);
11957862Sralph 	}
12060020Sralph 	addr = (u_long)(vm->Sysmap + ((va - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT));
12157862Sralph 	/*
12257862Sralph 	 * Can't use KREAD to read kernel segment table entries.
12357862Sralph 	 * Fortunately it is 1-to-1 mapped so we don't have to.
12457862Sralph 	 */
12557862Sralph 	if (lseek(kd->pmfd, (off_t)addr, 0) < 0 ||
12657862Sralph 	    read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0)
12757862Sralph 		goto invalid;
12860020Sralph 	if (!(pte & PG_V))
12960020Sralph 		goto invalid;
13057862Sralph 	*pa = (pte & PG_FRAME) | offset;
13157862Sralph 	return (NBPG - offset);
13257862Sralph 
13357862Sralph invalid:
13457862Sralph 	_kvm_err(kd, 0, "invalid address (%x)", va);
13557862Sralph 	return (0);
13657862Sralph }
13757862Sralph 
13857862Sralph /*
13957862Sralph  * Translate a user virtual address to a physical address.
14057862Sralph  */
14157862Sralph int
_kvm_uvatop(kd,p,va,pa)14257862Sralph _kvm_uvatop(kd, p, va, pa)
14357862Sralph 	kvm_t *kd;
14457862Sralph 	const struct proc *p;
14557862Sralph 	u_long va;
14657862Sralph 	u_long *pa;
14757862Sralph {
14857862Sralph 	register struct vmspace *vms = p->p_vmspace;
14960020Sralph 	u_long kva, offset;
15057862Sralph 
15160020Sralph 	if (va >= KERNBASE)
15260020Sralph 		goto invalid;
15360020Sralph 
15460020Sralph 	/* read the address of the first level table */
15560020Sralph 	kva = (u_long)&vms->vm_pmap.pm_segtab;
15660020Sralph 	if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva))
15760020Sralph 		goto invalid;
15860020Sralph 	if (kva == 0)
15960020Sralph 		goto invalid;
16060020Sralph 
16160020Sralph 	/* read the address of the second level table */
16260020Sralph 	kva += (va >> SEGSHIFT) * sizeof(caddr_t);
16360020Sralph 	if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva))
16460020Sralph 		goto invalid;
16560020Sralph 	if (kva == 0)
16660020Sralph 		goto invalid;
16760020Sralph 
16860020Sralph 	/* read the pte from the second level table */
16960020Sralph 	kva += (va >> PGSHIFT) & (NPTEPG - 1);
17060020Sralph 	if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva))
17160020Sralph 		goto invalid;
17260020Sralph 	if (!(kva & PG_V))
17360020Sralph 		goto invalid;
17460020Sralph 	offset = va & PGOFSET;
17560020Sralph 	*pa = (kva & PG_FRAME) | offset;
17660020Sralph 	return (NBPG - offset);
17760020Sralph 
17860020Sralph invalid:
17957862Sralph 	_kvm_err(kd, 0, "invalid address (%x)", va);
18057862Sralph 	return (0);
18157862Sralph }
182