Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mips/minidump_machdep.c
Show First 20 Lines • Show All 48 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); | ||||
uint32_t *vm_page_dump; | |||||
int vm_page_dump_size; | |||||
static struct kerneldumpheader kdh; | static struct kerneldumpheader kdh; | ||||
/* 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; | ||||
CTASSERT(sizeof(*vm_page_dump) == 4); | |||||
static int | static int | ||||
is_dumpable(vm_paddr_t pa) | is_dumpable(vm_paddr_t pa) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
int i; | int i; | ||||
if ((m = vm_phys_paddr_to_vm_page(pa)) != NULL) | if ((m = vm_phys_paddr_to_vm_page(pa)) != NULL) | ||||
return ((m->flags & PG_NODUMP) == 0); | return ((m->flags & PG_NODUMP) == 0); | ||||
for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) { | for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) { | ||||
if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) | if (pa >= dump_avail[i] && pa < dump_avail[i + 1]) | ||||
return (1); | return (1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | |||||
dump_add_page(vm_paddr_t pa) | |||||
{ | |||||
int idx, bit; | |||||
pa >>= PAGE_SHIFT; | |||||
idx = pa >> 5; /* 2^5 = 32 */ | |||||
bit = pa & 31; | |||||
atomic_set_int(&vm_page_dump[idx], 1ul << bit); | |||||
} | |||||
void | |||||
dump_drop_page(vm_paddr_t pa) | |||||
{ | |||||
int idx, bit; | |||||
pa >>= PAGE_SHIFT; | |||||
idx = pa >> 5; /* 2^5 = 32 */ | |||||
bit = pa & 31; | |||||
atomic_clear_int(&vm_page_dump[idx], 1ul << bit); | |||||
} | |||||
static struct { | static struct { | ||||
int min_per; | int min_per; | ||||
int max_per; | int max_per; | ||||
int visited; | int visited; | ||||
} progress_track[10] = { | } progress_track[10] = { | ||||
{ 0, 10, 0}, | { 0, 10, 0}, | ||||
{ 10, 20, 0}, | { 10, 20, 0}, | ||||
{ 20, 30, 0}, | { 20, 30, 0}, | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | write_buffer(struct dumperinfo *di, char *ptr, size_t sz) | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
minidumpsys(struct dumperinfo *di) | minidumpsys(struct dumperinfo *di) | ||||
{ | { | ||||
struct minidumphdr mdhdr; | struct minidumphdr mdhdr; | ||||
uint32_t ptesize; | uint32_t ptesize; | ||||
uint32_t bits; | |||||
vm_paddr_t pa; | vm_paddr_t pa; | ||||
vm_offset_t prev_pte = 0; | vm_offset_t prev_pte = 0; | ||||
uint32_t count = 0; | uint32_t count = 0; | ||||
vm_offset_t va; | vm_offset_t va; | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
int i, bit, error; | int i, bit, error; | ||||
void *dump_va; | void *dump_va; | ||||
Show All 24 Lines | minidumpsys(struct dumperinfo *di) | ||||
for (pa = 0; pa < phys_avail[0]; pa += PAGE_SIZE) { | 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(BITSET_SIZE(vm_page_dump_pages)); | ||||
for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { | VM_PAGE_DUMP_FOREACH(bit, pa) { | ||||
bits = vm_page_dump[i]; | |||||
while (bits) { | |||||
bit = ffs(bits) - 1; | |||||
pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + | |||||
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); | |||||
} | } | ||||
} | |||||
dumpsize += PAGE_SIZE; | dumpsize += PAGE_SIZE; | ||||
progress = dumpsize; | progress = dumpsize; | ||||
/* 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 = BITSET_SIZE(vm_page_dump_pages); | ||||
mdhdr.ptesize = ptesize; | mdhdr.ptesize = ptesize; | ||||
mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; | mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; | ||||
dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_MIPS_VERSION, | dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_MIPS_VERSION, | ||||
dumpsize); | dumpsize); | ||||
error = dump_start(di, &kdh); | error = dump_start(di, &kdh); | ||||
if (error != 0) | if (error != 0) | ||||
Show All 12 Lines | minidumpsys(struct dumperinfo *di) | ||||
/* Dump msgbuf up front */ | /* Dump msgbuf up front */ | ||||
error = write_buffer(di, (char *)msgbufp->msg_ptr, | error = write_buffer(di, (char *)msgbufp->msg_ptr, | ||||
round_page(msgbufp->msg_size)); | round_page(msgbufp->msg_size)); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump bitmap */ | /* Dump bitmap */ | ||||
error = write_buffer(di, (char *)vm_page_dump, | error = write_buffer(di, (char *)vm_page_dump, | ||||
round_page(vm_page_dump_size)); | round_page(BITSET_SIZE(vm_page_dump_pages))); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* 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) { | ||||
Show All 17 Lines | if (count) { | ||||
error = write_buffer(di, (char*)prev_pte, count * PAGE_SIZE); | error = write_buffer(di, (char*)prev_pte, count * PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
count = 0; | count = 0; | ||||
prev_pte = 0; | prev_pte = 0; | ||||
} | } | ||||
/* Dump memory chunks page by page*/ | /* Dump memory chunks page by page*/ | ||||
for (i = 0; i < vm_page_dump_size / sizeof(*vm_page_dump); i++) { | VM_PAGE_DUMP_FOREACH(bit, pa) { | ||||
bits = vm_page_dump[i]; | |||||
while (bits) { | |||||
bit = ffs(bits) - 1; | |||||
pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + | |||||
bit) * PAGE_SIZE; | |||||
dump_va = pmap_kenter_temporary(pa, 0); | dump_va = pmap_kenter_temporary(pa, 0); | ||||
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); | |||||
} | |||||
} | } | ||||
error = dump_finish(di, &kdh); | 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); | ||||
Show All 14 Lines |