PERFORCE change 79086 for review
Paul Saab
ps at FreeBSD.org
Tue Jun 28 18:17:16 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=79086
Change 79086 by ps at butter.corp on 2005/06/28 18:16:57
With the help of Peter, add support for PAE crashdumps.
Affected files ...
.. //depot/projects/hammer/lib/libkvm/kvm_i386.c#4 edit
.. //depot/projects/hammer/lib/libkvm/kvm_private.h#2 edit
Differences ...
==== //depot/projects/hammer/lib/libkvm/kvm_i386.c#4 (text+ko) ====
@@ -73,10 +73,15 @@
#define ptob(x) (i386_ptob(x))
#endif
+#define PG_FRAME_PAE (~((uint64_t)PAGE_MASK))
+#define PDRSHIFT_PAE 21
+#define NPTEPG_PAE (PAGE_SIZE/sizeof(uint64_t))
+
struct vmstate {
void *mmapbase;
size_t mmapsize;
- pd_entry_t *PTD;
+ void *PTD;
+ int pae;
};
/*
@@ -109,7 +114,7 @@
* (Taken from kvm_ia64.c)
*/
static size_t
-_kvm_pa2off(kvm_t *kd, uint64_t pa, u_long *ofs)
+_kvm_pa2off(kvm_t *kd, uint64_t pa, uint64_t *ofs)
{
Elf_Ehdr *e = kd->vmst->mmapbase;
Elf_Phdr *p = (Elf_Phdr*)((char*)e + e->e_phoff);
@@ -173,29 +178,58 @@
else
kernbase = nlist[0].n_value;
- nlist[0].n_name = "IdlePTD";
+ nlist[0].n_name = "IdlePDPT";
nlist[1].n_name = 0;
- if (kvm_nlist(kd, nlist) != 0) {
- _kvm_err(kd, kd->program, "bad namelist");
- return (-1);
- }
- if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, sizeof(pa)) !=
- sizeof(pa)) {
- _kvm_err(kd, kd->program, "cannot read IdlePTD");
- return (-1);
- }
- PTD = _kvm_malloc(kd, PAGE_SIZE);
- if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) {
- _kvm_err(kd, kd->program, "cannot read PTD");
- return (-1);
+ if (kvm_nlist(kd, nlist) == 0) {
+ uint64_t pa64;
+
+ if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa,
+ sizeof(pa)) != sizeof(pa)) {
+ _kvm_err(kd, kd->program, "cannot read IdlePDPT");
+ return (-1);
+ }
+
+ if (kvm_read(kd, pa, &pa64, sizeof(pa64)) != sizeof(pa64)) {
+ _kvm_err(kd, kd->program, "Cannot read PDPT");
+ return (-1);
+ }
+
+ PTD = _kvm_malloc(kd, 4 * PAGE_SIZE);
+ if (kvm_read(kd, pa64 & PG_FRAME_PAE, PTD, 4 * PAGE_SIZE) !=
+ (4 * PAGE_SIZE)) {
+ _kvm_err(kd, kd->program, "cannot read PDPT");
+ return (-1);
+ }
+ kd->vmst->PTD = PTD;
+ kd->vmst->pae = 1;
+ } else {
+ nlist[0].n_name = "IdlePTD";
+ nlist[1].n_name = 0;
+
+ if (kvm_nlist(kd, nlist) != 0) {
+ _kvm_err(kd, kd->program, "bad namelist");
+ return (-1);
+ }
+ if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, sizeof(pa)) !=
+ sizeof(pa)) {
+ _kvm_err(kd, kd->program, "cannot read IdlePTD");
+ return (-1);
+ }
+ PTD = _kvm_malloc(kd, PAGE_SIZE);
+ if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) {
+ _kvm_err(kd, kd->program, "cannot read PTD");
+ return (-1);
+ }
+ kd->vmst->PTD = PTD;
+ return (0);
+ kd->vmst->pae = 0;
}
- kd->vmst->PTD = PTD;
return (0);
}
int
-_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa)
+kvm_kvatop(kvm_t *kd, u_long va, uint64_t *pa)
{
struct vmstate *vm;
u_long offset;
@@ -206,7 +240,9 @@
u_long pdeindex;
u_long pteindex;
size_t s;
- u_long a, ofs;
+ u_long a;
+ uint64_t ofs;
+ uint32_t *PTD;
if (ISALIVE(kd)) {
@@ -215,13 +251,14 @@
}
vm = kd->vmst;
+ PTD = (uint32_t *)vm->PTD;
offset = va & (PAGE_SIZE - 1);
/*
* If we are initializing (kernel page table descriptor pointer
* not yet set) then return pa == va to avoid infinite recursion.
*/
- if (vm->PTD == 0) {
+ if (PTD == 0) {
s = _kvm_pa2off(kd, va, pa);
if (s == 0) {
_kvm_err(kd, kd->program,
@@ -232,7 +269,7 @@
}
pdeindex = va >> PDRSHIFT;
- pde = vm->PTD[pdeindex];
+ pde = PTD[pdeindex];
if (((u_long)pde & PG_V) == 0)
goto invalid;
@@ -256,7 +293,7 @@
}
pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1);
- pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t));
+ pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pde));
s = _kvm_pa2off(kd, pte_pa, &ofs);
if (s <= sizeof pte) {
@@ -288,3 +325,109 @@
_kvm_err(kd, 0, "invalid address (%x)", va);
return (0);
}
+
+int
+kvm_kvatop_pae(kvm_t *kd, u_long va, uint64_t *pa)
+{
+ struct vmstate *vm;
+ uint64_t offset;
+ uint64_t pte_pa;
+ uint64_t pde_pa;
+ uint64_t pde;
+ uint64_t pte;
+ u_long pdeindex;
+ u_long pteindex;
+ size_t s;
+ uint64_t a, ofs;
+ uint64_t *PTD;
+
+
+ if (ISALIVE(kd)) {
+ _kvm_err(kd, 0, "vatop called in live kernel!");
+ return((off_t)0);
+ }
+
+ vm = kd->vmst;
+ PTD = (uint64_t *)vm->PTD;
+ offset = va & (PAGE_SIZE - 1);
+
+ /*
+ * If we are initializing (kernel page table descriptor pointer
+ * not yet set) then return pa == va to avoid infinite recursion.
+ */
+ if (PTD == 0) {
+ s = _kvm_pa2off(kd, va, pa);
+ if (s == 0) {
+ _kvm_err(kd, kd->program,
+ "_kvm_kvatop: bootstrap data not in dump");
+ goto invalid;
+ } else
+ return (PAGE_SIZE - offset);
+ }
+
+ pdeindex = va >> PDRSHIFT_PAE;
+ pde = PTD[pdeindex];
+ if (((u_long)pde & PG_V) == 0)
+ goto invalid;
+
+ if ((u_long)pde & PG_PS) {
+ /*
+ * No second-level page table; ptd describes one 4MB page.
+ * (We assume that the kernel wouldn't set PG_PS without enabling
+ * it cr0, and that the kernel doesn't support 36-bit physical
+ * addresses).
+ */
+#define PAGE4M_MASK (NBPDR - 1)
+#define PG_FRAME4M (~PAGE4M_MASK)
+ pde_pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK);
+ s = _kvm_pa2off(kd, pde_pa, &ofs);
+ if (s <= sizeof pde) {
+ _kvm_syserr(kd, kd->program, "_kvm_kvatop: pde_pa not found");
+ goto invalid;
+ }
+ *pa = ofs;
+ return (NBPDR - (va & PAGE4M_MASK));
+ }
+
+ pteindex = (va >> PAGE_SHIFT) & (NPTEPG_PAE-1);
+ pte_pa = ((uint64_t)pde & PG_FRAME_PAE) + (pteindex * sizeof(pde));
+
+ s = _kvm_pa2off(kd, pte_pa, &ofs);
+ if (s <= sizeof pte) {
+ _kvm_err(kd, kd->program, "_kvm_kvatop: pdpe_pa not found");
+ goto invalid;
+ }
+
+ /* XXX This has to be a physical address read, kvm_read is virtual */
+ if (lseek(kd->pmfd, ofs, 0) == -1) {
+ _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek");
+ goto invalid;
+ }
+ if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) {
+ _kvm_syserr(kd, kd->program, "_kvm_vatop: read");
+ goto invalid;
+ }
+ if (((uint64_t)pte & PG_V) == 0)
+ goto invalid;
+
+ a = ((uint64_t)pte & PG_FRAME_PAE) + offset;
+ s =_kvm_pa2off(kd, a, pa);
+ if (s == 0) {
+ _kvm_err(kd, kd->program, "_kvm_kvatop: address not in dump");
+ goto invalid;
+ } else
+ return (PAGE_SIZE - offset);
+
+invalid:
+ _kvm_err(kd, 0, "invalid address (%x)", va);
+ return (0);
+}
+
+int
+_kvm_kvatop(kvm_t *kd, u_long va, uint64_t *pa)
+{
+ if (kd->vmst->pae)
+ kvm_kvatop_pae(kd, va, pa);
+ else
+ kvm_kvatop(kd, va, pa);
+}
==== //depot/projects/hammer/lib/libkvm/kvm_private.h#2 (text+ko) ====
@@ -75,7 +75,7 @@
void _kvm_freeprocs(kvm_t *kd);
void _kvm_freevtop(kvm_t *);
int _kvm_initvtop(kvm_t *);
-int _kvm_kvatop(kvm_t *, u_long, u_long *);
+int _kvm_kvatop(kvm_t *, u_long, uint64_t *);
void *_kvm_malloc(kvm_t *kd, size_t);
void *_kvm_realloc(kvm_t *kd, void *, size_t);
void _kvm_syserr (kvm_t *kd, const char *program, const char *fmt, ...)
More information about the p4-projects
mailing list