Index: head/sys/arm/arm/minidump_machdep.c =================================================================== --- head/sys/arm/arm/minidump_machdep.c +++ head/sys/arm/arm/minidump_machdep.c @@ -61,8 +61,6 @@ uint32_t *vm_page_dump; int vm_page_dump_size; -#ifndef ARM_NEW_PMAP - static struct kerneldumpheader kdh; static off_t dumplo; @@ -196,8 +194,9 @@ return (0); } -/* A fake page table page, to avoid having to handle both 4K and 2M pages */ -static pt_entry_t fakept[NPTEPG]; +/* A buffer for general use. Its size must be one page at least. */ +static char dumpbuf[PAGE_SIZE]; +CTASSERT(sizeof(dumpbuf) % sizeof(pt2_entry_t) == 0); int minidumpsys(struct dumperinfo *di) @@ -208,9 +207,7 @@ uint32_t bits; uint32_t pa, prev_pa = 0, count = 0; vm_offset_t va; - pd_entry_t *pdp; - pt_entry_t *pt, *ptp; - int i, k, bit, error; + int i, bit, error; char *addr; /* @@ -228,48 +225,11 @@ counter = 0; /* Walk page table pages, set bits in vm_page_dump */ ptesize = 0; - for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) { - /* - * We always write a page, even if it is zero. Each - * page written corresponds to 2MB of space - */ - ptesize += L2_TABLE_SIZE_REAL; - pmap_get_pde_pte(pmap_kernel(), va, &pdp, &ptp); - if (pmap_pde_v(pdp) && pmap_pde_section(pdp)) { - /* This is a section mapping 1M page. */ - pa = (*pdp & L1_S_ADDR_MASK) | (va & ~L1_S_ADDR_MASK); - for (k = 0; k < (L1_S_SIZE / PAGE_SIZE); k++) { - if (is_dumpable(pa)) - dump_add_page(pa); - pa += PAGE_SIZE; - } - continue; - } - if (pmap_pde_v(pdp) && pmap_pde_page(pdp)) { - /* Set bit for each valid page in this 1MB block */ - addr = pmap_kenter_temporary(*pdp & L1_C_ADDR_MASK, 0); - pt = (pt_entry_t*)(addr + - (((uint32_t)*pdp & L1_C_ADDR_MASK) & PAGE_MASK)); - for (k = 0; k < 256; k++) { - if ((pt[k] & L2_TYPE_MASK) == L2_TYPE_L) { - pa = (pt[k] & L2_L_FRAME) | - (va & L2_L_OFFSET); - for (i = 0; i < 16; i++) { - if (is_dumpable(pa)) - dump_add_page(pa); - k++; - pa += PAGE_SIZE; - } - } else if ((pt[k] & L2_TYPE_MASK) == L2_TYPE_S) { - pa = (pt[k] & L2_S_FRAME) | - (va & L2_S_OFFSET); - if (is_dumpable(pa)) - dump_add_page(pa); - } - } - } else { - /* Nothing, we're going to dump a null page */ - } + for (va = KERNBASE; va < kernel_vm_end; va += PAGE_SIZE) { + pa = pmap_dump_kextract(va, NULL); + if (pa != 0 && is_dumpable(pa)) + dump_add_page(pa); + ptesize += sizeof(pt2_entry_t); } /* Calculate dump size. */ @@ -331,9 +291,9 @@ dumplo += sizeof(kdh); /* Dump my header */ - bzero(&fakept, sizeof(fakept)); - bcopy(&mdhdr, &fakept, sizeof(mdhdr)); - error = blk_write(di, (char *)&fakept, 0, PAGE_SIZE); + bzero(dumpbuf, sizeof(dumpbuf)); + bcopy(&mdhdr, dumpbuf, sizeof(mdhdr)); + error = blk_write(di, dumpbuf, 0, PAGE_SIZE); if (error) goto fail; @@ -349,81 +309,21 @@ goto fail; /* Dump kernel page table pages */ - for (va = KERNBASE; va < kernel_vm_end; va += NBPDR) { - /* We always write a page, even if it is zero */ - pmap_get_pde_pte(pmap_kernel(), va, &pdp, &ptp); - - if (pmap_pde_v(pdp) && pmap_pde_section(pdp)) { - if (count) { - error = blk_write_cont(di, prev_pa, - count * L2_TABLE_SIZE_REAL); - if (error) - goto fail; - count = 0; - prev_pa = 0; - } - /* This is a single 2M block. Generate a fake PTP */ - pa = (*pdp & L1_S_ADDR_MASK) | (va & ~L1_S_ADDR_MASK); - for (k = 0; k < (L1_S_SIZE / PAGE_SIZE); k++) { - fakept[k] = L2_S_PROTO | (pa + (k * PAGE_SIZE)) | - L2_S_PROT(PTE_KERNEL, - VM_PROT_READ | VM_PROT_WRITE); - } - error = blk_write(di, (char *)&fakept, 0, - L2_TABLE_SIZE_REAL); - if (error) - goto fail; - /* Flush, in case we reuse fakept in the same block */ - error = blk_flush(di); - if (error) - goto fail; - continue; - } - if (pmap_pde_v(pdp) && pmap_pde_page(pdp)) { - pa = *pdp & L1_C_ADDR_MASK; - if (!count) { - prev_pa = pa; - count++; - } - else { - if (pa == (prev_pa + count * L2_TABLE_SIZE_REAL)) - count++; - else { - error = blk_write_cont(di, prev_pa, - count * L2_TABLE_SIZE_REAL); - if (error) - goto fail; - count = 1; - prev_pa = pa; - } - } - } else { - if (count) { - error = blk_write_cont(di, prev_pa, - count * L2_TABLE_SIZE_REAL); - if (error) - goto fail; - count = 0; - prev_pa = 0; - } - bzero(fakept, sizeof(fakept)); - error = blk_write(di, (char *)&fakept, 0, - L2_TABLE_SIZE_REAL); - if (error) - goto fail; - /* Flush, in case we reuse fakept in the same block */ - error = blk_flush(di); - if (error) + addr = dumpbuf; + for (va = KERNBASE; va < kernel_vm_end; va += PAGE_SIZE) { + pmap_dump_kextract(va, (pt2_entry_t *)addr); + addr += sizeof(pt2_entry_t); + if (addr == dumpbuf + sizeof(dumpbuf)) { + error = blk_write(di, dumpbuf, 0, sizeof(dumpbuf)); + if (error != 0) goto fail; + addr = dumpbuf; } } - - if (count) { - error = blk_write_cont(di, prev_pa, count * L2_TABLE_SIZE_REAL); - if (error) + if (addr != dumpbuf) { + error = blk_write(di, dumpbuf, 0, addr - dumpbuf); + if (error != 0) goto fail; - count = 0; - prev_pa = 0; } /* Dump memory chunks */ @@ -484,17 +384,6 @@ return (0); } -#else /* ARM_NEW_PMAP */ - -int -minidumpsys(struct dumperinfo *di) -{ - - return (0); -} - -#endif - void dump_add_page(vm_paddr_t pa) { Index: head/sys/arm/arm/pmap-v6-new.c =================================================================== --- head/sys/arm/arm/pmap-v6-new.c +++ head/sys/arm/arm/pmap-v6-new.c @@ -1049,6 +1049,36 @@ return (pa); } +/* + * Extract from the kernel page table the physical address + * that is mapped by the given virtual address "va". Also + * return L2 page table entry which maps the address. + * + * This is only intended to be used for panic dumps. + */ +vm_paddr_t +pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p) +{ + vm_paddr_t pa; + pt1_entry_t pte1; + pt2_entry_t pte2; + + pte1 = pte1_load(kern_pte1(va)); + if (pte1_is_section(pte1)) { + pa = pte1_pa(pte1) | (va & PTE1_OFFSET); + pte2 = pa | ATTR_TO_L2(pte1) | PTE2_V; + } else if (pte1_is_link(pte1)) { + pte2 = pte2_load(pt2map_entry(va)); + pa = pte2_pa(pte2); + } else { + pte2 = 0; + pa = 0; + } + if (pte2p != NULL) + *pte2p = pte2; + return (pa); +} + /***************************************************************************** * * PMAP second stage initialization and utility functions Index: head/sys/arm/arm/pmap-v6.c =================================================================== --- head/sys/arm/arm/pmap-v6.c +++ head/sys/arm/arm/pmap-v6.c @@ -3536,6 +3536,52 @@ return (m); } +vm_paddr_t +pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p) +{ + struct l2_dtable *l2; + pd_entry_t l1pd; + pt_entry_t *ptep, pte; + vm_paddr_t pa; + u_int l1idx; + + l1idx = L1_IDX(va); + l1pd = kernel_pmap->pm_l1->l1_kva[l1idx]; + if (l1pte_section_p(l1pd)) { + if (l1pd & L1_S_SUPERSEC) + pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); + else + pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET); + pte = L2_S_PROTO | pa | + L2_S_PROT(PTE_KERNEL, VM_PROT_READ | VM_PROT_WRITE); + } else { + l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]; + if (l2 == NULL || + (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) { + pte = 0; + pa = 0; + goto out; + } + pte = ptep[l2pte_index(va)]; + if (pte == 0) { + pa = 0; + goto out; + } + switch (pte & L2_TYPE_MASK) { + case L2_TYPE_L: + pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET); + break; + default: + pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); + break; + } + } +out: + if (pte2p != NULL) + *pte2p = pte; + return (pa); +} + /* * Initialize a preallocated and zeroed pmap structure, * such as one in a vmspace structure. Index: head/sys/arm/arm/pmap.c =================================================================== --- head/sys/arm/arm/pmap.c +++ head/sys/arm/arm/pmap.c @@ -3738,6 +3738,52 @@ return (m); } +vm_paddr_t +pmap_dump_kextract(vm_offset_t va, pt2_entry_t *pte2p) +{ + struct l2_dtable *l2; + pd_entry_t l1pd; + pt_entry_t *ptep, pte; + vm_paddr_t pa; + u_int l1idx; + + l1idx = L1_IDX(va); + l1pd = kernel_pmap->pm_l1->l1_kva[l1idx]; + if (l1pte_section_p(l1pd)) { + if (l1pd & L1_S_SUPERSEC) + pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); + else + pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET); + pte = L2_S_PROTO | pa | + L2_S_PROT(PTE_KERNEL, VM_PROT_READ | VM_PROT_WRITE); + } else { + l2 = kernel_pmap->pm_l2[L2_IDX(l1idx)]; + if (l2 == NULL || + (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) { + pte = 0; + pa = 0; + goto out; + } + pte = ptep[l2pte_index(va)]; + if (pte == 0) { + pa = 0; + goto out; + } + switch (pte & L2_TYPE_MASK) { + case L2_TYPE_L: + pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET); + break; + default: + pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); + break; + } + } +out: + if (pte2p != NULL) + *pte2p = pte; + return (pa); +} + /* * Initialize a preallocated and zeroed pmap structure, * such as one in a vmspace structure. Index: head/sys/arm/include/pmap-v6.h =================================================================== --- head/sys/arm/include/pmap-v6.h +++ head/sys/arm/include/pmap-v6.h @@ -200,6 +200,8 @@ void pmap_dcache_wb_range(vm_paddr_t , vm_size_t , vm_memattr_t ); vm_paddr_t pmap_kextract(vm_offset_t ); +vm_paddr_t pmap_dump_kextract(vm_offset_t, pt2_entry_t *); + int pmap_fault(pmap_t , vm_offset_t , uint32_t , int , bool); #define vtophys(va) pmap_kextract((vm_offset_t)(va)) Index: head/sys/arm/include/pmap.h =================================================================== --- head/sys/arm/include/pmap.h +++ head/sys/arm/include/pmap.h @@ -263,6 +263,7 @@ void *pmap_kenter_temporary(vm_paddr_t pa, int i); void pmap_kenter_user(vm_offset_t va, vm_paddr_t pa); vm_paddr_t pmap_kextract(vm_offset_t va); +vm_paddr_t pmap_dump_kextract(vm_offset_t, pt2_entry_t *); void pmap_kremove(vm_offset_t); void *pmap_mapdev(vm_offset_t, vm_size_t); void pmap_unmapdev(vm_offset_t, vm_size_t); Index: head/sys/arm/include/pte.h =================================================================== --- head/sys/arm/include/pte.h +++ head/sys/arm/include/pte.h @@ -43,6 +43,7 @@ #ifndef LOCORE typedef uint32_t pd_entry_t; /* page directory entry */ typedef uint32_t pt_entry_t; /* page table entry */ +typedef pt_entry_t pt2_entry_t; /* compatibility with v6 */ #endif #define PG_FRAME 0xfffff000