Index: sys/arch/aarch64/aarch64/aarch64_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/aarch64/aarch64/aarch64_machdep.c,v retrieving revision 1.18 diff -p -u -r1.18 aarch64_machdep.c --- sys/arch/aarch64/aarch64/aarch64_machdep.c 1 Nov 2018 20:34:49 -0000 1.18 +++ sys/arch/aarch64/aarch64/aarch64_machdep.c 8 Nov 2018 08:37:02 -0000 @@ -47,6 +47,9 @@ __KERNEL_RCSID(1, "$NetBSD: aarch64_mach #include #include #include +#include +#include +#include #include #include @@ -65,6 +68,7 @@ __KERNEL_RCSID(1, "$NetBSD: aarch64_mach #include #include #include +#include #include #include @@ -107,6 +111,15 @@ u_long kern_vtopdiff __attribute__((__se 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 @@ cpu_startup(void) 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; } Index: sys/arch/aarch64/aarch64/aarch64_reboot.c =================================================================== RCS file: /cvsroot/src/sys/arch/aarch64/aarch64/aarch64_reboot.c,v retrieving revision 1.2 diff -p -u -r1.2 aarch64_reboot.c --- sys/arch/aarch64/aarch64/aarch64_reboot.c 31 May 2018 23:22:50 -0000 1.2 +++ sys/arch/aarch64/aarch64/aarch64_reboot.c 8 Nov 2018 08:37:02 -0000 @@ -236,11 +236,9 @@ cpu_reboot(int howto, char *bootstr) /* Say NO to interrupts for the duration of the dump */ int s = splhigh(); -#if notyet /* XXX */ /* Do a dump if requested. */ if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) dumpsys(); -#endif splx(s); Index: sys/arch/aarch64/include/kcore.h =================================================================== RCS file: /cvsroot/src/sys/arch/aarch64/include/kcore.h,v retrieving revision 1.1 diff -p -u -r1.1 kcore.h --- sys/arch/aarch64/include/kcore.h 10 Aug 2014 05:47:38 -0000 1.1 +++ sys/arch/aarch64/include/kcore.h 8 Nov 2018 08:37:02 -0000 @@ -37,6 +37,7 @@ typedef struct cpu_kcore_hdr { uint64_t kh_tcr1; /* TCR for EL1 */ uint64_t kh_ttbr1; /* TTBR for EL1 */ + uint64_t kh_nramsegs; phys_ram_seg_t kh_ramsegs[0]; } cpu_kcore_hdr_t;