diff options
Diffstat (limited to 'lib/libkvm/kvm_sparc64.c')
-rw-r--r-- | lib/libkvm/kvm_sparc64.c | 141 |
1 files changed, 82 insertions, 59 deletions
diff --git a/lib/libkvm/kvm_sparc64.c b/lib/libkvm/kvm_sparc64.c index 1f925a9..97cb516 100644 --- a/lib/libkvm/kvm_sparc64.c +++ b/lib/libkvm/kvm_sparc64.c @@ -47,65 +47,54 @@ static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; */ #include <sys/param.h> -#include <sys/user.h> -#include <sys/proc.h> -#include <sys/stat.h> +#include <kvm.h> +#include <limits.h> +#include <stdint.h> #include <stdlib.h> #include <unistd.h> -#include <nlist.h> -#include <kvm.h> - -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <machine/kerneldump.h> -#include <machine/tte.h> -#include <machine/tlb.h> -#include <machine/tsb.h> - -#include <limits.h> +#include "../../sys/sparc64/include/kerneldump.h" #include "kvm_private.h" - -#ifndef btop -#define btop(x) (sparc64_btop(x)) -#define ptob(x) (sparc64_ptob(x)) -#endif +#include "kvm_sparc64.h" struct vmstate { off_t vm_tsb_off; - vm_size_t vm_tsb_mask; + uint64_t vm_tsb_mask; int vm_nregions; struct sparc64_dump_reg *vm_regions; }; -void -_kvm_freevtop(kvm_t *kd) +static int +_sparc64_probe(kvm_t *kd) { - if (kd->vmst != 0) { - free(kd->vmst->vm_regions); - free(kd->vmst); - } + + return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_SPARCV9)); +} + +static void +_sparc64_freevtop(kvm_t *kd) +{ + + free(kd->vmst->vm_regions); + free(kd->vmst); + kd->vmst = NULL; } static int -_kvm_read_phys(kvm_t *kd, off_t pos, void *buf, size_t size) +_sparc64_read_phys(kvm_t *kd, off_t pos, void *buf, size_t size) { /* XXX This has to be a raw file read, kvm_read is virtual. */ - if (lseek(kd->pmfd, pos, SEEK_SET) == -1) { - _kvm_syserr(kd, kd->program, "_kvm_read_phys: lseek"); - return (0); - } - if (read(kd->pmfd, buf, size) != (ssize_t)size) { - _kvm_syserr(kd, kd->program, "_kvm_read_phys: read"); + if (pread(kd->pmfd, buf, size, pos) != (ssize_t)size) { + _kvm_syserr(kd, kd->program, "_sparc64_read_phys: pread"); return (0); } return (1); } static int -_kvm_reg_cmp(const void *a, const void *b) +_sparc64_reg_cmp(const void *a, const void *b) { const struct sparc64_dump_reg *ra, *rb; @@ -122,14 +111,14 @@ _kvm_reg_cmp(const void *a, const void *b) #define KVM_OFF_NOTFOUND 0 static off_t -_kvm_find_off(struct vmstate *vm, vm_offset_t pa, vm_size_t size) +_sparc64_find_off(struct vmstate *vm, uint64_t pa, uint64_t size) { struct sparc64_dump_reg *reg, key; vm_offset_t o; key.dr_pa = pa; reg = bsearch(&key, vm->vm_regions, vm->vm_nregions, - sizeof(*vm->vm_regions), _kvm_reg_cmp); + sizeof(*vm->vm_regions), _sparc64_reg_cmp); if (reg == NULL) return (KVM_OFF_NOTFOUND); o = pa - reg->dr_pa; @@ -138,14 +127,15 @@ _kvm_find_off(struct vmstate *vm, vm_offset_t pa, vm_size_t size) return (reg->dr_offs + o); } -int -_kvm_initvtop(kvm_t *kd) +static int +_sparc64_initvtop(kvm_t *kd) { struct sparc64_dump_hdr hdr; struct sparc64_dump_reg *regs; struct vmstate *vm; size_t regsz; - vm_offset_t pa; + uint64_t pa; + int i; vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); if (vm == NULL) { @@ -154,8 +144,13 @@ _kvm_initvtop(kvm_t *kd) } kd->vmst = vm; - if (!_kvm_read_phys(kd, 0, &hdr, sizeof(hdr))) + if (!_sparc64_read_phys(kd, 0, &hdr, sizeof(hdr))) goto fail_vm; + hdr.dh_hdr_size = be64toh(hdr.dh_hdr_size); + hdr.dh_tsb_pa = be64toh(hdr.dh_tsb_pa); + hdr.dh_tsb_size = be64toh(hdr.dh_tsb_size); + hdr.dh_tsb_mask = be64toh(hdr.dh_tsb_mask); + hdr.dh_nregions = be32toh(hdr.dh_nregions); pa = hdr.dh_tsb_pa; regsz = hdr.dh_nregions * sizeof(*regs); @@ -164,14 +159,19 @@ _kvm_initvtop(kvm_t *kd) _kvm_err(kd, kd->program, "cannot allocate regions"); goto fail_vm; } - if (!_kvm_read_phys(kd, sizeof(hdr), regs, regsz)) + if (!_sparc64_read_phys(kd, sizeof(hdr), regs, regsz)) goto fail_regs; - qsort(regs, hdr.dh_nregions, sizeof(*regs), _kvm_reg_cmp); + for (i = 0; i < hdr.dh_nregions; i++) { + regs[i].dr_pa = be64toh(regs[i].dr_pa); + regs[i].dr_size = be64toh(regs[i].dr_size); + regs[i].dr_offs = be64toh(regs[i].dr_offs); + } + qsort(regs, hdr.dh_nregions, sizeof(*regs), _sparc64_reg_cmp); vm->vm_tsb_mask = hdr.dh_tsb_mask; vm->vm_regions = regs; vm->vm_nregions = hdr.dh_nregions; - vm->vm_tsb_off = _kvm_find_off(vm, hdr.dh_tsb_pa, hdr.dh_tsb_size); + vm->vm_tsb_off = _sparc64_find_off(vm, hdr.dh_tsb_pa, hdr.dh_tsb_size); if (vm->vm_tsb_off == KVM_OFF_NOTFOUND) { _kvm_err(kd, kd->program, "tsb not found in dump"); goto fail_regs; @@ -185,37 +185,60 @@ fail_vm: return (-1); } -int -_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) +static int +_sparc64_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) { - struct tte tte; + struct sparc64_tte tte; off_t tte_off; - u_long vpn; + kvaddr_t vpn; off_t pa_off; - u_long pg_off; + kvaddr_t pg_off; int rest; - pg_off = va & PAGE_MASK; - if (va >= VM_MIN_DIRECT_ADDRESS) - pa_off = TLB_DIRECT_TO_PHYS(va) & ~PAGE_MASK; + pg_off = va & SPARC64_PAGE_MASK; + if (va >= SPARC64_MIN_DIRECT_ADDRESS) + pa_off = SPARC64_DIRECT_TO_PHYS(va) & ~SPARC64_PAGE_MASK; else { - vpn = btop(va); + vpn = va >> SPARC64_PAGE_SHIFT; tte_off = kd->vmst->vm_tsb_off + - ((vpn & kd->vmst->vm_tsb_mask) << TTE_SHIFT); - if (!_kvm_read_phys(kd, tte_off, &tte, sizeof(tte))) + ((vpn & kd->vmst->vm_tsb_mask) << SPARC64_TTE_SHIFT); + if (!_sparc64_read_phys(kd, tte_off, &tte, sizeof(tte))) goto invalid; - if (!tte_match(&tte, va)) + tte.tte_vpn = be64toh(tte.tte_vpn); + tte.tte_data = be64toh(tte.tte_data); + if (!sparc64_tte_match(&tte, va)) goto invalid; - pa_off = TTE_GET_PA(&tte); + pa_off = SPARC64_TTE_GET_PA(&tte); } - rest = PAGE_SIZE - pg_off; - pa_off = _kvm_find_off(kd->vmst, pa_off, rest); + rest = SPARC64_PAGE_SIZE - pg_off; + pa_off = _sparc64_find_off(kd->vmst, pa_off, rest); if (pa_off == KVM_OFF_NOTFOUND) goto invalid; *pa = pa_off + pg_off; return (rest); invalid: - _kvm_err(kd, 0, "invalid address (%lx)", va); + _kvm_err(kd, 0, "invalid address (%jx)", (uintmax_t)va); return (0); } + +static int +_sparc64_native(kvm_t *kd) +{ + +#ifdef __sparc64__ + return (1); +#else + return (0); +#endif +} + +struct kvm_arch kvm_sparc64 = { + .ka_probe = _sparc64_probe, + .ka_initvtop = _sparc64_initvtop, + .ka_freevtop = _sparc64_freevtop, + .ka_kvatop = _sparc64_kvatop, + .ka_native = _sparc64_native, +}; + +KVM_ARCH(kvm_sparc64); |