From owner-svn-src-head@FreeBSD.ORG Sat May 12 20:42:57 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5BDB81065672; Sat, 12 May 2012 20:42:57 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4798C8FC1A; Sat, 12 May 2012 20:42:57 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q4CKgvfP051547; Sat, 12 May 2012 20:42:57 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q4CKgvWJ051542; Sat, 12 May 2012 20:42:57 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201205122042.q4CKgvWJ051542@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 12 May 2012 20:42:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235372 - head/sys/vm X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 12 May 2012 20:42:57 -0000 Author: kib Date: Sat May 12 20:42:56 2012 New Revision: 235372 URL: http://svn.freebsd.org/changeset/base/235372 Log: Add a facility to register a range of physical addresses to be used for allocation of fictitious pages, for which PHYS_TO_VM_PAGE() returns proper fictitious vm_page_t. The range should be de-registered after consumer stopped using it. De-inline the PHYS_TO_VM_PAGE() since it now carries code to iterate over registered ranges. A hash container might be developed instead of range registration interface, and fake pages could be put automatically into the hash, were PHYS_TO_VM_PAGE() could look them up later. This should be considered before the MFC of the commit is done. Sponsored by: The FreeBSD Foundation Reviewed by: alc MFC after: 1 month Modified: head/sys/vm/vm_page.c head/sys/vm/vm_page.h head/sys/vm/vm_phys.c head/sys/vm/vm_phys.h Modified: head/sys/vm/vm_page.c ============================================================================== --- head/sys/vm/vm_page.c Sat May 12 20:41:40 2012 (r235371) +++ head/sys/vm/vm_page.c Sat May 12 20:42:56 2012 (r235372) @@ -633,6 +633,30 @@ vm_page_unhold_pages(vm_page_t *ma, int mtx_unlock(mtx); } +vm_page_t +PHYS_TO_VM_PAGE(vm_paddr_t pa) +{ + vm_page_t m; + +#ifdef VM_PHYSSEG_SPARSE + m = vm_phys_paddr_to_vm_page(pa); + if (m == NULL) + m = vm_phys_fictitious_to_vm_page(pa); + return (m); +#elif defined(VM_PHYSSEG_DENSE) + long pi; + + pi = atop(pa); + if (pi >= first_page && pi < vm_page_array_size) { + m = &vm_page_array[pi - first_page]; + return (m); + } + return (vm_phys_fictitious_to_vm_page(pa)); +#else +#error "Either VM_PHYSSEG_DENSE or VM_PHYSSEG_SPARSE must be defined." +#endif +} + /* * vm_page_getfake: * Modified: head/sys/vm/vm_page.h ============================================================================== --- head/sys/vm/vm_page.h Sat May 12 20:41:40 2012 (r235371) +++ head/sys/vm/vm_page.h Sat May 12 20:42:56 2012 (r235372) @@ -321,19 +321,7 @@ extern long first_page; /* first physi vm_page_t vm_phys_paddr_to_vm_page(vm_paddr_t pa); -static __inline vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); - -static __inline vm_page_t -PHYS_TO_VM_PAGE(vm_paddr_t pa) -{ -#ifdef VM_PHYSSEG_SPARSE - return (vm_phys_paddr_to_vm_page(pa)); -#elif defined(VM_PHYSSEG_DENSE) - return (&vm_page_array[atop(pa) - first_page]); -#else -#error "Either VM_PHYSSEG_DENSE or VM_PHYSSEG_SPARSE must be defined." -#endif -} +vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa); extern struct vpglocks vm_page_queue_lock; Modified: head/sys/vm/vm_phys.c ============================================================================== --- head/sys/vm/vm_phys.c Sat May 12 20:41:40 2012 (r235371) +++ head/sys/vm/vm_phys.c Sat May 12 20:42:56 2012 (r235372) @@ -87,6 +87,15 @@ static struct vm_phys_seg vm_phys_segs[V static int vm_phys_nsegs; +#define VM_PHYS_FICTITIOUS_NSEGS 8 +static struct vm_phys_fictitious_seg { + vm_paddr_t start; + vm_paddr_t end; + vm_page_t first_page; +} vm_phys_fictitious_segs[VM_PHYS_FICTITIOUS_NSEGS]; +static struct mtx vm_phys_fictitious_reg_mtx; +MALLOC_DEFINE(M_FICT_PAGES, "", ""); + static struct vm_freelist vm_phys_free_queues[VM_RAW_NFREELIST][VM_NFREEPOOL][VM_NFREEORDER]; static struct vm_freelist @@ -366,6 +375,8 @@ vm_phys_init(void) for (flind = 0; flind < vm_nfreelists; flind++) vm_phys_lookup_lists[0][flind] = &vm_phys_free_queues[flind]; #endif + + mtx_init(&vm_phys_fictitious_reg_mtx, "vmfctr", NULL, MTX_DEF); } /* @@ -510,6 +521,112 @@ vm_phys_paddr_to_vm_page(vm_paddr_t pa) return (NULL); } +vm_page_t +vm_phys_fictitious_to_vm_page(vm_paddr_t pa) +{ + struct vm_phys_fictitious_seg *seg; + vm_page_t m; + int segind; + + m = NULL; + for (segind = 0; segind < VM_PHYS_FICTITIOUS_NSEGS; segind++) { + seg = &vm_phys_fictitious_segs[segind]; + if (pa >= seg->start && pa < seg->end) { + m = &seg->first_page[atop(pa - seg->start)]; + KASSERT((m->flags & PG_FICTITIOUS) != 0, + ("%p not fictitious", m)); + break; + } + } + return (m); +} + +int +vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end, + vm_memattr_t memattr) +{ + struct vm_phys_fictitious_seg *seg; + vm_page_t fp; + long i, page_count; + int segind; +#ifdef VM_PHYSSEG_DENSE + long pi; + boolean_t malloced; +#endif + + page_count = (end - start) / PAGE_SIZE; + +#ifdef VM_PHYSSEG_DENSE + pi = atop(start); + if (pi >= first_page && atop(end) < vm_page_array_size) { + fp = &vm_page_array[pi - first_page]; + malloced = FALSE; + } else +#endif + { + fp = malloc(page_count * sizeof(struct vm_page), M_FICT_PAGES, + M_WAITOK | M_ZERO); +#ifdef VM_PHYSSEG_DENSE + malloced = TRUE; +#endif + } + for (i = 0; i < page_count; i++) { + vm_page_initfake(&fp[i], start + PAGE_SIZE * i, memattr); + pmap_page_init(&fp[i]); + fp[i].oflags &= ~(VPO_BUSY | VPO_UNMANAGED); + } + mtx_lock(&vm_phys_fictitious_reg_mtx); + for (segind = 0; segind < VM_PHYS_FICTITIOUS_NSEGS; segind++) { + seg = &vm_phys_fictitious_segs[segind]; + if (seg->start == 0 && seg->end == 0) { + seg->start = start; + seg->end = end; + seg->first_page = fp; + mtx_unlock(&vm_phys_fictitious_reg_mtx); + return (0); + } + } + mtx_unlock(&vm_phys_fictitious_reg_mtx); +#ifdef VM_PHYSSEG_DENSE + if (malloced) +#endif + free(fp, M_FICT_PAGES); + return (EBUSY); +} + +void +vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end) +{ + struct vm_phys_fictitious_seg *seg; + vm_page_t fp; + int segind; +#ifdef VM_PHYSSEG_DENSE + long pi; +#endif + +#ifdef VM_PHYSSEG_DENSE + pi = atop(start); +#endif + + mtx_lock(&vm_phys_fictitious_reg_mtx); + for (segind = 0; segind < VM_PHYS_FICTITIOUS_NSEGS; segind++) { + seg = &vm_phys_fictitious_segs[segind]; + if (seg->start == start && seg->end == end) { + seg->start = seg->end = 0; + fp = seg->first_page; + seg->first_page = NULL; + mtx_unlock(&vm_phys_fictitious_reg_mtx); +#ifdef VM_PHYSSEG_DENSE + if (pi < first_page || atop(end) >= vm_page_array_size) +#endif + free(fp, M_FICT_PAGES); + return; + } + } + mtx_unlock(&vm_phys_fictitious_reg_mtx); + KASSERT(0, ("Unregistering not registered fictitious range")); +} + /* * Find the segment containing the given physical address. */ Modified: head/sys/vm/vm_phys.h ============================================================================== --- head/sys/vm/vm_phys.h Sat May 12 20:41:40 2012 (r235371) +++ head/sys/vm/vm_phys.h Sat May 12 20:42:56 2012 (r235372) @@ -57,6 +57,10 @@ vm_page_t vm_phys_alloc_contig(u_long np u_long alignment, vm_paddr_t boundary); vm_page_t vm_phys_alloc_freelist_pages(int flind, int pool, int order); vm_page_t vm_phys_alloc_pages(int pool, int order); +int vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end, + vm_memattr_t memattr); +void vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end); +vm_page_t vm_phys_fictitious_to_vm_page(vm_paddr_t pa); void vm_phys_free_contig(vm_page_t m, u_long npages); void vm_phys_free_pages(vm_page_t m, int order); void vm_phys_init(void);