Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/minidump_machdep.c
Show First 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz) | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
cpu_minidumpsys(struct dumperinfo *di, struct minidumpstate *state) | cpu_minidumpsys(struct dumperinfo *di, struct minidumpstate *state) | ||||
{ | { | ||||
struct minidumphdr mdhdr; | struct minidumphdr mdhdr; | ||||
pd_entry_t *l0, *l1, *l2; | pd_entry_t *l0, *l1, l1e, *l2, l2e; | ||||
pt_entry_t *l3; | pt_entry_t *l3, l3e; | ||||
vm_offset_t va; | vm_offset_t va, kva_end; | ||||
vm_paddr_t pa; | vm_paddr_t pa; | ||||
uint32_t pmapsize; | uint32_t pmapsize; | ||||
int error, i, j, retry_count; | int error, i, j, retry_count; | ||||
retry_count = 0; | retry_count = 0; | ||||
retry: | retry: | ||||
retry_count++; | retry_count++; | ||||
error = 0; | error = 0; | ||||
pmapsize = 0; | pmapsize = 0; | ||||
for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += L2_SIZE) { | |||||
/* 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. | |||||
*/ | |||||
for (va = VM_MIN_KERNEL_ADDRESS; va < kva_end; va += L2_SIZE) { | |||||
pmapsize += PAGE_SIZE; | pmapsize += PAGE_SIZE; | ||||
if (!pmap_get_tables(pmap_kernel(), va, &l0, &l1, &l2, &l3)) | if (!pmap_get_tables(pmap_kernel(), va, &l0, &l1, &l2, &l3)) | ||||
continue; | continue; | ||||
if ((*l1 & ATTR_DESCR_MASK) == L1_BLOCK) { | l1e = *l1; | ||||
pa = *l1 & ~ATTR_MASK; | l2e = *l2; | ||||
if ((l1e & ATTR_DESCR_MASK) == L1_BLOCK) { | |||||
pa = l1e & ~ATTR_MASK; | |||||
for (i = 0; i < Ln_ENTRIES * Ln_ENTRIES; | for (i = 0; i < Ln_ENTRIES * Ln_ENTRIES; | ||||
i++, pa += PAGE_SIZE) | i++, pa += PAGE_SIZE) | ||||
if (dump_page_is_dumpable(pa)) | if (dump_page_is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
pmapsize += (Ln_ENTRIES - 1) * PAGE_SIZE; | pmapsize += (Ln_ENTRIES - 1) * PAGE_SIZE; | ||||
va += L1_SIZE - L2_SIZE; | va += L1_SIZE - L2_SIZE; | ||||
} else if ((*l2 & ATTR_DESCR_MASK) == L2_BLOCK) { | } else if ((l2e & ATTR_DESCR_MASK) == L2_BLOCK) { | ||||
pa = *l2 & ~ATTR_MASK; | pa = l2e & ~ATTR_MASK; | ||||
for (i = 0; i < Ln_ENTRIES; i++, pa += PAGE_SIZE) { | for (i = 0; i < Ln_ENTRIES; i++, pa += PAGE_SIZE) { | ||||
if (dump_page_is_dumpable(pa)) | if (dump_page_is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
} | } | ||||
} else if ((*l2 & ATTR_DESCR_MASK) == L2_TABLE) { | } else if ((l2e & ATTR_DESCR_MASK) == L2_TABLE) { | ||||
for (i = 0; i < Ln_ENTRIES; i++) { | for (i = 0; i < Ln_ENTRIES; i++) { | ||||
if ((l3[i] & ATTR_DESCR_MASK) != L3_PAGE) | l3e = l3[i]; | ||||
if ((l3e & ATTR_DESCR_MASK) != L3_PAGE) | |||||
continue; | continue; | ||||
pa = l3[i] & ~ATTR_MASK; | pa = l3e & ~ATTR_MASK; | ||||
if (dump_page_is_dumpable(pa)) | if (dump_page_is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Calculate dump size. */ | /* Calculate dump size. */ | ||||
dumpsize = pmapsize; | dumpsize = pmapsize; | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | retry: | ||||
/* 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 directory pages */ | /* Dump kernel page directory pages */ | ||||
bzero(&tmpbuffer, sizeof(tmpbuffer)); | bzero(&tmpbuffer, sizeof(tmpbuffer)); | ||||
for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += L2_SIZE) { | for (va = VM_MIN_KERNEL_ADDRESS; va < kva_end; va += L2_SIZE) { | ||||
if (!pmap_get_tables(pmap_kernel(), va, &l0, &l1, &l2, &l3)) { | if (!pmap_get_tables(pmap_kernel(), va, &l0, &l1, &l2, &l3)) { | ||||
/* We always write a page, even if it is zero */ | /* We always write a page, even if it is zero */ | ||||
error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE); | error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* flush, in case we reuse tmpbuffer in the same block*/ | /* flush, in case we reuse tmpbuffer in the same block*/ | ||||
error = blk_flush(di); | error = blk_flush(di); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
} else if ((*l1 & ATTR_DESCR_MASK) == L1_BLOCK) { | continue; | ||||
} | |||||
l1e = *l1; | |||||
l2e = *l2; | |||||
if ((l1e & ATTR_DESCR_MASK) == L1_BLOCK) { | |||||
/* | /* | ||||
* Handle a 1GB block mapping: write out 512 fake L2 | * Handle a 1GB block mapping: write out 512 fake L2 | ||||
* pages. | * pages. | ||||
*/ | */ | ||||
pa = (*l1 & ~ATTR_MASK) | (va & L1_OFFSET); | pa = (l1e & ~ATTR_MASK) | (va & L1_OFFSET); | ||||
for (i = 0; i < Ln_ENTRIES; i++) { | for (i = 0; i < Ln_ENTRIES; i++) { | ||||
for (j = 0; j < Ln_ENTRIES; j++) { | for (j = 0; j < Ln_ENTRIES; j++) { | ||||
tmpbuffer[j] = pa + i * L2_SIZE + | tmpbuffer[j] = pa + i * L2_SIZE + | ||||
j * PAGE_SIZE | ATTR_DEFAULT | | j * PAGE_SIZE | ATTR_DEFAULT | | ||||
L3_PAGE; | L3_PAGE; | ||||
} | } | ||||
error = blk_write(di, (char *)&tmpbuffer, 0, | error = blk_write(di, (char *)&tmpbuffer, 0, | ||||
PAGE_SIZE); | PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
} | } | ||||
/* flush, in case we reuse tmpbuffer in the same block*/ | /* flush, in case we reuse tmpbuffer in the same block*/ | ||||
error = blk_flush(di); | error = blk_flush(di); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
bzero(&tmpbuffer, sizeof(tmpbuffer)); | bzero(&tmpbuffer, sizeof(tmpbuffer)); | ||||
va += L1_SIZE - L2_SIZE; | va += L1_SIZE - L2_SIZE; | ||||
} else if ((*l2 & ATTR_DESCR_MASK) == L2_BLOCK) { | } else if ((l2e & ATTR_DESCR_MASK) == L2_BLOCK) { | ||||
pa = (*l2 & ~ATTR_MASK) | (va & L2_OFFSET); | pa = (l2e & ~ATTR_MASK) | (va & L2_OFFSET); | ||||
/* Generate fake l3 entries based upon the l1 entry */ | /* Generate fake l3 entries based upon the l1 entry */ | ||||
for (i = 0; i < Ln_ENTRIES; i++) { | for (i = 0; i < Ln_ENTRIES; i++) { | ||||
tmpbuffer[i] = pa + (i * PAGE_SIZE) | | tmpbuffer[i] = pa + (i * PAGE_SIZE) | | ||||
ATTR_DEFAULT | L3_PAGE; | ATTR_DEFAULT | L3_PAGE; | ||||
} | } | ||||
error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE); | error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* flush, in case we reuse fakepd in the same block */ | /* flush, in case we reuse fakepd in the same block */ | ||||
error = blk_flush(di); | error = blk_flush(di); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
bzero(&tmpbuffer, sizeof(tmpbuffer)); | bzero(&tmpbuffer, sizeof(tmpbuffer)); | ||||
continue; | continue; | ||||
} else { | } else { | ||||
pa = *l2 & ~ATTR_MASK; | pa = l2e & ~ATTR_MASK; | ||||
error = blk_write(di, NULL, pa, PAGE_SIZE); | error = blk_write(di, NULL, pa, PAGE_SIZE); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
} | } | ||||
} | } | ||||
/* Dump memory chunks */ | /* Dump memory chunks */ | ||||
Show All 39 Lines |