Correct a very old and very obscure bug: vmspace_fork() calls
pmap_copy() if the mapping is VM_INHERIT_SHARE. Suppose the mapping is also wired. vmspace_fork() clears the wiring attributes in the vm map entry but pmap_copy() copies the PG_W attribute in the PTE. I don't think this is catastrophic. It blocks pmap_remove_pages() from destroying the mapping and corrupts the pmap's wiring count. This revision fixes the problem by changing pmap_copy() to clear the PG_W attribute. Reviewed by: tegge@
This commit is contained in:
parent
2624aa9b6b
commit
49b81721c7
@ -2674,7 +2674,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
|
||||
PHYS_TO_DMAP(VM_PAGE_TO_PHYS(dstmpde));
|
||||
pde = &pde[pmap_pde_index(addr)];
|
||||
if (*pde == 0) {
|
||||
*pde = srcptepaddr;
|
||||
*pde = srcptepaddr & ~PG_W;
|
||||
dst_pmap->pm_stats.resident_count +=
|
||||
NBPDR / PAGE_SIZE;
|
||||
} else
|
||||
@ -2708,11 +2708,12 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
|
||||
pmap_try_insert_pv_entry(dst_pmap, addr,
|
||||
PHYS_TO_VM_PAGE(ptetemp & PG_FRAME))) {
|
||||
/*
|
||||
* Clear the modified and
|
||||
* Clear the wired, modified, and
|
||||
* accessed (referenced) bits
|
||||
* during the copy.
|
||||
*/
|
||||
*dst_pte = ptetemp & ~(PG_M | PG_A);
|
||||
*dst_pte = ptetemp & ~(PG_W | PG_M |
|
||||
PG_A);
|
||||
dst_pmap->pm_stats.resident_count++;
|
||||
} else
|
||||
pmap_unwire_pte_hold(dst_pmap, addr,
|
||||
|
@ -2711,7 +2711,8 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
|
||||
|
||||
if (srcptepaddr & PG_PS) {
|
||||
if (dst_pmap->pm_pdir[ptepindex] == 0) {
|
||||
dst_pmap->pm_pdir[ptepindex] = srcptepaddr;
|
||||
dst_pmap->pm_pdir[ptepindex] = srcptepaddr &
|
||||
~PG_W;
|
||||
dst_pmap->pm_stats.resident_count +=
|
||||
NBPDR / PAGE_SIZE;
|
||||
}
|
||||
@ -2742,11 +2743,12 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
|
||||
pmap_try_insert_pv_entry(dst_pmap, addr,
|
||||
PHYS_TO_VM_PAGE(ptetemp & PG_FRAME))) {
|
||||
/*
|
||||
* Clear the modified and
|
||||
* Clear the wired, modified, and
|
||||
* accessed (referenced) bits
|
||||
* during the copy.
|
||||
*/
|
||||
*dst_pte = ptetemp & ~(PG_M | PG_A);
|
||||
*dst_pte = ptetemp & ~(PG_W | PG_M |
|
||||
PG_A);
|
||||
dst_pmap->pm_stats.resident_count++;
|
||||
} else
|
||||
pmap_unwire_pte_hold(dst_pmap, dstmpte);
|
||||
|
Loading…
Reference in New Issue
Block a user