Date: Mon, 25 Mar 2013 13:03:24 +0000 (UTC) From: "Cherry G. Mathew" <cherry@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r248701 - projects/amd64_xen_pv/sys/amd64/xen Message-ID: <201303251303.r2PD3OOZ019458@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: cherry Date: Mon Mar 25 13:03:24 2013 New Revision: 248701 URL: http://svnweb.freebsd.org/changeset/base/248701 Log: Add a two functions to pmap_pv tracking: i) To run a callback on every iterated entry ii) To free a pv entry and it's associated chunk (from amd64/amd64/pmap.c) Approved by: gibbs(implicit) Modified: projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.c projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.h Modified: projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.c ============================================================================== --- projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.c Mon Mar 25 12:38:45 2013 (r248700) +++ projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.c Mon Mar 25 13:03:24 2013 (r248701) @@ -168,6 +168,58 @@ pv_to_chunk(pv_entry_t pv) #include <vm/vm_extern.h> #include <vm/vm_kern.h> + + +static void +free_pv_chunk(struct pv_chunk *pc) +{ + vm_page_t m; + + mtx_lock(&pv_chunks_mutex); + TAILQ_REMOVE(&pv_chunks, pc, pc_lru); + mtx_unlock(&pv_chunks_mutex); + PV_STAT(atomic_subtract_int(&pv_entry_spare, _NPCPV)); + PV_STAT(atomic_subtract_int(&pc_chunk_count, 1)); + PV_STAT(atomic_add_int(&pc_chunk_frees, 1)); + /* entire chunk is free, return it */ + m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pc)); + pmap_kremove((vm_offset_t)pc); + dump_drop_page(m->phys_addr); + vm_page_unwire(m, 0); + vm_page_free(m); +} + +/* + * free the pv_entry back to the free list + */ +static void +free_pv_entry(pmap_t pmap, pv_entry_t pv) +{ + struct pv_chunk *pc; + int idx, field, bit; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + PV_STAT(atomic_add_long(&pv_entry_frees, 1)); + PV_STAT(atomic_add_int(&pv_entry_spare, 1)); + PV_STAT(atomic_subtract_long(&pv_entry_count, 1)); + pc = pv_to_chunk(pv); + idx = pv - &pc->pc_pventry[0]; + field = idx / 64; + bit = idx % 64; + pc->pc_map[field] |= 1ul << bit; + if (pc->pc_map[0] != PC_FREE0 || pc->pc_map[1] != PC_FREE1 || + pc->pc_map[2] != PC_FREE2) { + /* 98% of the time, pc is already at the head of the list. */ + if (__predict_false(pc != TAILQ_FIRST(&pmap->pm_pvchunk))) { + TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); + TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list); + } + return; + } + TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); + free_pv_chunk(pc); +} + pv_entry_t pmap_get_pv_entry(pmap_t pmap) { @@ -281,6 +333,7 @@ pmap_free_pv_entry(pmap_t pmap, vm_offse TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { if (pmap == PV_PMAP(pv) && va == pv->pv_va) { TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); + free_pv_entry(pmap, pv); found = true; break; } @@ -384,3 +437,40 @@ pmap_pv_vm_page_mapped(pmap_t pmap, vm_p (VM_MAX_KERNEL_ADDRESS + 1)) ? false : true; } + +/* + * Iterate through all mappings, until callback returns 'true' + * Returns the number of iterations. + */ + +int +pmap_pv_iterate(vm_page_t m, pv_cb_t cb) +{ + int iter = 0; + pv_entry_t next_pv, pv; + + rw_wlock(&pvh_global_lock); + + TAILQ_FOREACH_SAFE(pv, &m->md.pv_list, pv_list, next_pv) { + iter++; + if (cb(PV_PMAP(pv), pv->pv_va, m)) break; + } + rw_wunlock(&pvh_global_lock); + return iter; +} + +/* + * Destroy all pv mappings for a given physical page. + */ +void +pmap_pv_page_unmap(vm_page_t m) +{ + pv_entry_t pv, next_pv; + + rw_wlock(&pvh_global_lock); + TAILQ_FOREACH_SAFE(pv, &m->md.pv_list, pv_list, next_pv) { + TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); + } + rw_wunlock(&pvh_global_lock); + return; +} Modified: projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.h ============================================================================== --- projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.h Mon Mar 25 12:38:45 2013 (r248700) +++ projects/amd64_xen_pv/sys/amd64/xen/pmap_pv.h Mon Mar 25 13:03:24 2013 (r248701) @@ -36,6 +36,12 @@ #ifndef _MACHINE_PMAP_PV_H_ #define _MACHINE_PMAP_PV_H_ +/* + * Used as a callback when iterating through multiple pmaps + * If the callback returns 'true', iteration is stopped. + */ +typedef bool pv_cb_t(pmap_t pmap, vm_offset_t va, vm_page_t m) ; + void pmap_pv_init(void); void pmap_pv_pmap_init(pmap_t pmap); void pmap_pv_vm_page_init(vm_page_t m); @@ -45,5 +51,7 @@ pv_entry_t pmap_get_pv_entry(pmap_t pmap void pmap_put_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m); bool pmap_free_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m); pv_entry_t pmap_find_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m); +int pmap_pv_iterate(vm_page_t m, pv_cb_t cb); +void pmap_pv_page_unmap(vm_page_t m); #endif /* !_MACHINE_PMAP_PV_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303251303.r2PD3OOZ019458>