* grow the number of kernel page table entries, if needed */
| 4753 | * grow the number of kernel page table entries, if needed |
| 4754 | */ |
| 4755 | void |
| 4756 | pmap_growkernel(vm_offset_t addr) |
| 4757 | { |
| 4758 | vm_paddr_t paddr; |
| 4759 | vm_page_t nkpg; |
| 4760 | pd_entry_t *pde, newpdir; |
| 4761 | pdp_entry_t *pdpe; |
| 4762 | |
| 4763 | mtx_assert(&kernel_map->system_mtx, MA_OWNED); |
| 4764 | |
| 4765 | /* |
| 4766 | * Return if "addr" is within the range of kernel page table pages |
| 4767 | * that were preallocated during pmap bootstrap. Moreover, leave |
| 4768 | * "kernel_vm_end" and the kernel page table as they were. |
| 4769 | * |
| 4770 | * The correctness of this action is based on the following |
| 4771 | * argument: vm_map_insert() allocates contiguous ranges of the |
| 4772 | * kernel virtual address space. It calls this function if a range |
| 4773 | * ends after "kernel_vm_end". If the kernel is mapped between |
| 4774 | * "kernel_vm_end" and "addr", then the range cannot begin at |
| 4775 | * "kernel_vm_end". In fact, its beginning address cannot be less |
| 4776 | * than the kernel. Thus, there is no immediate need to allocate |
| 4777 | * any new kernel page table pages between "kernel_vm_end" and |
| 4778 | * "KERNBASE". |
| 4779 | */ |
| 4780 | if (KERNBASE < addr && addr <= KERNBASE + nkpt * NBPDR) |
| 4781 | return; |
| 4782 | |
| 4783 | addr = roundup2(addr, NBPDR); |
| 4784 | if (addr - 1 >= vm_map_max(kernel_map)) |
| 4785 | addr = vm_map_max(kernel_map); |
| 4786 | while (kernel_vm_end < addr) { |
| 4787 | pdpe = pmap_pdpe(kernel_pmap, kernel_vm_end); |
| 4788 | if ((*pdpe & X86_PG_V) == 0) { |
| 4789 | /* We need a new PDP entry */ |
| 4790 | nkpg = vm_page_alloc(NULL, kernel_vm_end >> PDPSHIFT, |
| 4791 | VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | |
| 4792 | VM_ALLOC_WIRED | VM_ALLOC_ZERO); |
| 4793 | if (nkpg == NULL) |
| 4794 | panic("pmap_growkernel: no memory to grow kernel"); |
| 4795 | if ((nkpg->flags & PG_ZERO) == 0) |
| 4796 | pmap_zero_page(nkpg); |
| 4797 | paddr = VM_PAGE_TO_PHYS(nkpg); |
| 4798 | *pdpe = (pdp_entry_t)(paddr | X86_PG_V | X86_PG_RW | |
| 4799 | X86_PG_A | X86_PG_M); |
| 4800 | continue; /* try again */ |
| 4801 | } |
| 4802 | pde = pmap_pdpe_to_pde(pdpe, kernel_vm_end); |
| 4803 | if ((*pde & X86_PG_V) != 0) { |
| 4804 | kernel_vm_end = (kernel_vm_end + NBPDR) & ~PDRMASK; |
| 4805 | if (kernel_vm_end - 1 >= vm_map_max(kernel_map)) { |
| 4806 | kernel_vm_end = vm_map_max(kernel_map); |
| 4807 | break; |
| 4808 | } |
| 4809 | continue; |
| 4810 | } |
| 4811 | |
| 4812 | nkpg = vm_page_alloc(NULL, pmap_pde_pindex(kernel_vm_end), |
nothing calls this directly
no test coverage detected