diff options
Diffstat (limited to 'lib/libkvm/kvm_alpha.c')
-rw-r--r-- | lib/libkvm/kvm_alpha.c | 108 |
1 files changed, 104 insertions, 4 deletions
diff --git a/lib/libkvm/kvm_alpha.c b/lib/libkvm/kvm_alpha.c index d07681a7f8d..ec8e8cff7ac 100644 --- a/lib/libkvm/kvm_alpha.c +++ b/lib/libkvm/kvm_alpha.c @@ -1,5 +1,5 @@ -/* $OpenBSD: kvm_alpha.c,v 1.2 1996/05/05 14:56:50 deraadt Exp $ */ -/* $NetBSD: kvm_alpha.c,v 1.2 1995/09/29 03:57:48 cgd Exp $ */ +/* $OpenBSD: kvm_alpha.c,v 1.3 1997/02/26 16:46:29 niklas Exp $ */ +/* $NetBSD: kvm_alpha.c,v 1.5 1996/10/01 21:12:05 cgd Exp $ */ /* * Copyright (c) 1994, 1995 Carnegie-Mellon University. @@ -32,6 +32,8 @@ #include <sys/user.h> #include <sys/proc.h> #include <sys/stat.h> +#include <sys/kcore.h> +#include <machine/kcore.h> #include <unistd.h> #include <nlist.h> #include <kvm.h> @@ -49,6 +51,9 @@ _kvm_freevtop(kd) kvm_t *kd; { + /* Not actually used for anything right now, but safe. */ + if (kd->vmst != 0) + free(kd->vmst); } int @@ -65,8 +70,103 @@ _kvm_kvatop(kd, va, pa) u_long va; u_long *pa; { + cpu_kcore_hdr_t *cpu_kh; + int rv, page_off; + alpha_pt_entry_t pte; + off_t pteoff; - /* don't forget k0seg translations! */ + if (ISALIVE(kd)) { + _kvm_err(kd, 0, "vatop called in live kernel!"); + return(0); + } - return (0); + cpu_kh = kd->cpu_data; + page_off = va & (cpu_kh->page_size - 1); + + if (va >= ALPHA_K0SEG_BASE && va <= ALPHA_K0SEG_END) { + /* + * Direct-mapped address: just convert it. + */ + + *pa = ALPHA_K0SEG_TO_PHYS(va); + rv = cpu_kh->page_size - page_off; + } else if (va >= ALPHA_K1SEG_BASE && va <= ALPHA_K1SEG_END) { + /* + * Real kernel virtual address: do the translation. + */ + + /* Find and read the L1 PTE. */ + pteoff = cpu_kh->lev1map_pa + + kvtol1pte(va) * sizeof(alpha_pt_entry_t); + if (lseek(kd->pmfd, _kvm_pa2off(kd, pteoff), 0) == -1 || + read(kd->pmfd, (char *)&pte, sizeof(pte)) != sizeof(pte)) { + _kvm_syserr(kd, 0, "could not read L1 PTE"); + goto lose; + } + + /* Find and read the L2 PTE. */ + if ((pte & ALPHA_PTE_VALID) == 0) { + _kvm_err(kd, 0, "invalid translation (invalid L1 PTE)"); + goto lose; + } + pteoff = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size + + vatoste(va) * sizeof(alpha_pt_entry_t); + if (lseek(kd->pmfd, _kvm_pa2off(kd, pteoff), 0) == -1 || + read(kd->pmfd, (char *)&pte, sizeof(pte)) != sizeof(pte)) { + _kvm_syserr(kd, 0, "could not read L2 PTE"); + goto lose; + } + + /* Find and read the L3 PTE. */ + if ((pte & ALPHA_PTE_VALID) == 0) { + _kvm_err(kd, 0, "invalid translation (invalid L2 PTE)"); + goto lose; + } + pteoff = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size + + vatopte(va) * sizeof(alpha_pt_entry_t); + if (lseek(kd->pmfd, _kvm_pa2off(kd, pteoff), 0) == -1 || + read(kd->pmfd, (char *)&pte, sizeof(pte)) != sizeof(pte)) { + _kvm_syserr(kd, 0, "could not read L3 PTE"); + goto lose; + } + + /* Fill in the PA. */ + if ((pte & ALPHA_PTE_VALID) == 0) { + _kvm_err(kd, 0, "invalid translation (invalid L3 PTE)"); + goto lose; + } + *pa = ALPHA_PTE_TO_PFN(pte) * cpu_kh->page_size + page_off; + vatopte(va) * sizeof(alpha_pt_entry_t); + rv = cpu_kh->page_size - page_off; + } else { + /* + * Bogus address (not in KV space): punt. + */ + + _kvm_err(kd, 0, "invalid kernel virtual address"); +lose: + *pa = -1; + rv = 0; + } + + return (rv); +} + +/* + * Translate a physical address to a file-offset in the crash-dump. + */ +off_t +_kvm_pa2off(kd, pa) + kvm_t *kd; + u_long pa; +{ + off_t off; + cpu_kcore_hdr_t *cpu_kh; + + cpu_kh = kd->cpu_data; + + off = 0; + pa -= cpu_kh->core_seg.start; + + return (kd->dump_off + off + pa); } |