Adapt to handle the new sparc64 core dump format correctly.
Reviewed by: jake
This commit is contained in:
parent
5c94fe601c
commit
2e1d70d9a2
@ -62,6 +62,7 @@ static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <machine/kerneldump.h>
|
||||
#include <machine/tte.h>
|
||||
#include <machine/tsb.h>
|
||||
|
||||
@ -75,23 +76,78 @@ static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif
|
||||
|
||||
struct vmstate {
|
||||
vm_offset_t vm_tsb;
|
||||
off_t vm_tsb_off;
|
||||
vm_size_t vm_tsb_mask;
|
||||
int vm_nregions;
|
||||
struct sparc64_dump_reg *vm_regions;
|
||||
};
|
||||
|
||||
void
|
||||
_kvm_freevtop(kvm_t *kd)
|
||||
{
|
||||
if (kd->vmst != 0) {
|
||||
free(kd->vmst->vm_regions);
|
||||
free(kd->vmst);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_kvm_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) != size) {
|
||||
_kvm_syserr(kd, kd->program, "_kvm_read_phys: read");
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
_kvm_reg_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct sparc64_dump_reg *ra, *rb;
|
||||
|
||||
ra = a;
|
||||
rb = b;
|
||||
if (ra->dr_pa < rb->dr_pa)
|
||||
return (-1);
|
||||
else if (ra->dr_pa >= rb->dr_pa + rb->dr_size)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define KVM_OFF_NOTFOUND 0
|
||||
|
||||
static off_t
|
||||
_kvm_find_off(struct vmstate *vm, vm_offset_t pa, vm_size_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);
|
||||
if (reg == NULL)
|
||||
return (KVM_OFF_NOTFOUND);
|
||||
o = pa - reg->dr_pa;
|
||||
if (o + size > reg->dr_size)
|
||||
return (KVM_OFF_NOTFOUND);
|
||||
return (reg->dr_offs + o);
|
||||
}
|
||||
|
||||
int
|
||||
_kvm_initvtop(kvm_t *kd)
|
||||
{
|
||||
struct nlist nlist[2];
|
||||
struct sparc64_dump_hdr hdr;
|
||||
struct sparc64_dump_reg *regs;
|
||||
struct vmstate *vm;
|
||||
size_t regsz;
|
||||
vm_offset_t pa;
|
||||
vm_size_t mask;
|
||||
|
||||
@ -101,25 +157,36 @@ _kvm_initvtop(kvm_t *kd)
|
||||
return (-1);
|
||||
}
|
||||
kd->vmst = vm;
|
||||
vm->vm_tsb = 0;
|
||||
|
||||
nlist[0].n_name = "tsb_kernel_phys";
|
||||
nlist[1].n_name = "tsb_kernel_mask";
|
||||
nlist[2].n_name = 0;
|
||||
if (!_kvm_read_phys(kd, 0, &hdr, sizeof(hdr)))
|
||||
goto fail_vm;
|
||||
pa = hdr.dh_tsb_pa;
|
||||
|
||||
if (kvm_nlist(kd, nlist) != 0) {
|
||||
_kvm_err(kd, kd->program, "bad namelist");
|
||||
return (-1);
|
||||
regsz = hdr.dh_nregions * sizeof(*regs);
|
||||
regs = _kvm_malloc(kd, regsz);
|
||||
if (regs == NULL) {
|
||||
_kvm_err(kd, kd->program, "cannot allocate regions");
|
||||
goto fail_vm;
|
||||
}
|
||||
if (kvm_read(kd, nlist[0].n_value, &pa, sizeof(pa)) != sizeof(pa) ||
|
||||
kvm_read(kd, nlist[1].n_value, &mask, sizeof(mask)) !=
|
||||
sizeof(mask)) {
|
||||
_kvm_err(kd, kd->program, "cannot read tsb_kernel_phys");
|
||||
return (-1);
|
||||
if (!_kvm_read_phys(kd, sizeof(hdr), regs, regsz))
|
||||
goto fail_regs;
|
||||
qsort(regs, hdr.dh_nregions, sizeof(*regs), _kvm_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);
|
||||
if (vm->vm_tsb_off == KVM_OFF_NOTFOUND) {
|
||||
_kvm_err(kd, kd->program, "tsb not found in dump");
|
||||
goto fail_regs;
|
||||
}
|
||||
vm->vm_tsb = pa;
|
||||
vm->vm_tsb_mask = mask;
|
||||
return (0);
|
||||
|
||||
fail_regs:
|
||||
free(regs);
|
||||
fail_vm:
|
||||
free(vm);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -127,29 +194,25 @@ _kvm_kvatop(kvm_t *kd, u_long va, u_long *pa)
|
||||
{
|
||||
struct vmstate *vm;
|
||||
struct tte tte;
|
||||
u_long offset;
|
||||
u_long tte_pa;
|
||||
u_long vpn;
|
||||
off_t tte_off, pa_off;
|
||||
u_long pg_off, vpn;
|
||||
int rest;
|
||||
|
||||
vpn = btop(va);
|
||||
offset = va & PAGE_MASK;
|
||||
tte_pa = kd->vmst->vm_tsb +
|
||||
pg_off = va & PAGE_MASK;
|
||||
tte_off = kd->vmst->vm_tsb_off +
|
||||
((vpn & kd->vmst->vm_tsb_mask) << TTE_SHIFT);
|
||||
|
||||
/* XXX This has to be a physical address read, kvm_read is virtual */
|
||||
if (lseek(kd->pmfd, tte_pa, 0) == -1) {
|
||||
_kvm_syserr(kd, kd->program, "_kvm_vatop: lseek");
|
||||
if (!_kvm_read_phys(kd, tte_off, &tte, sizeof(tte)))
|
||||
goto invalid;
|
||||
}
|
||||
if (read(kd->pmfd, &tte, sizeof(tte)) != sizeof(tte)) {
|
||||
_kvm_syserr(kd, kd->program, "_kvm_vatop: read");
|
||||
goto invalid;
|
||||
}
|
||||
if (!tte_match(&tte, va))
|
||||
goto invalid;
|
||||
|
||||
*pa = TTE_GET_PA(&tte) + offset;
|
||||
return (PAGE_SIZE - offset);
|
||||
rest = PAGE_SIZE - pg_off;
|
||||
pa_off = _kvm_find_off(kd->vmst, TTE_GET_PA(&tte), rest);
|
||||
if (pa_off == KVM_OFF_NOTFOUND)
|
||||
goto invalid;
|
||||
*pa = pa_off + pg_off;
|
||||
return (rest);
|
||||
|
||||
invalid:
|
||||
_kvm_err(kd, 0, "invalid address (%x)", va);
|
||||
|
Loading…
x
Reference in New Issue
Block a user