Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mips/minidump_machdep.c
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/vmparam.h> | #include <machine/vmparam.h> | ||||
#include <machine/minidump.h> | #include <machine/minidump.h> | ||||
#include <machine/cache.h> | #include <machine/cache.h> | ||||
CTASSERT(sizeof(struct kerneldumpheader) == 512); | CTASSERT(sizeof(struct kerneldumpheader) == 512); | ||||
/* | |||||
* Don't touch the first SIZEOF_METADATA bytes on the dump device. This | |||||
* is to protect us from metadata and to protect metadata from us. | |||||
*/ | |||||
#define SIZEOF_METADATA (64*1024) | |||||
uint32_t *vm_page_dump; | uint32_t *vm_page_dump; | ||||
int vm_page_dump_size; | int vm_page_dump_size; | ||||
static struct kerneldumpheader kdh; | static struct kerneldumpheader kdh; | ||||
static off_t dumplo; | static off_t dumplo; | ||||
static off_t origdumplo; | |||||
/* Handle chunked writes. */ | /* Handle chunked writes. */ | ||||
static uint64_t counter, progress, dumpsize; | static uint64_t counter, progress, dumpsize; | ||||
/* Just auxiliary bufffer */ | /* Just auxiliary bufffer */ | ||||
static char tmpbuffer[PAGE_SIZE]; | static char tmpbuffer[PAGE_SIZE]; | ||||
extern pd_entry_t *kernel_segmap; | extern pd_entry_t *kernel_segmap; | ||||
▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | for (pa = 0; pa < phys_avail[0]; pa += PAGE_SIZE) { | ||||
if (is_dumpable(pa)) | if (is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
} | } | ||||
/* Calculate dump size. */ | /* Calculate dump size. */ | ||||
dumpsize = ptesize; | dumpsize = ptesize; | ||||
dumpsize += round_page(msgbufp->msg_size); | dumpsize += round_page(msgbufp->msg_size); | ||||
dumpsize += round_page(vm_page_dump_size); | dumpsize += round_page(vm_page_dump_size); | ||||
for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { | for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { | ||||
bits = vm_page_dump[i]; | bits = vm_page_dump[i]; | ||||
while (bits) { | while (bits) { | ||||
bit = ffs(bits) - 1; | bit = ffs(bits) - 1; | ||||
pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + | pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + | ||||
bit) * PAGE_SIZE; | bit) * PAGE_SIZE; | ||||
/* Clear out undumpable pages now if needed */ | /* Clear out undumpable pages now if needed */ | ||||
if (is_dumpable(pa)) | if (is_dumpable(pa)) | ||||
dumpsize += PAGE_SIZE; | dumpsize += PAGE_SIZE; | ||||
else | else | ||||
dump_drop_page(pa); | dump_drop_page(pa); | ||||
bits &= ~(1ul << bit); | bits &= ~(1ul << bit); | ||||
} | } | ||||
} | } | ||||
dumpsize += PAGE_SIZE; | dumpsize += PAGE_SIZE; | ||||
/* Determine dump offset on device. */ | |||||
if (di->mediasize < SIZEOF_METADATA + dumpsize + di->blocksize * 2 + | |||||
kerneldumpcrypto_dumpkeysize(di->kdc)) { | |||||
error = ENOSPC; | |||||
goto fail; | |||||
} | |||||
origdumplo = dumplo = di->mediaoffset + di->mediasize - dumpsize; | |||||
dumplo -= di->blocksize * 2; | |||||
dumplo -= kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
progress = dumpsize; | progress = dumpsize; | ||||
/* Initialize kernel dump crypto. */ | |||||
error = kerneldumpcrypto_init(di->kdc); | |||||
if (error) | |||||
goto fail; | |||||
/* Initialize mdhdr */ | /* Initialize mdhdr */ | ||||
bzero(&mdhdr, sizeof(mdhdr)); | bzero(&mdhdr, sizeof(mdhdr)); | ||||
strcpy(mdhdr.magic, MINIDUMP_MAGIC); | strcpy(mdhdr.magic, MINIDUMP_MAGIC); | ||||
mdhdr.version = MINIDUMP_VERSION; | mdhdr.version = MINIDUMP_VERSION; | ||||
mdhdr.msgbufsize = msgbufp->msg_size; | mdhdr.msgbufsize = msgbufp->msg_size; | ||||
mdhdr.bitmapsize = vm_page_dump_size; | mdhdr.bitmapsize = vm_page_dump_size; | ||||
mdhdr.ptesize = ptesize; | mdhdr.ptesize = ptesize; | ||||
mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; | mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; | ||||
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_MIPS_VERSION, dumpsize, | mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_MIPS_VERSION, dumpsize, | ||||
kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); | kerneldumpcrypto_dumpkeysize(di->kdc), di->blocksize); | ||||
printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, | printf("Dumping %llu out of %ju MB:", (long long)dumpsize >> 20, | ||||
ptoa((uintmax_t)physmem) / 1048576); | ptoa((uintmax_t)physmem) / 1048576); | ||||
/* Dump leader */ | error = dump_start(di, &kdh, &dumplo); | ||||
error = dump_write_header(di, &kdh, 0, dumplo); | if (error != 0) | ||||
if (error) | |||||
goto fail; | goto fail; | ||||
dumplo += di->blocksize; | |||||
/* Dump key */ | |||||
error = dump_write_key(di, 0, dumplo); | |||||
if (error) | |||||
goto fail; | |||||
dumplo += kerneldumpcrypto_dumpkeysize(di->kdc); | |||||
/* Dump my header */ | /* Dump my header */ | ||||
bzero(tmpbuffer, sizeof(tmpbuffer)); | bzero(tmpbuffer, sizeof(tmpbuffer)); | ||||
bcopy(&mdhdr, tmpbuffer, sizeof(mdhdr)); | bcopy(&mdhdr, tmpbuffer, sizeof(mdhdr)); | ||||
error = write_buffer(di, tmpbuffer, PAGE_SIZE); | error = write_buffer(di, tmpbuffer, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump msgbuf up front */ | /* Dump msgbuf up front */ | ||||
Show All 10 Lines | minidumpsys(struct dumperinfo *di) | ||||
/* Dump kernel page table pages */ | /* Dump kernel page table pages */ | ||||
for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += NBPDR) { | for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += NBPDR) { | ||||
pte = pmap_pte(kernel_pmap, va); | pte = pmap_pte(kernel_pmap, va); | ||||
KASSERT(pte != NULL, ("pte for %jx is NULL", (uintmax_t)va)); | KASSERT(pte != NULL, ("pte for %jx is NULL", (uintmax_t)va)); | ||||
if (!count) { | if (!count) { | ||||
prev_pte = (vm_offset_t)pte; | prev_pte = (vm_offset_t)pte; | ||||
count++; | count++; | ||||
} | } else { | ||||
else { | |||||
if ((vm_offset_t)pte == (prev_pte + count * PAGE_SIZE)) | if ((vm_offset_t)pte == (prev_pte + count * PAGE_SIZE)) | ||||
count++; | count++; | ||||
else { | else { | ||||
error = write_buffer(di, (char*)prev_pte, | error = write_buffer(di, (char*)prev_pte, | ||||
count * PAGE_SIZE); | count * PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
count = 1; | count = 1; | ||||
Show All 21 Lines | while (bits) { | ||||
error = write_buffer(di, dump_va, PAGE_SIZE); | error = write_buffer(di, dump_va, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
pmap_kenter_temporary_free(pa); | pmap_kenter_temporary_free(pa); | ||||
bits &= ~(1ul << bit); | bits &= ~(1ul << bit); | ||||
} | } | ||||
} | } | ||||
/* Dump trailer */ | error = dump_finish(di, &kdh, dumplo); | ||||
error = dump_write_header(di, &kdh, 0, dumplo); | if (error != 0) | ||||
if (error) | |||||
goto fail; | goto fail; | ||||
dumplo += di->blocksize; | |||||
/* Signal completion, signoff and exit stage left. */ | |||||
dump_write(di, NULL, 0, 0, 0); | |||||
printf("\nDump complete\n"); | printf("\nDump complete\n"); | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
if (error < 0) | if (error < 0) | ||||
error = -error; | error = -error; | ||||
if (error == ECANCELED) | if (error == ECANCELED) | ||||
printf("\nDump aborted\n"); | printf("\nDump aborted\n"); | ||||
else if (error == ENOSPC) | else if (error == E2BIG) | ||||
printf("\nDump failed. Partition too small.\n"); | printf("\nDump failed. Partition too small.\n"); | ||||
else | else | ||||
printf("\n** DUMP FAILED (ERROR %d) **\n", error); | printf("\n** DUMP FAILED (ERROR %d) **\n", error); | ||||
return (error); | return (error); | ||||
} | } |