Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/aarch64 implement dumpsys() and friends for arm64.
details: https://anonhg.NetBSD.org/src/rev/ca831f176174
branches: trunk
changeset: 994462:ca831f176174
user: mrg <mrg%NetBSD.org@localhost>
date: Fri Nov 09 04:05:27 2018 +0000
description:
implement dumpsys() and friends for arm64.
this is almost a direct copy of the arm code, which is simply
as the basic structures about physical memory are the same
between arm and arm64. the main change i made was to use
the direct map instead of a virtual dump page that is remapped
to whatever physical page is being dumped.
i also changed the existing cpu_kcore_hdr_t to include the
missing number of ram segments.
note that this is not a complete solution for crash dumps yet,
as the libkvm code needs some work. i'm fairly positive that
this side is correct, as i can see the data i expect to see,
but libkvm's _kvm_kvtop() function returns garbage so far.
there is no "minidump" support here yet, ala amd64, but we
probably want it eventually.
ok skrll@.
diffstat:
sys/arch/aarch64/aarch64/aarch64_machdep.c | 237 ++++++++++++++++++++++++++++-
sys/arch/aarch64/aarch64/aarch64_reboot.c | 6 +-
sys/arch/aarch64/include/kcore.h | 3 +-
3 files changed, 239 insertions(+), 7 deletions(-)
diffs (truncated from 327 to 300 lines):
diff -r 44ffed2a6752 -r ca831f176174 sys/arch/aarch64/aarch64/aarch64_machdep.c
--- a/sys/arch/aarch64/aarch64/aarch64_machdep.c Fri Nov 09 02:11:04 2018 +0000
+++ b/sys/arch/aarch64/aarch64/aarch64_machdep.c Fri Nov 09 04:05:27 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: aarch64_machdep.c,v 1.18 2018/11/01 20:34:49 maxv Exp $ */
+/* $NetBSD: aarch64_machdep.c,v 1.19 2018/11/09 04:05:27 mrg Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: aarch64_machdep.c,v 1.18 2018/11/01 20:34:49 maxv Exp $");
+__KERNEL_RCSID(1, "$NetBSD: aarch64_machdep.c,v 1.19 2018/11/09 04:05:27 mrg Exp $");
#include "opt_arm_debug.h"
#include "opt_ddb.h"
@@ -47,6 +47,9 @@
#include <sys/msgbuf.h>
#include <sys/sysctl.h>
#include <sys/reboot.h>
+#include <sys/kcore.h>
+#include <sys/core.h>
+#include <sys/conf.h>
#include <sys/asan.h>
#include <dev/mm.h>
@@ -65,6 +68,7 @@
#include <aarch64/pmap.h>
#include <aarch64/pte.h>
#include <aarch64/vmparam.h>
+#include <aarch64/kcore.h>
#include <arch/evbarm/fdt/platform.h>
#include <arm/fdt/arm_fdtvar.h>
@@ -107,6 +111,15 @@
long kernend_extra; /* extra memory allocated from round_page(_end[]) */
+/* dump configuration */
+int cpu_dump(void);
+int cpu_dumpsize(void);
+u_long cpu_dump_mempagecnt(void);
+
+uint32_t dumpmag = 0x8fca0101; /* magic number for savecore */
+int dumpsize = 0; /* also for savecore */
+long dumplo = 0;
+
void
cpu_kernel_vm_init(uint64_t memory_start, uint64_t memory_size)
{
@@ -646,7 +659,227 @@
banner();
}
+/*
+ * cpu_dump: dump the machine-dependent kernel core dump headers.
+ */
+int
+cpu_dump(void)
+{
+ int (*dump)(dev_t, daddr_t, void *, size_t);
+ char bf[dbtob(1)];
+ kcore_seg_t *segp;
+ cpu_kcore_hdr_t *cpuhdrp;
+ phys_ram_seg_t *memsegp;
+ const struct bdevsw *bdev;
+ int i;
+
+ bdev = bdevsw_lookup(dumpdev);
+ if (bdev == NULL)
+ return (ENXIO);
+ dump = bdev->d_dump;
+
+ memset(bf, 0, sizeof bf);
+ segp = (kcore_seg_t *)bf;
+ cpuhdrp = (cpu_kcore_hdr_t *)&bf[ALIGN(sizeof(*segp))];
+ memsegp = &cpuhdrp->kh_ramsegs[0];
+
+ /*
+ * Generate a segment header.
+ */
+ CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
+ segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
+
+ /*
+ * Add the machine-dependent header info.
+ */
+ cpuhdrp->kh_tcr1 = reg_tcr_el1_read();
+ cpuhdrp->kh_ttbr1 = reg_ttbr1_el1_read();
+ cpuhdrp->kh_nramsegs = bootconfig.dramblocks;
+
+ /*
+ * Fill in the memory segment descriptors.
+ */
+ for (i = 0; i < bootconfig.dramblocks; i++) {
+ memsegp[i].start = bootconfig.dram[i].address;
+ memsegp[i].size = bootconfig.dram[i].pages * PAGE_SIZE;
+ }
+
+ return (dump(dumpdev, dumplo, bf, dbtob(1)));
+}
+
+void
+dumpsys(void)
+{
+ const struct bdevsw *bdev;
+ daddr_t blkno;
+ int psize;
+ int error;
+ paddr_t addr = 0;
+ int block;
+ psize_t len;
+ vaddr_t dumpspace;
+
+ /* flush everything out of caches */
+ cpu_dcache_wbinv_all();
+
+ if (dumpdev == NODEV)
+ return;
+ if (dumpsize == 0) {
+ cpu_dumpconf();
+ }
+ if (dumplo <= 0 || dumpsize == 0) {
+ printf("\ndump to dev %u,%u not possible\n",
+ major(dumpdev), minor(dumpdev));
+ delay(5000000);
+ return;
+ }
+ printf("\ndumping to dev %u,%u offset %ld\n",
+ major(dumpdev), minor(dumpdev), dumplo);
+
+
+ bdev = bdevsw_lookup(dumpdev);
+ if (bdev == NULL || bdev->d_psize == NULL)
+ return;
+ psize = bdev_size(dumpdev);
+ printf("dump ");
+ if (psize == -1) {
+ printf("area unavailable\n");
+ return;
+ }
+
+ if ((error = cpu_dump()) != 0)
+ goto err;
+
+ blkno = dumplo + cpu_dumpsize();
+ error = 0;
+ len = 0;
+
+ for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) {
+ addr = bootconfig.dram[block].address;
+ for (; addr < (bootconfig.dram[block].address
+ + (bootconfig.dram[block].pages * PAGE_SIZE));
+ addr += PAGE_SIZE) {
+ if ((len % (1024*1024)) == 0)
+ printf("%lu ", len / (1024*1024));
+
+ if (!mm_md_direct_mapped_phys(addr, &dumpspace)) {
+ error = ENOMEM;
+ goto err;
+ }
+ error = (*bdev->d_dump)(dumpdev,
+ blkno, (void *) dumpspace, PAGE_SIZE);
+
+ if (error)
+ goto err;
+ blkno += btodb(PAGE_SIZE);
+ len += PAGE_SIZE;
+ }
+ }
+err:
+ switch (error) {
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ case EINTR:
+ printf("aborted from console\n");
+ break;
+
+ case ENOMEM:
+ printf("no direct map for %lx\n", addr);
+ break;
+
+ case 0:
+ printf("succeeded\n");
+ break;
+
+ default:
+ printf("error %d\n", error);
+ break;
+ }
+ printf("\n\n");
+ delay(5000000);
+}
+
+/*
+ * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
+ */
+int
+cpu_dumpsize(void)
+{
+ int size;
+
+ size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
+ ALIGN(bootconfig.dramblocks * sizeof(phys_ram_seg_t));
+ if (roundup(size, dbtob(1)) != dbtob(1))
+ return -1;
+
+ return (1);
+}
+
+/*
+ * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
+ */
+u_long
+cpu_dump_mempagecnt(void)
+{
+ u_long i, n;
+
+ n = 0;
+ for (i = 0; i < bootconfig.dramblocks; i++) {
+ n += bootconfig.dram[i].pages;
+ }
+
+ return (n);
+}
+
+/*
+ * This is called by main to set dumplo and dumpsize.
+ * Dumps always skip the first PAGE_SIZE of disk space
+ * in case there might be a disk label stored there.
+ * If there is extra space, put dump at the end to
+ * reduce the chance that swapping trashes it.
+ */
+
void
cpu_dumpconf(void)
{
+ u_long nblks, dumpblks; /* size of dump area */
+
+ if (dumpdev == NODEV)
+ return;
+ nblks = bdev_size(dumpdev);
+ if (nblks <= ctod(1))
+ return;
+
+ dumpblks = cpu_dumpsize();
+ if (dumpblks < 0)
+ goto bad;
+ dumpblks += ctod(cpu_dump_mempagecnt());
+
+ /* If dump won't fit (incl. room for possible label), punt. */
+ if (dumpblks > (nblks - ctod(1)))
+ goto bad;
+
+ /* Put dump at end of partition */
+ dumplo = nblks - dumpblks;
+
+ /* dumpsize is in page units, and doesn't include headers. */
+ dumpsize = cpu_dump_mempagecnt();
+ return;
+
+ bad:
+ dumpsize = 0;
}
diff -r 44ffed2a6752 -r ca831f176174 sys/arch/aarch64/aarch64/aarch64_reboot.c
--- a/sys/arch/aarch64/aarch64/aarch64_reboot.c Fri Nov 09 02:11:04 2018 +0000
+++ b/sys/arch/aarch64/aarch64/aarch64_reboot.c Fri Nov 09 04:05:27 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: aarch64_reboot.c,v 1.2 2018/05/31 23:22:50 mrg Exp $ */
+/* $NetBSD: aarch64_reboot.c,v 1.3 2018/11/09 04:05:27 mrg Exp $ */
/*
* Copyright (c) 2002, 2003, 2005 Genetec Corporation. All rights reserved.
@@ -122,7 +122,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: aarch64_reboot.c,v 1.2 2018/05/31 23:22:50 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: aarch64_reboot.c,v 1.3 2018/11/09 04:05:27 mrg Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -236,11 +236,9 @@
/* Say NO to interrupts for the duration of the dump */
Home |
Main Index |
Thread Index |
Old Index