diff options
author | kib <kib@FreeBSD.org> | 2014-09-01 07:58:15 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2014-09-01 07:58:15 +0000 |
commit | 798eea16149d6a39c6fb5f721410f61b5bb1134a (patch) | |
tree | 8a38ed27916582f1759cfcc70e76cd5fabbebce1 /sys/sparc64 | |
parent | 14d8fe45061d6304d3e6438cfe4267aa7e17c705 (diff) | |
download | FreeBSD-src-798eea16149d6a39c6fb5f721410f61b5bb1134a.zip FreeBSD-src-798eea16149d6a39c6fb5f721410f61b5bb1134a.tar.gz |
Fix a leak of the wired pages when unwiring of the PROT_NONE-mapped
wired region. Rework the handling of unwire to do the it in batch,
both at pmap and object level.
All commits below are by alc.
MFC r268327:
Introduce pmap_unwire().
MFC r268591:
Implement pmap_unwire() for powerpc.
MFC r268776:
Implement pmap_unwire() for arm.
MFC r268806:
pmap_unwire(9) man page.
MFC r269134:
When unwiring a region of an address space, do not assume that the
underlying physical pages are mapped by the pmap. This fixes a leak
of the wired pages on the unwiring of the region mapped with no access
allowed.
MFC r269339:
In the implementation of the new function pmap_unwire(), the call to
MOEA64_PVO_TO_PTE() must be performed before any changes are made to the
PVO. Otherwise, MOEA64_PVO_TO_PTE() will panic.
MFC r269365:
Correct a long-standing problem in moea{,64}_pvo_enter() that was revealed
by the combination of r268591 and r269134: When we attempt to add the
wired attribute to an existing mapping, moea{,64}_pvo_enter() do nothing.
(They only set the wired attribute on newly created mappings.)
MFC r269433:
Handle wiring failures in vm_map_wire() with the new functions
pmap_unwire() and vm_object_unwire().
Retire vm_fault_{un,}wire(), since they are no longer used.
MFC r269438:
Rewrite a loop in vm_map_wire() so that gcc doesn't think that the variable
"rv" is uninitialized.
MFC r269485:
Retire pmap_change_wiring().
Reviewed by: alc
Diffstat (limited to 'sys/sparc64')
-rw-r--r-- | sys/sparc64/sparc64/pmap.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 54e0b22..9073760 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -141,6 +141,8 @@ static void pmap_bootstrap_set_tte(struct tte *tp, u_long vpn, u_long data); static void pmap_cache_remove(vm_page_t m, vm_offset_t va); static int pmap_protect_tte(struct pmap *pm1, struct pmap *pm2, struct tte *tp, vm_offset_t va); +static int pmap_unwire_tte(pmap_t pm, pmap_t pm2, struct tte *tp, + vm_offset_t va); /* * Map the given physical page at the specified virtual address in the @@ -1668,27 +1670,40 @@ pmap_object_init_pt(pmap_t pm, vm_offset_t addr, vm_object_t object, ("pmap_object_init_pt: non-device object")); } +static int +pmap_unwire_tte(pmap_t pm, pmap_t pm2, struct tte *tp, vm_offset_t va) +{ + + PMAP_LOCK_ASSERT(pm, MA_OWNED); + if ((tp->tte_data & TD_WIRED) == 0) + panic("pmap_unwire_tte: tp %p is missing TD_WIRED", tp); + atomic_clear_long(&tp->tte_data, TD_WIRED); + pm->pm_stats.wired_count--; + return (1); +} + /* - * Change the wiring attribute for a map/virtual-address pair. - * The mapping must already exist in the pmap. + * Clear the wired attribute from the mappings for the specified range of + * addresses in the given pmap. Every valid mapping within that range must + * have the wired attribute set. In contrast, invalid mappings cannot have + * the wired attribute set, so they are ignored. + * + * The wired attribute of the translation table entry is not a hardware + * feature, so there is no need to invalidate any TLB entries. */ void -pmap_change_wiring(pmap_t pm, vm_offset_t va, boolean_t wired) +pmap_unwire(pmap_t pm, vm_offset_t sva, vm_offset_t eva) { + vm_offset_t va; struct tte *tp; - u_long data; PMAP_LOCK(pm); - if ((tp = tsb_tte_lookup(pm, va)) != NULL) { - if (wired) { - data = atomic_set_long(&tp->tte_data, TD_WIRED); - if ((data & TD_WIRED) == 0) - pm->pm_stats.wired_count++; - } else { - data = atomic_clear_long(&tp->tte_data, TD_WIRED); - if ((data & TD_WIRED) != 0) - pm->pm_stats.wired_count--; - } + if (eva - sva > PMAP_TSB_THRESH) + tsb_foreach(pm, NULL, sva, eva, pmap_unwire_tte); + else { + for (va = sva; va < eva; va += PAGE_SIZE) + if ((tp = tsb_tte_lookup(pm, va)) != NULL) + pmap_unwire_tte(pm, NULL, tp, va); } PMAP_UNLOCK(pm); } |