? sys/arch/i386/conf/TYAN251X ? sys/arch/i386/conf/TYAN251X.MP ? sys/arch/i386/conf/TYAN251X.MPDEBUG ? usr.sbin/user/.gdbinit ? usr.sbin/user/group.cat8 ? usr.sbin/user/groupadd.cat8 ? usr.sbin/user/groupdel ? usr.sbin/user/groupdel.cat8 ? usr.sbin/user/groupinfo.cat8 ? usr.sbin/user/groupmod.cat8 ? usr.sbin/user/user ? usr.sbin/user/user.c.diff ? usr.sbin/user/user.cat8 ? usr.sbin/user/useradd.cat8 ? usr.sbin/user/userdel.cat8 ? usr.sbin/user/userinfo.cat8 ? usr.sbin/user/usermgmt.conf.cat5 ? usr.sbin/user/usermod.cat8 Index: sys/arch/amd64/amd64/pmap.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/pmap.c,v retrieving revision 1.9.2.1.2.1 diff -u -r1.9.2.1.2.1 pmap.c --- sys/arch/amd64/amd64/pmap.c 8 Jun 2005 11:34:04 -0000 1.9.2.1.2.1 +++ sys/arch/amd64/amd64/pmap.c 16 Jun 2005 17:23:36 -0000 @@ -1608,7 +1608,7 @@ /* unmap the page */ dead_entries = NULL; uvm_unmap_remove(map, (vaddr_t)pvp, ((vaddr_t)pvp) + PAGE_SIZE, - &dead_entries); + &dead_entries, NULL); vm_map_unlock(map); if (dead_entries != NULL) Index: sys/arch/i386/i386/pmap.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/pmap.c,v retrieving revision 1.171.2.1.2.1 diff -u -r1.171.2.1.2.1 pmap.c --- sys/arch/i386/i386/pmap.c 8 Jun 2005 11:29:43 -0000 1.171.2.1.2.1 +++ sys/arch/i386/i386/pmap.c 16 Jun 2005 17:23:37 -0000 @@ -1494,7 +1494,7 @@ /* unmap the page */ dead_entries = NULL; uvm_unmap_remove(map, (vaddr_t)pvp, ((vaddr_t)pvp) + PAGE_SIZE, - &dead_entries); + &dead_entries, NULL); vm_map_unlock(map); if (dead_entries != NULL) Index: sys/arch/pc532/pc532/pmap.c =================================================================== RCS file: /cvsroot/src/sys/arch/pc532/pc532/pmap.c,v retrieving revision 1.74.6.1 diff -u -r1.74.6.1 pmap.c --- sys/arch/pc532/pc532/pmap.c 8 Jun 2005 11:35:09 -0000 1.74.6.1 +++ sys/arch/pc532/pc532/pmap.c 16 Jun 2005 17:23:37 -0000 @@ -1170,7 +1170,7 @@ /* unmap the page */ dead_entries = NULL; uvm_unmap_remove(map, (vaddr_t)pvp, ((vaddr_t)pvp) + PAGE_SIZE, - &dead_entries); + &dead_entries, NULL); vm_map_unlock(map); if (dead_entries != NULL) Index: sys/arch/xen/i386/pmap.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/i386/pmap.c,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 pmap.c --- sys/arch/xen/i386/pmap.c 22 May 2004 15:57:52 -0000 1.1.2.1 +++ sys/arch/xen/i386/pmap.c 16 Jun 2005 17:23:38 -0000 @@ -1690,7 +1690,7 @@ /* unmap the page */ dead_entries = NULL; uvm_unmap_remove(map, (vaddr_t)pvp, ((vaddr_t)pvp) + PAGE_SIZE, - &dead_entries); + &dead_entries, NULL); vm_map_unlock(map); if (dead_entries != NULL) Index: sys/uvm/uvm.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm.h,v retrieving revision 1.37 diff -u -r1.37 uvm.h --- sys/uvm/uvm.h 10 Feb 2004 01:30:49 -0000 1.37 +++ sys/uvm/uvm.h 16 Jun 2005 17:23:38 -0000 @@ -110,8 +110,6 @@ struct vm_anon *afree; /* anon free list */ struct simplelock afreelock; /* lock on anon free list */ - /* static kernel map entry pool */ - struct vm_map_entry *kentry_free; /* free page pool */ struct simplelock kentry_lock; /* aio_done is locked by uvm.pagedaemon_lock and splbio! */ Index: sys/uvm/uvm_amap.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_amap.c,v retrieving revision 1.53.4.1 diff -u -r1.53.4.1 uvm_amap.c --- sys/uvm/uvm_amap.c 16 Mar 2005 12:11:12 -0000 1.53.4.1 +++ sys/uvm/uvm_amap.c 16 Jun 2005 17:23:38 -0000 @@ -767,10 +767,10 @@ UVMHIST_LOG(maphist, " chunk amap ==> clip 0x%x->0x%x" "to 0x%x->0x%x", entry->start, entry->end, startva, endva); - UVM_MAP_CLIP_START(map, entry, startva); + UVM_MAP_CLIP_START(map, entry, startva, NULL); /* watch out for endva wrap-around! */ if (endva >= startva) - UVM_MAP_CLIP_END(map, entry, endva); + UVM_MAP_CLIP_END(map, entry, endva, NULL); } UVMHIST_LOG(maphist, "<- done [creating new amap 0x%x->0x%x]", Index: sys/uvm/uvm_extern.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_extern.h,v retrieving revision 1.91 diff -u -r1.91 uvm_extern.h --- sys/uvm/uvm_extern.h 24 Mar 2004 07:55:01 -0000 1.91 +++ sys/uvm/uvm_extern.h 16 Jun 2005 17:23:38 -0000 @@ -143,6 +143,7 @@ #define UVM_FLAG_AMAPPAD 0x100000 /* for bss: pad amap to reduce malloc() */ #define UVM_FLAG_TRYLOCK 0x200000 /* fail if we can not lock map */ #define UVM_FLAG_NOWAIT 0x400000 /* not allowed to sleep */ +#define UVM_FLAG_QUANTUM 0x800000 /* entry never be splitted later */ /* macros to extract info */ #define UVM_PROTECTION(X) ((X) & UVM_PROT_MASK) Index: sys/uvm/uvm_io.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_io.c,v retrieving revision 1.18 diff -u -r1.18 uvm_io.c --- sys/uvm/uvm_io.c 23 Apr 2003 00:55:21 -0000 1.18 +++ sys/uvm/uvm_io.c 16 Jun 2005 17:23:38 -0000 @@ -142,7 +142,8 @@ */ vm_map_lock(kernel_map); - uvm_unmap_remove(kernel_map, kva, kva + chunksz, &dead_entries); + uvm_unmap_remove(kernel_map, kva, kva + chunksz, &dead_entries, + NULL); vm_map_unlock(kernel_map); if (dead_entries != NULL) uvm_unmap_detach(dead_entries, AMAP_REFALL); Index: sys/uvm/uvm_km.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_km.c,v retrieving revision 1.69 diff -u -r1.69 uvm_km.c --- sys/uvm/uvm_km.c 24 Mar 2004 07:47:32 -0000 1.69 +++ sys/uvm/uvm_km.c 16 Jun 2005 17:23:38 -0000 @@ -155,6 +155,7 @@ */ static struct vm_map kernel_map_store; +static struct vm_map_entry kernel_first_mapent_store; /* * uvm_km_init: init kernel maps and objects to reflect reality (i.e. @@ -187,12 +188,25 @@ uvm_map_setup(&kernel_map_store, base, end, VM_MAP_PAGEABLE); kernel_map_store.pmap = pmap_kernel(); - if (start != base && - uvm_map(&kernel_map_store, &base, start - base, NULL, - UVM_UNKNOWN_OFFSET, 0, + if (start != base) { + int error; + struct uvm_map_args args; + + error = uvm_map_prepare(&kernel_map_store, base, start - base, + NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE, - UVM_ADV_RANDOM, UVM_FLAG_FIXED)) != 0) - panic("uvm_km_init: could not reserve space for kernel"); + UVM_ADV_RANDOM, UVM_FLAG_FIXED), &args); + if (!error) { + kernel_first_mapent_store.flags = + UVM_MAP_KERNEL | UVM_MAP_FIRST; + error = uvm_map_enter(&kernel_map_store, &args, + &kernel_first_mapent_store); + } + + if (error) + panic( + "uvm_km_init: could not reserve space for kernel"); + } /* * install! @@ -398,7 +412,8 @@ if (__predict_false(uvm_map(map, &kva, size, obj, prefer, align, UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE, UVM_ADV_RANDOM, - (flags & (UVM_KMF_TRYLOCK | UVM_KMF_NOWAIT)))) + (flags & (UVM_KMF_TRYLOCK | UVM_KMF_NOWAIT)) + | UVM_FLAG_QUANTUM)) != 0)) { UVMHIST_LOG(maphist, "<- done (no VM)",0,0,0,0); return(0); @@ -448,7 +463,8 @@ if ((flags & UVM_KMF_NOWAIT) || ((flags & UVM_KMF_CANFAIL) && uvm_swapisfull())) { /* free everything! */ - uvm_unmap(map, kva, kva + size); + uvm_unmap1(map, kva, kva + size, + UVM_FLAG_QUANTUM); return (0); } else { uvm_wait("km_getwait2"); /* sleep here */ @@ -489,7 +505,8 @@ vaddr_t addr; vsize_t size; { - uvm_unmap(map, trunc_page(addr), round_page(addr+size)); + uvm_unmap1(map, trunc_page(addr), round_page(addr+size), + UVM_FLAG_QUANTUM); } /* @@ -509,7 +526,7 @@ vm_map_lock(map); uvm_unmap_remove(map, trunc_page(addr), round_page(addr + size), - &dead_entries); + &dead_entries, NULL); wakeup(map); vm_map_unlock(map); if (dead_entries != NULL) @@ -545,7 +562,7 @@ if (__predict_false(uvm_map(map, &kva, size, uvm.kernel_object, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE, UVM_ADV_RANDOM, - 0)) != 0)) { + UVM_FLAG_QUANTUM)) != 0)) { UVMHIST_LOG(maphist,"<- done (no VM)",0,0,0,0); return(0); } @@ -632,6 +649,7 @@ if (size > vm_map_max(map) - vm_map_min(map)) return (0); + flags |= UVM_FLAG_QUANTUM; for (;;) { kva = vm_map_min(map); /* hint */ Index: sys/uvm/uvm_map.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_map.c,v retrieving revision 1.164.2.3.2.2 diff -u -r1.164.2.3.2.2 uvm_map.c --- sys/uvm/uvm_map.c 11 May 2005 19:15:43 -0000 1.164.2.3.2.2 +++ sys/uvm/uvm_map.c 16 Jun 2005 17:23:38 -0000 @@ -101,8 +101,6 @@ #include #endif -extern struct vm_map *pager_map; - #ifndef UVMMAP_NOCOUNTERS #include struct evcnt map_ubackmerge = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, @@ -160,7 +158,6 @@ */ struct pool uvm_map_entry_pool; -struct pool uvm_map_entry_kmem_pool; MALLOC_DEFINE(M_VMMAP, "VM map", "VM map structures"); MALLOC_DEFINE(M_VMPMAP, "VM pmap", "VM pmap"); @@ -181,6 +178,14 @@ */ /* + * VM_MAP_USE_KMAPENT: determine if uvm_kmapent_alloc/free is used + * for the vm_map. + */ +extern struct vm_map *pager_map; /* XXX */ +#define VM_MAP_USE_KMAPENT(map) \ + (((map)->flags & VM_MAP_INTRSAFE) || (map) == kernel_map) + +/* * uvm_map_entry_link: insert entry into a map * * => map must be locked @@ -240,8 +245,15 @@ static struct vm_map_entry * uvm_mapent_alloc(struct vm_map *, int); +static struct vm_map_entry * + uvm_mapent_alloc_split(struct vm_map *, + const struct vm_map_entry *, int, + struct uvm_mapent_reservation *); static void uvm_mapent_copy(struct vm_map_entry *, struct vm_map_entry *); static void uvm_mapent_free(struct vm_map_entry *); +static struct vm_map_entry * + uvm_kmapent_alloc(struct vm_map *, int); +static void uvm_kmapent_free(struct vm_map_entry *); static void uvm_map_entry_unwire(struct vm_map *, struct vm_map_entry *); static void uvm_map_reference_amap(struct vm_map_entry *, int); static int uvm_map_space_avail(vaddr_t *, vsize_t, voff_t, vsize_t, int, @@ -416,6 +428,8 @@ * local inlines */ +static __inline struct vm_map *uvm_kmapent_map(struct vm_map_entry *); + /* * uvm_mapent_alloc: allocate a map entry */ @@ -424,29 +438,11 @@ uvm_mapent_alloc(struct vm_map *map, int flags) { struct vm_map_entry *me; - int s; int pflags = (flags & UVM_FLAG_NOWAIT) ? PR_NOWAIT : PR_WAITOK; UVMHIST_FUNC("uvm_mapent_alloc"); UVMHIST_CALLED(maphist); - if (map->flags & VM_MAP_INTRSAFE || cold) { - s = splvm(); - simple_lock(&uvm.kentry_lock); - me = uvm.kentry_free; - if (me) - uvm.kentry_free = me->next; - simple_unlock(&uvm.kentry_lock); - splx(s); - if (__predict_false(me == NULL)) { - panic("uvm_mapent_alloc: out of static map entries, " - "check MAX_KMAPENT (currently %d)", - MAX_KMAPENT); - } - me->flags = UVM_MAP_STATIC; - } else if (map == kernel_map) { - me = pool_get(&uvm_map_entry_kmem_pool, pflags); - if (__predict_false(me == NULL)) - return NULL; - me->flags = UVM_MAP_KMEM; + if (VM_MAP_USE_KMAPENT(map)) { + me = uvm_kmapent_alloc(map, flags); } else { me = pool_get(&uvm_map_entry_pool, pflags); if (__predict_false(me == NULL)) @@ -460,28 +456,88 @@ } /* + * uvm_mapent_alloc_split: allocate a map entry for clipping. + */ + +static __inline struct vm_map_entry * +uvm_mapent_alloc_split(struct vm_map *map, + const struct vm_map_entry *old_entry, int flags, + struct uvm_mapent_reservation *umr) +{ + struct vm_map_entry *me; + + KASSERT(!VM_MAP_USE_KMAPENT(map) || + (old_entry->flags & UVM_MAP_QUANTUM) || !UMR_EMPTY(umr)); + + if (old_entry->flags & UVM_MAP_QUANTUM) { + int s; + + s = splvm(); + simple_lock(&uvm.kentry_lock); + me = map->merged_entries; + KASSERT(me); + map->merged_entries = me->next; + simple_unlock(&uvm.kentry_lock); + splx(s); + KASSERT(me->flags & UVM_MAP_QUANTUM); + } else { + me = uvm_mapent_alloc(map, flags); + } + + return me; +} + +/* * uvm_mapent_free: free map entry */ static __inline void uvm_mapent_free(struct vm_map_entry *me) { - int s; UVMHIST_FUNC("uvm_mapent_free"); UVMHIST_CALLED(maphist); UVMHIST_LOG(maphist,"<- freeing map entry=0x%x [flags=%d]", me, me->flags, 0, 0); - if (me->flags & UVM_MAP_STATIC) { + if (me->flags & UVM_MAP_KERNEL) { + uvm_kmapent_free(me); + } else { + pool_put(&uvm_map_entry_pool, me); + } +} + +/* + * uvm_mapent_free_merge: free merged map entry + * + * => keep the entry if needed. + * => caller shouldn't hold map locked. + */ + +static __inline void +uvm_mapent_free_merged(struct vm_map *map, struct vm_map_entry *me) +{ + + KASSERT(!(me->flags & UVM_MAP_KERNEL) || uvm_kmapent_map(me) == map); + + if (me->flags & UVM_MAP_QUANTUM) { + /* + * keep this entry for later splitting. + */ + struct vm_map *map; + int s; + + KASSERT(VM_MAP_IS_KERNEL(map)); + KASSERT(!VM_MAP_USE_KMAPENT(map) || + (me->flags & UVM_MAP_KERNEL)); + + map = uvm_kmapent_map(me); s = splvm(); simple_lock(&uvm.kentry_lock); - me->next = uvm.kentry_free; - uvm.kentry_free = me; + me->next = map->merged_entries; + map->merged_entries = me; simple_unlock(&uvm.kentry_lock); splx(s); - } else if (me->flags & UVM_MAP_KMEM) { - pool_put(&uvm_map_entry_kmem_pool, me); } else { - pool_put(&uvm_map_entry_pool, me); + uvm_mapent_free(me); } } @@ -544,12 +600,10 @@ void uvm_map_init(void) { - static struct vm_map_entry kernel_map_entry[MAX_KMAPENT]; #if defined(UVMHIST) static struct uvm_history_ent maphistbuf[100]; static struct uvm_history_ent pdhistbuf[100]; #endif - int lcv; /* * first, init logging system. @@ -562,15 +616,12 @@ UVMHIST_LOG(maphist,"", 0, 0, 0, 0); /* - * now set up static pool of kernel map entrys ... + * initialize the global lock for kernel map entry. + * + * XXX is it worth to have per-map lock instead? */ simple_lock_init(&uvm.kentry_lock); - uvm.kentry_free = NULL; - for (lcv = 0 ; lcv < MAX_KMAPENT ; lcv++) { - kernel_map_entry[lcv].next = uvm.kentry_free; - uvm.kentry_free = &kernel_map_entry[lcv]; - } /* * initialize the map-related pools. @@ -579,8 +630,6 @@ 0, 0, 0, "vmsppl", &pool_allocator_nointr); pool_init(&uvm_map_entry_pool, sizeof(struct vm_map_entry), 0, 0, 0, "vmmpepl", &pool_allocator_nointr); - pool_init(&uvm_map_entry_kmem_pool, sizeof(struct vm_map_entry), - 0, 0, 0, "vmmpekpl", NULL); } /* @@ -598,7 +647,7 @@ void uvm_map_clip_start(struct vm_map *map, struct vm_map_entry *entry, - vaddr_t start) + vaddr_t start, struct uvm_mapent_reservation *umr) { struct vm_map_entry *new_entry; vaddr_t new_adj; @@ -612,8 +661,7 @@ * entry BEFORE this one, so that this entry has the specified * starting address. */ - - new_entry = uvm_mapent_alloc(map, 0); + new_entry = uvm_mapent_alloc_split(map, entry, 0, umr); uvm_mapent_copy(entry, new_entry); /* entry -> new_entry */ new_entry->end = start; @@ -654,18 +702,19 @@ */ void -uvm_map_clip_end(struct vm_map *map, struct vm_map_entry *entry, vaddr_t end) +uvm_map_clip_end(struct vm_map *map, struct vm_map_entry *entry, vaddr_t end, + struct uvm_mapent_reservation *umr) { struct vm_map_entry * new_entry; vaddr_t new_adj; /* #bytes we move start forward */ uvm_tree_sanity(map, "clip_end entry"); + /* * Create a new entry and insert it * AFTER the specified entry */ - - new_entry = uvm_mapent_alloc(map, 0); + new_entry = uvm_mapent_alloc_split(map, entry, 0, umr); uvm_mapent_copy(entry, new_entry); /* entry -> new_entry */ new_entry->start = entry->end = end; @@ -727,20 +776,59 @@ uvm_map(struct vm_map *map, vaddr_t *startp /* IN/OUT */, vsize_t size, struct uvm_object *uobj, voff_t uoffset, vsize_t align, uvm_flag_t flags) { - struct vm_map_entry *prev_entry, *new_entry; - const int amapwaitflag = (flags & UVM_FLAG_NOWAIT) ? - AMAP_EXTEND_NOWAIT : 0; - vm_prot_t prot = UVM_PROTECTION(flags), maxprot = - UVM_MAXPROTECTION(flags); - vm_inherit_t inherit = UVM_INHERIT(flags); - int advice = UVM_ADVICE(flags); - int error, merged = 0, kmap = (vm_map_pmap(map) == pmap_kernel()); - int newetype; - UVMHIST_FUNC("uvm_map"); + struct uvm_map_args args; + struct vm_map_entry *new_entry; + int error; + + KASSERT((flags & UVM_FLAG_QUANTUM) == 0 || VM_MAP_IS_KERNEL(map)); + + /* + * for pager_map, allocate the new entry first to avoid sleeping + * for memory while we have the map locked. + * + * besides, because we allocates entries for in-kernel maps + * a bit differently (cf. uvm_kmapent_alloc/free), we need to + * allocate them before locking the map. + */ + + new_entry = NULL; + if (VM_MAP_USE_KMAPENT(map) || (flags & UVM_FLAG_QUANTUM) || + map == pager_map) { + new_entry = uvm_mapent_alloc(map, (flags & UVM_FLAG_NOWAIT)); + if (__predict_false(new_entry == NULL)) + return ENOMEM; + if (flags & UVM_FLAG_QUANTUM) + new_entry->flags |= UVM_MAP_QUANTUM; + } + if (map == pager_map) + flags |= UVM_FLAG_NOMERGE; + + error = uvm_map_prepare(map, *startp, size, uobj, uoffset, align, + flags, &args); + if (!error) { + error = uvm_map_enter(map, &args, new_entry); + *startp = args.uma_start; + } else if (new_entry) { + uvm_mapent_free(new_entry); + } + + return error; +} + +int +uvm_map_prepare(struct vm_map *map, vaddr_t start, vsize_t size, + struct uvm_object *uobj, voff_t uoffset, vsize_t align, uvm_flag_t flags, + struct uvm_map_args *args) +{ + struct vm_map_entry *prev_entry; + vm_prot_t prot = UVM_PROTECTION(flags); + vm_prot_t maxprot = UVM_MAXPROTECTION(flags); + + UVMHIST_FUNC("uvm_map_prepare"); UVMHIST_CALLED(maphist); - UVMHIST_LOG(maphist, "(map=0x%x, *startp=0x%x, size=%d, flags=0x%x)", - map, *startp, size, flags); + UVMHIST_LOG(maphist, "(map=0x%x, start=0x%x, size=%d, flags=0x%x)", + map, start, size, flags); UVMHIST_LOG(maphist, " uobj/offset 0x%x/%d", uobj, uoffset,0,0); /* @@ -768,37 +856,19 @@ } /* - * for pager_map, allocate the new entry first to avoid sleeping - * for memory while we have the map locked. - */ - - new_entry = NULL; - if (map == pager_map) { - new_entry = uvm_mapent_alloc(map, (flags & UVM_FLAG_NOWAIT)); - if (__predict_false(new_entry == NULL)) - return ENOMEM; - } - - /* * figure out where to put new VM range */ if (vm_map_lock_try(map) == FALSE) { if (flags & UVM_FLAG_TRYLOCK) { - if (new_entry) { - uvm_mapent_free(new_entry); - } return EAGAIN; } vm_map_lock(map); /* could sleep here */ } - if ((prev_entry = uvm_map_findspace(map, *startp, size, startp, + if ((prev_entry = uvm_map_findspace(map, start, size, &start, uobj, uoffset, align, flags)) == NULL) { UVMHIST_LOG(maphist,"<- uvm_map_findspace failed!",0,0,0,0); vm_map_unlock(map); - if (new_entry) { - uvm_mapent_free(new_entry); - } return ENOMEM; } @@ -807,8 +877,8 @@ * If the kernel pmap can't map the requested space, * then allocate more resources for it. */ - if (map == kernel_map && uvm_maxkaddr < (*startp + size)) - uvm_maxkaddr = pmap_growkernel(*startp + size); + if (map == kernel_map && uvm_maxkaddr < (start + size)) + uvm_maxkaddr = pmap_growkernel(start + size); #endif UVMCNT_INCR(uvm_map_call); @@ -834,10 +904,60 @@ } else { if (uoffset == UVM_UNKNOWN_OFFSET) { KASSERT(UVM_OBJ_IS_KERN_OBJECT(uobj)); - uoffset = *startp - vm_map_min(kernel_map); + uoffset = start - vm_map_min(kernel_map); } } + args->uma_flags = flags; + args->uma_prev = prev_entry; + args->uma_start = start; + args->uma_size = size; + args->uma_uobj = uobj; + args->uma_uoffset = uoffset; + + return 0; +} + +int +uvm_map_enter(struct vm_map *map, const struct uvm_map_args *args, + struct vm_map_entry *new_entry) +{ + struct vm_map_entry *prev_entry = args->uma_prev; + struct vm_map_entry *dead = NULL; + + const uvm_flag_t flags = args->uma_flags; + const vm_prot_t prot = UVM_PROTECTION(flags); + const vm_prot_t maxprot = UVM_MAXPROTECTION(flags); + const vm_inherit_t inherit = UVM_INHERIT(flags); + const int amapwaitflag = (flags & UVM_FLAG_NOWAIT) ? + AMAP_EXTEND_NOWAIT : 0; + const int advice = UVM_ADVICE(flags); + const int meflagmask = UVM_MAP_NOMERGE | UVM_MAP_QUANTUM; + const int meflagval = (flags & UVM_FLAG_QUANTUM) ? + UVM_MAP_QUANTUM : 0; + + vaddr_t start = args->uma_start; + vsize_t size = args->uma_size; + struct uvm_object *uobj = args->uma_uobj; + voff_t uoffset = args->uma_uoffset; + + const int kmap = (vm_map_pmap(map) == pmap_kernel()); + int merged = 0; + int error; + int newetype; + + UVMHIST_FUNC("uvm_map_enter"); + UVMHIST_CALLED(maphist); + + UVMHIST_LOG(maphist, "(map=0x%x, start=0x%x, size=%d, flags=0x%x)", + map, start, size, flags); + UVMHIST_LOG(maphist, " uobj/offset 0x%x/%d", uobj, uoffset,0,0); + + if (flags & UVM_FLAG_QUANTUM) { + KASSERT(new_entry); + KASSERT(new_entry->flags & UVM_MAP_QUANTUM); + } + if (uobj) newetype = UVM_ET_OBJ; else @@ -859,11 +979,11 @@ goto nomerge; if (prev_entry->etype == newetype && - prev_entry->end == *startp && + prev_entry->end == start && prev_entry != &map->header && prev_entry->object.uvm_obj == uobj) { - if (prev_entry->flags & UVM_MAP_NOMERGE) + if ((prev_entry->flags & meflagmask) != meflagval) goto forwardmerge; if (uobj && prev_entry->offset + @@ -896,13 +1016,8 @@ if (prev_entry->aref.ar_amap) { error = amap_extend(prev_entry, size, amapwaitflag | AMAP_EXTEND_FORWARDS); - if (error) { - vm_map_unlock(map); - if (new_entry) { - uvm_mapent_free(new_entry); - } - return error; - } + if (error) + goto done; } if (kmap) @@ -925,20 +1040,16 @@ uvm_tree_sanity(map, "map backmerged"); UVMHIST_LOG(maphist,"<- done (via backmerge)!", 0, 0, 0, 0); - if (new_entry) { - uvm_mapent_free(new_entry); - new_entry = NULL; - } merged++; } forwardmerge: if (prev_entry->next->etype == newetype && - prev_entry->next->start == (*startp + size) && + prev_entry->next->start == (start + size) && prev_entry->next != &map->header && prev_entry->next->object.uvm_obj == uobj) { - if (prev_entry->next->flags & UVM_MAP_NOMERGE) + if ((prev_entry->next->flags & meflagmask) != meflagval) goto nomerge; if (uobj && prev_entry->next->offset != uoffset + size) @@ -1025,13 +1136,8 @@ if (prev_entry->next->aref.ar_amap) { error = amap_extend(prev_entry->next, size, amapwaitflag | AMAP_EXTEND_BACKWARDS); - if (error) { - vm_map_unlock(map); - if (new_entry) { - uvm_mapent_free(new_entry); - } - return error; - } + if (error) + goto done; } } @@ -1060,14 +1166,13 @@ uobj->pgops->pgo_detach(uobj); if (merged) { - struct vm_map_entry *dead = prev_entry->next; + dead = prev_entry->next; prev_entry->end = dead->end; uvm_map_entry_unlink(map, dead); if (dead->aref.ar_amap != NULL) { prev_entry->aref = dead->aref; dead->aref.ar_amap = NULL; } - uvm_mapent_free(dead); } else { prev_entry->next->start -= size; if (prev_entry != &map->header) @@ -1079,10 +1184,6 @@ uvm_tree_sanity(map, "map forwardmerged"); UVMHIST_LOG(maphist,"<- done forwardmerge", 0, 0, 0, 0); - if (new_entry) { - uvm_mapent_free(new_entry); - new_entry = NULL; - } merged++; } @@ -1102,11 +1203,11 @@ new_entry = uvm_mapent_alloc(map, (flags & UVM_FLAG_NOWAIT)); if (__predict_false(new_entry == NULL)) { - vm_map_unlock(map); - return ENOMEM; + error = ENOMEM; + goto done; } } - new_entry->start = *startp; + new_entry->start = start; new_entry->end = new_entry->start + size; new_entry->object.uvm_obj = uobj; new_entry->offset = uoffset; @@ -1134,9 +1235,8 @@ struct vm_amap *amap = amap_alloc(size, to_add, (flags & UVM_FLAG_NOWAIT) ? M_NOWAIT : M_WAITOK); if (__predict_false(amap == NULL)) { - vm_map_unlock(map); - uvm_mapent_free(new_entry); - return ENOMEM; + error = ENOMEM; + goto done; } new_entry->aref.ar_pageoff = 0; new_entry->aref.ar_amap = amap; @@ -1153,13 +1253,30 @@ if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start)) map->first_free = new_entry; + + new_entry = NULL; } map->size += size; UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0); + + error = 0; +done: vm_map_unlock(map); - return 0; + if (new_entry) { + if (error == 0) { + KDASSERT(merged); + uvm_mapent_free_merged(map, new_entry); + } else { + uvm_mapent_free(new_entry); + } + } + if (dead) { + KDASSERT(merged); + uvm_mapent_free_merged(map, dead); + } + return error; } /* @@ -1690,7 +1807,8 @@ void uvm_unmap_remove(struct vm_map *map, vaddr_t start, vaddr_t end, - struct vm_map_entry **entry_list /* OUT */) + struct vm_map_entry **entry_list /* OUT */, + struct uvm_mapent_reservation *umr) { struct vm_map_entry *entry, *first_entry, *next; vaddr_t len; @@ -1709,7 +1827,7 @@ if (uvm_map_lookup_entry(map, start, &first_entry) == TRUE) { /* clip and go... */ entry = first_entry; - UVM_MAP_CLIP_START(map, entry, start); + UVM_MAP_CLIP_START(map, entry, start, umr); /* critical! prevents stale hint */ SAVE_HINT(map, entry, entry->prev); } else { @@ -1749,7 +1867,9 @@ */ while ((entry != &map->header) && (entry->start < end)) { - UVM_MAP_CLIP_END(map, entry, end); + KASSERT((entry->flags & UVM_MAP_FIRST) == 0); + + UVM_MAP_CLIP_END(map, entry, end, umr); next = entry->next; len = entry->end - entry->start; @@ -1770,8 +1890,11 @@ * this is mostly used for kmem_map and mb_map. */ - uvm_km_pgremove_intrsafe(entry->start, entry->end); - pmap_kremove(entry->start, len); + if ((entry->flags & UVM_MAP_KMAPENT) == 0) { + uvm_km_pgremove_intrsafe(entry->start, + entry->end); + pmap_kremove(entry->start, len); + } } else if (UVM_ET_ISOBJ(entry) && UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)) { KASSERT(vm_map_pmap(map) == pmap_kernel()); @@ -2167,7 +2290,7 @@ * fudge is zero) */ - UVM_MAP_CLIP_START(srcmap, entry, start); + UVM_MAP_CLIP_START(srcmap, entry, start, NULL); SAVE_HINT(srcmap, srcmap->hint, entry->prev); fudge = 0; } @@ -2196,7 +2319,7 @@ /* if we are not doing a quick reference, clip it */ if ((flags & UVM_EXTRACT_QREF) == 0) - UVM_MAP_CLIP_END(srcmap, entry, end); + UVM_MAP_CLIP_END(srcmap, entry, end, NULL); /* clear needs_copy (allow chunking) */ if (UVM_ET_ISNEEDSCOPY(entry)) { @@ -2435,14 +2558,17 @@ struct vm_map *submap) { struct vm_map_entry *entry; + struct uvm_mapent_reservation umr; int error; + uvm_mapent_reserve(map, &umr, 2, 0); + vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (uvm_map_lookup_entry(map, start, &entry)) { - UVM_MAP_CLIP_START(map, entry, start); - UVM_MAP_CLIP_END(map, entry, end); /* to be safe */ + UVM_MAP_CLIP_START(map, entry, start, &umr); + UVM_MAP_CLIP_END(map, entry, end, &umr); /* to be safe */ } else { entry = NULL; } @@ -2460,6 +2586,9 @@ error = EINVAL; } vm_map_unlock(map); + + uvm_mapent_unreserve(map, &umr); + return error; } @@ -2487,7 +2616,7 @@ vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (uvm_map_lookup_entry(map, start, &entry)) { - UVM_MAP_CLIP_START(map, entry, start); + UVM_MAP_CLIP_START(map, entry, start, NULL); } else { entry = entry->next; } @@ -2531,7 +2660,7 @@ while ((current != &map->header) && (current->start < end)) { vm_prot_t old_prot; - UVM_MAP_CLIP_END(map, current, end); + UVM_MAP_CLIP_END(map, current, end, NULL); old_prot = current->protection; if (set_max) current->protection = @@ -2601,6 +2730,7 @@ out: vm_map_unlock(map); + UVMHIST_LOG(maphist, "<- done, error=%d",error,0,0,0); return error; } @@ -2638,12 +2768,12 @@ VM_MAP_RANGE_CHECK(map, start, end); if (uvm_map_lookup_entry(map, start, &temp_entry)) { entry = temp_entry; - UVM_MAP_CLIP_START(map, entry, start); + UVM_MAP_CLIP_START(map, entry, start, NULL); } else { entry = temp_entry->next; } while ((entry != &map->header) && (entry->start < end)) { - UVM_MAP_CLIP_END(map, entry, end); + UVM_MAP_CLIP_END(map, entry, end, NULL); entry->inheritance = new_inheritance; entry = entry->next; } @@ -2670,7 +2800,7 @@ VM_MAP_RANGE_CHECK(map, start, end); if (uvm_map_lookup_entry(map, start, &temp_entry)) { entry = temp_entry; - UVM_MAP_CLIP_START(map, entry, start); + UVM_MAP_CLIP_START(map, entry, start, NULL); } else { entry = temp_entry->next; } @@ -2680,7 +2810,7 @@ */ while ((entry != &map->header) && (entry->start < end)) { - UVM_MAP_CLIP_END(map, entry, end); + UVM_MAP_CLIP_END(map, entry, end, NULL); switch (new_advice) { case MADV_NORMAL: @@ -2757,7 +2887,7 @@ */ if (new_pageable) { /* unwire */ - UVM_MAP_CLIP_START(map, entry, start); + UVM_MAP_CLIP_START(map, entry, start, NULL); /* * unwiring. first ensure that the range to be unwired is @@ -2785,7 +2915,7 @@ entry = start_entry; while ((entry != &map->header) && (entry->start < end)) { - UVM_MAP_CLIP_END(map, entry, end); + UVM_MAP_CLIP_END(map, entry, end, NULL); if (VM_MAPENT_ISWIRED(entry)) uvm_map_entry_unwire(map, entry); entry = entry->next; @@ -2838,8 +2968,8 @@ } } } - UVM_MAP_CLIP_START(map, entry, start); - UVM_MAP_CLIP_END(map, entry, end); + UVM_MAP_CLIP_START(map, entry, start, NULL); + UVM_MAP_CLIP_END(map, entry, end, NULL); entry->wired_count++; /* @@ -3605,7 +3735,7 @@ #endif if (map->nentries) { uvm_unmap_remove(map, map->min_offset, map->max_offset, - &dead_entries); + &dead_entries, NULL); if (dead_entries != NULL) uvm_unmap_detach(dead_entries, 0); } @@ -3854,6 +3984,311 @@ } +/* + * in-kernel map entry allocation. + */ + +int ukh_alloc, ukh_free; +int uke_alloc, uke_free; + +struct uvm_kmapent_hdr { + LIST_ENTRY(uvm_kmapent_hdr) ukh_listq; + int ukh_nused; + struct vm_map_entry *ukh_freelist; + struct vm_map *ukh_map; + struct vm_map_entry ukh_entries[0]; +}; + +#define UVM_KMAPENT_CHUNK \ + ((PAGE_SIZE - sizeof(struct uvm_kmapent_hdr)) \ + / sizeof(struct vm_map_entry)) + +#define UVM_KHDR_FIND(entry) \ + ((struct uvm_kmapent_hdr *)(((vaddr_t)entry) & ~PAGE_MASK)) + +static __inline struct vm_map_entry *uvm_kmapent_get(struct uvm_kmapent_hdr *); +static __inline void uvm_kmapent_put(struct uvm_kmapent_hdr *, + struct vm_map_entry *); + +static __inline struct vm_map * +uvm_kmapent_map(struct vm_map_entry *entry) +{ + const struct uvm_kmapent_hdr *ukh; + + ukh = UVM_KHDR_FIND(entry); + return ukh->ukh_map; +} + +static __inline struct vm_map_entry * +uvm_kmapent_get(struct uvm_kmapent_hdr *ukh) +{ + struct vm_map_entry *entry; + + KASSERT(ukh->ukh_nused <= UVM_KMAPENT_CHUNK); + KASSERT(ukh->ukh_nused >= 0); + + entry = ukh->ukh_freelist; + if (entry) { + KASSERT((entry->flags & (UVM_MAP_KERNEL | UVM_MAP_KMAPENT)) + == UVM_MAP_KERNEL); + ukh->ukh_freelist = entry->next; + ukh->ukh_nused++; + KASSERT(ukh->ukh_nused <= UVM_KMAPENT_CHUNK); + } else { + KASSERT(ukh->ukh_nused == UVM_KMAPENT_CHUNK); + } + + return entry; +} + +static __inline void +uvm_kmapent_put(struct uvm_kmapent_hdr *ukh, struct vm_map_entry *entry) +{ + + KASSERT((entry->flags & (UVM_MAP_KERNEL | UVM_MAP_KMAPENT)) + == UVM_MAP_KERNEL); + KASSERT(ukh->ukh_nused <= UVM_KMAPENT_CHUNK); + KASSERT(ukh->ukh_nused > 0); + KASSERT(ukh->ukh_freelist != NULL || + ukh->ukh_nused == UVM_KMAPENT_CHUNK); + KASSERT(ukh->ukh_freelist == NULL || + ukh->ukh_nused < UVM_KMAPENT_CHUNK); + + ukh->ukh_nused--; + entry->next = ukh->ukh_freelist; + ukh->ukh_freelist = entry; +} + +/* + * uvm_kmapent_alloc: allocate a map entry for in-kernel map + */ + +static struct vm_map_entry * +uvm_kmapent_alloc(struct vm_map *map, int flags) +{ + struct vm_page *pg; + struct uvm_map_args args; + struct uvm_kmapent_hdr *ukh; + struct vm_map_entry *entry; + uvm_flag_t mapflags = UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, + UVM_INH_NONE, UVM_ADV_RANDOM, flags | UVM_FLAG_NOMERGE); + vaddr_t va; + int error; + int i; + int s; + + KDASSERT(UVM_KMAPENT_CHUNK > 2); + KDASSERT(kernel_map != NULL); + KASSERT(vm_map_pmap(map) == pmap_kernel()); + + uke_alloc++; + entry = NULL; +again: + /* + * try to grab an entry from freelist. + */ + s = splvm(); + simple_lock(&uvm.kentry_lock); + ukh = LIST_FIRST(&map->kentry_free); + if (ukh) { + entry = uvm_kmapent_get(ukh); + if (ukh->ukh_nused == UVM_KMAPENT_CHUNK) + LIST_REMOVE(ukh, ukh_listq); + } + simple_unlock(&uvm.kentry_lock); + splx(s); + + if (entry) + return entry; + + /* + * there's no free entry for this vm_map. + * now we need to allocate some vm_map_entry. + * for simplicity, always allocate one page chunk of them at once. + */ + + pg = uvm_pagealloc(NULL, 0, NULL, 0); + if (__predict_false(pg == NULL)) { + if (flags & UVM_FLAG_NOWAIT) + return NULL; + uvm_wait("kme_alloc"); + goto again; + } + + error = uvm_map_prepare(map, 0, PAGE_SIZE, NULL, 0, 0, mapflags, &args); + if (error) { + uvm_pagefree(pg); + return NULL; + } + + va = args.uma_start; + + pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg), VM_PROT_READ|VM_PROT_WRITE); + pmap_update(vm_map_pmap(map)); + + ukh = (void *)va; + + /* + * use the first entry for ukh itsself. + */ + + entry = &ukh->ukh_entries[0]; + entry->flags = UVM_MAP_KERNEL | UVM_MAP_KMAPENT; + error = uvm_map_enter(map, &args, entry); + KASSERT(error == 0); + + ukh->ukh_nused = UVM_KMAPENT_CHUNK; + ukh->ukh_map = map; + ukh->ukh_freelist = NULL; + for (i = UVM_KMAPENT_CHUNK - 1; i >= 2; i--) { + struct vm_map_entry *entry = &ukh->ukh_entries[i]; + + entry->flags = UVM_MAP_KERNEL; + uvm_kmapent_put(ukh, entry); + } + KASSERT(ukh->ukh_nused == 2); + + s = splvm(); + simple_lock(&uvm.kentry_lock); + LIST_INSERT_HEAD(&map->kentry_free, ukh, ukh_listq); + simple_unlock(&uvm.kentry_lock); + splx(s); + + /* + * return second entry. + */ + + entry = &ukh->ukh_entries[1]; + entry->flags = UVM_MAP_KERNEL; + ukh_alloc++; + return entry; +} + +/* + * uvm_mapent_free: free map entry for in-kernel map + */ + +static void +uvm_kmapent_free(struct vm_map_entry *entry) +{ + struct uvm_kmapent_hdr *ukh; + struct vm_page *pg; + struct vm_map *map; + struct pmap *pmap; + vaddr_t va; + paddr_t pa; + struct vm_map_entry *deadentry; + int s; + + uke_free++; + ukh = UVM_KHDR_FIND(entry); + map = ukh->ukh_map; + + s = splvm(); + simple_lock(&uvm.kentry_lock); + uvm_kmapent_put(ukh, entry); + if (ukh->ukh_nused > 1) { + if (ukh->ukh_nused == UVM_KMAPENT_CHUNK - 1) + LIST_INSERT_HEAD(&map->kentry_free, ukh, ukh_listq); + simple_unlock(&uvm.kentry_lock); + splx(s); + return; + } + + /* + * now we can free this ukh. + * + * however, keep an empty ukh to avoid ping-pong. + */ + + if (LIST_FIRST(&map->kentry_free) == ukh && + LIST_NEXT(ukh, ukh_listq) == NULL) { + simple_unlock(&uvm.kentry_lock); + splx(s); + return; + } + LIST_REMOVE(ukh, ukh_listq); + simple_unlock(&uvm.kentry_lock); + splx(s); + + KASSERT(ukh->ukh_nused == 1); + + /* + * remove map entry for ukh itsself. + */ + + va = (vaddr_t)ukh; + KASSERT((va & PAGE_MASK) == 0); + uvm_unmap_remove(map, va, va + PAGE_SIZE, &deadentry, NULL); + KASSERT(deadentry->flags & UVM_MAP_KERNEL); + KASSERT(deadentry->flags & UVM_MAP_KMAPENT); + KASSERT(deadentry->next == NULL); + KASSERT(deadentry == &ukh->ukh_entries[0]); + + /* + * unmap the page from pmap and free it. + */ + + pmap = vm_map_pmap(map); + KASSERT(pmap == pmap_kernel()); + if (!pmap_extract(pmap, va, &pa)) + panic("%s: no mapping", __func__); + pmap_kremove(va, PAGE_SIZE); + pg = PHYS_TO_VM_PAGE(pa); + uvm_pagefree(pg); + ukh_free++; +} + +/* + * map entry reservation + */ + +/* + * uvm_mapent_reserve: reserve map entries for clipping before locking map. + * + * => needed when unmapping entries allocated without UVM_FLAG_QUANTUM. + * => caller shouldn't hold map locked. + */ +int +uvm_mapent_reserve(struct vm_map *map, struct uvm_mapent_reservation *umr, + int nentries, int flags) +{ + + umr->umr_nentries = 0; + + if ((flags & UVM_FLAG_QUANTUM) != 0) + return 0; + + if (!VM_MAP_USE_KMAPENT(map)) + return 0; + + while (nentries--) { + struct vm_map_entry *ent; + ent = uvm_kmapent_alloc(map, flags); + if (!ent) { + uvm_mapent_unreserve(map, umr); + return ENOMEM; + } + UMR_PUTENTRY(umr, ent); + } + + return 0; +} + +/* + * uvm_mapent_unreserve: + * + * => caller shouldn't hold map locked. + * => never fail or sleep. + */ +void +uvm_mapent_unreserve(struct vm_map *map, struct uvm_mapent_reservation *umr) +{ + + while (!UMR_EMPTY(umr)) + uvm_kmapent_free(UMR_GETENTRY(umr)); +} + #if defined(DDB) /* Index: sys/uvm/uvm_map.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_map.h,v retrieving revision 1.39 diff -u -r1.39 uvm_map.h --- sys/uvm/uvm_map.h 10 Feb 2004 01:30:49 -0000 1.39 +++ sys/uvm/uvm_map.h 16 Jun 2005 17:23:38 -0000 @@ -86,8 +86,8 @@ * => map must be locked by caller */ -#define UVM_MAP_CLIP_START(MAP,ENTRY,VA) { \ - if ((VA) > (ENTRY)->start) uvm_map_clip_start(MAP,ENTRY,VA); } +#define UVM_MAP_CLIP_START(MAP,ENTRY,VA,UMR) { \ + if ((VA) > (ENTRY)->start) uvm_map_clip_start(MAP,ENTRY,VA,UMR); } /* * UVM_MAP_CLIP_END: ensure that the entry ends at or before @@ -96,8 +96,8 @@ * => map must be locked by caller */ -#define UVM_MAP_CLIP_END(MAP,ENTRY,VA) { \ - if ((VA) < (ENTRY)->end) uvm_map_clip_end(MAP,ENTRY,VA); } +#define UVM_MAP_CLIP_END(MAP,ENTRY,VA,UMR) { \ + if ((VA) < (ENTRY)->end) uvm_map_clip_end(MAP,ENTRY,VA,UMR); } /* * extract flags @@ -142,8 +142,11 @@ #define uvm_map_entry_stop_copy flags u_int8_t flags; /* flags */ -#define UVM_MAP_STATIC 0x01 /* static map entry */ -#define UVM_MAP_KMEM 0x02 /* from kmem entry pool */ +#define UVM_MAP_KERNEL 0x01 /* kernel map entry */ +#define UVM_MAP_KMAPENT 0x02 /* contains map entries */ +#define UVM_MAP_FIRST 0x04 /* the first special entry */ +#define UVM_MAP_QUANTUM 0x08 /* allocated with + * UVM_FLAG_QUANTUM */ #define UVM_MAP_NOMERGE 0x10 /* this entry is not mergable */ }; @@ -226,6 +229,11 @@ int flags; /* flags */ struct simplelock flags_lock; /* Lock for flags field */ unsigned int timestamp; /* Version number */ + LIST_HEAD(, uvm_kmapent_hdr) kentry_free; /* Freelist of map entry */ + + struct vm_map_entry *merged_entries;/* Merged entries, kept for + * later splitting */ + #define min_offset header.end #define max_offset header.start }; @@ -239,15 +247,28 @@ #define VM_MAP_DYING 0x20 /* rw: map is being destroyed */ #define VM_MAP_TOPDOWN 0x40 /* ro: arrange map top-down */ -/* XXX: number of kernel maps and entries to statically allocate */ +#ifdef _KERNEL +struct uvm_mapent_reservation { + struct vm_map_entry *umr_entries[2]; + int umr_nentries; +}; +#define UMR_EMPTY(umr) ((umr) == NULL || (umr)->umr_nentries == 0) +#define UMR_GETENTRY(umr) ((umr)->umr_entries[--(umr)->umr_nentries]) +#define UMR_PUTENTRY(umr, ent) \ + (umr)->umr_entries[(umr)->umr_nentries++] = (ent) + +struct uvm_map_args { + struct vm_map_entry *uma_prev; -#if !defined(MAX_KMAPENT) -#if (50 + (2 * NPROC) > 1000) -#define MAX_KMAPENT (50 + (2 * NPROC)) -#else -#define MAX_KMAPENT 1000 /* XXXCDC: no crash */ -#endif -#endif /* !defined MAX_KMAPENT */ + vaddr_t uma_start; + vsize_t uma_size; + + struct uvm_object *uma_uobj; + voff_t uma_uoffset; + + uvm_flag_t uma_flags; +}; +#endif /* _KERNEL */ #ifdef _KERNEL #define vm_map_modflags(map, set, clear) \ @@ -287,9 +308,9 @@ int uvm_map_clean(struct vm_map *, vaddr_t, vaddr_t, int); void uvm_map_clip_start(struct vm_map *, struct vm_map_entry *, - vaddr_t); + vaddr_t, struct uvm_mapent_reservation *); void uvm_map_clip_end(struct vm_map *, struct vm_map_entry *, - vaddr_t); + vaddr_t, struct uvm_mapent_reservation *); MAP_INLINE struct vm_map *uvm_map_create(pmap_t, vaddr_t, vaddr_t, int); int uvm_map_extract(struct vm_map *, vaddr_t, vsize_t, @@ -313,10 +334,23 @@ int uvm_map_submap(struct vm_map *, vaddr_t, vaddr_t, struct vm_map *); MAP_INLINE -void uvm_unmap(struct vm_map *, vaddr_t, vaddr_t); +void uvm_unmap1(struct vm_map *, vaddr_t, vaddr_t, int); +#define uvm_unmap(map, s, e) uvm_unmap1((map), (s), (e), 0) void uvm_unmap_detach(struct vm_map_entry *,int); void uvm_unmap_remove(struct vm_map *, vaddr_t, vaddr_t, - struct vm_map_entry **); + struct vm_map_entry **, struct uvm_mapent_reservation *); + +int uvm_map_prepare(struct vm_map *, vaddr_t, vsize_t, + struct uvm_object *, voff_t, vsize_t, uvm_flag_t, + struct uvm_map_args *); +int uvm_map_enter(struct vm_map *, const struct uvm_map_args *, + struct vm_map_entry *); + +int uvm_mapent_reserve(struct vm_map *, + struct uvm_mapent_reservation *, int, int); +void uvm_mapent_unreserve(struct vm_map *, + struct uvm_mapent_reservation *); + #endif /* _KERNEL */ @@ -464,6 +498,7 @@ if (oflags & VM_MAP_WANTLOCK) \ wakeup(&(map)->flags); \ } while (/*CONSTCOND*/ 0) + #endif /* _KERNEL */ /* Index: sys/uvm/uvm_map_i.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_map_i.h,v retrieving revision 1.28 diff -u -r1.28 uvm_map_i.h --- sys/uvm/uvm_map_i.h 10 Feb 2004 01:30:49 -0000 1.28 +++ sys/uvm/uvm_map_i.h 16 Jun 2005 17:23:38 -0000 @@ -120,6 +120,8 @@ simple_lock_init(&map->ref_lock); simple_lock_init(&map->hint_lock); simple_lock_init(&map->flags_lock); + LIST_INIT(&map->kentry_free); + map->merged_entries = NULL; } @@ -128,16 +130,18 @@ */ /* - * uvm_unmap: remove mappings from a vm_map (from "start" up to "stop") + * uvm_unmap1: remove mappings from a vm_map (from "start" up to "stop") * * => caller must check alignment and size * => map must be unlocked (we will lock it) + * => flags is UVM_FLAG_QUANTUM or 0. */ MAP_INLINE void -uvm_unmap(struct vm_map *map, vaddr_t start, vaddr_t end) +uvm_unmap1(struct vm_map *map, vaddr_t start, vaddr_t end, int flags) { struct vm_map_entry *dead_entries; + struct uvm_mapent_reservation umr; UVMHIST_FUNC("uvm_unmap"); UVMHIST_CALLED(maphist); UVMHIST_LOG(maphist, " (map=0x%x, start=0x%x, end=0x%x)", @@ -146,9 +150,11 @@ * work now done by helper functions. wipe the pmap's and then * detach from the dead entries... */ + uvm_mapent_reserve(map, &umr, 2, flags); vm_map_lock(map); - uvm_unmap_remove(map, start, end, &dead_entries); + uvm_unmap_remove(map, start, end, &dead_entries, &umr); vm_map_unlock(map); + uvm_mapent_unreserve(map, &umr); if (dead_entries != NULL) uvm_unmap_detach(dead_entries, 0); Index: sys/uvm/uvm_mmap.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_mmap.c,v retrieving revision 1.82 diff -u -r1.82 uvm_mmap.c --- sys/uvm/uvm_mmap.c 24 Mar 2004 07:47:33 -0000 1.82 +++ sys/uvm/uvm_mmap.c 16 Jun 2005 17:23:38 -0000 @@ -685,7 +685,7 @@ return (EINVAL); } #endif - uvm_unmap_remove(map, addr, addr + size, &dead_entries); + uvm_unmap_remove(map, addr, addr + size, &dead_entries, NULL); vm_map_unlock(map); if (dead_entries != NULL) uvm_unmap_detach(dead_entries, 0); Index: sys/uvm/uvm_pager.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_pager.c,v retrieving revision 1.62.2.1 diff -u -r1.62.2.1 uvm_pager.c --- sys/uvm/uvm_pager.c 10 May 2004 14:26:44 -0000 1.62.2.1 +++ sys/uvm/uvm_pager.c 16 Jun 2005 17:23:38 -0000 @@ -224,7 +224,7 @@ } vm_map_lock(pager_map); - uvm_unmap_remove(pager_map, kva, kva + size, &entries); + uvm_unmap_remove(pager_map, kva, kva + size, &entries, NULL); simple_lock(&pager_map_wanted_lock); if (pager_map_wanted) { pager_map_wanted = FALSE; Index: usr.bin/pmap/pmap.c =================================================================== RCS file: /cvsroot/src/usr.bin/pmap/pmap.c,v retrieving revision 1.22 diff -u -r1.22 pmap.c --- usr.bin/pmap/pmap.c 10 Feb 2004 01:31:41 -0000 1.22 +++ usr.bin/pmap/pmap.c 16 Jun 2005 17:23:39 -0000 @@ -321,10 +321,12 @@ printf("%*s aref = { ar_pageoff = %x, ar_amap = %p },", indent(2), "", vme->aref.ar_pageoff, vme->aref.ar_amap); printf(" advice = %d,\n", vme->advice); - printf("%*s flags = %x <%s%s%s > }\n", indent(2), "", + printf("%*s flags = %x <%s%s%s%s%s > }\n", indent(2), "", vme->flags, - vme->flags & UVM_MAP_KMEM ? " KMEM" : "", - vme->flags & UVM_MAP_STATIC ? " STATIC" : "", + vme->flags & UVM_MAP_KERNEL ? " KERNEL" : "", + vme->flags & UVM_MAP_KMAPENT ? " KMAPENT" : "", + vme->flags & UVM_MAP_FIRST ? " FIRST" : "", + vme->flags & UVM_MAP_QUANTUM ? " QUANTUM" : "", vme->flags & UVM_MAP_NOMERGE ? " NOMERGE" : ""); } Index: usr.sbin/user/user.c =================================================================== RCS file: /cvsroot/src/usr.sbin/user/user.c,v retrieving revision 1.75 diff -u -r1.75 user.c --- usr.sbin/user/user.c 14 Jan 2004 09:35:33 -0000 1.75 +++ usr.sbin/user/user.c 16 Jun 2005 17:23:39 -0000 @@ -1977,6 +1977,10 @@ if (argc != 1) { usermgmt_usage("groupdel"); } + + if (getgrnam(*argv) == NULL) { + err(EXIT_FAILURE, "can't find group `%s' to delete", *argv); + } checkeuid(); openlog("groupdel", LOG_PID, LOG_USER); if (!modify_gid(*argv, NULL)) {