Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_dump.c
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/pcb.h> | #include <machine/pcb.h> | ||||
CTASSERT(sizeof(struct kerneldumpheader) == 512); | CTASSERT(sizeof(struct kerneldumpheader) == 512); | ||||
#define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) | #define MD_ALIGN(x) roundup2((off_t)(x), PAGE_SIZE) | ||||
off_t dumplo; | |||||
/* Handle buffered writes. */ | /* Handle buffered writes. */ | ||||
static size_t fragsz; | static size_t fragsz; | ||||
struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; | struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; | ||||
#if !defined(__powerpc__) && !defined(__sparc__) | #if !defined(__powerpc__) && !defined(__sparc__) | ||||
void | void | ||||
dumpsys_gen_pa_init(void) | dumpsys_gen_pa_init(void) | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | dumpsys_buf_seek(struct dumperinfo *di, size_t sz) | ||||
size_t nbytes; | size_t nbytes; | ||||
int error; | int error; | ||||
bzero(buf, sizeof(buf)); | bzero(buf, sizeof(buf)); | ||||
while (sz > 0) { | while (sz > 0) { | ||||
nbytes = MIN(sz, sizeof(buf)); | nbytes = MIN(sz, sizeof(buf)); | ||||
error = dump_write(di, buf, 0, dumplo, nbytes); | error = dump_append(di, buf, 0, nbytes); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
dumplo += nbytes; | |||||
sz -= nbytes; | sz -= nbytes; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz) | dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz) | ||||
{ | { | ||||
size_t len; | size_t len; | ||||
int error; | int error; | ||||
while (sz) { | while (sz) { | ||||
len = di->blocksize - fragsz; | len = di->blocksize - fragsz; | ||||
if (len > sz) | if (len > sz) | ||||
len = sz; | len = sz; | ||||
memcpy((char *)di->blockbuf + fragsz, ptr, len); | memcpy((char *)di->blockbuf + fragsz, ptr, len); | ||||
fragsz += len; | fragsz += len; | ||||
ptr += len; | ptr += len; | ||||
sz -= len; | sz -= len; | ||||
if (fragsz == di->blocksize) { | if (fragsz == di->blocksize) { | ||||
error = dump_write(di, di->blockbuf, 0, dumplo, | error = dump_append(di, di->blockbuf, 0, di->blocksize); | ||||
di->blocksize); | |||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
dumplo += di->blocksize; | |||||
fragsz = 0; | fragsz = 0; | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
dumpsys_buf_flush(struct dumperinfo *di) | dumpsys_buf_flush(struct dumperinfo *di) | ||||
{ | { | ||||
int error; | int error; | ||||
if (fragsz == 0) | if (fragsz == 0) | ||||
return (0); | return (0); | ||||
error = dump_write(di, di->blockbuf, 0, dumplo, di->blocksize); | error = dump_append(di, di->blockbuf, 0, di->blocksize); | ||||
dumplo += di->blocksize; | |||||
fragsz = 0; | fragsz = 0; | ||||
return (error); | return (error); | ||||
} | } | ||||
CTASSERT(PAGE_SHIFT < 20); | CTASSERT(PAGE_SHIFT < 20); | ||||
#define PG2MB(pgs) ((pgs + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT)) | #define PG2MB(pgs) ((pgs + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT)) | ||||
int | int | ||||
Show All 31 Lines | if (counter >> 24) { | ||||
counter &= (1 << 24) - 1; | counter &= (1 << 24) - 1; | ||||
} | } | ||||
dumpsys_map_chunk(pa, chunk, &va); | dumpsys_map_chunk(pa, chunk, &va); | ||||
#ifdef SW_WATCHDOG | #ifdef SW_WATCHDOG | ||||
wdog_kern_pat(WD_LASTVAL); | wdog_kern_pat(WD_LASTVAL); | ||||
#endif | #endif | ||||
error = dump_write(di, va, 0, dumplo, sz); | error = dump_append(di, va, 0, sz); | ||||
dumpsys_unmap_chunk(pa, chunk, va); | dumpsys_unmap_chunk(pa, chunk, va); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
dumplo += sz; | |||||
pgs -= chunk; | pgs -= chunk; | ||||
pa += sz; | pa += sz; | ||||
/* Check for user abort. */ | /* Check for user abort. */ | ||||
c = cncheckc(); | c = cncheckc(); | ||||
if (c == 0x03) | if (c == 0x03) | ||||
return (ECANCELED); | return (ECANCELED); | ||||
if (c != -1) | if (c != -1) | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | #endif | ||||
hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); | hdrgap = fileofs - roundup2((off_t)hdrsz, di->blocksize); | ||||
dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, | dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_ARCH_VERSION, | ||||
dumpsize); | dumpsize); | ||||
printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, | printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20, | ||||
ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); | ehdr.e_phnum - DUMPSYS_NUM_AUX_HDRS); | ||||
error = dump_start(di, &kdh, &dumplo); | error = dump_start(di, &kdh); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
/* Dump ELF header */ | /* Dump ELF header */ | ||||
error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); | error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump program headers */ | /* Dump program headers */ | ||||
error = dumpsys_foreach_chunk(cb_dumphdr, di); | error = dumpsys_foreach_chunk(cb_dumphdr, di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
error = dumpsys_write_aux_headers(di); | error = dumpsys_write_aux_headers(di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
dumpsys_buf_flush(di); | dumpsys_buf_flush(di); | ||||
/* | /* | ||||
* All headers are written using blocked I/O, so we know the | * All headers are written using blocked I/O, so we know the | ||||
* current offset is (still) block aligned. Skip the alignement | * current offset is (still) block aligned. Skip the alignement | ||||
* in the file to have the segment contents aligned at page | * in the file to have the segment contents aligned at page | ||||
* boundary. We cannot use MD_ALIGN on dumplo, because we don't | * boundary. | ||||
* care and may very well be unaligned within the dump device. | |||||
*/ | */ | ||||
error = dumpsys_buf_seek(di, (size_t)hdrgap); | error = dumpsys_buf_seek(di, (size_t)hdrgap); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump memory chunks (updates dumplo) */ | /* Dump memory chunks. */ | ||||
error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); | error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di); | ||||
if (error < 0) | if (error < 0) | ||||
goto fail; | goto fail; | ||||
error = dump_finish(di, &kdh, dumplo); | error = dump_finish(di, &kdh); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
printf("\nDump complete\n"); | printf("\nDump complete\n"); | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
if (error < 0) | if (error < 0) | ||||
Show All 11 Lines |