diff options
Diffstat (limited to 'sys/sparc64/sparc64/pmap.c')
-rw-r--r-- | sys/sparc64/sparc64/pmap.c | 78 |
1 files changed, 64 insertions, 14 deletions
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 4485a55..60c264d 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -951,31 +951,41 @@ pmap_qremove(vm_offset_t sva, int count) tlb_range_demap(kernel_pmap, sva, sva + (count * PAGE_SIZE) - 1); } +#ifndef KSTACK_MAX_PAGES +#define KSTACK_MAX_PAGES 32 +#endif + /* * Create the kernel stack and pcb for a new thread. * This routine directly affects the fork perf for a process and * create performance for a thread. */ void -pmap_new_thread(struct thread *td) +pmap_new_thread(struct thread *td, int pages) { - vm_page_t ma[KSTACK_PAGES]; + vm_page_t ma[KSTACK_MAX_PAGES]; vm_object_t ksobj; vm_offset_t ks; vm_page_t m; u_int i; + /* Bounds check */ + if (pages <= 1) + pages = KSTACK_PAGES; + else if (pages > KSTACK_MAX_PAGES) + pages = KSTACK_MAX_PAGES; + /* * Allocate object for the kstack, */ - ksobj = vm_object_allocate(OBJT_DEFAULT, KSTACK_PAGES); + ksobj = vm_object_allocate(OBJT_DEFAULT, pages); td->td_kstack_obj = ksobj; /* * Get a kernel virtual address for the kstack for this thread. */ ks = kmem_alloc_nofault(kernel_map, - (KSTACK_PAGES + KSTACK_GUARD_PAGES) * PAGE_SIZE); + (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE); if (ks == 0) panic("pmap_new_thread: kstack allocation failed"); if (KSTACK_GUARD_PAGES != 0) { @@ -984,7 +994,13 @@ pmap_new_thread(struct thread *td) } td->td_kstack = ks; - for (i = 0; i < KSTACK_PAGES; i++) { + /* + * Knowing the number of pages allocated is useful when you + * want to deallocate them. + */ + td->td_kstack_pages = pages; + + for (i = 0; i < pages; i++) { /* * Get a kernel stack page. */ @@ -1000,7 +1016,7 @@ pmap_new_thread(struct thread *td) /* * Enter the page into the kernel address space. */ - pmap_qenter(ks, ma, KSTACK_PAGES); + pmap_qenter(ks, ma, pages); } /* @@ -1014,10 +1030,12 @@ pmap_dispose_thread(struct thread *td) vm_offset_t ks; vm_page_t m; int i; + int pages; + pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; ks = td->td_kstack; - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages ; i++) { m = vm_page_lookup(ksobj, i); if (m == NULL) panic("pmap_dispose_thread: kstack already missing?"); @@ -1027,13 +1045,41 @@ pmap_dispose_thread(struct thread *td) vm_page_free(m); vm_page_unlock_queues(); } - pmap_qremove(ks, KSTACK_PAGES); + pmap_qremove(ks, pages); kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE), - (KSTACK_PAGES + KSTACK_GUARD_PAGES) * PAGE_SIZE); + (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE); vm_object_deallocate(ksobj); } /* + * Set up a variable sized alternate kstack. + */ +void +pmap_new_altkstack(struct thread *td, int pages) +{ + /* shuffle the original stack */ + td->td_altkstack_obj = td->td_kstack_obj; + td->td_altkstack = td->td_kstack; + td->td_altkstack_pages = td->td_kstack_pages; + + pmap_new_thread(td, pages); +} + +void +pmap_dispose_altkstack(struct thread *td) +{ + pmap_dispose_thread(td); + + /* restore the original kstack */ + td->td_kstack = td->td_altkstack; + td->td_kstack_obj = td->td_altkstack_obj; + td->td_kstack_pages = td->td_altkstack_pages; + td->td_altkstack = 0; + td->td_altkstack_obj = NULL; + td->td_altkstack_pages = 0; +} + +/* * Allow the kernel stack for a thread to be prejudicially paged out. */ void @@ -1043,10 +1089,12 @@ pmap_swapout_thread(struct thread *td) vm_offset_t ks; vm_page_t m; int i; + int pages; + pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; ks = (vm_offset_t)td->td_kstack; - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages; i++) { m = vm_page_lookup(ksobj, i); if (m == NULL) panic("pmap_swapout_thread: kstack already missing?"); @@ -1055,7 +1103,7 @@ pmap_swapout_thread(struct thread *td) vm_page_unwire(m, 0); vm_page_unlock_queues(); } - pmap_qremove(ks, KSTACK_PAGES); + pmap_qremove(ks, pages); } /* @@ -1064,16 +1112,18 @@ pmap_swapout_thread(struct thread *td) void pmap_swapin_thread(struct thread *td) { - vm_page_t ma[KSTACK_PAGES]; + vm_page_t ma[KSTACK_MAX_PAGES]; vm_object_t ksobj; vm_offset_t ks; vm_page_t m; int rv; int i; + int pages; + pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; ks = td->td_kstack; - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages; i++) { m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if (m->valid != VM_PAGE_BITS_ALL) { rv = vm_pager_get_pages(ksobj, &m, 1, 0); @@ -1088,7 +1138,7 @@ pmap_swapin_thread(struct thread *td) vm_page_wakeup(m); vm_page_unlock_queues(); } - pmap_qenter(ks, ma, KSTACK_PAGES); + pmap_qenter(ks, ma, pages); } /* |