svn commit: r336881 - head/sys/arm/arm
Alan Cox
alc at FreeBSD.org
Mon Jul 30 01:54:26 UTC 2018
Author: alc
Date: Mon Jul 30 01:54:25 2018
New Revision: 336881
URL: https://svnweb.freebsd.org/changeset/base/336881
Log:
Prepare for adding psind == 1 support to armv6's pmap_enter().
Precompute the new PTE before entering the critical section.
Eliminate duplication of the pmap and pv list unlock operations in
pmap_enter() by implementing a single return path. Otherwise, the
duplication will only increase with the upcoming support for psind == 1.
Reviewed by: mmel
Tested by: mmel
Discussed with: kib, markj
MFC after: 3 weeks
Differential Revision: https://reviews.freebsd.org/D16443
Modified:
head/sys/arm/arm/pmap-v6.c
Modified: head/sys/arm/arm/pmap-v6.c
==============================================================================
--- head/sys/arm/arm/pmap-v6.c Mon Jul 30 00:08:36 2018 (r336880)
+++ head/sys/arm/arm/pmap-v6.c Mon Jul 30 01:54:25 2018 (r336881)
@@ -3849,18 +3849,36 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
pv_entry_t pv;
vm_paddr_t opa, pa;
vm_page_t mpte2, om;
- boolean_t wired;
+ int rv;
va = trunc_page(va);
- mpte2 = NULL;
- wired = (flags & PMAP_ENTER_WIRED) != 0;
-
KASSERT(va <= vm_max_kernel_address, ("%s: toobig", __func__));
KASSERT(va < UPT2V_MIN_ADDRESS || va >= UPT2V_MAX_ADDRESS,
("%s: invalid to pmap_enter page table pages (va: 0x%x)", __func__,
va));
+ KASSERT((m->oflags & VPO_UNMANAGED) != 0 || va < kmi.clean_sva ||
+ va >= kmi.clean_eva,
+ ("%s: managed mapping within the clean submap", __func__));
if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
VM_OBJECT_ASSERT_LOCKED(m->object);
+ KASSERT((flags & PMAP_ENTER_RESERVED) == 0,
+ ("%s: flags %u has reserved bits set", __func__, flags));
+ pa = VM_PAGE_TO_PHYS(m);
+ npte2 = PTE2(pa, PTE2_A, vm_page_pte2_attr(m));
+ if ((flags & VM_PROT_WRITE) == 0)
+ npte2 |= PTE2_NM;
+ if ((prot & VM_PROT_WRITE) == 0)
+ npte2 |= PTE2_RO;
+ KASSERT((npte2 & (PTE2_NM | PTE2_RO)) != PTE2_RO,
+ ("pmap_enter: flags includes VM_PROT_WRITE but prot doesn't"));
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ npte2 |= PTE2_NX;
+ if ((flags & PMAP_ENTER_WIRED) != 0)
+ npte2 |= PTE2_W;
+ if (va < VM_MAXUSER_ADDRESS)
+ npte2 |= PTE2_U;
+ if (pmap != kernel_pmap)
+ npte2 |= PTE2_NG;
rw_wlock(&pvh_global_lock);
PMAP_LOCK(pmap);
@@ -3875,12 +3893,11 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
if (mpte2 == NULL) {
KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0,
("pmap_allocpte2 failed with sleep allowed"));
- sched_unpin();
- rw_wunlock(&pvh_global_lock);
- PMAP_UNLOCK(pmap);
- return (KERN_RESOURCE_SHORTAGE);
+ rv = KERN_RESOURCE_SHORTAGE;
+ goto out;
}
- }
+ } else
+ mpte2 = NULL;
pte1p = pmap_pte1(pmap, va);
if (pte1_is_section(pte1_load(pte1p)))
panic("%s: attempted on 1MB page", __func__);
@@ -3889,7 +3906,6 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
panic("%s: invalid L1 page table entry va=%#x", __func__, va);
om = NULL;
- pa = VM_PAGE_TO_PHYS(m);
opte2 = pte2_load(pte2p);
opa = pte2_pa(opte2);
/*
@@ -3902,9 +3918,9 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
* are valid mappings in them. Hence, if a user page is wired,
* the PT2 page will be also.
*/
- if (wired && !pte2_is_wired(opte2))
+ if (pte2_is_wired(npte2) && !pte2_is_wired(opte2))
pmap->pm_stats.wired_count++;
- else if (!wired && pte2_is_wired(opte2))
+ else if (!pte2_is_wired(npte2) && pte2_is_wired(opte2))
pmap->pm_stats.wired_count--;
/*
@@ -3953,11 +3969,10 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
* Enter on the PV list if part of our managed memory.
*/
if ((m->oflags & VPO_UNMANAGED) == 0) {
- KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
- ("%s: managed mapping within the clean submap", __func__));
- if (pv == NULL)
+ if (pv == NULL) {
pv = get_pv_entry(pmap, FALSE);
- pv->pv_va = va;
+ pv->pv_va = va;
+ }
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
} else if (pv != NULL)
free_pv_entry(pmap, pv);
@@ -3965,28 +3980,17 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, v
/*
* Increment counters
*/
- if (wired)
+ if (pte2_is_wired(npte2))
pmap->pm_stats.wired_count++;
validate:
/*
* Now validate mapping with desired protection/wiring.
*/
- npte2 = PTE2(pa, PTE2_NM, vm_page_pte2_attr(m));
if (prot & VM_PROT_WRITE) {
if (pte2_is_managed(npte2))
vm_page_aflag_set(m, PGA_WRITEABLE);
}
- else
- npte2 |= PTE2_RO;
- if ((prot & VM_PROT_EXECUTE) == 0)
- npte2 |= PTE2_NX;
- if (wired)
- npte2 |= PTE2_W;
- if (va < VM_MAXUSER_ADDRESS)
- npte2 |= PTE2_U;
- if (pmap != kernel_pmap)
- npte2 |= PTE2_NG;
/*
* If the mapping or permission bits are different, we need
@@ -4016,9 +4020,6 @@ validate:
(opa != pa || (opte2 & PTE2_NX)))
cache_icache_sync_fresh(va, pa, PAGE_SIZE);
- npte2 |= PTE2_A;
- if (flags & VM_PROT_WRITE)
- npte2 &= ~PTE2_NM;
if (opte2 & PTE2_V) {
/* Change mapping with break-before-make approach. */
opte2 = pte2_load_clear(pte2p);
@@ -4063,10 +4064,13 @@ validate:
vm_reserv_level_iffullpop(m) == 0)
pmap_promote_pte1(pmap, pte1p, va);
#endif
+
+ rv = KERN_SUCCESS;
+out:
sched_unpin();
rw_wunlock(&pvh_global_lock);
PMAP_UNLOCK(pmap);
- return (KERN_SUCCESS);
+ return (rv);
}
/*
More information about the svn-src-head
mailing list