summaryrefslogtreecommitdiffstats
path: root/sys/sparc64/sparc64/pmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/sparc64/sparc64/pmap.c')
-rw-r--r--sys/sparc64/sparc64/pmap.c78
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);
}
/*
OpenPOWER on IntegriCloud