Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/amd64/minidump_machdep.c
Show First 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/minidump.h> | #include <machine/minidump.h> | ||||
CTASSERT(sizeof(struct kerneldumpheader) == 512); | CTASSERT(sizeof(struct kerneldumpheader) == 512); | ||||
uint64_t *vm_page_dump; | |||||
int vm_page_dump_size; | |||||
static struct kerneldumpheader kdh; | static struct kerneldumpheader kdh; | ||||
/* Handle chunked writes. */ | /* Handle chunked writes. */ | ||||
static size_t fragsz; | static size_t fragsz; | ||||
static void *dump_va; | static void *dump_va; | ||||
static size_t counter, progress, dumpsize, wdog_next; | static size_t counter, progress, dumpsize, wdog_next; | ||||
CTASSERT(sizeof(*vm_page_dump) == 8); | |||||
static int dump_retry_count = 5; | static int dump_retry_count = 5; | ||||
SYSCTL_INT(_machdep, OID_AUTO, dump_retry_count, CTLFLAG_RWTUN, | SYSCTL_INT(_machdep, OID_AUTO, dump_retry_count, CTLFLAG_RWTUN, | ||||
&dump_retry_count, 0, "Number of times dump has to retry before bailing out"); | &dump_retry_count, 0, "Number of times dump has to retry before bailing out"); | ||||
static int | static int | ||||
is_dumpable(vm_paddr_t pa) | is_dumpable(vm_paddr_t pa) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | |||||
static pd_entry_t fakepd[NPDEPG]; | static pd_entry_t fakepd[NPDEPG]; | ||||
int | int | ||||
minidumpsys(struct dumperinfo *di) | minidumpsys(struct dumperinfo *di) | ||||
{ | { | ||||
uint32_t pmapsize; | uint32_t pmapsize; | ||||
vm_offset_t va; | vm_offset_t va; | ||||
int error; | int error; | ||||
uint64_t bits; | |||||
uint64_t *pml4, *pdp, *pd, *pt, pa; | uint64_t *pml4, *pdp, *pd, *pt, pa; | ||||
int i, ii, j, k, n, bit; | int i, ii, j, k, n, bit; | ||||
kib: Might be it is time to change bit type to long ? | |||||
scottphAuthorUnsubmitted Done Inline ActionsINT_MAX bits for pages can cover almost 8 TiB of memory, so I think int is still working with existing hardware. I could do it now if you'd like or we can wait a year or two probably. scottph: INT_MAX bits for pages can cover almost 8 TiB of memory, so I think int is still working with… | |||||
kibUnsubmitted Done Inline ActionsIndeed INT_MAX covers 8T, and this is the current limit for DMAP on amd64. I see a value in fixing places as we see them. kib: Indeed INT_MAX covers 8T, and this is the current limit for DMAP on amd64.
I see a value in… | |||||
scottphAuthorUnsubmitted Done Inline ActionsSounds good, I've updated the FOREACH macro to use vm_pindex_t for the bit type. scottph: Sounds good, I've updated the FOREACH macro to use vm_pindex_t for the bit type. | |||||
int retry_count; | int retry_count; | ||||
struct minidumphdr mdhdr; | struct minidumphdr mdhdr; | ||||
retry_count = 0; | retry_count = 0; | ||||
retry: | retry: | ||||
retry_count++; | retry_count++; | ||||
counter = 0; | counter = 0; | ||||
for (i = 0; i < nitems(progress_track); i++) | for (i = 0; i < nitems(progress_track); i++) | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | for (n = 0; n < NPDEPG; n++, va += NBPDR) { | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Calculate dump size. */ | /* Calculate dump size. */ | ||||
dumpsize = pmapsize; | dumpsize = pmapsize; | ||||
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 = bsfq(bits); | |||||
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; | ||||
wdog_next = progress = dumpsize; | wdog_next = 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.pmapsize = pmapsize; | mdhdr.pmapsize = pmapsize; | ||||
mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; | mdhdr.kernbase = VM_MIN_KERNEL_ADDRESS; | ||||
mdhdr.dmapbase = DMAP_MIN_ADDRESS; | mdhdr.dmapbase = DMAP_MIN_ADDRESS; | ||||
mdhdr.dmapend = DMAP_MAX_ADDRESS; | mdhdr.dmapend = DMAP_MAX_ADDRESS; | ||||
dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, | dump_init_header(di, &kdh, KERNELDUMPMAGIC, KERNELDUMP_AMD64_VERSION, | ||||
dumpsize); | dumpsize); | ||||
Show All 12 Lines | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump msgbuf up front */ | /* Dump msgbuf up front */ | ||||
error = blk_write(di, (char *)msgbufp->msg_ptr, 0, round_page(msgbufp->msg_size)); | error = blk_write(di, (char *)msgbufp->msg_ptr, 0, round_page(msgbufp->msg_size)); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump bitmap */ | /* Dump bitmap */ | ||||
error = blk_write(di, (char *)vm_page_dump, 0, round_page(vm_page_dump_size)); | error = blk_write(di, (char *)vm_page_dump, 0, | ||||
round_page(BITSET_SIZE(vm_page_dump_pages))); | |||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* Dump kernel page directory pages */ | /* Dump kernel page directory pages */ | ||||
bzero(fakepd, sizeof(fakepd)); | bzero(fakepd, sizeof(fakepd)); | ||||
for (va = VM_MIN_KERNEL_ADDRESS; va < MAX(KERNBASE + nkpt * NBPDR, | for (va = VM_MIN_KERNEL_ADDRESS; va < MAX(KERNBASE + nkpt * NBPDR, | ||||
kernel_vm_end); va += NBPDP) { | kernel_vm_end); va += NBPDP) { | ||||
ii = pmap_pml4e_index(va); | ii = pmap_pml4e_index(va); | ||||
Show All 35 Lines | for (va = VM_MIN_KERNEL_ADDRESS; va < MAX(KERNBASE + nkpt * NBPDR, | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
error = blk_flush(di); | error = blk_flush(di); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
} | } | ||||
/* Dump memory chunks */ | /* Dump memory chunks */ | ||||
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 = bsfq(bits); | |||||
pa = (((uint64_t)i * sizeof(*vm_page_dump) * NBBY) + bit) * PAGE_SIZE; | |||||
error = blk_write(di, 0, pa, PAGE_SIZE); | error = blk_write(di, 0, pa, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
bits &= ~(1ul << bit); | |||||
} | } | ||||
} | |||||
error = blk_flush(di); | error = blk_flush(di); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
error = dump_finish(di, &kdh); | error = dump_finish(di, &kdh); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
Show All 17 Lines | fail: | ||||
else if (error == ECANCELED) | else if (error == ECANCELED) | ||||
printf("Dump aborted\n"); | printf("Dump aborted\n"); | ||||
else if (error == E2BIG) { | else if (error == E2BIG) { | ||||
printf("Dump failed. Partition too small (about %lluMB were " | printf("Dump failed. Partition too small (about %lluMB were " | ||||
"needed this time).\n", (long long)dumpsize >> 20); | "needed this time).\n", (long long)dumpsize >> 20); | ||||
} else | } else | ||||
printf("** DUMP FAILED (ERROR %d) **\n", error); | printf("** DUMP FAILED (ERROR %d) **\n", error); | ||||
return (error); | return (error); | ||||
} | |||||
void | |||||
dump_add_page(vm_paddr_t pa) | |||||
{ | |||||
int idx, bit; | |||||
pa >>= PAGE_SHIFT; | |||||
idx = pa >> 6; /* 2^6 = 64 */ | |||||
bit = pa & 63; | |||||
atomic_set_long(&vm_page_dump[idx], 1ul << bit); | |||||
} | |||||
void | |||||
dump_drop_page(vm_paddr_t pa) | |||||
{ | |||||
int idx, bit; | |||||
pa >>= PAGE_SHIFT; | |||||
idx = pa >> 6; /* 2^6 = 64 */ | |||||
bit = pa & 63; | |||||
atomic_clear_long(&vm_page_dump[idx], 1ul << bit); | |||||
} | } |
Might be it is time to change bit type to long ?