* Copy the range specified by src_addr/len * from the source map to the range dst_addr/len * in the destination map. * * This routine is only advisory and need not do anything. * * Because the executable mappings created by this routine are copied, * it should not have to flush the instruction cache. */
| 4681 | * it should not have to flush the instruction cache. |
| 4682 | */ |
| 4683 | void |
| 4684 | pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len, |
| 4685 | vm_offset_t src_addr) |
| 4686 | { |
| 4687 | struct rwlock *lock; |
| 4688 | pd_entry_t *l0, *l1, *l2, srcptepaddr; |
| 4689 | pt_entry_t *dst_pte, mask, nbits, ptetemp, *src_pte; |
| 4690 | vm_offset_t addr, end_addr, va_next; |
| 4691 | vm_page_t dst_m, dstmpte, srcmpte; |
| 4692 | |
| 4693 | PMAP_ASSERT_STAGE1(dst_pmap); |
| 4694 | PMAP_ASSERT_STAGE1(src_pmap); |
| 4695 | |
| 4696 | if (dst_addr != src_addr) |
| 4697 | return; |
| 4698 | end_addr = src_addr + len; |
| 4699 | lock = NULL; |
| 4700 | if (dst_pmap < src_pmap) { |
| 4701 | PMAP_LOCK(dst_pmap); |
| 4702 | PMAP_LOCK(src_pmap); |
| 4703 | } else { |
| 4704 | PMAP_LOCK(src_pmap); |
| 4705 | PMAP_LOCK(dst_pmap); |
| 4706 | } |
| 4707 | for (addr = src_addr; addr < end_addr; addr = va_next) { |
| 4708 | l0 = pmap_l0(src_pmap, addr); |
| 4709 | if (pmap_load(l0) == 0) { |
| 4710 | va_next = (addr + L0_SIZE) & ~L0_OFFSET; |
| 4711 | if (va_next < addr) |
| 4712 | va_next = end_addr; |
| 4713 | continue; |
| 4714 | } |
| 4715 | |
| 4716 | va_next = (addr + L1_SIZE) & ~L1_OFFSET; |
| 4717 | if (va_next < addr) |
| 4718 | va_next = end_addr; |
| 4719 | l1 = pmap_l0_to_l1(l0, addr); |
| 4720 | if (pmap_load(l1) == 0) |
| 4721 | continue; |
| 4722 | if ((pmap_load(l1) & ATTR_DESCR_MASK) == L1_BLOCK) { |
| 4723 | KASSERT(va_next <= end_addr, |
| 4724 | ("partial update of non-transparent 1G page " |
| 4725 | "l1 %#lx addr %#lx end_addr %#lx va_next %#lx", |
| 4726 | pmap_load(l1), addr, end_addr, va_next)); |
| 4727 | srcptepaddr = pmap_load(l1); |
| 4728 | l1 = pmap_l1(dst_pmap, addr); |
| 4729 | if (l1 == NULL) { |
| 4730 | if (_pmap_alloc_l3(dst_pmap, |
| 4731 | pmap_l0_pindex(addr), NULL) == NULL) |
| 4732 | break; |
| 4733 | l1 = pmap_l1(dst_pmap, addr); |
| 4734 | } else { |
| 4735 | l0 = pmap_l0(dst_pmap, addr); |
| 4736 | dst_m = PHYS_TO_VM_PAGE(pmap_load(l0) & |
| 4737 | ~ATTR_MASK); |
| 4738 | dst_m->ref_count++; |
| 4739 | } |
| 4740 | KASSERT(pmap_load(l1) == 0, |
nothing calls this directly
no test coverage detected