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