From cb67f0018f1ab1611ac13fd92b3c6d8d7becda8f Mon Sep 17 00:00:00 2001 From: Jake Burkholder Date: Sun, 18 Nov 2001 03:28:28 +0000 Subject: [PATCH] 1. Convert the tstate saved in the pcb to a pstate and test for PSTATE_PEF to determine if a process is using floating point. in order to avoid sign extending a 13 bit immediate. 2. We don't need to context switch cwp anymore, it is better to just fiddle the save tstate on return from traps. See exception.s 1.10 and 1.12. 3. Completely remove pcb_cwp. 4. Implement vmapbuf, vunmapbuf and vm_fault_quick. Completely remove TODOs from vm_machdep.c (yay!). Submitted by: tmm (1, 3, 4) Obtained from: existing archs (4) --- sys/sparc64/include/pcb.h | 10 +-- sys/sparc64/sparc64/swtch.S | 23 ++---- sys/sparc64/sparc64/swtch.s | 23 ++---- sys/sparc64/sparc64/vm_machdep.c | 122 ++++++++++++++++++++++++++++--- 4 files changed, 128 insertions(+), 50 deletions(-) diff --git a/sys/sparc64/include/pcb.h b/sys/sparc64/include/pcb.h index 7db380a48472..d5782b032fcf 100644 --- a/sys/sparc64/include/pcb.h +++ b/sys/sparc64/include/pcb.h @@ -32,19 +32,11 @@ #include #include -/* - * XXX: MAXWIN should probably be done dynamically, pcb_wscratch is therefore - * at the end of the pcb. - */ -#define MAXWIN 8 - -/* Used in pcb_fcwp to mark the wscratch stack as empty. */ -#define PCB_CWP_EMPTY 0xff +#define MAXWIN 8 /* NOTE: pcb_fpstate must be aligned on a 64 byte boundary. */ struct pcb { struct fpstate pcb_fpstate; - u_long pcb_cwp; u_long pcb_fp; u_long pcb_pc; u_long pcb_y; diff --git a/sys/sparc64/sparc64/swtch.S b/sys/sparc64/sparc64/swtch.S index 137ca1a48ded..145861e6802f 100644 --- a/sys/sparc64/sparc64/swtch.S +++ b/sys/sparc64/sparc64/swtch.S @@ -113,7 +113,8 @@ ENTRY(cpu_switch) rd %fprs, %l3 stx %l3, [%l2 + PCB_FPSTATE + FP_FPRS] ldx [%l1 + TF_TSTATE], %l1 - andcc %l1, TSTATE_PEF, %l1 + srlx %l1, TSTATE_PSTATE_SHIFT, %l1 + andcc %l1, PSTATE_PEF, %l1 be,pt %xcc, 1f nop savefp %l2 + PCB_FPSTATE, %l4, %l3 @@ -124,8 +125,6 @@ ENTRY(cpu_switch) */ 1: flushw wrpr %g0, 0, %cleanwin - rdpr %cwp, %l3 - stx %l3, [%l2 + PCB_CWP] stx %fp, [%l2 + PCB_FP] stx %i7, [%l2 + PCB_PC] @@ -135,7 +134,7 @@ ENTRY(cpu_switch) */ .Lsw1: ldx [%o0 + TD_PCB], %o1 #if KTR_COMPILE & KTR_PROC - CATR(KTR_PROC, "cpu_switch: to=%p pc=%#lx fp=%#lx sp=%#lx cwp=%#lx" + CATR(KTR_PROC, "cpu_switch: to=%p pc=%#lx fp=%#lx sp=%#lx" , %g1, %g2, %g3, 7, 8, 9) stx %o0, [%g1 + KTR_PARM1] ldx [%o1 + PCB_PC], %g2 @@ -144,17 +143,7 @@ ENTRY(cpu_switch) stx %g2, [%g1 + KTR_PARM3] sub %g2, CCFSZ, %g2 stx %g2, [%g1 + KTR_PARM4] - ldx [%o1 + PCB_CWP], %g2 - stx %g2, [%g1 + KTR_PARM5] 9: -#endif -#if 1 - mov %o0, %g4 - mov %l0, %g5 - ldx [%o1 + PCB_CWP], %o2 - wrpr %o2, %cwp - mov %g4, %o0 - mov %g5, %l0 #endif ldx [%o0 + TD_PCB], %o1 ldx [%o1 + PCB_FP], %fp @@ -187,7 +176,8 @@ ENTRY(cpu_switch) */ ldx [%o0 + TD_FRAME], %o4 ldx [%o4 + TF_TSTATE], %o4 - andcc %o4, TSTATE_PEF, %o4 + srlx %o4, TSTATE_PSTATE_SHIFT, %o4 + andcc %o4, PSTATE_PEF, %o4 be,pt %xcc, 2f nop restrfp %o1 + PCB_FPSTATE, %o4 @@ -274,7 +264,8 @@ ENTRY(savectx) ldx [PCPU(CURTHREAD)], %l0 ldx [%l0 + TD_FRAME], %l0 ldx [%l0 + TF_TSTATE], %l0 - andcc %l0, TSTATE_PEF, %l0 + srlx %l0, TSTATE_PSTATE_SHIFT, %l0 + andcc %l0, PSTATE_PEF, %l0 be,pt %xcc, 1f stx %fp, [%i0 + PCB_FP] add %i0, PCB_FPSTATE, %o0 diff --git a/sys/sparc64/sparc64/swtch.s b/sys/sparc64/sparc64/swtch.s index 137ca1a48ded..145861e6802f 100644 --- a/sys/sparc64/sparc64/swtch.s +++ b/sys/sparc64/sparc64/swtch.s @@ -113,7 +113,8 @@ ENTRY(cpu_switch) rd %fprs, %l3 stx %l3, [%l2 + PCB_FPSTATE + FP_FPRS] ldx [%l1 + TF_TSTATE], %l1 - andcc %l1, TSTATE_PEF, %l1 + srlx %l1, TSTATE_PSTATE_SHIFT, %l1 + andcc %l1, PSTATE_PEF, %l1 be,pt %xcc, 1f nop savefp %l2 + PCB_FPSTATE, %l4, %l3 @@ -124,8 +125,6 @@ ENTRY(cpu_switch) */ 1: flushw wrpr %g0, 0, %cleanwin - rdpr %cwp, %l3 - stx %l3, [%l2 + PCB_CWP] stx %fp, [%l2 + PCB_FP] stx %i7, [%l2 + PCB_PC] @@ -135,7 +134,7 @@ ENTRY(cpu_switch) */ .Lsw1: ldx [%o0 + TD_PCB], %o1 #if KTR_COMPILE & KTR_PROC - CATR(KTR_PROC, "cpu_switch: to=%p pc=%#lx fp=%#lx sp=%#lx cwp=%#lx" + CATR(KTR_PROC, "cpu_switch: to=%p pc=%#lx fp=%#lx sp=%#lx" , %g1, %g2, %g3, 7, 8, 9) stx %o0, [%g1 + KTR_PARM1] ldx [%o1 + PCB_PC], %g2 @@ -144,17 +143,7 @@ ENTRY(cpu_switch) stx %g2, [%g1 + KTR_PARM3] sub %g2, CCFSZ, %g2 stx %g2, [%g1 + KTR_PARM4] - ldx [%o1 + PCB_CWP], %g2 - stx %g2, [%g1 + KTR_PARM5] 9: -#endif -#if 1 - mov %o0, %g4 - mov %l0, %g5 - ldx [%o1 + PCB_CWP], %o2 - wrpr %o2, %cwp - mov %g4, %o0 - mov %g5, %l0 #endif ldx [%o0 + TD_PCB], %o1 ldx [%o1 + PCB_FP], %fp @@ -187,7 +176,8 @@ ENTRY(cpu_switch) */ ldx [%o0 + TD_FRAME], %o4 ldx [%o4 + TF_TSTATE], %o4 - andcc %o4, TSTATE_PEF, %o4 + srlx %o4, TSTATE_PSTATE_SHIFT, %o4 + andcc %o4, PSTATE_PEF, %o4 be,pt %xcc, 2f nop restrfp %o1 + PCB_FPSTATE, %o4 @@ -274,7 +264,8 @@ ENTRY(savectx) ldx [PCPU(CURTHREAD)], %l0 ldx [%l0 + TD_FRAME], %l0 ldx [%l0 + TF_TSTATE], %l0 - andcc %l0, TSTATE_PEF, %l0 + srlx %l0, TSTATE_PSTATE_SHIFT, %l0 + andcc %l0, PSTATE_PEF, %l0 be,pt %xcc, 1f stx %fp, [%i0 + PCB_FP] add %i0, PCB_FPSTATE, %o0 diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c index d08cdd9d92bd..904d5e9044f0 100644 --- a/sys/sparc64/sparc64/vm_machdep.c +++ b/sys/sparc64/sparc64/vm_machdep.c @@ -57,7 +57,10 @@ #include #include #include +#include +#include +#include #include #include #include @@ -108,7 +111,6 @@ cpu_fork(struct thread *td1, struct proc *p2, int flags) __asm __volatile("flushw"); /* Copy the pcb (this will copy the windows saved in the pcb, too). */ bcopy(td1->td_pcb, pcb, sizeof(*pcb)); - pcb->pcb_cwp = 2; /* * Create a new fresh stack for the new process. @@ -127,7 +129,6 @@ cpu_fork(struct thread *td1, struct proc *p2, int flags) fp->f_local[0] = (u_long)fork_return; fp->f_local[1] = (u_long)td2; fp->f_local[2] = (u_long)tf; - pcb->pcb_cwp = 0; pcb->pcb_fp = (u_long)fp - SPOFF; pcb->pcb_pc = (u_long)fork_trampoline - 8; @@ -157,7 +158,7 @@ cpu_reset(void) bspec[0] = '\0'; bspec[sizeof(bspec) - 1] = '\0'; } - + openfirmware_exit(&args); } @@ -188,30 +189,133 @@ int is_physical_memory(vm_offset_t addr) { - TODO; + /* There is no device memory in the midst of the normal RAM. */ + return (1); } void swi_vm(void *v) { - TODO; + + /* + * Nothing to do here yet - busdma bounce buffers are not yet + * implemented. + */ } +/* + * quick version of vm_fault + */ int vm_fault_quick(caddr_t v, int prot) { - TODO; - return (0); + int r; + + if (prot & VM_PROT_WRITE) + r = subyte(v, fubyte(v)); + else + r = fubyte(v); + return(r); } +/* + * Map an IO request into kernel virtual address space. + * + * All requests are (re)mapped into kernel VA space. + * Notice that we use b_bufsize for the size of the buffer + * to be mapped. b_bcount might be modified by the driver. + */ void vmapbuf(struct buf *bp) { - TODO; + caddr_t addr, kva; + vm_offset_t pa; + int pidx; + struct vm_page *m; + pmap_t pmap; + + GIANT_REQUIRED; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); + + pmap = &curproc->p_vmspace->vm_pmap; + for (addr = (caddr_t)trunc_page((vm_offset_t)bp->b_data), pidx = 0; + addr < bp->b_data + bp->b_bufsize; addr += PAGE_SIZE, pidx++) { + /* + * Do the vm_fault if needed; do the copy-on-write thing + * when reading stuff off device into memory. + */ + vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data, + (bp->b_iocmd == BIO_READ) ? (VM_PROT_READ | VM_PROT_WRITE) : + VM_PROT_READ); + pa = trunc_page(pmap_extract(pmap, (vm_offset_t)addr)); + if (pa == 0) + panic("vmapbuf: page not present"); + m = PHYS_TO_VM_PAGE(pa); + vm_page_hold(m); + bp->b_pages[pidx] = m; + } + if (pidx > btoc(MAXPHYS)) + panic("vmapbuf: mapped more than MAXPHYS"); + pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx); + + kva = bp->b_saveaddr; + bp->b_npages = pidx; + bp->b_saveaddr = bp->b_data; + bp->b_data = kva + (((vm_offset_t)bp->b_data) & PAGE_MASK); + if (CACHE_BADALIAS(trunc_page(bp->b_data), + trunc_page(bp->b_saveaddr))) { + /* + * bp->data (the virtual address the buffer got mapped to in the + * kernel) is an illegal alias to the user address. + * If the kernel had mapped this buffer previously (during a + * past IO operation) at this address, there might still be + * stale but valid tagged data in the cache, so flush it. + * XXX: the kernel address should be selected such that this + * cannot happen. + * XXX: pmap_kenter() maps physically uncacheable right now, so + * this cannot happen. + */ + dcache_inval(pmap, (vm_offset_t)bp->b_data, + (vm_offset_t)bp->b_data + bp->b_bufsize - 1); + } } +/* + * Free the io map PTEs associated with this IO operation. + * We also invalidate the TLB entries and restore the original b_addr. + */ void vunmapbuf(struct buf *bp) { - TODO; + int pidx; + int npages; + + GIANT_REQUIRED; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); + + npages = bp->b_npages; + pmap_qremove(trunc_page((vm_offset_t)bp->b_data), + npages); + for (pidx = 0; pidx < npages; pidx++) + vm_page_unhold(bp->b_pages[pidx]); + + if (CACHE_BADALIAS(trunc_page(bp->b_data), + trunc_page(bp->b_saveaddr))) { + /* + * bp->data (the virtual address the buffer got mapped to in the + * kernel) is an illegal alias to the user address. In this + * case, D$ of the user adress needs to be flushed to avoid the + * user reading stale data. + * XXX: the kernel address should be selected such that this + * cannot happen. + */ + dcache_inval(&curproc->p_vmspace->vm_pmap, + (vm_offset_t)bp->b_saveaddr, (vm_offset_t)bp->b_saveaddr + + bp->b_bufsize - 1); + } + bp->b_data = bp->b_saveaddr; }