Changeset View
Changeset View
Standalone View
Standalone View
sys/riscv/riscv/minidump_machdep.c
Show First 20 Lines • Show All 149 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, const struct minidumpstate *state) | cpu_minidumpsys(struct dumperinfo *di, const struct minidumpstate *state) | ||||
{ | { | ||||
pd_entry_t *l1, *l2; | pd_entry_t *l1, *l2, l2e; | ||||
pt_entry_t *l3; | pt_entry_t *l3, l3e; | ||||
struct minidumphdr mdhdr; | struct minidumphdr mdhdr; | ||||
uint32_t pmapsize; | uint32_t pmapsize; | ||||
vm_offset_t va; | vm_offset_t va, kva_max; | ||||
vm_paddr_t pa; | vm_paddr_t pa; | ||||
int error; | int error; | ||||
int i; | int i; | ||||
int retry_count; | int retry_count; | ||||
retry_count = 0; | retry_count = 0; | ||||
retry: | retry: | ||||
retry_count++; | retry_count++; | ||||
error = 0; | error = 0; | ||||
pmapsize = 0; | pmapsize = 0; | ||||
/* Build set of dumpable pages from kernel pmap */ | /* Snapshot the KVA upper bound in case it grows. */ | ||||
for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += L2_SIZE) { | kva_max = 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_max; va += L2_SIZE) { | |||||
pmapsize += PAGE_SIZE; | pmapsize += PAGE_SIZE; | ||||
if (!pmap_get_tables(pmap_kernel(), va, &l1, &l2, &l3)) | if (!pmap_get_tables(pmap_kernel(), va, &l1, &l2, &l3)) | ||||
continue; | continue; | ||||
/* We should always be using the l2 table for kvm */ | /* We should always be using the l2 table for kvm */ | ||||
if (l2 == NULL) | if (l2 == NULL) | ||||
continue; | continue; | ||||
/* l2 may be a superpage */ | /* l2 may be a superpage */ | ||||
if ((*l2 & PTE_RWX) != 0) { | l2e = atomic_load_64(l2); | ||||
pa = (*l2 >> PTE_PPN1_S) << L2_SHIFT; | if ((l2e & PTE_RWX) != 0) { | ||||
pa = (l2e >> PTE_PPN1_S) << L2_SHIFT; | |||||
for (i = 0; i < Ln_ENTRIES; i++, pa += PAGE_SIZE) { | for (i = 0; i < Ln_ENTRIES; i++, pa += PAGE_SIZE) { | ||||
if (vm_phys_is_dumpable(pa)) | if (vm_phys_is_dumpable(pa)) | ||||
dump_add_page(pa); | dump_add_page(pa); | ||||
} | } | ||||
} else { | } else { | ||||
for (i = 0; i < Ln_ENTRIES; i++) { | for (i = 0; i < Ln_ENTRIES; i++) { | ||||
if ((l3[i] & PTE_V) == 0) | l3e = atomic_load_64(&l3[i]); | ||||
if ((l3e & PTE_V) == 0) | |||||
continue; | continue; | ||||
pa = (l3[i] >> PTE_PPN0_S) * PAGE_SIZE; | pa = (l3e >> PTE_PPN0_S) * PAGE_SIZE; | ||||
if (vm_phys_is_dumpable(pa)) | if (PHYS_IN_DMAP(pa) && vm_phys_is_dumpable(pa)) | ||||
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(sizeof(dump_avail)); | dumpsize += round_page(sizeof(dump_avail)); | ||||
dumpsize += round_page(BITSET_SIZE(vm_page_dump_pages)); | dumpsize += round_page(BITSET_SIZE(vm_page_dump_pages)); | ||||
VM_PAGE_DUMP_FOREACH(pa) { | VM_PAGE_DUMP_FOREACH(pa) { | ||||
/* Clear out undumpable pages now if needed */ | /* Clear out undumpable pages now if needed */ | ||||
if (vm_phys_is_dumpable(pa)) | if (PHYS_IN_DMAP(pa) && vm_phys_is_dumpable(pa)) | ||||
dumpsize += PAGE_SIZE; | dumpsize += PAGE_SIZE; | ||||
else | else | ||||
dump_drop_page(pa); | dump_drop_page(pa); | ||||
} | } | ||||
dumpsize += PAGE_SIZE; | dumpsize += PAGE_SIZE; | ||||
dumpsys_pb_init(dumpsize); | dumpsys_pb_init(dumpsize); | ||||
▲ Show 20 Lines • Show All 45 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_max; va += L2_SIZE) { | ||||
if (!pmap_get_tables(pmap_kernel(), va, &l1, &l2, &l3)) { | if (!pmap_get_tables(pmap_kernel(), va, &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 ((*l2 & PTE_RWX) != 0) { | continue; | ||||
} | |||||
l2e = atomic_load_64(l2); | |||||
if ((l2e & PTE_RWX) != 0) { | |||||
/* Generate fake l3 entries based on the l2 superpage */ | /* Generate fake l3 entries based on the l2 superpage */ | ||||
for (i = 0; i < Ln_ENTRIES; i++) { | for (i = 0; i < Ln_ENTRIES; i++) { | ||||
tmpbuffer[i] = (*l2 | (i << PTE_PPN0_S)); | tmpbuffer[i] = (l2e | (i << PTE_PPN0_S)); | ||||
} | } | ||||
/* 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; | ||||
bzero(&tmpbuffer, sizeof(tmpbuffer)); | bzero(&tmpbuffer, sizeof(tmpbuffer)); | ||||
} else { | } else { | ||||
pa = (*l2 >> PTE_PPN0_S) * PAGE_SIZE; | pa = (l2e >> PTE_PPN0_S) * PAGE_SIZE; | ||||
/* We always write a page, even if it is zero */ | /* | ||||
* We always write a page, even if it is zero. If pa | |||||
* is malformed, write the zeroed tmpbuffer. | |||||
*/ | |||||
if (PHYS_IN_DMAP(pa) && vm_phys_is_dumpable(pa)) | |||||
error = blk_write(di, NULL, pa, PAGE_SIZE); | error = blk_write(di, NULL, pa, PAGE_SIZE); | ||||
else | |||||
error = blk_write(di, (char *)&tmpbuffer, 0, | |||||
PAGE_SIZE); | |||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
} | } | ||||
} | } | ||||
/* Dump memory chunks */ | /* Dump memory chunks */ | ||||
/* XXX cluster it up and use blk_dump() */ | /* XXX cluster it up and use blk_dump() */ | ||||
VM_PAGE_DUMP_FOREACH(pa) { | VM_PAGE_DUMP_FOREACH(pa) { | ||||
Show All 38 Lines |