From owner-p4-projects@FreeBSD.ORG Tue Jun 28 18:17:16 2005 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 905B116A421; Tue, 28 Jun 2005 18:17:15 +0000 (GMT) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5F4B416A41C for ; Tue, 28 Jun 2005 18:17:15 +0000 (GMT) (envelope-from ps@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 20E1643D48 for ; Tue, 28 Jun 2005 18:17:15 +0000 (GMT) (envelope-from ps@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j5SIHFIj094471 for ; Tue, 28 Jun 2005 18:17:15 GMT (envelope-from ps@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j5SIHEbP094468 for perforce@freebsd.org; Tue, 28 Jun 2005 18:17:14 GMT (envelope-from ps@freebsd.org) Date: Tue, 28 Jun 2005 18:17:14 GMT Message-Id: <200506281817.j5SIHEbP094468@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ps@freebsd.org using -f From: Paul Saab To: Perforce Change Reviews Cc: Subject: PERFORCE change 79086 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Jun 2005 18:17:16 -0000 http://perforce.freebsd.org/chv.cgi?CH=79086 Change 79086 by ps@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, ...)