Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/arm/pmap-v6.c
Show First 20 Lines • Show All 2,537 Lines • ▼ Show 20 Lines | if (pte1_is_link(pte1)) { | ||||
*/ | */ | ||||
m = _pmap_allocpte2(pmap, va, flags); | m = _pmap_allocpte2(pmap, va, flags); | ||||
if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0) | if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0) | ||||
goto retry; | goto retry; | ||||
} | } | ||||
return (m); | return (m); | ||||
} | } | ||||
static __inline void | |||||
pmap_free_zero_pages(struct spglist *free) | |||||
{ | |||||
vm_page_t m; | |||||
while ((m = SLIST_FIRST(free)) != NULL) { | |||||
SLIST_REMOVE_HEAD(free, plinks.s.ss); | |||||
/* Preserve the page's PG_ZERO setting. */ | |||||
vm_page_free_toq(m); | |||||
} | |||||
} | |||||
/* | /* | ||||
markj: Style requires a blank line at the beginning of the function if there are no local variable… | |||||
Not Done Inline ActionsThe function is removed. ota_j.email.ne.jp: The function is removed. | |||||
* Schedule the specified unused L2 page table page to be freed. Specifically, | * Schedule the specified unused L2 page table page to be freed. Specifically, | ||||
* add the page to the specified list of pages that will be released to the | * add the page to the specified list of pages that will be released to the | ||||
* physical memory manager after the TLB has been updated. | * physical memory manager after the TLB has been updated. | ||||
*/ | */ | ||||
static __inline void | static __inline void | ||||
pmap_add_delayed_free_list(vm_page_t m, struct spglist *free) | pmap_add_delayed_free_list(vm_page_t m, struct spglist *free) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 368 Lines • ▼ Show 20 Lines | out: | ||||
} | } | ||||
if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) { | if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) { | ||||
m_pc = SLIST_FIRST(&free); | m_pc = SLIST_FIRST(&free); | ||||
SLIST_REMOVE_HEAD(&free, plinks.s.ss); | SLIST_REMOVE_HEAD(&free, plinks.s.ss); | ||||
/* Recycle a freed page table page. */ | /* Recycle a freed page table page. */ | ||||
m_pc->wire_count = 1; | m_pc->wire_count = 1; | ||||
atomic_add_int(&vm_cnt.v_wire_count, 1); | atomic_add_int(&vm_cnt.v_wire_count, 1); | ||||
} | } | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, false); | ||||
return (m_pc); | return (m_pc); | ||||
} | } | ||||
static void | static void | ||||
free_pv_chunk(struct pv_chunk *pc) | free_pv_chunk(struct pv_chunk *pc) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
▲ Show 20 Lines • Show All 746 Lines • ▼ Show 20 Lines | if ((opte1 & PTE1_A) == 0 || (m = pmap_pt2_page(pmap, va)) == NULL) { | ||||
* "failure" if the mapping was never accessed or the | * "failure" if the mapping was never accessed or the | ||||
* allocation of the new page table page fails. | * allocation of the new page table page fails. | ||||
*/ | */ | ||||
if ((opte1 & PTE1_A) == 0 || (m = vm_page_alloc(NULL, | if ((opte1 & PTE1_A) == 0 || (m = vm_page_alloc(NULL, | ||||
pte1_index(va) & ~PT2PG_MASK, VM_ALLOC_NOOBJ | | pte1_index(va) & ~PT2PG_MASK, VM_ALLOC_NOOBJ | | ||||
VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) { | VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) { | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
pmap_remove_pte1(pmap, pte1p, pte1_trunc(va), &free); | pmap_remove_pte1(pmap, pte1p, pte1_trunc(va), &free); | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, false); | ||||
CTR3(KTR_PMAP, "%s: failure for va %#x in pmap %p", | CTR3(KTR_PMAP, "%s: failure for va %#x in pmap %p", | ||||
__func__, va, pmap); | __func__, va, pmap); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
if (va < VM_MAXUSER_ADDRESS) | if (va < VM_MAXUSER_ADDRESS) | ||||
pmap->pm_stats.resident_count++; | pmap->pm_stats.resident_count++; | ||||
isnew = 1; | isnew = 1; | ||||
▲ Show 20 Lines • Show All 507 Lines • ▼ Show 20 Lines | for (pte2p = pmap_pte2_quick(pmap, sva); sva != nextva; | ||||
if (pmap_remove_pte2(pmap, pte2p, sva, &free)) | if (pmap_remove_pte2(pmap, pte2p, sva, &free)) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
out: | out: | ||||
sched_unpin(); | sched_unpin(); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, false); | ||||
} | } | ||||
/* | /* | ||||
* Routine: pmap_remove_all | * Routine: pmap_remove_all | ||||
* Function: | * Function: | ||||
* Removes this physical page from | * Removes this physical page from | ||||
* all physical maps in which it resides. | * all physical maps in which it resides. | ||||
* Reflects back modify bits to the pager. | * Reflects back modify bits to the pager. | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { | ||||
pmap_unuse_pt2(pmap, pv->pv_va, &free); | pmap_unuse_pt2(pmap, pv->pv_va, &free); | ||||
TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); | TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); | ||||
free_pv_entry(pmap, pv); | free_pv_entry(pmap, pv); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
} | } | ||||
vm_page_aflag_clear(m, PGA_WRITEABLE); | vm_page_aflag_clear(m, PGA_WRITEABLE); | ||||
sched_unpin(); | sched_unpin(); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, false); | ||||
} | } | ||||
/* | /* | ||||
* Just subroutine for pmap_remove_pages() to reasonably satisfy | * Just subroutine for pmap_remove_pages() to reasonably satisfy | ||||
* good coding style, a.k.a. 80 character line width limit hell. | * good coding style, a.k.a. 80 character line width limit hell. | ||||
*/ | */ | ||||
static __inline void | static __inline void | ||||
pmap_remove_pte1_quick(pmap_t pmap, pt1_entry_t pte1, pv_entry_t pv, | pmap_remove_pte1_quick(pmap_t pmap, pt1_entry_t pte1, pv_entry_t pv, | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | if (allfree) { | ||||
TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); | TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); | ||||
free_pv_chunk(pc); | free_pv_chunk(pc); | ||||
} | } | ||||
} | } | ||||
tlb_flush_all_ng_local(); | tlb_flush_all_ng_local(); | ||||
sched_unpin(); | sched_unpin(); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, false); | ||||
} | } | ||||
/* | /* | ||||
* This code makes some *MAJOR* assumptions: | * This code makes some *MAJOR* assumptions: | ||||
* 1. Current pmap & pmap exists. | * 1. Current pmap & pmap exists. | ||||
* 2. Not wired. | * 2. Not wired. | ||||
* 3. Read access. | * 3. Read access. | ||||
* 4. No L2 page table pages. | * 4. No L2 page table pages. | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, | ||||
* Enter on the PV list if part of our managed memory. | * Enter on the PV list if part of our managed memory. | ||||
*/ | */ | ||||
if ((m->oflags & VPO_UNMANAGED) == 0 && | if ((m->oflags & VPO_UNMANAGED) == 0 && | ||||
!pmap_try_insert_pv_entry(pmap, va, m)) { | !pmap_try_insert_pv_entry(pmap, va, m)) { | ||||
if (mpt2pg != NULL) { | if (mpt2pg != NULL) { | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
if (pmap_unwire_pt2(pmap, va, mpt2pg, &free)) { | if (pmap_unwire_pt2(pmap, va, mpt2pg, &free)) { | ||||
pmap_tlb_flush(pmap, va); | pmap_tlb_flush(pmap, va); | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, false); | ||||
} | } | ||||
mpt2pg = NULL; | mpt2pg = NULL; | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 1,457 Lines • ▼ Show 20 Lines | while (addr < nextva) { | ||||
temp_pte2 |= PTE2_NM; | temp_pte2 |= PTE2_NM; | ||||
pte2_store(dst_pte2p, temp_pte2); | pte2_store(dst_pte2p, temp_pte2); | ||||
dst_pmap->pm_stats.resident_count++; | dst_pmap->pm_stats.resident_count++; | ||||
} else { | } else { | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
if (pmap_unwire_pt2(dst_pmap, addr, | if (pmap_unwire_pt2(dst_pmap, addr, | ||||
dst_mpt2pg, &free)) { | dst_mpt2pg, &free)) { | ||||
pmap_tlb_flush(dst_pmap, addr); | pmap_tlb_flush(dst_pmap, addr); | ||||
pmap_free_zero_pages(&free); | vm_page_free_spglist(&free, | ||||
false); | |||||
} | } | ||||
goto out; | goto out; | ||||
} | } | ||||
if (pt2_wirecount_get(dst_mpt2pg, pte1_idx) >= | if (pt2_wirecount_get(dst_mpt2pg, pte1_idx) >= | ||||
pt2_wirecount_get(src_mpt2pg, pte1_idx)) | pt2_wirecount_get(src_mpt2pg, pte1_idx)) | ||||
break; | break; | ||||
} | } | ||||
addr += PAGE_SIZE; | addr += PAGE_SIZE; | ||||
▲ Show 20 Lines • Show All 809 Lines • Show Last 20 Lines |
Style requires a blank line at the beginning of the function if there are no local variable definitions.