Apply access flags for managed and unmanaged pages properly on ARMv6/v7

When entering a mapping via pmap_enter() unmanaged pages ought to be
naturally excluded from the "modified" and "referenced" emulation.
RW permission should be granted implicitly when requested,
otherwise unmanaged page will not recover from the permission fault
since there will be no PV entry to indicate that the page can be written.

In addition, only managed pages that participate in "modified"
emulation need to be marked as "dirty" and "writeable" when entered
with RW permissions. Likewise with "referenced" flag for managed pages.
Unmanaged ones however should not be marked as such.

Reviewed by:	cognet, gber
This commit is contained in:
zbb 2013-11-19 23:37:50 +00:00
parent 35c06ede2c
commit 2e7b9532a0

View File

@ -3079,36 +3079,38 @@ pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
* then continue setting mapping parameters
*/
if (m != NULL) {
if (prot & (VM_PROT_ALL)) {
if ((m->oflags & VPO_UNMANAGED) == 0)
if ((m->oflags & VPO_UNMANAGED) == 0) {
if (prot & (VM_PROT_ALL)) {
vm_page_aflag_set(m, PGA_REFERENCED);
} else {
/*
* Need to do page referenced emulation.
*/
npte &= ~L2_S_REF;
} else {
/*
* Need to do page referenced emulation.
*/
npte &= ~L2_S_REF;
}
}
if (prot & VM_PROT_WRITE) {
/*
* Enable write permission if the access type
* indicates write intention. Emulate modified
* bit otherwise.
*/
if ((access & VM_PROT_WRITE) != 0)
npte &= ~(L2_APX);
if ((m->oflags & VPO_UNMANAGED) == 0) {
vm_page_aflag_set(m, PGA_WRITEABLE);
/*
* The access type and permissions indicate
* that the page will be written as soon as
* returned from fault service.
* Mark it dirty from the outset.
* Enable write permission if the access type
* indicates write intention. Emulate modified
* bit otherwise.
*/
if ((access & VM_PROT_WRITE) != 0)
if ((access & VM_PROT_WRITE) != 0) {
npte &= ~(L2_APX);
vm_page_aflag_set(m, PGA_WRITEABLE);
/*
* The access type and permissions
* indicate that the page will be
* written as soon as returned from
* fault service.
* Mark it dirty from the outset.
*/
vm_page_dirty(m);
}
}
} else
npte &= ~(L2_APX);
}
if (!(prot & VM_PROT_EXECUTE))
npte |= L2_XN;