libkvm - Add ability to access userspace from kgdb on cores
authorMatthew Dillon <dillon@apollo.backplane.com>
Sat, 23 Oct 2010 02:32:01 +0000 (19:32 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 24 Oct 2010 16:35:03 +0000 (09:35 -0700)
* Use %cr3 from the dumppcb instead of KPML4phys on x86_64, and similarly
  for i386, to access the full page table as of when the panic occured
  instead of just the kernel page table.

* minidumps do not dump userspace so userspace will still not be available,
  but this gives us the option of sysctl'ing off minidumps when userspace
  access is desired, and kgdb will then be able to access the current
  userspace context as of the panic, as well.

lib/libkvm/kvm_i386.c
lib/libkvm/kvm_x86_64.c

index 3fed91a..5f63ba2 100644 (file)
@@ -163,6 +163,7 @@ _kvm_initvtop(kvm_t *kd)
        Elf_Ehdr        *ehdr;
        size_t          hdrsz;
        char            minihdr[8];
+       struct pcb      dumppcb;
 
        if (pread(kd->pmfd, &minihdr, 8, 0) == 8)
                if (memcmp(&minihdr, "minidump", 8) == 0)
@@ -200,18 +201,21 @@ _kvm_initvtop(kvm_t *kd)
        else
                kernbase = nlist[0].n_value;
 
-       nlist[0].n_name = "_IdlePTD";
+       nlist[0].n_name = "_dumppcb";
        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");
+
+       if (kvm_read(kd, (nlist[0].n_value - kernbase), &dumppcb,
+                    sizeof(dumppcb)) != sizeof(dumppcb)) {
+               _kvm_err(kd, kd->program, "cannot read dumppcb");
                return (-1);
        }
+       pa = dumppcb.pcb_cr3 & PG_FRAME;
+
        PTD = _kvm_malloc(kd, PAGE_SIZE);
        if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) {
                _kvm_err(kd, kd->program, "cannot read PTD");
@@ -279,7 +283,7 @@ _kvm_vatop(kvm_t *kd, u_long va, off_t *pa)
 #endif
                pde_pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK);
                s = _kvm_pa2off(kd, pde_pa, &ofs);
-               if (s <= sizeof pde) {
+               if (s < sizeof pde) {
                        _kvm_syserr(kd, kd->program,
                            "_kvm_vatop: pde_pa not found");
                        goto invalid;
@@ -293,7 +297,7 @@ _kvm_vatop(kvm_t *kd, u_long va, off_t *pa)
        pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pde));
 
        s = _kvm_pa2off(kd, pte_pa, &ofs);
-       if (s <= sizeof pte) {
+       if (s < sizeof pte) {
                _kvm_err(kd, kd->program, "_kvm_vatop: pdpe_pa not found");
                goto invalid;
        }
index 38593b2..eb15a91 100644 (file)
@@ -161,6 +161,7 @@ _kvm_initvtop(kvm_t *kd)
        Elf_Ehdr *ehdr;
        size_t hdrsz;
        char    minihdr[8];
+       struct pcb dumppcb;
 
        if (pread(kd->pmfd, &minihdr, 8, 0) == 8)
                if (memcmp(&minihdr, "minidump", 8) == 0)
@@ -176,8 +177,8 @@ _kvm_initvtop(kvm_t *kd)
        if (_kvm_maphdrs(kd, sizeof(Elf_Ehdr)) == -1)
                return (-1);
        /*
-        * Check if this is indeed an ELF header. If not, assume old style dump or
-        * memory layout.
+        * Check if this is indeed an ELF header. If not, assume old style
+         *dump or memory layout.
         */
        ehdr = kd->vmst->mmapbase;
        if (!IS_ELF(*ehdr)) {
@@ -199,21 +200,23 @@ _kvm_initvtop(kvm_t *kd)
        }
        kernbase = nlist[0].n_value;
 
-       nlist[0].n_name = "KPML4phys";
+       nlist[0].n_name = "dumppcb";
        nlist[1].n_name = 0;
 
        if (kvm_nlist(kd, nlist) != 0) {
-               _kvm_err(kd, kd->program, "bad namelist - no KPML4phys");
+               _kvm_err(kd, kd->program, "bad namelist - no dumppcb");
                return (-1);
        }
-       if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, sizeof(pa)) !=
-           sizeof(pa)) {
-               _kvm_err(kd, kd->program, "cannot read KPML4phys");
+       if (kvm_read(kd, (nlist[0].n_value - kernbase), &dumppcb,
+                    sizeof(dumppcb)) != sizeof(dumppcb)) {
+               _kvm_err(kd, kd->program, "cannot read dumppcb");
                return (-1);
        }
+       pa = dumppcb.pcb_cr3 & PG_FRAME;
+
        PML4 = _kvm_malloc(kd, PAGE_SIZE);
        if (kvm_read(kd, pa, PML4, PAGE_SIZE) != PAGE_SIZE) {
-               _kvm_err(kd, kd->program, "cannot read KPML4phys");
+               _kvm_err(kd, kd->program, "cannot read dumppcb");
                return (-1);
        }
        kd->vmst->PML4 = PML4;
@@ -269,7 +272,7 @@ _kvm_vatop(kvm_t *kd, u_long va, off_t *pa)
            (pdpeindex * sizeof(pdp_entry_t));
 
        s = _kvm_pa2off(kd, pdpe_pa, &ofs);
-       if (s <= sizeof pdpe) {
+       if (s < sizeof pdpe) {
                _kvm_err(kd, kd->program, "_kvm_vatop: pdpe_pa not found");
                goto invalid;
        }
@@ -286,12 +289,11 @@ _kvm_vatop(kvm_t *kd, u_long va, off_t *pa)
                goto invalid;
        }
 
-
        pdeindex = (va >> PDRSHIFT) & (NPDEPG-1);
        pde_pa = ((u_long)pdpe & PG_FRAME) + (pdeindex * sizeof(pd_entry_t));
 
        s = _kvm_pa2off(kd, pde_pa, &ofs);
-       if (s <= sizeof pde) {
+       if (s < sizeof pde) {
                _kvm_syserr(kd, kd->program, "_kvm_vatop: pde_pa not found");
                goto invalid;
        }
@@ -329,7 +331,7 @@ _kvm_vatop(kvm_t *kd, u_long va, off_t *pa)
        pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t));
 
        s = _kvm_pa2off(kd, pte_pa, &ofs);
-       if (s <= sizeof pte) {
+       if (s < sizeof pte) {
                _kvm_err(kd, kd->program, "_kvm_vatop: pte_pa not found");
                goto invalid;
        }