summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/powerpc/aim/mmu_oea.c108
-rw-r--r--sys/powerpc/powerpc/mmu_oea.c108
-rw-r--r--sys/powerpc/powerpc/pmap.c108
3 files changed, 294 insertions, 30 deletions
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 8802cfb68c87..2aca63e42b01 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -1544,11 +1544,18 @@ pmap_remove_pages(pmap_t pm, vm_offset_t sva, vm_offset_t eva)
void
pmap_new_thread(struct thread *td, int 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.
*/
@@ -1578,46 +1585,127 @@ pmap_new_thread(struct thread *td, int pages)
*/
m = vm_page_grab(ksobj, i,
VM_ALLOC_NORMAL | VM_ALLOC_RETRY | VM_ALLOC_WIRED);
-
- /*
- * Enter the page into the kernel address space.
- */
- pmap_kenter(ks + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m));
+ ma[i] = m;
vm_page_wakeup(m);
vm_page_flag_clear(m, PG_ZERO);
m->valid = VM_PAGE_BITS_ALL;
}
+
+ /*
+ * Enter the page into the kernel address space
+ */
+ pmap_qenter(ks, ma, pages);
}
void
pmap_dispose_thread(struct thread *td)
{
- TODO;
+ vm_object_t ksobj;
+ 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 < pages ; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_dispose_thread: kstack already missing?");
+ vm_page_lock_queues();
+ vm_page_busy(m);
+ vm_page_unwire(m, 0);
+ vm_page_free(m);
+ vm_page_unlock_queues();
+ }
+ pmap_qremove(ks, pages);
+ kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE),
+ (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE);
+ vm_object_deallocate(ksobj);
}
void
pmap_new_altkstack(struct thread *td, int pages)
{
- TODO;
+ /* 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)
{
- TODO;
+ 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;
}
void
pmap_swapin_thread(struct thread *td)
{
- TODO;
+ 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 < 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);
+ if (rv != VM_PAGER_OK)
+ panic("pmap_swapin_thread: cannot get kstack");
+ m = vm_page_lookup(ksobj, i);
+ m->valid = VM_PAGE_BITS_ALL;
+ }
+ ma[i] = m;
+ vm_page_lock_queues();
+ vm_page_wire(m);
+ vm_page_wakeup(m);
+ vm_page_unlock_queues();
+ }
+ pmap_qenter(ks, ma, pages);
}
+
void
pmap_swapout_thread(struct thread *td)
{
- TODO;
+ vm_object_t ksobj;
+ 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 < pages; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_swapout_thread: kstack already missing?");
+ vm_page_lock_queues();
+ vm_page_dirty(m);
+ vm_page_unwire(m, 0);
+ vm_page_unlock_queues();
+ }
+ pmap_qremove(ks, pages);
}
/*
diff --git a/sys/powerpc/powerpc/mmu_oea.c b/sys/powerpc/powerpc/mmu_oea.c
index 8802cfb68c87..2aca63e42b01 100644
--- a/sys/powerpc/powerpc/mmu_oea.c
+++ b/sys/powerpc/powerpc/mmu_oea.c
@@ -1544,11 +1544,18 @@ pmap_remove_pages(pmap_t pm, vm_offset_t sva, vm_offset_t eva)
void
pmap_new_thread(struct thread *td, int 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.
*/
@@ -1578,46 +1585,127 @@ pmap_new_thread(struct thread *td, int pages)
*/
m = vm_page_grab(ksobj, i,
VM_ALLOC_NORMAL | VM_ALLOC_RETRY | VM_ALLOC_WIRED);
-
- /*
- * Enter the page into the kernel address space.
- */
- pmap_kenter(ks + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m));
+ ma[i] = m;
vm_page_wakeup(m);
vm_page_flag_clear(m, PG_ZERO);
m->valid = VM_PAGE_BITS_ALL;
}
+
+ /*
+ * Enter the page into the kernel address space
+ */
+ pmap_qenter(ks, ma, pages);
}
void
pmap_dispose_thread(struct thread *td)
{
- TODO;
+ vm_object_t ksobj;
+ 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 < pages ; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_dispose_thread: kstack already missing?");
+ vm_page_lock_queues();
+ vm_page_busy(m);
+ vm_page_unwire(m, 0);
+ vm_page_free(m);
+ vm_page_unlock_queues();
+ }
+ pmap_qremove(ks, pages);
+ kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE),
+ (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE);
+ vm_object_deallocate(ksobj);
}
void
pmap_new_altkstack(struct thread *td, int pages)
{
- TODO;
+ /* 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)
{
- TODO;
+ 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;
}
void
pmap_swapin_thread(struct thread *td)
{
- TODO;
+ 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 < 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);
+ if (rv != VM_PAGER_OK)
+ panic("pmap_swapin_thread: cannot get kstack");
+ m = vm_page_lookup(ksobj, i);
+ m->valid = VM_PAGE_BITS_ALL;
+ }
+ ma[i] = m;
+ vm_page_lock_queues();
+ vm_page_wire(m);
+ vm_page_wakeup(m);
+ vm_page_unlock_queues();
+ }
+ pmap_qenter(ks, ma, pages);
}
+
void
pmap_swapout_thread(struct thread *td)
{
- TODO;
+ vm_object_t ksobj;
+ 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 < pages; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_swapout_thread: kstack already missing?");
+ vm_page_lock_queues();
+ vm_page_dirty(m);
+ vm_page_unwire(m, 0);
+ vm_page_unlock_queues();
+ }
+ pmap_qremove(ks, pages);
}
/*
diff --git a/sys/powerpc/powerpc/pmap.c b/sys/powerpc/powerpc/pmap.c
index 8802cfb68c87..2aca63e42b01 100644
--- a/sys/powerpc/powerpc/pmap.c
+++ b/sys/powerpc/powerpc/pmap.c
@@ -1544,11 +1544,18 @@ pmap_remove_pages(pmap_t pm, vm_offset_t sva, vm_offset_t eva)
void
pmap_new_thread(struct thread *td, int 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.
*/
@@ -1578,46 +1585,127 @@ pmap_new_thread(struct thread *td, int pages)
*/
m = vm_page_grab(ksobj, i,
VM_ALLOC_NORMAL | VM_ALLOC_RETRY | VM_ALLOC_WIRED);
-
- /*
- * Enter the page into the kernel address space.
- */
- pmap_kenter(ks + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m));
+ ma[i] = m;
vm_page_wakeup(m);
vm_page_flag_clear(m, PG_ZERO);
m->valid = VM_PAGE_BITS_ALL;
}
+
+ /*
+ * Enter the page into the kernel address space
+ */
+ pmap_qenter(ks, ma, pages);
}
void
pmap_dispose_thread(struct thread *td)
{
- TODO;
+ vm_object_t ksobj;
+ 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 < pages ; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_dispose_thread: kstack already missing?");
+ vm_page_lock_queues();
+ vm_page_busy(m);
+ vm_page_unwire(m, 0);
+ vm_page_free(m);
+ vm_page_unlock_queues();
+ }
+ pmap_qremove(ks, pages);
+ kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE),
+ (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE);
+ vm_object_deallocate(ksobj);
}
void
pmap_new_altkstack(struct thread *td, int pages)
{
- TODO;
+ /* 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)
{
- TODO;
+ 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;
}
void
pmap_swapin_thread(struct thread *td)
{
- TODO;
+ 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 < 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);
+ if (rv != VM_PAGER_OK)
+ panic("pmap_swapin_thread: cannot get kstack");
+ m = vm_page_lookup(ksobj, i);
+ m->valid = VM_PAGE_BITS_ALL;
+ }
+ ma[i] = m;
+ vm_page_lock_queues();
+ vm_page_wire(m);
+ vm_page_wakeup(m);
+ vm_page_unlock_queues();
+ }
+ pmap_qenter(ks, ma, pages);
}
+
void
pmap_swapout_thread(struct thread *td)
{
- TODO;
+ vm_object_t ksobj;
+ 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 < pages; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_swapout_thread: kstack already missing?");
+ vm_page_lock_queues();
+ vm_page_dirty(m);
+ vm_page_unwire(m, 0);
+ vm_page_unlock_queues();
+ }
+ pmap_qremove(ks, pages);
}
/*