diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2007-05-29 02:36:20 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2007-05-29 02:36:20 +0000 |
commit | 17d8bd4bf87531fc31c4ea301438da0f7355d137 (patch) | |
tree | 77e6a6422e8bdf3d840a3ff1a940053fae2fb4b8 | |
parent | afc6d2c3ebf4a335b4913c815891553e43d25d28 (diff) |
PMAP_STEAL_MEMORY for amd64
drahn@ ok
-rw-r--r-- | sys/arch/amd64/amd64/pmap.c | 71 | ||||
-rw-r--r-- | sys/arch/amd64/include/pmap.h | 3 |
2 files changed, 69 insertions, 5 deletions
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 15e60b4da0a..464f19a6e18 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.24 2007/05/27 08:58:31 art Exp $ */ +/* $OpenBSD: pmap.c,v 1.25 2007/05/29 02:36:19 art Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* @@ -2376,15 +2376,16 @@ pmap_get_physpage(vaddr_t va, int level, paddr_t *paddrp) struct pmap *kpm = pmap_kernel(); if (uvm.page_init_done == FALSE) { + vaddr_t va; + /* * we're growing the kernel pmap early (from * uvm_pageboot_alloc()). this case must be * handled a little differently. */ - if (uvm_page_physget(paddrp) == FALSE) - panic("pmap_get_physpage: out of memory"); - memset((void *)PMAP_DIRECT_MAP(*paddrp), 0, PAGE_SIZE); + va = pmap_steal_memory(PAGE_SIZE, NULL, NULL); + *paddrp = PMAP_DIRECT_UNMAP(va); } else { ptp = uvm_pagealloc(&kpm->pm_obj[level - 1], ptp_va2o(va, level), NULL, @@ -2510,6 +2511,68 @@ pmap_growkernel(vaddr_t maxkvaddr) return maxkvaddr; } +vaddr_t +pmap_steal_memory(vsize_t size, vaddr_t *start, vaddr_t *end) +{ + int segno; + u_int npg; + vaddr_t va; + paddr_t pa; + struct vm_physseg *seg; + + size = round_page(size); + npg = atop(size); + + for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) { + if (seg->avail_end - seg->avail_start < npg) + continue; + /* + * We can only steal at an ``unused'' segment boundary, + * i.e. either at the start or at the end. + */ + if (seg->avail_start == seg->start || + seg->avail_end == seg->end) + break; + } + if (segno == vm_nphysseg) { + panic("pmap_steal_memory: out of memory"); + } else { + if (seg->avail_start == seg->start) { + pa = ptoa(seg->avail_start); + seg->avail_start += npg; + seg->start += npg; + } else { + pa = ptoa(seg->avail_end) - size; + seg->avail_end -= npg; + seg->end -= npg; + } + /* + * If all the segment has been consumed now, remove it. + * Note that the crash dump code still knows about it + * and will dump it correctly. + */ + if (seg->start == seg->end) { + if (vm_nphysseg-- == 1) + panic("pmap_steal_memory: out of memory"); + while (segno < vm_nphysseg) { + seg[0] = seg[1]; /* struct copy */ + seg++; + segno++; + } + } + + va = PMAP_DIRECT_MAP(pa); + memset((void *)va, 0, size); + } + + if (start != NULL) + *start = virtual_avail; + if (end != NULL) + *end = VM_MAX_KERNEL_ADDRESS; + + return (va); +} + #ifdef DEBUG void pmap_dump(struct pmap *, vaddr_t, vaddr_t); diff --git a/sys/arch/amd64/include/pmap.h b/sys/arch/amd64/include/pmap.h index 2aa0fefb23f..65af4832e94 100644 --- a/sys/arch/amd64/include/pmap.h +++ b/sys/arch/amd64/include/pmap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.h,v 1.14 2007/05/27 21:06:05 jason Exp $ */ +/* $OpenBSD: pmap.h,v 1.15 2007/05/29 02:36:19 art Exp $ */ /* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */ /* @@ -433,6 +433,7 @@ void pmap_prealloc_lowmem_ptps(void); void pagezero(vaddr_t); +#define PMAP_STEAL_MEMORY /* enable pmap_steal_memory() */ #define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */ /* |