[PowerPC64LE] libkvm powerpc64le support.

* Add missing _kvm16toh() function.
* Teach libkvm about powerpc64le.

Sponsored by:	Tag1 Consulting, Inc.
This commit is contained in:
Brandon Bergren 2020-09-23 02:11:24 +00:00
parent b257310103
commit f4eb39ba6b
2 changed files with 61 additions and 19 deletions

View File

@ -53,22 +53,23 @@ struct vmstate {
}; };
static int static int
valid_elf_header(Elf64_Ehdr *eh) valid_elf_header(kvm_t *kd, Elf64_Ehdr *eh)
{ {
if (!IS_ELF(*eh)) if (!IS_ELF(*eh))
return (0); return (0);
if (eh->e_ident[EI_CLASS] != ELFCLASS64) if (eh->e_ident[EI_CLASS] != ELFCLASS64)
return (0); return (0);
if (eh->e_ident[EI_DATA] != ELFDATA2MSB) if (eh->e_ident[EI_DATA] != ELFDATA2MSB &&
eh->e_ident[EI_DATA] != ELFDATA2LSB)
return (0); return (0);
if (eh->e_ident[EI_VERSION] != EV_CURRENT) if (eh->e_ident[EI_VERSION] != EV_CURRENT)
return (0); return (0);
if (eh->e_ident[EI_OSABI] != ELFOSABI_STANDALONE) if (eh->e_ident[EI_OSABI] != ELFOSABI_STANDALONE)
return (0); return (0);
if (be16toh(eh->e_type) != ET_CORE) if (_kvm16toh(kd, eh->e_type) != ET_CORE)
return (0); return (0);
if (be16toh(eh->e_machine) != EM_PPC64) if (_kvm16toh(kd, eh->e_machine) != EM_PPC64)
return (0); return (0);
/* Can't think of anything else to check... */ /* Can't think of anything else to check... */
return (1); return (1);
@ -80,7 +81,8 @@ dump_header_size(struct kerneldumpheader *dh)
if (strcmp(dh->magic, KERNELDUMPMAGIC) != 0) if (strcmp(dh->magic, KERNELDUMPMAGIC) != 0)
return (0); return (0);
if (strcmp(dh->architecture, "powerpc64") != 0) if (strcmp(dh->architecture, "powerpc64") != 0 &&
strcmp(dh->architecture, "powerpc64le") != 0)
return (0); return (0);
/* That should do it... */ /* That should do it... */
return (sizeof(*dh)); return (sizeof(*dh));
@ -107,7 +109,7 @@ powerpc_maphdrs(kvm_t *kd)
} }
vm->dmphdrsz = 0; vm->dmphdrsz = 0;
vm->eh = vm->map; vm->eh = vm->map;
if (!valid_elf_header(vm->eh)) { if (!valid_elf_header(kd, vm->eh)) {
/* /*
* Hmmm, no ELF header. Maybe we still have a dump header. * Hmmm, no ELF header. Maybe we still have a dump header.
* This is normal when the core file wasn't created by * This is normal when the core file wasn't created by
@ -118,11 +120,11 @@ powerpc_maphdrs(kvm_t *kd)
if (vm->dmphdrsz == 0) if (vm->dmphdrsz == 0)
goto inval; goto inval;
vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz); vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz);
if (!valid_elf_header(vm->eh)) if (!valid_elf_header(kd, vm->eh))
goto inval; goto inval;
} }
mapsz = be16toh(vm->eh->e_phentsize) * be16toh(vm->eh->e_phnum) + mapsz = _kvm16toh(kd, vm->eh->e_phentsize) *
be64toh(vm->eh->e_phoff); _kvm16toh(kd, vm->eh->e_phnum) + _kvm64toh(kd, vm->eh->e_phoff);
munmap(vm->map, vm->mapsz); munmap(vm->map, vm->mapsz);
/* Map all headers. */ /* Map all headers. */
@ -134,7 +136,7 @@ powerpc_maphdrs(kvm_t *kd)
} }
vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz); vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz);
vm->ph = (void *)((uintptr_t)vm->eh + vm->ph = (void *)((uintptr_t)vm->eh +
(uintptr_t)be64toh(vm->eh->e_phoff)); (uintptr_t)_kvm64toh(kd, vm->eh->e_phoff));
return (0); return (0);
inval: inval:
@ -155,19 +157,21 @@ powerpc64_va2off(kvm_t *kd, kvaddr_t va, off_t *ofs)
int nph; int nph;
ph = vm->ph; ph = vm->ph;
nph = be16toh(vm->eh->e_phnum); nph = _kvm16toh(kd, vm->eh->e_phnum);
while (nph && (va < be64toh(ph->p_vaddr) || while (nph && (va < _kvm64toh(kd, ph->p_vaddr) ||
va >= be64toh(ph->p_vaddr) + be64toh(ph->p_memsz))) { va >= _kvm64toh(kd, ph->p_vaddr) + _kvm64toh(kd, ph->p_memsz))) {
nph--; nph--;
ph = (void *)((uintptr_t)ph + be16toh(vm->eh->e_phentsize)); ph = (void *)((uintptr_t)ph +
_kvm16toh(kd, vm->eh->e_phentsize));
} }
if (nph == 0) if (nph == 0)
return (0); return (0);
/* Segment found. Return file offset and range. */ /* Segment found. Return file offset and range. */
*ofs = vm->dmphdrsz + be64toh(ph->p_offset) + *ofs = vm->dmphdrsz + _kvm64toh(kd, ph->p_offset) +
(va - be64toh(ph->p_vaddr)); (va - _kvm64toh(kd, ph->p_vaddr));
return (be64toh(ph->p_memsz) - (va - be64toh(ph->p_vaddr))); return (_kvm64toh(kd, ph->p_memsz) -
(va - _kvm64toh(kd, ph->p_vaddr)));
} }
static void static void
@ -189,6 +193,14 @@ _powerpc64_probe(kvm_t *kd)
kd->nlehdr.e_ident[EI_DATA] == ELFDATA2MSB); kd->nlehdr.e_ident[EI_DATA] == ELFDATA2MSB);
} }
static int
_powerpc64le_probe(kvm_t *kd)
{
return (_kvm_probe_elf_kernel(kd, ELFCLASS64, EM_PPC64) &&
kd->nlehdr.e_ident[EI_DATA] == ELFDATA2LSB);
}
static int static int
_powerpc64_initvtop(kvm_t *kd) _powerpc64_initvtop(kvm_t *kd)
{ {
@ -209,7 +221,7 @@ _powerpc64_kvatop(kvm_t *kd, kvaddr_t va, off_t *ofs)
struct vmstate *vm; struct vmstate *vm;
vm = kd->vmst; vm = kd->vmst;
if (be64toh(vm->ph->p_paddr) == 0xffffffffffffffff) if (_kvm64toh(kd, vm->ph->p_paddr) == 0xffffffffffffffff)
return ((int)powerpc64_va2off(kd, va, ofs)); return ((int)powerpc64_va2off(kd, va, ofs));
_kvm_err(kd, kd->program, "Raw corefile not supported"); _kvm_err(kd, kd->program, "Raw corefile not supported");
@ -220,7 +232,18 @@ static int
_powerpc64_native(kvm_t *kd __unused) _powerpc64_native(kvm_t *kd __unused)
{ {
#ifdef __powerpc64__ #if defined(__powerpc64__) && BYTE_ORDER == BIG_ENDIAN
return (1);
#else
return (0);
#endif
}
static int
_powerpc64le_native(kvm_t *kd __unused)
{
#if defined(__powerpc64__) && BYTE_ORDER == LITTLE_ENDIAN
return (1); return (1);
#else #else
return (0); return (0);
@ -235,4 +258,13 @@ static struct kvm_arch kvm_powerpc64 = {
.ka_native = _powerpc64_native, .ka_native = _powerpc64_native,
}; };
static struct kvm_arch kvm_powerpc64le = {
.ka_probe = _powerpc64le_probe,
.ka_initvtop = _powerpc64_initvtop,
.ka_freevtop = _powerpc64_freevtop,
.ka_kvatop = _powerpc64_kvatop,
.ka_native = _powerpc64le_native,
};
KVM_ARCH(kvm_powerpc64); KVM_ARCH(kvm_powerpc64);
KVM_ARCH(kvm_powerpc64le);

View File

@ -134,6 +134,16 @@ struct kvm_bitmap {
/* /*
* Functions used internally by kvm, but across kvm modules. * Functions used internally by kvm, but across kvm modules.
*/ */
static inline uint16_t
_kvm16toh(kvm_t *kd, uint16_t val)
{
if (kd->nlehdr.e_ident[EI_DATA] == ELFDATA2LSB)
return (le16toh(val));
else
return (be16toh(val));
}
static inline uint32_t static inline uint32_t
_kvm32toh(kvm_t *kd, uint32_t val) _kvm32toh(kvm_t *kd, uint32_t val)
{ {