Enhance pmap_change_attr(). Use pmap_demote_pde() to demote a 2MB page
mapping to 4KB page mappings when the specified attribute change only applies to a portion of the 2MB page. Previously, in such cases, pmap_change_attr() gave up and returned an error. Submitted by: Magesh Dhasayyan
This commit is contained in:
parent
5573021d78
commit
91842e53a9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=180845
@ -4373,27 +4373,40 @@ pmap_change_attr(va, size, mode)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* XXX: We have to support tearing 2MB pages down into 4k pages if
|
||||
* needed here.
|
||||
* Pages that aren't mapped aren't supported. Also break down 2MB pages
|
||||
* into 4KB pages if required.
|
||||
*/
|
||||
/* Pages that aren't mapped aren't supported. */
|
||||
for (tmpva = base; tmpva < (base + size); ) {
|
||||
PMAP_LOCK(kernel_pmap);
|
||||
for (tmpva = base; tmpva < base + size; ) {
|
||||
pde = pmap_pde(kernel_pmap, tmpva);
|
||||
if (*pde == 0)
|
||||
if (*pde == 0) {
|
||||
PMAP_UNLOCK(kernel_pmap);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (*pde & PG_PS) {
|
||||
/* Handle 2MB pages that are completely contained. */
|
||||
if (size >= NBPDR) {
|
||||
/*
|
||||
* If the current offset aligns with a 2MB page frame
|
||||
* and there is at least 2MB left within the range, then
|
||||
* we need not break down this page into 4KB pages.
|
||||
*/
|
||||
if ((tmpva & PDRMASK) == 0 &&
|
||||
tmpva + PDRMASK < base + size) {
|
||||
tmpva += NBPDR;
|
||||
continue;
|
||||
}
|
||||
return (EINVAL);
|
||||
if (!pmap_demote_pde(kernel_pmap, pde, tmpva)) {
|
||||
PMAP_UNLOCK(kernel_pmap);
|
||||
return (ENOMEM);
|
||||
}
|
||||
}
|
||||
pte = vtopte(tmpva);
|
||||
if (*pte == 0)
|
||||
if (*pte == 0) {
|
||||
PMAP_UNLOCK(kernel_pmap);
|
||||
return (EINVAL);
|
||||
}
|
||||
tmpva += PAGE_SIZE;
|
||||
}
|
||||
PMAP_UNLOCK(kernel_pmap);
|
||||
|
||||
/*
|
||||
* Ok, all the pages exist, so run through them updating their
|
||||
|
Loading…
Reference in New Issue
Block a user