Module Name: src Committed By: matt Date: Sat Dec 3 01:56:56 UTC 2011
Modified Files: src/sys/arch/evbmips/rmixl [matt-nb5-mips64]: machdep.c src/sys/arch/mips/include [matt-nb5-mips64]: cpu.h pmap.h src/sys/arch/mips/mips [matt-nb5-mips64]: cpu_subr.c genassym.cf mipsX_subr.S pmap_tlb.c src/sys/arch/mips/rmi [matt-nb5-mips64]: rmixl_subr.S Log Message: Rework things a bit for the XLR/XLS/XLP TLB. Before dealing with the TLB when MP on the XL?, disable interrupts and take out a lock to prevent concurrent updates to the TLB. In the TLB miss and invalid exception handlers, if the lock is already owned by another CPU, simply return from the exception and let it continue or restart as appropriate. This prevents concurrent TLB exceptions in multiple threads from possibly updating the TLB multiple times for a single address. To generate a diff of this commit: cvs rdiff -u -r1.1.2.36 -r1.1.2.37 src/sys/arch/evbmips/rmixl/machdep.c cvs rdiff -u -r1.90.16.37 -r1.90.16.38 src/sys/arch/mips/include/cpu.h cvs rdiff -u -r1.54.26.18 -r1.54.26.19 src/sys/arch/mips/include/pmap.h cvs rdiff -u -r1.1.2.20 -r1.1.2.21 src/sys/arch/mips/mips/cpu_subr.c cvs rdiff -u -r1.44.12.29 -r1.44.12.30 src/sys/arch/mips/mips/genassym.cf cvs rdiff -u -r1.26.36.1.2.49 -r1.26.36.1.2.50 \ src/sys/arch/mips/mips/mipsX_subr.S cvs rdiff -u -r1.1.2.18 -r1.1.2.19 src/sys/arch/mips/mips/pmap_tlb.c cvs rdiff -u -r1.1.2.9 -r1.1.2.10 src/sys/arch/mips/rmi/rmixl_subr.S Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbmips/rmixl/machdep.c diff -u src/sys/arch/evbmips/rmixl/machdep.c:1.1.2.36 src/sys/arch/evbmips/rmixl/machdep.c:1.1.2.37 --- src/sys/arch/evbmips/rmixl/machdep.c:1.1.2.36 Tue Nov 29 07:48:32 2011 +++ src/sys/arch/evbmips/rmixl/machdep.c Sat Dec 3 01:56:55 2011 @@ -253,6 +253,12 @@ mach_init(int argc, int32_t *argv, void rmixl_pcr_init_core(); +#ifdef MULTIPROCESSOR + __asm __volatile("dmtc0 %0,$%1,2" + :: "r"(&pmap_tlb0_info.ti_hwlock->mtx_lock), + "n"(MIPS_COP_0_OSSCRATCH)); +#endif + /* * Clear the BSS segment. */ @@ -374,8 +380,8 @@ mach_init(int argc, int32_t *argv, void #ifdef MULTIPROCESSOR /* reserve the cpu_wakeup_info area */ mem_cluster_cnt = ram_seg_resv(mem_clusters, mem_cluster_cnt, - (u_quad_t)trunc_page(rcp->rc_cpu_wakeup_info), - (u_quad_t)round_page(rcp->rc_cpu_wakeup_end)); + (u_quad_t)trunc_page((vaddr_t)rcp->rc_cpu_wakeup_info), + (u_quad_t)round_page((vaddr_t)rcp->rc_cpu_wakeup_end)); #endif #ifdef MEMLIMIT @@ -455,9 +461,6 @@ mach_init(int argc, int32_t *argv, void __asm __volatile("dmtc0 %0,$%1" :: "r"(&cpu_info_store), "n"(MIPS_COP_0_OSSCRATCH)); #ifdef MULTIPROCESSOR - __asm __volatile("dmtc0 %0,$%1,2" - :: "r"(&pmap_tlb0_info.ti_lock->mtx_lock), - "n"(MIPS_COP_0_OSSCRATCH)); mips_fixup_exceptions(rmixl_fixup_cop0_oscratch); #endif rmixl_fixup_curcpu(); Index: src/sys/arch/mips/include/cpu.h diff -u src/sys/arch/mips/include/cpu.h:1.90.16.37 src/sys/arch/mips/include/cpu.h:1.90.16.38 --- src/sys/arch/mips/include/cpu.h:1.90.16.37 Thu May 26 19:21:55 2011 +++ src/sys/arch/mips/include/cpu.h Sat Dec 3 01:56:55 2011 @@ -107,7 +107,9 @@ struct cpu_info { volatile u_int ci_softints; struct evcnt ci_ev_fpu_loads; /* fpu load counter */ struct evcnt ci_ev_fpu_saves; /* fpu save counter */ - struct evcnt ci_ev_tlbmisses; + struct evcnt ci_ev_kern_tlbmisses; + struct evcnt ci_ev_user_tlbmisses; + struct evcnt ci_ev_tlblocked; /* * Per-cpu pmap information Index: src/sys/arch/mips/include/pmap.h diff -u src/sys/arch/mips/include/pmap.h:1.54.26.18 src/sys/arch/mips/include/pmap.h:1.54.26.19 --- src/sys/arch/mips/include/pmap.h:1.54.26.18 Fri Apr 29 08:26:21 2011 +++ src/sys/arch/mips/include/pmap.h Sat Dec 3 01:56:55 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.54.26.18 2011/04/29 08:26:21 matt Exp $ */ +/* $NetBSD: pmap.h,v 1.54.26.19 2011/12/03 01:56:55 matt Exp $ */ /* * Copyright (c) 1992, 1993 @@ -202,6 +202,7 @@ struct pmap_tlb_info { uint32_t ti_asid_max; LIST_HEAD(, pmap_asid_info) ti_pais; /* list of active ASIDs */ #ifdef MULTIPROCESSOR + kmutex_t *ti_hwlock; pmap_t ti_victim; uint32_t ti_synci_page_bitmap; /* page indices needing a syncicache */ uint32_t ti_cpu_mask; /* bitmask of CPUs sharing this TLB */ Index: src/sys/arch/mips/mips/cpu_subr.c diff -u src/sys/arch/mips/mips/cpu_subr.c:1.1.2.20 src/sys/arch/mips/mips/cpu_subr.c:1.1.2.21 --- src/sys/arch/mips/mips/cpu_subr.c:1.1.2.20 Tue Nov 29 07:48:31 2011 +++ src/sys/arch/mips/mips/cpu_subr.c Sat Dec 3 01:56:55 2011 @@ -242,9 +242,15 @@ cpu_attach_common(device_t self, struct evcnt_attach_dynamic(&ci->ci_ev_fpu_saves, EVCNT_TYPE_MISC, NULL, xname, "fpu saves"); - evcnt_attach_dynamic(&ci->ci_ev_tlbmisses, + evcnt_attach_dynamic(&ci->ci_ev_user_tlbmisses, EVCNT_TYPE_TRAP, NULL, xname, - "tlb misses"); + "user tlb misses"); + evcnt_attach_dynamic(&ci->ci_ev_kern_tlbmisses, + EVCNT_TYPE_TRAP, NULL, xname, + "kern tlb misses"); + evcnt_attach_dynamic(&ci->ci_ev_tlblocked, + EVCNT_TYPE_MISC, NULL, xname, + "tlb locked"); if (ci == &cpu_info_store) pmap_tlb_info_evcnt_attach(ci->ci_tlb_info); Index: src/sys/arch/mips/mips/genassym.cf diff -u src/sys/arch/mips/mips/genassym.cf:1.44.12.29 src/sys/arch/mips/mips/genassym.cf:1.44.12.30 --- src/sys/arch/mips/mips/genassym.cf:1.44.12.29 Fri Dec 2 00:01:37 2011 +++ src/sys/arch/mips/mips/genassym.cf Sat Dec 3 01:56:55 2011 @@ -284,14 +284,18 @@ define MTX_OWNER offsetof(struct kmutex, define MTX_LOCK offsetof(struct kmutex, mtx_lock) define MTX_IPL offsetof(struct kmutex, mtx_ipl) -define TI_LOCK offsetof(struct pmap_tlb_info, ti_lock) +ifdef MULTIPROCESSOR +define TI_HWLOCK offsetof(struct pmap_tlb_info, ti_hwlock) +endif # CPU info define CPU_INFO_CPL offsetof(struct cpu_info, ci_cpl) define CPU_INFO_IDEPTH offsetof(struct cpu_info, ci_idepth) define CPU_INFO_CURLWP offsetof(struct cpu_info, ci_curlwp) define CPU_INFO_IDLELWP offsetof(struct cpu_info, ci_data.cpu_idlelwp) -define CPU_INFO_EV_TLBMISSES offsetof(struct cpu_info, ci_ev_tlbmisses.ev_count) +define CPU_INFO_EV_USER_TLBMISSES offsetof(struct cpu_info, ci_ev_user_tlbmisses.ev_count) +define CPU_INFO_EV_KERN_TLBMISSES offsetof(struct cpu_info, ci_ev_kern_tlbmisses.ev_count) +define CPU_INFO_EV_TLBLOCKED offsetof(struct cpu_info, ci_ev_tlblocked.ev_count) define CPU_INFO_PMAP_SEG0TAB offsetof(struct cpu_info, ci_pmap_seg0tab) ifdef _LP64 define CPU_INFO_PMAP_SEGTAB offsetof(struct cpu_info, ci_pmap_segtab) Index: src/sys/arch/mips/mips/mipsX_subr.S diff -u src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.49 src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.50 --- src/sys/arch/mips/mips/mipsX_subr.S:1.26.36.1.2.49 Fri Dec 2 00:01:37 2011 +++ src/sys/arch/mips/mips/mipsX_subr.S Sat Dec 3 01:56:55 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: mipsX_subr.S,v 1.26.36.1.2.49 2011/12/02 00:01:37 matt Exp $ */ +/* $NetBSD: mipsX_subr.S,v 1.26.36.1.2.50 2011/12/03 01:56:55 matt Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -345,7 +345,7 @@ VECTOR(MIPSX(tlb_miss), unknown) .set noat #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 - _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 #00: get tlbinfo lock addr + _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 #00: get tlbinfo hwlock addr li k0, __SIMPLELOCK_LOCKED #01: lock value swapw k0, k1 #02: swap it in place bnez k0, MIPSX(tlblocked) #03: a lie @@ -432,10 +432,10 @@ MIPSX(tlb_miss_common): _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 #1a get tlbinfo lock addr INT_S zero, 0(k1) #1b clear lock #elif (MIPS3 + MIPS64 + MIPS64R2 + MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 - lui k1, %hi(CPUVAR(EV_TLBMISSES)) #1a: k1=hi of tlbmisses - REG_L k0, %lo(CPUVAR(EV_TLBMISSES))(k1) #1b + lui k1, %hi(CPUVAR(EV_USER_TLBMISSES)) #1a: k1=hi of tlbmisses + REG_L k0, %lo(CPUVAR(EV_USER_TLBMISSES))(k1) #1b REG_ADDU k0, 1 #1c - REG_S k0, %lo(CPUVAR(EV_TLBMISSES))(k1) #1d + REG_S k0, %lo(CPUVAR(EV_USER_TLBMISSES))(k1) #1d #endif eret #1e: return from exception .set at @@ -566,18 +566,28 @@ MIPSX(kernelfault): nop MIPSX(nopagetable): #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 - _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 #14: get tlbinfo lock addr - INT_S zero, 0(k1) #15: clear lock + _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 #14: get tlbinfo hwlock addr + INT_S zero, 0(k1) #15: clear lock #endif lui k1, %hi(CPUVAR(CURLWP)) #16: k1=hi of curlwp j MIPSX(slowfault) #17: no page table present PTR_L k1, %lo(CPUVAR(CURLWP))(k1) #18: k1=lo of curlwp nop #19: branch delay slot #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 +/* + * If the TLB was locked, then it must have been locked by another thread + * context. If so, that thread is updating the TLB and may be updated the + * address we are concerned with. So the best thing we can do is just return + * from the exception and hope the other thread has fixed the reason for this + * exception. If not, another exception will be raised and hopefully then + * we'll get the TLB hwlock. + */ MIPSX(tlblocked): - _MFC0 k1, MIPS_COP_0_OSSCRATCH, 0 #1a: k1=hi of curlwp - j MIPSX(slowfault) #1b: no page table present - PTR_L k1, CPU_INFO_CURLWP(k1) #1c: k1=lo of curlwp + lui k1, %hi(CPUVAR(EV_TLBLOCKED)) #1a: k1=hi of tlbmisses + REG_L k0, %lo(CPUVAR(EV_TLBLOCKED))(k1) #1b + REG_ADDU k0, 1 #1c + REG_S k0, %lo(CPUVAR(EV_TLBLOCKED))(k1) #1d + eret #1e #endif .set at _VECTOR_END(MIPSX(exception)) @@ -1650,8 +1660,14 @@ LEAF_NOPROFILE(MIPSX(kern_tlb_miss)) nop nop #endif +#if (MIPS3 + MIPS64 + MIPS64R2 + MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + lui k1, %hi(CPUVAR(EV_KERN_TLBMISSES)) + REG_L k0, %lo(CPUVAR(EV_KERN_TLBMISSES))(k1) + REG_ADDU k0, 1 + REG_S k0, %lo(CPUVAR(EV_KERN_TLBMISSES))(k1) +#endif #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 - _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 # get tlbinfo lock addr + _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 # get tlbinfo hwlock addr INT_S zero, 0(k1) # clear lock #endif eret @@ -1660,7 +1676,7 @@ END(MIPSX(kern_tlb_miss)) /*---------------------------------------------------------------------------- * - * mipsN_tlb_invalid_exception -- + * mipsN_kern_tlb_invalid_exception -- * * Handle a TLB invalid exception from kernel mode in kernel space. * The BaddVAddr, Context, and EntryHi registers contain the failed @@ -1682,15 +1698,15 @@ END(MIPSX(kern_tlb_miss)) * *---------------------------------------------------------------------------- */ -LEAF_NOPROFILE(MIPSX(tlb_invalid_exception)) +LEAF_NOPROFILE(MIPSX(kern_tlb_invalid_exception)) .set noat #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 #define TLB_INVALID_EXCEPTION_EXIT _C_LABEL(MIPSX(tlbunlock_kern_gen_exception)) _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 # get tlblock addr li k0, __SIMPLELOCK_LOCKED -1: swapw k0, k1 # set it to locked - bnez k0, 1b # was it locked? - nop # if it was, try again + swapw k0, k1 # set it to locked + bnez k0, 99f # was it locked? + nop # if it was, do an eret #else #define TLB_INVALID_EXCEPTION_EXIT _C_LABEL(MIPSX(kern_gen_exception)) #endif @@ -1774,6 +1790,7 @@ LEAF_NOPROFILE(MIPSX(tlb_invalid_excepti #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 # get tlblock addr INT_S zero, 0(k1) # clear lock +99: #endif eret @@ -1826,12 +1843,12 @@ MIPSX(kern_tlbi_odd): * we locked. */ MIPSX(tlbunlock_kern_gen_exception): - _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 # get tlblock addr + _MFC0 k1, MIPS_COP_0_OSSCRATCH, 2 # get tlb hwlock addr b _C_LABEL(MIPSX(kern_gen_exception)) INT_S zero, 0(k1) # clear lock #endif -END(MIPSX(tlb_invalid_exception)) +END(MIPSX(kern_tlb_invalid_exception)) /* * Mark where code entered from exception hander jumptable @@ -1882,6 +1899,13 @@ LEAF(MIPSX(tlb_update_addr)) mfc0 v1, MIPS_COP_0_STATUS # Save the status register. mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif #if (PGSHIFT & 1) == 0 and t1, a0, MIPS3_PG_ODDPG # t1 = Even/Odd flag #endif @@ -1946,6 +1970,9 @@ LEAF(MIPSX(tlb_update_addr)) #endif _MTC0 t0, MIPS_COP_0_TLB_HI # restore PID COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) +#endif mtc0 v1, MIPS_COP_0_STATUS # Restore the status register JR_HB_RA END(MIPSX(tlb_update_addr)) @@ -1970,6 +1997,13 @@ LEAF(MIPSX(tlb_read_indexed)) mfc0 v1, MIPS_COP_0_STATUS # Save the status register. mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif mfc0 ta2, MIPS_COP_0_TLB_PG_MASK # save current pgMask #ifdef MIPS3 nop @@ -1987,6 +2021,9 @@ LEAF(MIPSX(tlb_read_indexed)) _MTC0 t0, MIPS_COP_0_TLB_HI # restore PID mtc0 ta2, MIPS_COP_0_TLB_PG_MASK # restore pgMask COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif mtc0 v1, MIPS_COP_0_STATUS # Restore the status register COP0_SYNC PTR_S t3, TLBMASK_HI(a1) @@ -2007,6 +2044,13 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_addr mfc0 v1, MIPS_COP_0_STATUS # save status register mtc0 zero, MIPS_COP_0_STATUS # disable interrupts COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif li v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID) _MFC0 t0, MIPS_COP_0_TLB_HI # save current ASID @@ -2035,6 +2079,9 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_addr _MTC0 t0, MIPS_COP_0_TLB_HI # restore current ASID mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif mtc0 v1, MIPS_COP_0_STATUS # restore status register JR_HB_RA END(MIPSX(tlb_invalidate_addr)) @@ -2050,6 +2097,13 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_asid mfc0 v1, MIPS_COP_0_STATUS # save status register mtc0 zero, MIPS_COP_0_STATUS # disable interrupts COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif _MFC0 t0, MIPS_COP_0_TLB_HI # Save the current PID. mfc0 t1, MIPS_COP_0_TLB_WIRED @@ -2093,6 +2147,9 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_asid _MTC0 t0, MIPS_COP_0_TLB_HI # restore PID. mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif mtc0 v1, MIPS_COP_0_STATUS # restore status register JR_HB_RA # new ASID will be set soon END(MIPSX(tlb_invalidate_asids)) @@ -2107,6 +2164,13 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_glob mfc0 v1, MIPS_COP_0_STATUS # save status register mtc0 zero, MIPS_COP_0_STATUS # disable interrupts COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif _MFC0 t0, MIPS_COP_0_TLB_HI # save current ASID mfc0 t1, MIPS_COP_0_TLB_WIRED @@ -2142,6 +2206,9 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_glob _MTC0 t0, MIPS_COP_0_TLB_HI # restore current ASID mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif mtc0 v1, MIPS_COP_0_STATUS # restore status register JR_HB_RA END(MIPSX(tlb_invalidate_globals)) @@ -2155,6 +2222,13 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_all) mfc0 v1, MIPS_COP_0_STATUS # save status register mtc0 zero, MIPS_COP_0_STATUS # disable interrupts COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif INT_L a0, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES @@ -2184,6 +2258,9 @@ LEAF_NOPROFILE(MIPSX(tlb_invalidate_all) _MTC0 t0, MIPS_COP_0_TLB_HI # restore ASID mtc0 t2, MIPS_COP_0_TLB_PG_MASK # restore pgMask COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif mtc0 v1, MIPS_COP_0_STATUS # restore status register JR_HB_RA END(MIPSX(tlb_invalidate_all)) @@ -2200,8 +2277,7 @@ LEAF_NOPROFILE(MIPSX(tlb_record_asids)) mfc0 ta0, MIPS_COP_0_TLB_WIRED INT_L ta1, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES move ta2, zero - li ta3, 1 - move v0, zero + li t3, 1 mfc0 v1, MIPS_COP_0_STATUS # save status register #ifdef _LP64 @@ -2212,6 +2288,15 @@ LEAF_NOPROFILE(MIPSX(tlb_record_asids)) mtc0 zero, MIPS_COP_0_STATUS # disable interrupts #endif COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#else + move v0, zero +#endif # do {} while (ta0 < ta1) 1: @@ -2228,7 +2313,7 @@ LEAF_NOPROFILE(MIPSX(tlb_record_asids)) srl a2, t0, 3 + LONG_SCALESHIFT # drop low 5 or 6 bits sll a2, LONG_SCALESHIFT # make an index for the bitmap - _SLLV t0, ta3, t0 # t0 is mask (ta3 == 1) + _SLLV t0, t3, t0 # t0 is mask (t3 == 1) PTR_ADDU a2, a0 # index into the bitmap beq a2, ta2, 3f # is the desired cell loaded? @@ -2242,7 +2327,7 @@ LEAF_NOPROFILE(MIPSX(tlb_record_asids)) LONG_L t2, 0(ta2) # and load it 3: and t1, t2, t0 # t1 = t2 & t0 - sltu t1, t1, ta3 # t1 = t1 < 1 (aka t1 == 0) + sltu t1, t1, t3 # t1 = t1 < 1 (aka t1 == 0) addu v0, t1 # v0 += t1 or t2, t0 # or in the new ASID bits 4: @@ -2258,6 +2343,9 @@ LEAF_NOPROFILE(MIPSX(tlb_record_asids)) _MTC0 a3, MIPS_COP_0_TLB_HI # restore ASID COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif mtc0 v1, MIPS_COP_0_STATUS # restore status register JR_HB_RA END(MIPSX(tlb_record_asids)) @@ -2267,6 +2355,15 @@ END(MIPSX(tlb_record_asids)) */ LEAF(MIPSX(tlb_enter)) .set noat + mfc0 v1, MIPS_COP_0_STATUS # save status + mtc0 zero, MIPS_COP_0_STATUS # disable interupts +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif _MFC0 ta0, MIPS_COP_0_TLB_HI # save EntryHi #if (PGSHIFT & 1) == 0 @@ -2306,8 +2403,8 @@ LEAF(MIPSX(tlb_enter)) * Clear the existing TLB entry for it. */ sll t1, v0, (1 | PGSHIFT) # make a fake addr for the entry - lui v1, %hi(MIPS_KSEG0_START) - or t1, v1 + lui t3, %hi(MIPS_KSEG0_START) + or t1, t3 _MTC0 t1, MIPS_COP_0_TLB_HI COP0_SYNC @@ -2327,17 +2424,17 @@ LEAF(MIPSX(tlb_enter)) 2: #if (PGSHIFT & 1) == 0 - and v1, a1, MIPS3_PG_ODDPG # odd or even page - sll v1, 31 - PGSHIFT # move to MSB - sra v1, 31 # v1 a mask (0/~0 = even/odd) - not v0, v1 # v0 a mask (~0/0 = even/odd) - - and ta2, t2, v1 - and ta3, a2, v0 - or t2, ta2, ta3 # t2 = (v1 & t2) | (~v1 & a2) - and ta2, t3, v0 - and ta3, a2, v1 - or t3, ta2, ta3 # t3 = (~v1 & t3) | (v1 & a2) + and t3, a1, MIPS3_PG_ODDPG # odd or even page + sll t3, 31 - PGSHIFT # move to MSB + sra t3, 31 # t3 a mask (0/~0 = even/odd) + not v0, t3 # v0 a mask (~0/0 = even/odd) + + and ta1, t2, t3 + and ta2, a2, v0 + or t2, ta1, ta2 # t2 = (t3 & t2) | (~t3 & a2) + and ta1, t3, v0 + and ta2, a2, t3 + or t3, ta1, ta2 # t3 = (~t3 & t3) | (t3 & a2) mtc0 t2, MIPS_COP_0_TLB_LO0 # set tlb_lo0 (even) mtc0 t3, MIPS_COP_0_TLB_LO1 # set tlb_lo1 (odd) @@ -2351,11 +2448,75 @@ LEAF(MIPSX(tlb_enter)) tlbwi # enter it into the TLB COP0_SYNC - _MTC0 ta1, MIPS_COP_0_TLB_HI # restore EntryHi + _MTC0 ta0, MIPS_COP_0_TLB_HI # restore EntryHi + COP0_SYNC + +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif + mtc0 v1, MIPS_COP_0_STATUS # restore status register JR_HB_RA .set at END(MIPSX(tlb_enter)) +/*-------------------------------------------------------------------------- + * + * mipsN_tlb_write_indexed -- + * + * Write the given entry into the TLB at the given index. + * Pass full R4000 style TLB info including variable page size mask. + * + * mipsN_tlb_write_indexed(size_t tlb_index, const struct tlbmask *tlb) + * + * Results: + * None. + * + * Side effects: + * TLB entry set. + * + *-------------------------------------------------------------------------- + */ +LEAF(MIPSX(tlb_write_indexed)) + /* + * Fetch the arguments first so we don't need to worry about KX/UX/PX + */ + INT_L t0, TLBMASK_LO0(a1) # fetch tlb->tlb_lo0 + INT_L t1, TLBMASK_LO1(a1) # fetch tlb->tlb_lo1 + INT_L t2, TLBMASK_MASK(a1) # fetch tlb->tlb_mask + PTR_L t3, TLBMASK_HI(a1) # fetch tlb->tlb_hi + mfc0 v1, MIPS_COP_0_STATUS # save status + mtc0 zero, MIPS_COP_0_STATUS # disable interrupts + COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 +1: li v0, __SIMPLELOCK_LOCKED + swapw v0, ta3 + bnez v0, 1b + nop +#endif + mfc0 ta1, MIPS_COP_0_TLB_PG_MASK # Save current page mask. + _MFC0 ta0, MIPS_COP_0_TLB_HI # Save the current PID. + + _MTC0 t0, MIPS_COP_0_TLB_LO0 # Set up entry lo0. + _MTC0 t1, MIPS_COP_0_TLB_LO1 # Set up entry lo1. + COP0_SYNC + mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. + mtc0 t2, MIPS_COP_0_TLB_PG_MASK # Set up entry pagemask. + _MTC0 t3, MIPS_COP_0_TLB_HI # Set up entry high. + COP0_SYNC + tlbwi # Write the TLB + COP0_SYNC + + _MTC0 ta0, MIPS_COP_0_TLB_HI # Restore the PID. + mtc0 ta1, MIPS_COP_0_TLB_PG_MASK # Restore page mask. + COP0_SYNC +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + INT_S zero, 0(ta3) # unlock the tlb +#endif + mtc0 v1, MIPS_COP_0_STATUS # Restore the status register + JR_HB_RA +END(MIPSX(tlb_write_indexed)) + /* * mipsN_lwp_trampoline() * @@ -2470,52 +2631,62 @@ LEAF_NOPROFILE(MIPSX(cpu_switch_resume)) #else INT_ADDU a2, a1, MIPS3_PG_NEXT # a2 = page following upte[0] #endif - PTR_L v0, L_PCB(a0) # va = l->l_addr + PTR_L a3, L_PCB(a0) # va = l->l_addr #if VM_MIN_KERNEL_ADDRESS == MIPS_KSEG2_START li t0, VM_MIN_KERNEL_ADDRESS # compute index - blt v0, t0, MIPSX(resume) + blt a3, t0, MIPSX(resume) nop #if defined(ENABLE_MIPS_KSEGX) li t0, VM_KSEGX_ADDRESS # below KSEGX? - blt v0, t0, 1f + blt a3, t0, 1f nop li t0, VM_KSEGX_ADDRESS+VM_KSEGX_SIZE # within KSEGX? - blt v0, t0, MIPSX(resume) + blt a3, t0, MIPSX(resume) nop 1: #endif #else li t0, MIPS_KSEG0_START # above XKSEG? - blt t0, v0, MIPSX(resume) + blt t0, a3, MIPSX(resume) nop li t0, VM_MIN_KERNEL_ADDRESS>>32 # below XKSEG? dsll32 t0, t0, 0 - blt v0, t0, MIPSX(resume) + blt a3, t0, MIPSX(resume) nop #endif -#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 +#ifdef MULTIPROCESSOR /* - * Grab the TLB lock (we could use LL/SC but this is shorter) + * Fetch TLB slot before zeroing status. */ - _MFC0 a3, MIPS_COP_0_OSSCRATCH, 2 - li v1, __SIMPLELOCK_LOCKED -1: swapw v1, a3 - bnez v1, 1b - nop + PTR_L t0, L_CPU(a0) # get cpu_info + INT_L t1, CPU_INFO_KSP_TLB_SLOT(t0) # get TLB# for KSP #endif #if (PGSHIFT & 1) == 0 - and t0, v0, MIPS3_PG_ODDPG - beqz t0, MIPSX(entry0) + and v0, a3, MIPS3_PG_ODDPG + beqz v0, MIPSX(entry0) nop PANIC("USPACE sat on odd page boundary") #endif MIPSX(entry0): - _MFC0 t3, MIPS_COP_0_TLB_HI # save TLB_HI - _MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va +#if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 + mfc0 v1, MIPS_COP_0_STATUS # save status + mtc0 zero, MIPS_COP_0_STATUS # disable interrupts + /* + * Grab the TLB lock (we could use LL/SC but this is shorter) + */ + _MFC0 ta3, MIPS_COP_0_OSSCRATCH, 2 + li v0, __SIMPLELOCK_LOCKED +1: swapw v0, ta3 + bnez v0, 1b + nop +#endif + + _MFC0 ta0, MIPS_COP_0_TLB_HI # save TLB_HI + _MTC0 a3, MIPS_COP_0_TLB_HI # VPN = va COP0_SYNC tlbp # probe VPN COP0_SYNC @@ -2524,7 +2695,7 @@ MIPSX(entry0): nop #endif bltz t0, MIPSX(entry0set) - sll t0, t0, (PGSHIFT | 1) # (PAGE_SHIFT | 1) + sll t0, (PGSHIFT | 1) # (PAGE_SHIFT | 1) PTR_LA t0, MIPS_KSEG0_START(t0) _MTC0 t0, MIPS_COP_0_TLB_HI _MTC0 zero, MIPS_COP_0_TLB_LO0 @@ -2532,12 +2703,10 @@ MIPSX(entry0): COP0_SYNC tlbwi COP0_SYNC - _MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again + _MTC0 a3, MIPS_COP_0_TLB_HI # set VPN again COP0_SYNC MIPSX(entry0set): #ifdef MULTIPROCESSOR - PTR_L t0, L_CPU(a0) # get cpu_info - INT_L t1, CPU_INFO_KSP_TLB_SLOT(t0) # get TLB# for KSP mtc0 t1, MIPS_COP_0_TLB_INDEX # TLB entry (virtual) #else mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0 (virtual) @@ -2550,10 +2719,11 @@ MIPSX(entry0set): COP0_SYNC tlbwi # set TLB entry #0 COP0_SYNC - _MTC0 t3, MIPS_COP_0_TLB_HI # restore TLB_HI + _MTC0 ta0, MIPS_COP_0_TLB_HI # restore TLB_HI COP0_SYNC #if defined(MULTIPROCESSOR) && (MIPS64_RMIXL + MIPS64R2_RMIXL) > 0 - INT_S zero, 0(a3) # clear tlb lock + mtc0 v1, MIPS_COP_0_STATUS # restore Status register + INT_S zero, 0(ta3) # clear tlb lock #endif MIPSX(resume): #endif /* PAGE_SIZE < USPACE */ @@ -2565,51 +2735,6 @@ MIPSX(resume): nop END(MIPSX(cpu_switch_resume)) -/*-------------------------------------------------------------------------- - * - * mipsN_tlb_write_indexed -- - * - * Write the given entry into the TLB at the given index. - * Pass full R4000 style TLB info including variable page size mask. - * - * mipsN_tlb_write_indexed(size_t tlb_index, const struct tlbmask *tlb) - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(MIPSX(tlb_write_indexed)) - mfc0 v1, MIPS_COP_0_STATUS # Save the status register. - RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0) - COP0_SYNC - INT_L a2, TLBMASK_LO0(a1) # fetch tlb->tlb_lo0 - INT_L a3, TLBMASK_LO1(a1) # fetch tlb->tlb_lo1 - mfc0 v0, MIPS_COP_0_TLB_PG_MASK # Save current page mask. - _MFC0 t0, MIPS_COP_0_TLB_HI # Save the current PID. - - _MTC0 a2, MIPS_COP_0_TLB_LO0 # Set up entry low0. - _MTC0 a3, MIPS_COP_0_TLB_LO1 # Set up entry low1. - COP0_SYNC - INT_L a2, TLBMASK_MASK(a1) # fetch tlb->tlb_mask - PTR_L a3, TLBMASK_HI(a1) # fetch tlb->tlb_hi - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. - mtc0 a2, MIPS_COP_0_TLB_PG_MASK # Set up entry pagemask. - _MTC0 a3, MIPS_COP_0_TLB_HI # Set up entry high. - COP0_SYNC - tlbwi # Write the TLB - COP0_SYNC - - _MTC0 t0, MIPS_COP_0_TLB_HI # Restore the PID. - mtc0 v0, MIPS_COP_0_TLB_PG_MASK # Restore page mask. - COP0_SYNC - mtc0 v1, MIPS_COP_0_STATUS # Restore the status register - JR_HB_RA -END(MIPSX(tlb_write_indexed)) - #if defined(MIPS3) /*---------------------------------------------------------------------------- * @@ -2759,8 +2884,8 @@ MIPSX(excpt_sw): #### PTR_WORD _C_LABEL(MIPSX(kern_intr)) # 0 external interrupt PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 1 TLB modification - PTR_WORD _C_LABEL(MIPSX(tlb_invalid_exception)) # 2 TLB miss (LW/I-fetch) - PTR_WORD _C_LABEL(MIPSX(tlb_invalid_exception)) # 3 TLB miss (SW) + PTR_WORD _C_LABEL(MIPSX(kern_tlb_invalid_exception)) # 2 TLB miss (LW/I-fetch) + PTR_WORD _C_LABEL(MIPSX(kern_tlb_invalid_exception)) # 3 TLB miss (SW) PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 4 address error (LW/I-fetch) PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 5 address error (SW) PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 6 bus error (I-fetch) Index: src/sys/arch/mips/mips/pmap_tlb.c diff -u src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.18 src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.19 --- src/sys/arch/mips/mips/pmap_tlb.c:1.1.2.18 Fri May 13 17:36:39 2011 +++ src/sys/arch/mips/mips/pmap_tlb.c Sat Dec 3 01:56:55 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap_tlb.c,v 1.1.2.18 2011/05/13 17:36:39 matt Exp $ */ +/* $NetBSD: pmap_tlb.c,v 1.1.2.19 2011/12/03 01:56:55 matt Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap_tlb.c,v 1.1.2.18 2011/05/13 17:36:39 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap_tlb.c,v 1.1.2.19 2011/12/03 01:56:55 matt Exp $"); /* * Manages address spaces in a TLB. @@ -143,7 +143,10 @@ __KERNEL_RCSID(0, "$NetBSD: pmap_tlb.c,v #include <mips/locore.h> #include <mips/pte.h> -static kmutex_t pmap_tlb0_mutex __aligned(32); +static kmutex_t pmap_tlb0_mutex __cacheline_aligned; +#ifdef MULTIPROCESSOR +static kmutex_t pmap_tlb0_hwmutex __cacheline_aligned; +#endif struct pmap_tlb_info pmap_tlb0_info = { .ti_name = "tlb0", @@ -156,6 +159,7 @@ struct pmap_tlb_info pmap_tlb0_info = { .ti_lock = &pmap_tlb0_mutex, .ti_pais = LIST_HEAD_INITIALIZER(pmap_tlb_info.ti_pais), #ifdef MULTIPROCESSOR + .ti_hwlock = &pmap_tlb0_hwmutex, .ti_cpu_mask = 1, .ti_tlbinvop = TLBINV_NOBODY, #endif @@ -252,6 +256,9 @@ pmap_tlb_info_init(struct pmap_tlb_info #endif /* MULTIPROCESSOR */ KASSERT(ti == &pmap_tlb0_info); mutex_init(ti->ti_lock, MUTEX_DEFAULT, IPL_SCHED); +#ifdef MULTIPROCESSOR + mutex_init(ti->ti_hwlock, MUTEX_DEFAULT, IPL_SCHED); +#endif if (!CPUISMIPSNN || !__builtin_constant_p(MIPS_TLB_NUM_PIDS)) { ti->ti_asid_max = mips_options.mips_num_tlb_entries - 1; ti->ti_asids_free = ti->ti_asid_max; @@ -281,6 +288,7 @@ pmap_tlb_info_init(struct pmap_tlb_info KASSERT(pmap_tlbs[pmap_ntlbs] == NULL); ti->ti_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SCHED); + ti->ti_hwlock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SCHED); ti->ti_asid_bitmap[0] = 1; ti->ti_asid_hint = 1; ti->ti_asid_max = pmap_tlb0_info.ti_asid_max; Index: src/sys/arch/mips/rmi/rmixl_subr.S diff -u src/sys/arch/mips/rmi/rmixl_subr.S:1.1.2.9 src/sys/arch/mips/rmi/rmixl_subr.S:1.1.2.10 --- src/sys/arch/mips/rmi/rmixl_subr.S:1.1.2.9 Thu May 26 19:21:57 2011 +++ src/sys/arch/mips/rmi/rmixl_subr.S Sat Dec 3 01:56:56 2011 @@ -171,7 +171,7 @@ NESTED(rmixl_cpu_trampoline, CALLFRAME_S REG_L a1, 2*SZREG(s0) /* XXX ta_cpuinfo */ dmtc0 a1, $22, 0 /* MIPS_COP_0_OSSCRATCH */ PTR_L v1, CPU_INFO_TLB_INFO(a1) - PTR_L v1, TI_LOCK(v1) + PTR_L v1, TI_HWLOCK(v1) PTR_ADDU v1, MTX_LOCK dmtc0 v1, $22, 2 j cpu_trampoline