#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/exec.h>
#include <sys/core.h>
#include <sys/kcore.h>
#include <uvm/uvm_extern.h>
#include <machine/bootconfig.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
#include <arm/kcore.h>
#include <arm/machdep.h>
extern dev_t dumpdev;
u_int32_t dumpmag = 0x8fca0101;
int dumpsize = 0;
long dumplo = 0;
cpu_kcore_hdr_t cpu_kcore_hdr;
struct pcb dumppcb;
void dumpconf(void);
void
dumpconf(void)
{
int nblks, block;
if (dumpdev == NODEV ||
(nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
return;
if (nblks <= ctod(1))
return;
dumpsize = physmem;
if (dumplo < ctod(1))
dumplo = ctod(1);
if (dumpsize + 1 > dtoc(nblks - dumplo))
dumpsize = dtoc(nblks - dumplo) - 1;
if (dumplo < nblks - ctod(dumpsize) - 1)
dumplo = nblks - ctod(dumpsize) - 1;
for (block = 0; block < bootconfig.dramblocks; block++) {
cpu_kcore_hdr.ram_segs[block].start =
bootconfig.dram[block].address;
cpu_kcore_hdr.ram_segs[block].size =
ptoa(bootconfig.dram[block].pages);
}
}
extern char *memhook;
void
dumpsys(void)
{
const struct bdevsw *bdev;
daddr_t blkno;
int psize;
int error;
int addr;
int block;
int len;
vaddr_t dumpspace;
kcore_seg_t *kseg_p;
cpu_kcore_hdr_t *chdr_p;
char dump_hdr[dbtob(1)];
savectx(&dumppcb);
cpu_dcache_wbinv_all();
cpu_sdcache_wbinv_all();
if (dumpdev == NODEV)
return;
if (dumpsize == 0) {
dumpconf();
if (dumpsize == 0)
return;
}
if (dumplo <= 0) {
printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
minor(dumpdev));
return;
}
printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
minor(dumpdev), dumplo);
blkno = dumplo;
dumpspace = (vaddr_t) memhook;
bdev = bdevsw_lookup(dumpdev);
if (bdev == NULL || bdev->d_psize == NULL)
return;
psize = (*bdev->d_psize)(dumpdev);
printf("dump ");
if (psize == -1) {
printf("area unavailable\n");
return;
}
kseg_p = (kcore_seg_t *)dump_hdr;
chdr_p = (cpu_kcore_hdr_t *)&dump_hdr[ALIGN(sizeof(*kseg_p))];
bzero(dump_hdr, sizeof(dump_hdr));
CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
kseg_p->c_size = sizeof(dump_hdr) - ALIGN(sizeof(*kseg_p));
*chdr_p = cpu_kcore_hdr;
error = (*bdev->d_dump)(dumpdev, blkno++, (caddr_t)dump_hdr,
sizeof(dump_hdr));
if (error != 0)
goto abort;
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("%d ", len / (1024*1024));
pmap_kenter_pa(dumpspace, addr, PROT_READ);
pmap_update(pmap_kernel());
error = (*bdev->d_dump)(dumpdev,
blkno, (caddr_t) dumpspace, PAGE_SIZE);
pmap_kremove(dumpspace, PAGE_SIZE);
pmap_update(pmap_kernel());
if (error) break;
blkno += btodb(PAGE_SIZE);
len += PAGE_SIZE;
}
}
abort:
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;
default:
printf("succeeded\n");
break;
}
printf("\n\n");
delay(1000000);
}