diff options
| -rw-r--r-- | sys/sparc64/include/pcb.h | 1 | ||||
| -rw-r--r-- | sys/sparc64/include/tlb.h | 5 | ||||
| -rw-r--r-- | sys/sparc64/sparc64/genassym.c | 2 | ||||
| -rw-r--r-- | sys/sparc64/sparc64/support.S | 252 | ||||
| -rw-r--r-- | sys/sparc64/sparc64/trap.c | 57 |
5 files changed, 169 insertions, 148 deletions
diff --git a/sys/sparc64/include/pcb.h b/sys/sparc64/include/pcb.h index a70f61a230db..36d978b025d9 100644 --- a/sys/sparc64/include/pcb.h +++ b/sys/sparc64/include/pcb.h @@ -39,7 +39,6 @@ struct pcb { struct fpstate pcb_fpstate; u_long pcb_fp; u_long pcb_pc; - caddr_t pcb_onfault; u_long pcb_nsaved; u_long pcb_rwsp[MAXWIN]; struct rwindow pcb_rw[MAXWIN]; diff --git a/sys/sparc64/include/tlb.h b/sys/sparc64/include/tlb.h index 8c6ce1a34a3d..6cffc1cfa169 100644 --- a/sys/sparc64/include/tlb.h +++ b/sys/sparc64/include/tlb.h @@ -81,7 +81,10 @@ #define MMU_SFSR_FT_SIZE (6) #define MMU_SFSR_CT_SIZE (2) -#define MMU_SFSR_W (1L << MMU_SFSR_W_SHIFT) +#define MMU_SFSR_GET_ASI(sfsr) \ + (((sfsr) >> MMU_SFSR_ASI_SHIFT) & ((1UL << MMU_SFSR_ASI_SIZE) - 1)) +#define MMU_SFSR_W (1UL << MMU_SFSR_W_SHIFT) +#define MMU_SFSR_FV (1UL << MMU_SFSR_FV_SHIFT) struct tlb_entry; diff --git a/sys/sparc64/sparc64/genassym.c b/sys/sparc64/sparc64/genassym.c index 57827b613d8d..9d0dfa2bc71c 100644 --- a/sys/sparc64/sparc64/genassym.c +++ b/sys/sparc64/sparc64/genassym.c @@ -240,8 +240,6 @@ ASSYM(PCB_SIZEOF, sizeof(struct pcb)); ASSYM(PCB_FPSTATE, offsetof(struct pcb, pcb_fpstate)); ASSYM(PCB_FP, offsetof(struct pcb, pcb_fp)); ASSYM(PCB_PC, offsetof(struct pcb, pcb_pc)); -ASSYM(PCB_Y, offsetof(struct pcb, pcb_pc)); -ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); ASSYM(PCB_NSAVED, offsetof(struct pcb, pcb_nsaved)); ASSYM(PCB_RWSP, offsetof(struct pcb, pcb_rwsp)); ASSYM(PCB_RW, offsetof(struct pcb, pcb_rw)); diff --git a/sys/sparc64/sparc64/support.S b/sys/sparc64/sparc64/support.S index 68cf714166a4..649f0b84bdf5 100644 --- a/sys/sparc64/sparc64/support.S +++ b/sys/sparc64/sparc64/support.S @@ -211,37 +211,45 @@ inc dst ; \ 6: -#define CATCH_SETUP(label) \ - SET(label, %g2, %g1) ; \ - stx %g1, [PCB_REG + PCB_ONFAULT] - -#define CATCH_END() \ - stx %g0, [PCB_REG + PCB_ONFAULT] - -#define FU_ALIGNED(loader, label) \ - CATCH_SETUP(label) ; \ - loader [%o0] ASI_AIUP, %o0 ; \ - retl ; \ - CATCH_END() - -#define FU_BYTES(loader, size, label) \ - btst (size) - 1, %o0 ; \ - bnz,pn %xcc, .Lfsalign ; \ - EMPTY ; \ - FU_ALIGNED(loader, label) - -#define SU_ALIGNED(storer, label) \ - CATCH_SETUP(label) ; \ - storer %o1, [%o0] ASI_AIUP ; \ - CATCH_END() ; \ - retl ; \ - clr %o0 +/* + * void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len) + */ +ENTRY(ascopy) + wr %o0, 0, %asi + _MEMCPY(%o2, %o1, %o3, a, %asi, a, %asi) + retl + nop +END(ascopy) -#define SU_BYTES(storer, size, label) \ - btst (size) - 1, %o0 ; \ - bnz,pn %xcc, .Lfsalign ; \ - EMPTY ; \ - SU_ALIGNED(storer, label) +/* + * void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len) + */ +ENTRY(ascopyfrom) + wr %o0, 0, %asi + _MEMCPY(%o2, %o1, %o3, E, E, a, %asi) + retl + nop +END(ascopyfrom) + +/* + * void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len) + */ +ENTRY(ascopyto) + wr %o1, 0, %asi + _MEMCPY(%o2, %o0, %o3, a, %asi, E, E) + retl + nop +END(ascopyto) + +/* + * void aszero(u_long asi, vm_offset_t pa, size_t len) + */ +ENTRY(aszero) + wr %o0, 0, %asi + _MEMSET(%o1, %g0, %o2, a, %asi) + retl + nop +END(aszero) /* * int bcmp(const void *b1, const void *b2, size_t len) @@ -308,44 +316,13 @@ ENTRY(bzero) END(bzero) /* - * void ascopy(u_long asi, vm_offset_t src, vm_offset_t dst, size_t len) - */ -ENTRY(ascopy) - wr %o0, 0, %asi - _MEMCPY(%o2, %o1, %o3, a, %asi, a, %asi) - retl - nop -END(ascopy) - -/* - * void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len) - */ -ENTRY(ascopyfrom) - wr %o0, 0, %asi - _MEMCPY(%o2, %o1, %o3, E, E, a, %asi) - retl - nop -END(ascopyfrom) - -/* - * void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len) - */ -ENTRY(ascopyto) - wr %o1, 0, %asi - _MEMCPY(%o2, %o0, %o3, a, %asi, E, E) - retl - nop -END(ascopyto) - -/* - * void aszero(u_long asi, vm_offset_t pa, size_t len) + * int copystr(const void *src, void *dst, size_t len, size_t *done) */ -ENTRY(aszero) - wr %o0, 0, %asi - _MEMSET(%o1, %g0, %o2, a, %asi) +ENTRY(copystr) + _COPYSTR(%o0, %o1, %o2, %o3, E, E, E, E) retl - nop -END(aszero) + mov %g1, %o0 +END(copystr) /* * void *memcpy(void *dst, const void *src, size_t len) @@ -367,14 +344,16 @@ ENTRY(memset) nop END(memset) + .globl copy_nofault_begin +copy_nofault_begin: + nop + /* * int copyin(const void *uaddr, void *kaddr, size_t len) */ ENTRY(copyin) - CATCH_SETUP(.Lefault) wr %g0, ASI_AIUP, %asi _MEMCPY(%o1, %o0, %o2, E, E, a, %asi) - CATCH_END() retl clr %o0 END(copyin) @@ -383,10 +362,8 @@ END(copyin) * int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) */ ENTRY(copyinstr) - CATCH_SETUP(.Lefault) wr %g0, ASI_AIUP, %asi _COPYSTR(%o0, %o1, %o2, %o3, a, %asi, E, E) - CATCH_END() retl mov %g1, %o0 END(copyinstr) @@ -395,128 +372,137 @@ END(copyinstr) * int copyout(const void *kaddr, void *uaddr, size_t len) */ ENTRY(copyout) - CATCH_SETUP(.Lefault) wr %g0, ASI_AIUP, %asi _MEMCPY(%o1, %o0, %o2, a, %asi, E, E) - CATCH_END() retl clr %o0 END(copyout) -.Lefault: - CATCH_END() - retl - mov EFAULT, %o0 + .globl copy_nofault_end +copy_nofault_end: + nop -/* - * int copystr(const void *src, void *dst, size_t len, size_t *done) - */ -ENTRY(copystr) - _COPYSTR(%o0, %o1, %o2, %o3, E, E, E, E) +ENTRY(copy_fault) retl - mov %g1, %o0 -END(copystr) + mov EFAULT, %o0 +END(copy_fault) -/* - * int fubyte(const void *base) - */ -ENTRY(fubyte) - FU_ALIGNED(lduba, .Lfsfault) -END(fubyte) + .globl fs_nofault_begin +fs_nofault_begin: + nop /* - * long fuword(const void *base) + * Chatty aliases for fetch, store functions. */ -ENTRY(fuword) - FU_BYTES(ldxa, 8, .Lfsfault) -END(fuword) + .globl fubyte, fusword, fuword, subyte, susword, suword + .set fubyte, fuword8 + .set fusword, fuword16 + .set fuword, fuword64 + .set subyte, suword8 + .set susword, suword16 + .set suword, suword64 /* - * int fuswintr(const void *base) + * int fuword8(const void *base) */ -ENTRY(fuswintr) - FU_BYTES(lduha, 2, fsbail) -END(fuswintr) +ENTRY(fuword8) + retl + lduba [%o0] ASI_AIUP, %o0 +END(fuword8) /* - * int16_t fuword16(const void *base) + * int fuword16(const void *base) */ ENTRY(fuword16) - FU_BYTES(lduha, 2, .Lfsfault) + retl + lduha [%o0] ASI_AIUP, %o0 END(fuword16) /* * int32_t fuword32(const void *base) */ ENTRY(fuword32) - FU_BYTES(lduwa, 4, .Lfsfault) + retl + lduwa [%o0] ASI_AIUP, %o0 END(fuword32) /* * int64_t fuword64(const void *base) */ ENTRY(fuword64) - FU_BYTES(ldxa, 8, .Lfsfault) + retl + ldxa [%o0] ASI_AIUP, %o0 END(fuword64) /* - * int subyte(const void *base, int byte) + * int suword8(const void *base, int word) */ -ENTRY(subyte) - SU_ALIGNED(stba, .Lfsfault) -END(subyte) - -/* - * int suword(const void *base, long word) - */ -ENTRY(suword) - SU_BYTES(stxa, 8, .Lfsfault) -END(suword) - -/* - * int suswintr(const void *base, int word) - */ -ENTRY(suswintr) - SU_BYTES(stwa, 2, fsbail) -END(suswintr) +ENTRY(suword8) + stba %o1, [%o0] ASI_AIUP + retl + clr %o0 +END(suword8) /* - * int suword16(const void *base, int16_t word) + * int suword16(const void *base, int word) */ ENTRY(suword16) - SU_BYTES(stha, 2, .Lfsfault) + stha %o1, [%o0] ASI_AIUP + retl + clr %o0 END(suword16) /* * int suword32(const void *base, int32_t word) */ ENTRY(suword32) - SU_BYTES(stwa, 4, .Lfsfault) + stwa %o1, [%o0] ASI_AIUP + retl + clr %o0 END(suword32) /* * int suword64(const void *base, int64_t word) */ ENTRY(suword64) - SU_BYTES(stxa, 8, .Lfsfault) + stxa %o1, [%o0] ASI_AIUP + retl + clr %o0 END(suword64) - _ALIGN_TEXT -.Lfsalign: + .globl fs_nofault_intr_begin +fs_nofault_intr_begin: + nop + +/* + * int fuswintr(const void *base) + */ +ENTRY(fuswintr) retl - mov -1, %o0 + lduha [%o0] ASI_AIUP, %o0 +END(fuswintr) - _ALIGN_TEXT -.Lfsfault: - CATCH_END() +/* + * int suswintr(const void *base, int word) + */ +ENTRY(suswintr) + stha %o1, [%o0] ASI_AIUP retl - mov -1, %o0 + clr %o0 +END(suswintr) + + .globl fs_nofault_intr_end +fs_nofault_intr_end: + nop + + .globl fs_nofault_end +fs_nofault_end: + nop -ENTRY(fsbail) - CATCH_END() +ENTRY(fs_fault) retl mov -1, %o0 -END(fsbail) +END(fsfault) ENTRY(longjmp) set 1, %g3 diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index 0ab35afd053c..65eda046f840 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -91,7 +91,15 @@ void syscall(struct trapframe *tf); static int trap_pfault(struct thread *td, struct trapframe *tf); -extern char fsbail[]; +extern char copy_fault[]; +extern char copy_nofault_begin[]; +extern char copy_nofault_end[]; + +extern char fs_fault[]; +extern char fs_nofault_begin[]; +extern char fs_nofault_end[]; +extern char fs_nofault_intr_begin[]; +extern char fs_nofault_intr_end[]; extern char *syscallnames[]; @@ -303,6 +311,24 @@ if ((type & ~T_KERNEL) != T_BREAKPOINT) goto out; break; #endif + case T_DATA_EXCEPTION | T_KERNEL: + case T_MEM_ADDRESS_NOT_ALIGNED | T_KERNEL: + if ((tf->tf_sfsr & MMU_SFSR_FV) == 0 || + MMU_SFSR_GET_ASI(tf->tf_sfsr) != ASI_AIUP) + break; + if (tf->tf_tpc >= (u_long)copy_nofault_begin && + tf->tf_tpc <= (u_long)copy_nofault_end) { + tf->tf_tpc = (u_long)copy_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + goto out; + } + if (tf->tf_tpc >= (u_long)fs_nofault_begin && + tf->tf_tpc <= (u_long)fs_nofault_end) { + tf->tf_tpc = (u_long)fs_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + goto out; + } + break; case T_DATA_MISS | T_KERNEL: case T_DATA_PROTECTION | T_KERNEL: case T_INSTRUCTION_MISS | T_KERNEL: @@ -439,9 +465,12 @@ trap_pfault(struct thread *td, struct trapframe *tf) if (ctx != TLB_CTX_KERNEL) { if ((tf->tf_tstate & TSTATE_PRIV) != 0 && - (td->td_intr_nesting_level != 0 || - pcb->pcb_onfault == NULL || pcb->pcb_onfault == fsbail)) - return (-1); + (tf->tf_tpc >= (u_long)fs_nofault_intr_begin && + tf->tf_tpc <= (u_long)fs_nofault_intr_end)) { + tf->tf_tpc = (u_long)fs_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + return (0); + } /* * This is a fault on non-kernel virtual memory. @@ -467,9 +496,9 @@ trap_pfault(struct thread *td, struct trapframe *tf) PROC_UNLOCK(p); } else { /* - * This is a fault on kernel virtual memory. Attempts to access - * kernel memory from user mode cause privileged action traps, - * not page fault. + * This is a fault on kernel virtual memory. Attempts to + * access kernel memory from user mode cause privileged + * action traps, not page fault. */ KASSERT(tf->tf_tstate & TSTATE_PRIV, ("trap_pfault: fault on nucleus context from user mode")); @@ -485,10 +514,16 @@ trap_pfault(struct thread *td, struct trapframe *tf) td, va, rv); if (rv == KERN_SUCCESS) return (0); - if ((tf->tf_tstate & TSTATE_PRIV) != 0) { - if (td->td_intr_nesting_level == 0 && - pcb->pcb_onfault != NULL) { - tf->tf_tpc = (u_long)pcb->pcb_onfault; + if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) { + if (tf->tf_tpc >= (u_long)fs_nofault_begin && + tf->tf_tpc <= (u_long)fs_nofault_end) { + tf->tf_tpc = (u_long)fs_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + return (0); + } + if (tf->tf_tpc >= (u_long)copy_nofault_begin && + tf->tf_tpc <= (u_long)copy_nofault_end) { + tf->tf_tpc = (u_long)copy_fault; tf->tf_tnpc = tf->tf_tpc + 4; return (0); } |
