xref: /csrg-svn/lib/libkvm/kvm_hp300.c (revision 61278)
142661Sbostic /*-
2*61278Sbostic  * Copyright (c) 1989, 1992, 1993
3*61278Sbostic  *	The Regents of the University of California.  All rights reserved.
440256Smarc  *
553658Sbostic  * This code is derived from software developed by the Computer Systems
653658Sbostic  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
753658Sbostic  * BG 91-66 and contributed to Berkeley.
853658Sbostic  *
942661Sbostic  * %sccs.include.redist.c%
1040256Smarc  */
1140256Smarc 
1242661Sbostic #if defined(LIBC_SCCS) && !defined(lint)
13*61278Sbostic static char sccsid[] = "@(#)kvm_hp300.c	8.1 (Berkeley) 06/04/93";
1442661Sbostic #endif /* LIBC_SCCS and not lint */
1540256Smarc 
1653121Smckusick /*
1759338Sbostic  * Hp300 machine dependent routines for kvm.  Hopefully, the forthcoming
1853121Smckusick  * vm code will one day obsolete this module.
1953121Smckusick  */
2053121Smckusick 
2140256Smarc #include <sys/param.h>
2249251Skarels #include <sys/user.h>
2340256Smarc #include <sys/proc.h>
2453121Smckusick #include <sys/stat.h>
2553723Smckusick #include <unistd.h>
2649251Skarels #include <nlist.h>
2741007Smarc #include <kvm.h>
2853121Smckusick 
2953121Smckusick #include <vm/vm.h>
3053121Smckusick #include <vm/vm_param.h>
3153121Smckusick 
3253121Smckusick #include <limits.h>
3353291Sbostic #include <db.h>
3440256Smarc 
3553121Smckusick #include "kvm_private.h"
3648619Skarels 
3754897Smckusick #if defined(hp300)
3853121Smckusick #include <hp300/hp300/pte.h>
3954897Smckusick #endif
4053121Smckusick 
4154897Smckusick #if defined(luna68k)
4254897Smckusick #include <luna68k/luna68k/pte.h>
4354897Smckusick #endif
4454897Smckusick 
4553121Smckusick #ifndef btop
4648619Skarels #define	btop(x)		(((unsigned)(x)) >> PGSHIFT)	/* XXX */
4748619Skarels #define	ptob(x)		((caddr_t)((x) << PGSHIFT))	/* XXX */
4849251Skarels #endif
4948619Skarels 
5053121Smckusick struct vmstate {
5153121Smckusick 	u_long lowram;
5253917Shibler 	int mmutype;
5353121Smckusick 	struct ste *Sysseg;
5440256Smarc };
5540256Smarc 
5653121Smckusick #define KREAD(kd, addr, p)\
5753121Smckusick 	(kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p)))
5846642Sbostic 
5953121Smckusick void
_kvm_freevtop(kd)6053121Smckusick _kvm_freevtop(kd)
6153121Smckusick 	kvm_t *kd;
6240256Smarc {
6353121Smckusick 	if (kd->vmst != 0)
6453121Smckusick 		free(kd->vmst);
6540256Smarc }
6640256Smarc 
6753121Smckusick int
_kvm_initvtop(kd)6853121Smckusick _kvm_initvtop(kd)
6953121Smckusick 	kvm_t *kd;
7041007Smarc {
7153121Smckusick 	struct vmstate *vm;
7253917Shibler 	struct nlist nlist[4];
7353121Smckusick 
7453121Smckusick 	vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
7553121Smckusick 	if (vm == 0)
7641007Smarc 		return (-1);
7753121Smckusick 	kd->vmst = vm;
7841007Smarc 
7953121Smckusick 	nlist[0].n_name = "_lowram";
8053917Shibler 	nlist[1].n_name = "_mmutype";
8153917Shibler 	nlist[2].n_name = "_Sysseg";
8253917Shibler 	nlist[3].n_name = 0;
8341007Smarc 
8453121Smckusick 	if (kvm_nlist(kd, nlist) != 0) {
8553121Smckusick 		_kvm_err(kd, kd->program, "bad namelist");
8653121Smckusick 		return (-1);
8741007Smarc 	}
8853121Smckusick 	vm->Sysseg = 0;
8953121Smckusick 	if (KREAD(kd, (u_long)nlist[0].n_value, &vm->lowram)) {
9053121Smckusick 		_kvm_err(kd, kd->program, "cannot read lowram");
9140256Smarc 		return (-1);
9240256Smarc 	}
9353917Shibler 	if (KREAD(kd, (u_long)nlist[1].n_value, &vm->mmutype)) {
9453917Shibler 		_kvm_err(kd, kd->program, "cannot read mmutype");
9553917Shibler 		return (-1);
9653917Shibler 	}
9753917Shibler 	if (KREAD(kd, (u_long)nlist[2].n_value, &vm->Sysseg)) {
9853121Smckusick 		_kvm_err(kd, kd->program, "cannot read segment table");
9940256Smarc 		return (-1);
10040256Smarc 	}
10153121Smckusick 	return (0);
10240256Smarc }
10340256Smarc 
10453121Smckusick static int
_kvm_vatop(kd,sta,va,pa)10553121Smckusick _kvm_vatop(kd, sta, va, pa)
10653121Smckusick 	kvm_t *kd;
10753121Smckusick 	struct ste *sta;
10853121Smckusick 	u_long va;
10953121Smckusick 	u_long *pa;
11040256Smarc {
11153121Smckusick 	register struct vmstate *vm;
11253917Shibler 	register u_long lowram;
11353121Smckusick 	register u_long addr;
11453121Smckusick 	int p, ste, pte;
11553121Smckusick 	int offset;
11640256Smarc 
11753917Shibler 	if (ISALIVE(kd)) {
11853917Shibler 		_kvm_err(kd, 0, "vatop called in live kernel!");
11953917Shibler 		return((off_t)0);
12053917Shibler 	}
12153121Smckusick 	vm = kd->vmst;
12253917Shibler 	offset = va & PGOFSET;
12348619Skarels 	/*
12453917Shibler 	 * If we are initializing (kernel segment table pointer not yet set)
12553917Shibler 	 * then return pa == va to avoid infinite recursion.
12648619Skarels 	 */
12753917Shibler 	if (vm->Sysseg == 0) {
12853121Smckusick 		*pa = va;
12953917Shibler 		return (NBPG - offset);
13048619Skarels 	}
13153917Shibler 	lowram = vm->lowram;
13253917Shibler 	if (vm->mmutype == -2) {
13353917Shibler 		struct ste *sta2;
13453917Shibler 
13553917Shibler 		addr = (u_long)&sta[va >> SG4_SHIFT1];
13653917Shibler 		/*
13753917Shibler 		 * Can't use KREAD to read kernel segment table entries.
13853917Shibler 		 * Fortunately it is 1-to-1 mapped so we don't have to.
13953917Shibler 		 */
14053917Shibler 		if (sta == vm->Sysseg) {
14153917Shibler 			if (lseek(kd->pmfd, (off_t)addr, 0) == -1 ||
14253917Shibler 			    read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
14353917Shibler 				goto invalid;
14453917Shibler 		} else if (KREAD(kd, addr, &ste))
14553917Shibler 			goto invalid;
14653917Shibler 		if ((ste & SG_V) == 0) {
14753917Shibler 			_kvm_err(kd, 0, "invalid level 1 descriptor (%x)",
14853917Shibler 				 ste);
14953917Shibler 			return((off_t)0);
15053917Shibler 		}
15153917Shibler 		sta2 = (struct ste *)(ste & SG4_ADDR1);
15253917Shibler 		addr = (u_long)&sta2[(va & SG4_MASK2) >> SG4_SHIFT2];
15353917Shibler 		/*
15453917Shibler 		 * Address from level 1 STE is a physical address,
15553917Shibler 		 * so don't use kvm_read.
15653917Shibler 		 */
15753917Shibler 		if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
15853121Smckusick 		    read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
15953121Smckusick 			goto invalid;
16053917Shibler 		if ((ste & SG_V) == 0) {
16153917Shibler 			_kvm_err(kd, 0, "invalid level 2 descriptor (%x)",
16253917Shibler 				 ste);
16353917Shibler 			return((off_t)0);
16453917Shibler 		}
16553917Shibler 		sta2 = (struct ste *)(ste & SG4_ADDR2);
16653917Shibler 		addr = (u_long)&sta2[(va & SG4_MASK3) >> SG4_SHIFT3];
16753917Shibler 	} else {
16853917Shibler 		addr = (u_long)&sta[va >> SEGSHIFT];
16953917Shibler 		/*
17053917Shibler 		 * Can't use KREAD to read kernel segment table entries.
17153917Shibler 		 * Fortunately it is 1-to-1 mapped so we don't have to.
17253917Shibler 		 */
17353917Shibler 		if (sta == vm->Sysseg) {
17453917Shibler 			if (lseek(kd->pmfd, (off_t)addr, 0) == -1 ||
17553917Shibler 			    read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0)
17653917Shibler 				goto invalid;
17753917Shibler 		} else if (KREAD(kd, addr, &ste))
17853917Shibler 			goto invalid;
17953917Shibler 		if ((ste & SG_V) == 0) {
18053917Shibler 			_kvm_err(kd, 0, "invalid segment (%x)", ste);
18153917Shibler 			return((off_t)0);
18253917Shibler 		}
18353917Shibler 		p = btop(va & SG_PMASK);
18453917Shibler 		addr = (ste & SG_FRAME) + (p * sizeof(struct pte));
18548619Skarels 	}
18653121Smckusick 	/*
18753121Smckusick 	 * Address from STE is a physical address so don't use kvm_read.
18853121Smckusick 	 */
18953917Shibler 	if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||
19053121Smckusick 	    read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0)
19153121Smckusick 		goto invalid;
19253121Smckusick 	addr = pte & PG_FRAME;
19353917Shibler 	if (pte == PG_NV) {
19453121Smckusick 		_kvm_err(kd, 0, "page not valid");
19553121Smckusick 		return (0);
19641007Smarc 	}
19753121Smckusick 	*pa = addr - lowram + offset;
19853121Smckusick 
19953121Smckusick 	return (NBPG - offset);
20053121Smckusick invalid:
20153121Smckusick 	_kvm_err(kd, 0, "invalid address (%x)", va);
20240256Smarc 	return (0);
20340256Smarc }
20440256Smarc 
20553121Smckusick int
_kvm_kvatop(kd,va,pa)20653121Smckusick _kvm_kvatop(kd, va, pa)
20753121Smckusick 	kvm_t *kd;
20853121Smckusick 	u_long va;
20953121Smckusick 	u_long *pa;
21050392Smarc {
21153917Shibler 	return (_kvm_vatop(kd, (u_long)kd->vmst->Sysseg, va, pa));
21240256Smarc }
21340256Smarc 
21440256Smarc /*
21553121Smckusick  * Translate a user virtual address to a physical address.
21640256Smarc  */
21753121Smckusick int
_kvm_uvatop(kd,p,va,pa)21853121Smckusick _kvm_uvatop(kd, p, va, pa)
21953121Smckusick 	kvm_t *kd;
22053121Smckusick 	const struct proc *p;
22153121Smckusick 	u_long va;
22253121Smckusick 	u_long *pa;
22340256Smarc {
22453121Smckusick 	register struct vmspace *vms = p->p_vmspace;
22553121Smckusick 	int kva;
22640256Smarc 
22753917Shibler 	/*
22853917Shibler 	 * If this is a live kernel we just look it up in the kernel
22953917Shibler 	 * virtually allocated flat 4mb page table (i.e. let the kernel
23053917Shibler 	 * do the table walk).  In this way, we avoid needing to know
23153917Shibler 	 * the MMU type.
23253917Shibler 	 */
23353917Shibler 	if (ISALIVE(kd)) {
23453917Shibler 		struct pte *ptab;
23553917Shibler 		int pte, offset;
23653917Shibler 
23753917Shibler 		kva = (int)&vms->vm_pmap.pm_ptab;
23853917Shibler 		if (KREAD(kd, kva, &ptab)) {
23953917Shibler 			_kvm_err(kd, 0, "invalid address (%x)", va);
24053917Shibler 			return (0);
24153917Shibler 		}
24253917Shibler 		kva = (int)&ptab[btop(va)];
24353917Shibler 		if (KREAD(kd, kva, &pte) || (pte & PG_V) == 0) {
24453917Shibler 			_kvm_err(kd, 0, "invalid address (%x)", va);
24553917Shibler 			return (0);
24653917Shibler 		}
24753917Shibler 		offset = va & PGOFSET;
24853917Shibler 		*pa = (pte & PG_FRAME) | offset;
24953917Shibler 		return (NBPG - offset);
25053917Shibler 	}
25153917Shibler 	/*
25253917Shibler 	 * Otherwise, we just walk the table ourself.
25353917Shibler 	 */
25453121Smckusick 	kva = (int)&vms->vm_pmap.pm_stab;
25553917Shibler 	if (KREAD(kd, kva, &kva)) {
25653121Smckusick 		_kvm_err(kd, 0, "invalid address (%x)", va);
25753121Smckusick 		return (0);
25840256Smarc 	}
25953121Smckusick 	return (_kvm_vatop(kd, kva, va, pa));
26040256Smarc }
261