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