summaryrefslogtreecommitdiffstats
path: root/lib/libkvm
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2011-09-15 22:14:35 +0000
committergrehan <grehan@FreeBSD.org>2011-09-15 22:14:35 +0000
commit2256cbe5692847d9defa97bdd74ce0aa9e74157d (patch)
tree42ba64b8c25f527cf3d9b56c4ce4c51c11d445d1 /lib/libkvm
parent1823067d93fba5ecf7990fee39428954fa5cbf1b (diff)
parente6011fb6bc29d6740516409bd2963015c583c2e9 (diff)
downloadFreeBSD-src-2256cbe5692847d9defa97bdd74ce0aa9e74157d.zip
FreeBSD-src-2256cbe5692847d9defa97bdd74ce0aa9e74157d.tar.gz
IFC @ r225592
sys/dev/bvm/bvm_console.c - move up to the new alt-break order.
Diffstat (limited to 'lib/libkvm')
-rw-r--r--lib/libkvm/kvm_ia64.c88
-rw-r--r--lib/libkvm/kvm_proc.c4
2 files changed, 83 insertions, 9 deletions
diff --git a/lib/libkvm/kvm_ia64.c b/lib/libkvm/kvm_ia64.c
index 04b3c21..74e2b80 100644
--- a/lib/libkvm/kvm_ia64.c
+++ b/lib/libkvm/kvm_ia64.c
@@ -33,6 +33,7 @@
#include <sys/mman.h>
#include <machine/atomic.h>
+#include <machine/bootinfo.h>
#include <machine/pte.h>
#include <kvm.h>
@@ -51,11 +52,16 @@
#define KPTE_DIR0_INDEX(va,ps) ((((va)/(ps)) / NKPTEPG(ps)) / NKPTEDIR(ps))
#define KPTE_DIR1_INDEX(va,ps) ((((va)/(ps)) / NKPTEPG(ps)) % NKPTEDIR(ps))
+#define PBVM_BASE 0x9ffc000000000000UL
+#define PBVM_PGSZ (64 * 1024)
+
struct vmstate {
void *mmapbase;
size_t mmapsize;
size_t pagesize;
u_long kptdir;
+ u_long *pbvm_pgtbl;
+ u_int pbvm_pgtblsz;
};
/*
@@ -110,11 +116,28 @@ _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs, size_t pgsz)
return (pgsz - ((size_t)pa & (pgsz - 1)));
}
+static ssize_t
+_kvm_read_phys(kvm_t *kd, uint64_t pa, void *buf, size_t bufsz)
+{
+ off_t ofs;
+ size_t sz;
+
+ sz = _kvm_pa2off(kd, pa, &ofs, 0);
+ if (sz < bufsz)
+ return ((ssize_t)sz);
+
+ if (lseek(kd->pmfd, ofs, 0) == -1)
+ return (-1);
+ return (read(kd->pmfd, buf, bufsz));
+}
+
void
_kvm_freevtop(kvm_t *kd)
{
struct vmstate *vm = kd->vmst;
+ if (vm->pbvm_pgtbl != NULL)
+ free(vm->pbvm_pgtbl);
if (vm->mmapbase != NULL)
munmap(vm->mmapbase, vm->mmapsize);
free(vm);
@@ -124,10 +147,12 @@ _kvm_freevtop(kvm_t *kd)
int
_kvm_initvtop(kvm_t *kd)
{
+ struct bootinfo bi;
struct nlist nl[2];
uint64_t va;
Elf64_Ehdr *ehdr;
size_t hdrsz;
+ ssize_t sz;
kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst));
if (kd->vmst == NULL) {
@@ -146,6 +171,42 @@ _kvm_initvtop(kvm_t *kd)
return (-1);
/*
+ * Load the PBVM page table. We need this to resolve PBVM addresses.
+ * The PBVM page table is obtained from the bootinfo structure, of
+ * which the physical address is given to us in e_entry. If e_entry
+ * is 0, then this is assumed to be a pre-PBVM kernel.
+ */
+ if (ehdr->e_entry != 0) {
+ sz = _kvm_read_phys(kd, ehdr->e_entry, &bi, sizeof(bi));
+ if (sz != sizeof(bi)) {
+ _kvm_err(kd, kd->program,
+ "cannot read bootinfo from PA %#lx", ehdr->e_entry);
+ return (-1);
+ }
+ if (bi.bi_magic != BOOTINFO_MAGIC) {
+ _kvm_err(kd, kd->program, "invalid bootinfo");
+ return (-1);
+ }
+ kd->vmst->pbvm_pgtbl = _kvm_malloc(kd, bi.bi_pbvm_pgtblsz);
+ if (kd->vmst->pbvm_pgtbl == NULL) {
+ _kvm_err(kd, kd->program, "cannot allocate page table");
+ return (-1);
+ }
+ kd->vmst->pbvm_pgtblsz = bi.bi_pbvm_pgtblsz;
+ sz = _kvm_read_phys(kd, bi.bi_pbvm_pgtbl, kd->vmst->pbvm_pgtbl,
+ bi.bi_pbvm_pgtblsz);
+ if (sz != bi.bi_pbvm_pgtblsz) {
+ _kvm_err(kd, kd->program,
+ "cannot read page table from PA %#lx",
+ bi.bi_pbvm_pgtbl);
+ return (-1);
+ }
+ } else {
+ kd->vmst->pbvm_pgtbl = NULL;
+ kd->vmst->pbvm_pgtblsz = 0;
+ }
+
+ /*
* At this point we've got enough information to use kvm_read() for
* direct mapped (ie region 6 and region 7) address, such as symbol
* addresses/values.
@@ -174,17 +235,18 @@ _kvm_initvtop(kvm_t *kd)
}
int
-_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa)
+_kvm_kvatop(kvm_t *kd, u_long va, off_t *ofs)
{
struct ia64_lpte pte;
- uint64_t pgaddr, pt0addr, pt1addr;
+ uint64_t pa, pgaddr, pt0addr, pt1addr;
size_t pgno, pgsz, pt0no, pt1no;
if (va >= REGION_BASE(6)) {
/* Regions 6 and 7: direct mapped. */
- return (_kvm_pa2off(kd, REGION_ADDR(va), pa, 0));
+ pa = REGION_ADDR(va);
+ return (_kvm_pa2off(kd, pa, ofs, 0));
} else if (va >= REGION_BASE(5)) {
- /* Region 5: virtual. */
+ /* Region 5: Kernel Virtual Memory. */
va = REGION_ADDR(va);
pgsz = kd->vmst->pagesize;
pt0no = KPTE_DIR0_INDEX(va, pgsz);
@@ -207,12 +269,24 @@ _kvm_kvatop(kvm_t *kd, u_long va, off_t *pa)
goto fail;
if (!(pte.pte & PTE_PRESENT))
goto fail;
- va = (pte.pte & PTE_PPN_MASK) + (va & (pgsz - 1));
- return (_kvm_pa2off(kd, va, pa, pgsz));
+ pa = (pte.pte & PTE_PPN_MASK) + (va & (pgsz - 1));
+ return (_kvm_pa2off(kd, pa, ofs, pgsz));
+ } else if (va >= PBVM_BASE) {
+ /* Region 4: Pre-Boot Virtual Memory (PBVM). */
+ va -= PBVM_BASE;
+ pgsz = PBVM_PGSZ;
+ pt0no = va / pgsz;
+ if (pt0no >= (kd->vmst->pbvm_pgtblsz >> 3))
+ goto fail;
+ pt0addr = kd->vmst->pbvm_pgtbl[pt0no];
+ if (!(pt0addr & PTE_PRESENT))
+ goto fail;
+ pa = (pt0addr & PTE_PPN_MASK) + va % pgsz;
+ return (_kvm_pa2off(kd, pa, ofs, pgsz));
}
fail:
_kvm_err(kd, kd->program, "invalid kernel virtual address");
- *pa = ~0UL;
+ *ofs = ~0UL;
return (0);
}
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index 338d217..876af50 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -426,10 +426,10 @@ nopgrp:
kp->ki_lastcpu = mtd.td_lastcpu;
kp->ki_wchan = mtd.td_wchan;
if (mtd.td_name[0] != 0)
- strlcpy(kp->ki_ocomm, mtd.td_name, MAXCOMLEN);
+ strlcpy(kp->ki_tdname, mtd.td_name, MAXCOMLEN);
kp->ki_oncpu = mtd.td_oncpu;
if (mtd.td_name[0] != '\0')
- strlcpy(kp->ki_ocomm, mtd.td_name, sizeof(kp->ki_ocomm));
+ strlcpy(kp->ki_tdname, mtd.td_name, sizeof(kp->ki_tdname));
kp->ki_pctcpu = 0;
kp->ki_rqindex = 0;
} else {
OpenPOWER on IntegriCloud