Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/minidump_machdep_base.c
Show First 20 Lines • Show All 154 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) | cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) | ||||
{ | { | ||||
uint64_t dumpsize; | uint64_t dumpsize; | ||||
uint32_t ptesize; | uint32_t ptesize; | ||||
vm_offset_t va; | vm_offset_t va; | ||||
int error; | int error; | ||||
uint64_t pa; | uint64_t pa; | ||||
pd_entry_t *pd; | pd_entry_t *pd, pde; | ||||
pt_entry_t *pt; | pt_entry_t *pt, pte; | ||||
int j, k; | int j, k; | ||||
struct minidumphdr mdhdr; | struct minidumphdr mdhdr; | ||||
/* Walk page table pages, set bits in vm_page_dump */ | /* Snapshot the KVA upper bound in case it grows. */ | ||||
kva_end = kernel_vm_end; | |||||
/* | |||||
* Walk the kernel page table pages, setting the active entries in the | |||||
* dump bitmap. | |||||
* | |||||
* NB: for a live dump, we may be racing with updates to the page | |||||
* tables, so care must be taken to read each entry only once. | |||||
*/ | |||||
ptesize = 0; | ptesize = 0; | ||||
for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) { | for (va = KERNBASE; va < kva_end; va += NBPDR) { | ||||
/* | /* | ||||
* We always write a page, even if it is zero. Each | * We always write a page, even if it is zero. Each | ||||
* page written corresponds to 2MB of space | * page written corresponds to 2MB of space | ||||
*/ | */ | ||||
ptesize += PAGE_SIZE; | ptesize += PAGE_SIZE; | ||||
pd = IdlePTD; /* always mapped! */ | pd = IdlePTD; /* always mapped! */ | ||||
j = va >> PDRSHIFT; | j = va >> PDRSHIFT; | ||||
if ((pd[j] & (PG_PS | PG_V)) == (PG_PS | PG_V)) { | pde = pte_load(pd[va >> PDRSHIFT]); | ||||
if ((pde & (PG_PS | PG_V)) == (PG_PS | PG_V)) { | |||||
/* This is an entire 2M page. */ | /* This is an entire 2M page. */ | ||||
pa = pd[j] & PG_PS_FRAME; | pa = pde & PG_PS_FRAME; | ||||
for (k = 0; k < NPTEPG; k++) { | for (k = 0; k < NPTEPG; k++) { | ||||
if (vm_phys_is_dumpable(pa)) | if (vm_phys_is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
pa += PAGE_SIZE; | pa += PAGE_SIZE; | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
if ((pd[j] & PG_V) == PG_V) { | if ((pde & PG_V) == PG_V) { | ||||
/* set bit for each valid page in this 2MB block */ | /* set bit for each valid page in this 2MB block */ | ||||
pt = pmap_kenter_temporary(pd[j] & PG_FRAME, 0); | pt = pmap_kenter_temporary(pde & PG_FRAME, 0); | ||||
for (k = 0; k < NPTEPG; k++) { | for (k = 0; k < NPTEPG; k++) { | ||||
if ((pt[k] & PG_V) == PG_V) { | pte = pte_load(&pt[k]); | ||||
pa = pt[k] & PG_FRAME; | if ((pte & PG_V) == PG_V) { | ||||
pa = pte & PG_FRAME; | |||||
if (vm_phys_is_dumpable(pa)) | if (vm_phys_is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
/* nothing, we're going to dump a null page */ | /* nothing, we're going to dump a null page */ | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) | ||||
/* Dump bitmap */ | /* Dump bitmap */ | ||||
error = blk_write(di, (char *)vm_page_dump, 0, | error = blk_write(di, (char *)vm_page_dump, 0, | ||||
round_page(BITSET_SIZE(vm_page_dump_pages))); | 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 = KERNBASE; va < kernel_vm_end; va += NBPDR) { | for (va = KERNBASE; va < kva_end; va += NBPDR) { | ||||
/* We always write a page, even if it is zero */ | /* We always write a page, even if it is zero */ | ||||
pd = IdlePTD; /* always mapped! */ | pd = IdlePTD; /* always mapped! */ | ||||
j = va >> PDRSHIFT; | pde = pte_load(pd[va >> PDRSHIFT]); | ||||
markj: Should it be `pte_load(&pd[va >> PDRSHIFT])`? Same above. | |||||
mhorneAuthorUnsubmitted Done Inline ActionsYes, thank you. I am running a tinderbox for these patches now which also tripped on this. mhorne: Yes, thank you. I am running a tinderbox for these patches now which also tripped on this. | |||||
if ((pd[j] & (PG_PS | PG_V)) == (PG_PS | PG_V)) { | if ((pde & (PG_PS | PG_V)) == (PG_PS | PG_V)) { | ||||
/* This is a single 2M block. Generate a fake PTP */ | /* This is a single 2M block. Generate a fake PTP */ | ||||
pa = pd[j] & PG_PS_FRAME; | pa = pde & PG_PS_FRAME; | ||||
for (k = 0; k < NPTEPG; k++) { | for (k = 0; k < NPTEPG; k++) { | ||||
fakept[k] = (pa + (k * PAGE_SIZE)) | PG_V | PG_RW | PG_A | PG_M; | fakept[k] = (pa + (k * PAGE_SIZE)) | PG_V | PG_RW | PG_A | PG_M; | ||||
} | } | ||||
error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); | error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* flush, in case we reuse fakept in the same block */ | /* flush, in case we reuse fakept in the same block */ | ||||
error = blk_flush(di); | error = blk_flush(di); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
continue; | continue; | ||||
} | } | ||||
if ((pd[j] & PG_V) == PG_V) { | if ((pde & PG_V) == PG_V) { | ||||
pa = pd[j] & PG_FRAME; | pa = pde & PG_FRAME; | ||||
error = blk_write(di, 0, pa, PAGE_SIZE); | error = blk_write(di, 0, pa, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
} else { | } else { | ||||
bzero(fakept, sizeof(fakept)); | bzero(fakept, sizeof(fakept)); | ||||
error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); | error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
Show All 38 Lines |
Should it be pte_load(&pd[va >> PDRSHIFT])? Same above.