summaryrefslogtreecommitdiffstats
path: root/sys/alpha/alpha/pmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/alpha/alpha/pmap.c')
-rw-r--r--sys/alpha/alpha/pmap.c235
1 files changed, 199 insertions, 36 deletions
diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c
index eed5e5e..c03d3dd 100644
--- a/sys/alpha/alpha/pmap.c
+++ b/sys/alpha/alpha/pmap.c
@@ -337,7 +337,7 @@ static pmap_t pmap_active[MAXCPU];
static vm_zone_t pvzone;
static struct vm_zone pvzone_store;
static struct vm_object pvzone_obj;
-static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0;
+static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
static int pmap_pagedaemon_waken = 0;
static struct pv_entry *pvinit;
@@ -564,9 +564,9 @@ pmap_bootstrap(vm_offset_t ptaddr, u_int maxasn)
* Set up proc0's PCB such that the ptbr points to the right place
* and has the kernel pmap's.
*/
- proc0.p_addr->u_pcb.pcb_hw.apcb_ptbr =
+ thread0->td_pcb->pcb_hw.apcb_ptbr =
ALPHA_K0SEG_TO_PHYS((vm_offset_t)Lev1map) >> PAGE_SHIFT;
- proc0.p_addr->u_pcb.pcb_hw.apcb_asn = 0;
+ thread0->td_pcb->pcb_hw.apcb_asn = 0;
}
int
@@ -934,22 +934,22 @@ pmap_new_proc(struct proc *p)
*/
upobj = p->p_upages_obj;
if (upobj == NULL) {
- upobj = vm_object_allocate(OBJT_DEFAULT, UPAGES);
+ upobj = vm_object_allocate(OBJT_DEFAULT, UAREA_PAGES);
p->p_upages_obj = upobj;
}
/* get a kernel virtual address for the UPAGES for this proc */
- up = (vm_offset_t)p->p_addr;
+ up = (vm_offset_t)p->p_uarea;
if (up == 0) {
- up = kmem_alloc_nofault(kernel_map, UPAGES * PAGE_SIZE);
+ up = kmem_alloc_nofault(kernel_map, UAREA_PAGES * PAGE_SIZE);
if (up == 0)
panic("pmap_new_proc: upage allocation failed");
- p->p_addr = (struct user *)up;
+ p->p_uarea = (struct user *)up;
}
ptek = vtopte(up);
- for (i = 0; i < UPAGES; i++) {
+ for (i = 0; i < UAREA_PAGES; i++) {
/*
* Get a kernel stack page
*/
@@ -992,9 +992,9 @@ pmap_dispose_proc(p)
pt_entry_t *ptek, oldpte;
upobj = p->p_upages_obj;
- up = (vm_offset_t)p->p_addr;
+ up = (vm_offset_t)p->p_uarea;
ptek = vtopte(up);
- for (i = 0; i < UPAGES; i++) {
+ for (i = 0; i < UAREA_PAGES; i++) {
m = vm_page_lookup(upobj, i);
if (m == NULL)
panic("pmap_dispose_proc: upage already missing?");
@@ -1019,14 +1019,9 @@ pmap_swapout_proc(p)
vm_offset_t up;
vm_page_t m;
- /*
- * Make sure we aren't fpcurproc.
- */
- alpha_fpstate_save(p, 1);
-
upobj = p->p_upages_obj;
- up = (vm_offset_t)p->p_addr;
- for (i = 0; i < UPAGES; i++) {
+ up = (vm_offset_t)p->p_uarea;
+ for (i = 0; i < UAREA_PAGES; i++) {
m = vm_page_lookup(upobj, i);
if (m == NULL)
panic("pmap_swapout_proc: upage already missing?");
@@ -1049,8 +1044,8 @@ pmap_swapin_proc(p)
vm_page_t m;
upobj = p->p_upages_obj;
- up = (vm_offset_t)p->p_addr;
- for (i = 0; i < UPAGES; i++) {
+ up = (vm_offset_t)p->p_uarea;
+ for (i = 0; i < UAREA_PAGES; i++) {
m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
pmap_kenter(up + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m));
if (m->valid != VM_PAGE_BITS_ALL) {
@@ -1064,12 +1059,180 @@ pmap_swapin_proc(p)
vm_page_wakeup(m);
vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
}
+}
+
+/*
+ * Create the kernel stack for a new thread.
+ * This routine directly affects the fork perf for a process and thread.
+ */
+void
+pmap_new_thread(struct thread *td)
+{
+ int i;
+ vm_object_t ksobj;
+ vm_offset_t ks;
+ vm_page_t m;
+ pt_entry_t *ptek, oldpte;
+
+ /*
+ * allocate object for the upages
+ */
+ ksobj = td->td_kstack_obj;
+ if (ksobj == NULL) {
+ ksobj = vm_object_allocate(OBJT_DEFAULT, KSTACK_PAGES);
+ td->td_kstack_obj = ksobj;
+ }
+
+#ifdef KSTACK_GUARD
+ /* get a kernel virtual address for the kstack for this thread */
+ ks = td->td_kstack;
+ if (ks == 0) {
+ ks = kmem_alloc_nofault(kernel_map,
+ (KSTACK_PAGES + 1) * PAGE_SIZE);
+ if (ks == NULL)
+ panic("pmap_new_thread: kstack allocation failed");
+ ks += PAGE_SIZE;
+ td->td_kstack = ks;
+ }
+
+ ptek = vtopte(ks - PAGE_SIZE);
+ oldpte = *ptek;
+ *ptek = 0;
+ if (oldpte)
+ pmap_invalidate_page(kernel_pmap, ks - PAGE_SIZE);
+ ptek++;
+#else
+ /* get a kernel virtual address for the kstack for this thread */
+ ks = td->td_kstack;
+ if (ks == 0) {
+ ks = kmem_alloc_nofault(kernel_map, KSTACK_PAGES * PAGE_SIZE);
+ if (ks == NULL)
+ panic("pmap_new_thread: kstack allocation failed");
+ td->td_kstack = ks;
+ }
+ ptek = vtopte(ks);
+#endif
+ for (i = 0; i < KSTACK_PAGES; i++) {
+ /*
+ * Get a kernel stack page
+ */
+ m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
+
+ /*
+ * Wire the page
+ */
+ m->wire_count++;
+ cnt.v_wire_count++;
+
+ oldpte = *(ptek + i);
+ /*
+ * Enter the page into the kernel address space.
+ */
+ *(ptek + i) = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m))
+ | PG_ASM | PG_KRE | PG_KWE | PG_V;
+ if (oldpte)
+ pmap_invalidate_page(kernel_pmap, ks + i * PAGE_SIZE);
+
+ vm_page_wakeup(m);
+ vm_page_flag_clear(m, PG_ZERO);
+ vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
+ m->valid = VM_PAGE_BITS_ALL;
+ }
+}
+
+/*
+ * Dispose the kernel stack for a thread that has exited.
+ * This routine directly impacts the exit perf of a thread.
+ */
+void
+pmap_dispose_thread(td)
+ struct thread *td;
+{
+ int i;
+ vm_object_t ksobj;
+ vm_offset_t ks;
+ vm_page_t m;
+ pt_entry_t *ptek, oldpte;
+
+ ksobj = td->td_kstack_obj;
+ ks = td->td_kstack;
+ ptek = vtopte(ks);
+ for (i = 0; i < KSTACK_PAGES; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_dispose_thread: kstack already missing?");
+ vm_page_busy(m);
+ oldpte = *(ptek + i);
+ *(ptek + i) = 0;
+ pmap_invalidate_page(kernel_pmap, ks + i * PAGE_SIZE);
+ vm_page_unwire(m, 0);
+ vm_page_free(m);
+ }
+}
+
+/*
+ * Allow the kernel stack for a thread to be prejudicially paged out.
+ */
+void
+pmap_swapout_thread(td)
+ struct thread *td;
+{
+ int i;
+ vm_object_t ksobj;
+ vm_offset_t ks;
+ vm_page_t m;
+
+ /*
+ * Make sure we aren't fpcurthread.
+ */
+ alpha_fpstate_save(td, 1);
+
+ ksobj = td->td_kstack_obj;
+ ks = td->td_kstack;
+ for (i = 0; i < KSTACK_PAGES; i++) {
+ m = vm_page_lookup(ksobj, i);
+ if (m == NULL)
+ panic("pmap_swapout_thread: kstack already missing?");
+ vm_page_dirty(m);
+ vm_page_unwire(m, 0);
+ pmap_kremove(ks + i * PAGE_SIZE);
+ }
+}
+
+/*
+ * Bring the kernel stack for a specified thread back in.
+ */
+void
+pmap_swapin_thread(td)
+ struct thread *td;
+{
+ int i, rv;
+ vm_object_t ksobj;
+ vm_offset_t ks;
+ vm_page_t m;
+
+ ksobj = td->td_kstack_obj;
+ ks = td->td_kstack;
+ for (i = 0; i < KSTACK_PAGES; i++) {
+ m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
+ pmap_kenter(ks + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m));
+ 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 for proc: %d\n", td->td_proc->p_pid);
+ m = vm_page_lookup(ksobj, i);
+ m->valid = VM_PAGE_BITS_ALL;
+ }
+ vm_page_wire(m);
+ vm_page_wakeup(m);
+ vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE);
+ }
/*
* The pcb may be at a different physical address now so cache the
* new address.
*/
- p->p_md.md_pcbpaddr = (void*)vtophys((vm_offset_t)&p->p_addr->u_pcb);
+ td->td_md.md_pcbpaddr = (void *)vtophys((vm_offset_t)td->td_pcb);
}
/***************************************************
@@ -1677,7 +1840,7 @@ pmap_collect()
{
int i;
vm_page_t m;
- static int warningdone=0;
+ static int warningdone = 0;
if (pmap_pagedaemon_waken == 0)
return;
@@ -2917,7 +3080,7 @@ pmap_clear_reference(vm_page_t m)
* From NetBSD
*/
void
-pmap_emulate_reference(struct proc *p, vm_offset_t v, int user, int write)
+pmap_emulate_reference(struct vmspace *vm, vm_offset_t v, int user, int write)
{
pt_entry_t faultoff, *pte;
vm_offset_t pa;
@@ -2932,9 +3095,8 @@ pmap_emulate_reference(struct proc *p, vm_offset_t v, int user, int write)
pte = vtopte(v);
user_addr = 0;
} else {
- KASSERT(p != NULL, ("pmap_emulate_reference: bad proc"));
- KASSERT(p->p_vmspace != NULL, ("pmap_emulate_reference: bad p_vmspace"));
- pte = pmap_lev3pte(p->p_vmspace->vm_map.pmap, v);
+ KASSERT(vm != NULL, ("pmap_emulate_reference: bad vmspace"));
+ pte = pmap_lev3pte(vm->vm_map.pmap, v);
user_addr = 1;
}
#ifdef DEBUG /* These checks are more expensive */
@@ -2964,7 +3126,7 @@ pmap_emulate_reference(struct proc *p, vm_offset_t v, int user, int write)
KASSERT((*pte & PG_MANAGED) != 0,
("pmap_emulate_reference(%p, 0x%lx, %d, %d): pa 0x%lx not managed",
- p, v, user, write, pa));
+ curthread, v, user, write, pa));
/*
* Twiddle the appropriate bits to reflect the reference
@@ -3092,11 +3254,11 @@ pmap_mincore(pmap, addr)
}
void
-pmap_activate(struct proc *p)
+pmap_activate(struct thread *td)
{
pmap_t pmap;
- pmap = vmspace_pmap(p->p_vmspace);
+ pmap = vmspace_pmap(td->td_proc->p_vmspace);
if (pmap_active[PCPU_GET(cpuid)] && pmap != pmap_active[PCPU_GET(cpuid)]) {
atomic_clear_32(&pmap_active[PCPU_GET(cpuid)]->pm_active,
@@ -3104,7 +3266,7 @@ pmap_activate(struct proc *p)
pmap_active[PCPU_GET(cpuid)] = 0;
}
- p->p_addr->u_pcb.pcb_hw.apcb_ptbr =
+ td->td_pcb->pcb_hw.apcb_ptbr =
ALPHA_K0SEG_TO_PHYS((vm_offset_t) pmap->pm_lev1) >> PAGE_SHIFT;
if (pmap->pm_asn[PCPU_GET(cpuid)].gen != PCPU_GET(current_asngen))
@@ -3113,18 +3275,19 @@ pmap_activate(struct proc *p)
pmap_active[PCPU_GET(cpuid)] = pmap;
atomic_set_32(&pmap->pm_active, 1 << PCPU_GET(cpuid));
- p->p_addr->u_pcb.pcb_hw.apcb_asn = pmap->pm_asn[PCPU_GET(cpuid)].asn;
+ td->td_pcb->pcb_hw.apcb_asn = pmap->pm_asn[PCPU_GET(cpuid)].asn;
- if (p == curproc) {
- alpha_pal_swpctx((u_long)p->p_md.md_pcbpaddr);
+ if (td == curthread) {
+ alpha_pal_swpctx((u_long)td->td_md.md_pcbpaddr);
}
}
void
-pmap_deactivate(struct proc *p)
+pmap_deactivate(struct thread *td)
{
pmap_t pmap;
- pmap = vmspace_pmap(p->p_vmspace);
+
+ pmap = vmspace_pmap(td->td_proc->p_vmspace);
atomic_clear_32(&pmap->pm_active, 1 << PCPU_GET(cpuid));
pmap_active[PCPU_GET(cpuid)] = 0;
}
@@ -3154,14 +3317,14 @@ pmap_pid_dump(int pid)
int i,j;
index = 0;
pmap = vmspace_pmap(p->p_vmspace);
- for(i=0;i<1024;i++) {
+ for (i = 0; i < 1024; i++) {
pd_entry_t *pde;
pt_entry_t *pte;
unsigned base = i << PDRSHIFT;
pde = &pmap->pm_pdir[i];
if (pde && pmap_pde_v(pde)) {
- for(j=0;j<1024;j++) {
+ for (j = 0; j < 1024; j++) {
unsigned va = base + (j << PAGE_SHIFT);
if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) {
if (index) {
OpenPOWER on IntegriCloud