Module Name: src Committed By: uebayasi Date: Sun Apr 25 15:23:28 UTC 2010
Modified Files: src/sys/uvm [uebayasi-xip]: uvm_page.c Log Message: Refactor uvm_page_physload_common(). Memory allocation failure here is critical; panic if it happens. To generate a diff of this commit: cvs rdiff -u -r1.153.2.17 -r1.153.2.18 src/sys/uvm/uvm_page.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_page.c diff -u src/sys/uvm/uvm_page.c:1.153.2.17 src/sys/uvm/uvm_page.c:1.153.2.18 --- src/sys/uvm/uvm_page.c:1.153.2.17 Sun Apr 25 10:15:41 2010 +++ src/sys/uvm/uvm_page.c Sun Apr 25 15:23:27 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.c,v 1.153.2.17 2010/04/25 10:15:41 uebayasi Exp $ */ +/* $NetBSD: uvm_page.c,v 1.153.2.18 2010/04/25 15:23:27 uebayasi Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.17 2010/04/25 10:15:41 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.18 2010/04/25 15:23:27 uebayasi Exp $"); #include "opt_ddb.h" #include "opt_uvmhist.h" @@ -101,6 +101,7 @@ * physical memory config is stored in vm_physmem. */ /* XXXUEBS make these array of pointers */ +/* XXXUEBS merge these two */ struct vm_physseg vm_physmem[VM_PHYSSEG_MAX]; /* XXXCDC: uvm.physmem */ int vm_nphysmem = 0; /* XXXCDC: uvm.nphysmem */ @@ -748,8 +749,19 @@ */ static struct vm_physseg * -uvm_page_physload_common(struct vm_physseg * const, const int, +uvm_page_physload_common(struct vm_physseg * const, int *, const paddr_t, const paddr_t, const paddr_t, const paddr_t, const int); +#if 0 +static void +uvm_page_physunload_common(struct vm_physseg * const); +#endif +void +uvm_page_physload_common_alloc_pgs(struct vm_physseg *, + const paddr_t, const paddr_t, + const paddr_t, const paddr_t, const int); +static struct vm_physseg * +uvm_physseg_insert(struct vm_physseg *, int, + const paddr_t, const paddr_t); void * uvm_page_physload(paddr_t start, paddr_t end, paddr_t avail_start, @@ -757,9 +769,8 @@ { struct vm_physseg *seg; - seg = uvm_page_physload_common(vm_physmem, vm_nphysmem, start, end, + seg = uvm_page_physload_common(vm_physmem, &vm_nphysmem, start, end, avail_start, avail_end, free_list); - vm_nphysmem++; return seg; } @@ -770,9 +781,8 @@ { struct vm_physseg *seg; - seg = uvm_page_physload_common(vm_physdev, vm_nphysdev, start, end, + seg = uvm_page_physload_common(vm_physdev, &vm_nphysdev, start, end, avail_start, avail_end, free_list); - vm_nphysdev++; for (paddr_t pf = start; pf < end; pf++) vm_page_device_mdpage_insert(pf); @@ -781,13 +791,11 @@ #endif static struct vm_physseg * -uvm_page_physload_common(struct vm_physseg * const segs, const int nsegs, +uvm_page_physload_common(struct vm_physseg * const segs, int *rnsegs, const paddr_t start, const paddr_t end, const paddr_t avail_start, const paddr_t avail_end, const int free_list) { - int preload, lcv; - psize_t npages; - struct vm_page *pgs; + int lcv; struct vm_physseg *ps; if (uvmexp.pagesize == 0) @@ -796,84 +804,101 @@ panic("uvm_page_physload: bad free list %d", free_list); if (start >= end) panic("uvm_page_physload: start >= end"); - - /* - * do we have room? - */ - - if (nsegs == VM_PHYSSEG_MAX) { - printf("uvm_page_physload: unable to load physical memory " - "segment\n"); - printf("\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n", + if (*rnsegs == VM_PHYSSEG_MAX) + panic("uvm_page_physload: unable to load physical memory " + "segment\n" + "\t%d segments allocated, ignoring 0x%llx -> 0x%llx\n" + "\tincrease VM_PHYSSEG_MAX\n", VM_PHYSSEG_MAX, (long long)start, (long long)end); - printf("\tincrease VM_PHYSSEG_MAX\n"); - return NULL; - } -#ifdef DEVICE_PAGE - if (segs == vm_physdev) { - preload = false; - goto uvm_page_physload_common_insert; - } -#endif - - /* - * check to see if this is a "preload" (i.e. uvm_mem_init hasn't been - * called yet, so malloc is not available). - */ + ps = uvm_physseg_insert(segs, *rnsegs, start, end); + ps->start = start; + ps->end = end; - for (lcv = 0 ; lcv < nsegs ; lcv++) { - if (segs[lcv].pgs) - break; + if (segs == vm_physmem) { + ps->avail_start = avail_start; + ps->avail_end = avail_end; + /* + * check to see if this is a "preload" (i.e. uvm_mem_init hasn't been + * called yet, so malloc is not available). + */ + for (lcv = 0; lcv < *rnsegs; lcv++) { + if (segs[lcv].pgs) + break; + } + if (lcv == *rnsegs) { + /* "preload" - can't use malloc */ + ps->pgs = NULL; + ps->endpg = NULL; + ps->free_list = free_list; /* XXX */ + } else { + uvm_page_physload_common_alloc_pgs(ps, start, end, + avail_start, avail_end, free_list); + } + } else { + /* XXX */ } - preload = (lcv == nsegs); - /* - * if VM is already running, attempt to malloc() vm_page structures - */ - /* XXXUEBS this is super ugly */ + (*rnsegs)++; + return ps; +} + +/* + * if VM is already running, attempt to malloc() vm_page structures + */ +/* XXXUEBS this is super ugly */ +/* XXXUEBS struct vm_page [] should be allocated in the added segment itself + for NUMA's sake. */ +void +uvm_page_physload_common_alloc_pgs(struct vm_physseg *ps, + const paddr_t start, const paddr_t end, + const paddr_t avail_start, const paddr_t avail_end, const int free_list) +{ + struct vm_page *pgs; + psize_t npages; - if (!preload) { #if defined(VM_PHYSSEG_NOADD) - panic("uvm_page_physload: tried to add RAM after vm_mem_init"); + panic("uvm_page_physload: tried to add RAM after vm_mem_init"); #else - /* XXXCDC: need some sort of lockout for this case */ - paddr_t paddr; - npages = end - start; /* # of pages */ - pgs = malloc(sizeof(struct vm_page) * npages, - M_VMPAGE, M_NOWAIT); - if (pgs == NULL) { - printf("uvm_page_physload: can not malloc vm_page " - "structs for segment\n"); - printf("\tignoring 0x%lx -> 0x%lx\n", start, end); - return NULL; - } - /* zero data, init phys_addr, free_list, and free pages */ - memset(pgs, 0, sizeof(struct vm_page) * npages); - for (lcv = 0, paddr = ptoa(start) ; - lcv < npages ; lcv++, paddr += PAGE_SIZE) { + /* XXXCDC: need some sort of lockout for this case */ + paddr_t paddr; + npages = end - start; /* # of pages */ + pgs = malloc(sizeof(struct vm_page) * npages, + M_VMPAGE, M_NOWAIT); + if (pgs == NULL) { + panic("uvm_page_physload: can not malloc vm_page " + "structs for segment\n" + "0x%lx -> 0x%lx\n, start, end); + } + /* zero data, init phys_addr, free_list, and free pages */ + memset(pgs, 0, sizeof(struct vm_page) * npages); + for (lcv = 0, paddr = ptoa(start); lcv < npages; + lcv++, paddr += PAGE_SIZE) { #if 1 - pgs[lcv].phys_addr = paddr; + pgs[lcv].phys_addr = paddr; #endif - pgs[lcv].free_list = free_list; - if (atop(paddr) >= avail_start && - atop(paddr) <= avail_end) - uvm_pagefree(&pgs[lcv]); - } - /* XXXCDC: incomplete: need to update uvmexp.free, what else? */ - /* XXXCDC: need hook to tell pmap to rebuild pv_list, etc... */ -#endif - } else { - pgs = NULL; - npages = 0; + pgs[lcv].free_list = free_list; + if (atop(paddr) >= avail_start && + atop(paddr) <= avail_end) + uvm_pagefree(&pgs[lcv]); } - -#ifdef DEVICE_PAGE -uvm_page_physload_common_insert: + /* XXXCDC: incomplete: need to update uvmexp.free, what else? */ + /* XXXCDC: need hook to tell pmap to rebuild pv_list, etc... */ #endif - /* - * now insert us in the proper place in segs[] - */ + + ps->pgs = pgs; + ps->endpg = pgs + npages; + ps->free_list = free_list; + + uvmpdpol_reinit(); +} + +static struct vm_physseg * +uvm_physseg_insert(struct vm_physseg *segs, int nsegs, + const paddr_t start, const paddr_t end) +{ + struct vm_physseg *ps; + int lcv; #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) /* random: put it at the end (easy!) */ @@ -908,25 +933,6 @@ #else panic("uvm_page_physload: unknown physseg strategy selected!"); #endif - - ps->start = start; - ps->end = end; - -#ifdef DEVICE_PAGE - if (segs == vm_physdev) - return ps; -#endif - - /* XXXUEBS ugly */ - ps->avail_start = avail_start; - ps->avail_end = avail_end; - ps->pgs = pgs; - ps->endpg = pgs + npages; - ps->free_list = free_list; - - if (!preload) { - uvmpdpol_reinit(); - } return ps; }