sync with libkvm.old sources (change committed by pk):

>Catch up with system PMAP.
This commit is contained in:
cgd 1996-04-01 19:23:03 +00:00
parent 10ffa5da40
commit 82501b607b
1 changed files with 206 additions and 45 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kvm_sparc.c,v 1.8 1996/03/18 22:34:02 thorpej Exp $ */
/* $NetBSD: kvm_sparc.c,v 1.9 1996/04/01 19:23:03 cgd Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93";
#else
static char *rcsid = "$NetBSD: kvm_sparc.c,v 1.8 1996/03/18 22:34:02 thorpej Exp $";
static char *rcsid = "$NetBSD: kvm_sparc.c,v 1.9 1996/04/01 19:23:03 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@ -72,7 +72,7 @@ static char *rcsid = "$NetBSD: kvm_sparc.c,v 1.8 1996/03/18 22:34:02 thorpej Exp
#define MA_SIZE 32 /* XXX */
struct vmstate {
struct {
int x_seginval;
int x_seginval; /* [sun4/sun4c] only */
int x_npmemarr;
struct memarr x_pmemarr[MA_SIZE];
struct segmap x_segmap_store[NKREG*NSEGRG];
@ -81,7 +81,7 @@ struct vmstate {
#define npmemarr x.x_npmemarr
#define pmemarr x.x_pmemarr
#define segmap_store x.x_segmap_store
int *pte;
int *pte; /* [sun4/sun4c] only */
};
#define NPMEG(vm) ((vm)->seginval+1)
@ -89,26 +89,62 @@ static int cputyp = -1;
static int pgshift, nptesg;
#define VA_VPG(va) (cputyp==CPU_SUN4C ? VA_SUN4C_VPG(va) : VA_SUN4_VPG(va))
#define VA_VPG(va) ((cputyp == CPU_SUN4C || cputyp == CPU_SUN4M) \
? VA_SUN4C_VPG(va) \
: VA_SUN4_VPG(va))
static void
static int _kvm_mustinit __P((kvm_t *));
#if 0
static int
getcputyp()
{
int mib[2];
size_t size;
mib[0] = CTL_HW;
mib[1] = HW_CLASS;
size = sizeof cputyp;
if (sysctl(mib, 2, &cputyp, &size, NULL, 0) == -1)
return (-1);
}
#endif
static int
_kvm_mustinit(kd)
kvm_t *kd;
{
static struct nlist nlist[2] = {
# define X_CPUTYP 0
{ "_cputyp" },
{ NULL },
};
off_t foff;
if (cputyp != -1)
return;
return 0;
for (pgshift = 12; (1 << pgshift) != kd->nbpg; pgshift++)
;
nptesg = NBPSG / kd->nbpg;
#if 1
if (cputyp == -1) {
if (kd->nbpg == 8192)
cputyp = CPU_SUN4;
else
cputyp = CPU_SUN4C;
if (kvm_nlist(kd, nlist) != 0) {
_kvm_err(kd, kd->program, "cannot find `cputyp' symbol");
return (-1);
}
#endif
/* Assume kernel mappings are all within first memory bank. */
foff = nlist[X_CPUTYP].n_value - KERNBASE;
if (lseek(kd->pmfd, foff, 0) == -1 ||
read(kd->pmfd, &cputyp, sizeof(cputyp)) < 0) {
_kvm_err(kd, kd->program, "cannot read `cputyp");
return (-1);
}
if (cputyp != CPU_SUN4 &&
cputyp != CPU_SUN4C &&
cputyp != CPU_SUN4M)
return (-1);
return (0);
}
void
@ -123,6 +159,26 @@ _kvm_freevtop(kd)
}
}
/*
* Translate a kernel virtual address to a physical address using the
* mapping information in kd->vm. Returns the result in pa, and returns
* the number of bytes that are contiguously available from this
* physical address. This routine is used only for crashdumps.
*/
int
_kvm_kvatop(kd, va, pa)
kvm_t *kd;
u_long va;
u_long *pa;
{
if (_kvm_mustinit(kd) != 0)
return (-1);
return ((cputyp == CPU_SUN4M)
? _kvm_kvatop4m(kd, va, pa)
: _kvm_kvatop44c(kd, va, pa));
}
/*
* Prepare for translation of kernel virtual addresses into offsets
* into crash dump files. We use the MMU specific goop written at the
@ -133,13 +189,30 @@ int
_kvm_initvtop(kd)
kvm_t *kd;
{
register int i;
register int off;
register struct vmstate *vm;
struct stat st;
struct nlist nlist[5];
if (_kvm_mustinit(kd) != 0)
return (-1);
_kvm_mustinit(kd);
return ((cputyp == CPU_SUN4M)
? _kvm_initvtop4m(kd)
: _kvm_initvtop44c(kd));
}
#define VA_OFF(va) (va & (kd->nbpg - 1))
/*
* We use the MMU specific goop written at the end of crash dump
* by pmap_dumpmmu().
* (note: sun4 3-level MMU not yet supported)
*/
int
_kvm_initvtop44c(kd)
kvm_t *kd;
{
register struct vmstate *vm;
register int i;
off_t foff;
struct stat st;
if ((vm = kd->vmst) == 0) {
kd->vmst = vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
@ -153,9 +226,9 @@ _kvm_initvtop(kd)
* Read segment table.
*/
off = st.st_size - roundup(sizeof(vm->x), kd->nbpg);
foff = st.st_size - roundup(sizeof(vm->x), kd->nbpg);
errno = 0;
if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
if (lseek(kd->pmfd, (off_t)foff, 0) == -1 && errno != 0 ||
read(kd->pmfd, (char *)&vm->x, sizeof(vm->x)) < 0) {
_kvm_err(kd, kd->program, "cannot read segment map");
return (-1);
@ -171,11 +244,11 @@ _kvm_initvtop(kd)
/*
* Read PMEGs.
*/
off = st.st_size - roundup(sizeof(vm->x), kd->nbpg) -
foff = st.st_size - roundup(sizeof(vm->x), kd->nbpg) -
roundup(NPMEG(vm) * nptesg * sizeof(int), kd->nbpg);
errno = 0;
if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||
if (lseek(kd->pmfd, foff, 0) == -1 && errno != 0 ||
read(kd->pmfd, (char *)vm->pte, NPMEG(vm) * nptesg * sizeof(int)) < 0) {
_kvm_err(kd, kd->program, "cannot read PMEG table");
return (-1);
@ -184,16 +257,8 @@ _kvm_initvtop(kd)
return (0);
}
#define VA_OFF(va) (va & (kd->nbpg - 1))
/*
* Translate a kernel virtual address to a physical address using the
* mapping information in kd->vm. Returns the result in pa, and returns
* the number of bytes that are contiguously available from this
* physical address. This routine is used only for crashdumps.
*/
int
_kvm_kvatop(kd, va, pa)
_kvm_kvatop44c(kd, va, pa)
kvm_t *kd;
u_long va;
u_long *pa;
@ -204,8 +269,6 @@ _kvm_kvatop(kd, va, pa)
struct segmap *sp;
struct memarr *mp;
_kvm_mustinit(kd);
if (va < KERNBASE)
goto err;
@ -239,17 +302,115 @@ err:
return (0);
}
#if 0
static int
getcputyp()
/*
* Prepare for translation of kernel virtual addresses into offsets
* into crash dump files. Since the sun4m pagetables are all in memory,
* we use nlist to bootstrap the translation tables. This assumes that
* the kernel mappings all reside in the first physical memory bank.
*/
int
_kvm_initvtop4m(kd)
kvm_t *kd;
{
int mib[2];
size_t size;
register int i;
register off_t foff;
register struct vmstate *vm;
struct stat st;
static struct nlist nlist[4] = {
# define X_KSEGSTORE 0
{ "_kernel_segmap_store" },
# define X_PMEMARR 1
{ "_pmemarr" },
# define X_NPMEMARR 2
{ "_npmemarr" },
{ NULL },
};
mib[0] = CTL_HW;
mib[1] = HW_CLASS;
size = sizeof cputyp;
if (sysctl(mib, 2, &cputyp, &size, NULL, 0) == -1)
if ((vm = kd->vmst) == 0) {
kd->vmst = vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
if (vm == 0)
return (-1);
}
if (kvm_nlist(kd, nlist) != 0) {
_kvm_err(kd, kd->program, "cannot read symbols");
return (-1);
}
/* Assume kernel mappings are all within first memory bank. */
foff = nlist[X_KSEGSTORE].n_value - KERNBASE;
if (lseek(kd->pmfd, foff, 0) == -1 ||
read(kd->pmfd, vm->segmap_store, sizeof(vm->segmap_store)) < 0) {
_kvm_err(kd, kd->program, "cannot read segment map");
return (-1);
}
foff = nlist[X_PMEMARR].n_value - KERNBASE;
if (lseek(kd->pmfd, foff, 0) == -1 ||
read(kd->pmfd, vm->pmemarr, sizeof(vm->pmemarr)) < 0) {
_kvm_err(kd, kd->program, "cannot read pmemarr");
return (-1);
}
foff = nlist[X_NPMEMARR].n_value - KERNBASE;
if (lseek(kd->pmfd, foff, 0) == -1 ||
read(kd->pmfd, &vm->npmemarr, sizeof(vm->npmemarr)) < 0) {
_kvm_err(kd, kd->program, "cannot read npmemarr");
return (-1);
}
return (0);
}
int
_kvm_kvatop4m(kd, va, pa)
kvm_t *kd;
u_long va;
u_long *pa;
{
register struct vmstate *vm = kd->vmst;
register int vr, vs, nmem, off;
int pte;
off_t foff;
struct regmap *rp;
struct segmap *sp;
struct memarr *mp;
if (va < KERNBASE)
goto err;
vr = VA_VREG(va);
vs = VA_VSEG(va);
sp = &vm->segmap_store[(vr-NUREG)*NSEGRG + vs];
if (sp->sg_npte == 0)
goto err;
/* Assume kernel mappings are all within first memory bank. */
foff = (long)&sp->sg_pte[VA_VPG(va)] - KERNBASE;
if (lseek(kd->pmfd, foff, 0) == -1 ||
read(kd->pmfd, (void *)&pte, sizeof(pte)) < 0) {
_kvm_err(kd, kd->program, "cannot read pte");
goto err;
}
if ((pte & SRMMU_TETYPE) == SRMMU_TEPTE) {
register long p, dumpoff = 0;
off = VA_OFF(va);
p = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT;
/* Translate (sparse) pfnum to (packed) dump offset */
for (mp = vm->pmemarr, nmem = vm->npmemarr; --nmem >= 0; mp++) {
if (mp->addr <= p && p < mp->addr + mp->len)
break;
dumpoff += mp->len;
}
if (nmem < 0)
goto err;
*pa = (dumpoff + p - mp->addr) | off;
return (kd->nbpg - off);
}
err:
_kvm_err(kd, 0, "invalid address (%x)", va);
return (0);
}
#endif