Utilize pmap_enter(..., psind=1) in vm_fault_soft_fast() on amd64. (The
Differential Revision discusses the benefits of this change.) Add a function, vm_reserv_to_superpage(), that returns the superpage containing the specified base page. Reviewed by: kib, markj Tested by: pho MFC after: 10 days Differential Revision: https://reviews.freebsd.org/D11556
This commit is contained in:
parent
aca38eab8a
commit
8b5e1472d2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=321386
@ -266,8 +266,11 @@ static int
|
||||
vm_fault_soft_fast(struct faultstate *fs, vm_offset_t vaddr, vm_prot_t prot,
|
||||
int fault_type, int fault_flags, boolean_t wired, vm_page_t *m_hold)
|
||||
{
|
||||
vm_page_t m;
|
||||
int rv;
|
||||
vm_page_t m, m_map;
|
||||
#if defined(__amd64__) && VM_NRESERVLEVEL > 0
|
||||
vm_page_t m_super;
|
||||
#endif
|
||||
int flags, psind, rv;
|
||||
|
||||
MPASS(fs->vp == NULL);
|
||||
m = vm_page_lookup(fs->first_object, fs->first_pindex);
|
||||
@ -275,14 +278,46 @@ vm_fault_soft_fast(struct faultstate *fs, vm_offset_t vaddr, vm_prot_t prot,
|
||||
if (m == NULL || ((prot & VM_PROT_WRITE) != 0 &&
|
||||
vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL)
|
||||
return (KERN_FAILURE);
|
||||
rv = pmap_enter(fs->map->pmap, vaddr, m, prot, fault_type |
|
||||
PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED : 0), 0);
|
||||
m_map = m;
|
||||
psind = 0;
|
||||
#if defined(__amd64__) && VM_NRESERVLEVEL > 0
|
||||
if ((m->flags & PG_FICTITIOUS) == 0 &&
|
||||
(m_super = vm_reserv_to_superpage(m)) != NULL &&
|
||||
rounddown2(vaddr, pagesizes[m_super->psind]) >= fs->entry->start &&
|
||||
roundup2(vaddr + 1, pagesizes[m_super->psind]) <= fs->entry->end &&
|
||||
(vaddr & (pagesizes[m_super->psind] - 1)) == (VM_PAGE_TO_PHYS(m) &
|
||||
(pagesizes[m_super->psind] - 1)) &&
|
||||
pmap_ps_enabled(fs->map->pmap)) {
|
||||
flags = PS_ALL_VALID;
|
||||
if ((prot & VM_PROT_WRITE) != 0) {
|
||||
/*
|
||||
* Create a superpage mapping allowing write access
|
||||
* only if none of the constituent pages are busy and
|
||||
* all of them are already dirty (except possibly for
|
||||
* the page that was faulted on).
|
||||
*/
|
||||
flags |= PS_NONE_BUSY;
|
||||
if ((fs->first_object->flags & OBJ_UNMANAGED) == 0)
|
||||
flags |= PS_ALL_DIRTY;
|
||||
}
|
||||
if (vm_page_ps_test(m_super, flags, m)) {
|
||||
m_map = m_super;
|
||||
psind = m_super->psind;
|
||||
vaddr = rounddown2(vaddr, pagesizes[psind]);
|
||||
/* Preset the modified bit for dirty superpages. */
|
||||
if ((flags & PS_ALL_DIRTY) != 0)
|
||||
fault_type |= VM_PROT_WRITE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rv = pmap_enter(fs->map->pmap, vaddr, m_map, prot, fault_type |
|
||||
PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED : 0), psind);
|
||||
if (rv != KERN_SUCCESS)
|
||||
return (rv);
|
||||
vm_fault_fill_hold(m_hold, m);
|
||||
vm_fault_dirty(fs->entry, m, prot, fault_type, fault_flags, false);
|
||||
VM_OBJECT_RUNLOCK(fs->first_object);
|
||||
if (!wired)
|
||||
if (psind == 0 && !wired)
|
||||
vm_fault_prefault(fs, vaddr, PFBAK, PFFOR);
|
||||
vm_map_lookup_done(fs->map, fs->entry);
|
||||
curthread->td_ru.ru_minflt++;
|
||||
|
@ -1121,4 +1121,18 @@ vm_reserv_startup(vm_offset_t *vaddr, vm_paddr_t end, vm_paddr_t high_water)
|
||||
return (new_end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the superpage containing the given page.
|
||||
*/
|
||||
vm_page_t
|
||||
vm_reserv_to_superpage(vm_page_t m)
|
||||
{
|
||||
vm_reserv_t rv;
|
||||
|
||||
VM_OBJECT_ASSERT_LOCKED(m->object);
|
||||
rv = vm_reserv_from_page(m);
|
||||
return (rv->object == m->object && rv->popcnt == VM_LEVEL_0_NPAGES ?
|
||||
rv->pages : NULL);
|
||||
}
|
||||
|
||||
#endif /* VM_NRESERVLEVEL > 0 */
|
||||
|
@ -64,6 +64,7 @@ void vm_reserv_rename(vm_page_t m, vm_object_t new_object,
|
||||
int vm_reserv_size(int level);
|
||||
vm_paddr_t vm_reserv_startup(vm_offset_t *vaddr, vm_paddr_t end,
|
||||
vm_paddr_t high_water);
|
||||
vm_page_t vm_reserv_to_superpage(vm_page_t m);
|
||||
|
||||
#endif /* VM_NRESERVLEVEL > 0 */
|
||||
#endif /* _KERNEL */
|
||||
|
Loading…
Reference in New Issue
Block a user