summaryrefslogtreecommitdiffstats
path: root/lib/libkvm/kvm_sparc64.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkvm/kvm_sparc64.c')
-rw-r--r--lib/libkvm/kvm_sparc64.c141
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);
OpenPOWER on IntegriCloud