diff options
author | sm142603 <none@none> | 2008-02-29 22:27:40 -0800 |
---|---|---|
committer | sm142603 <none@none> | 2008-02-29 22:27:40 -0800 |
commit | 1426d65aa9264a283c76d271972aeb7f6a070be3 (patch) | |
tree | 2c6841fcdfc96a814f7482ad298951ceaf40d99b | |
parent | 0358d3a672326bc66debe0a1c3a2372cd9f0f662 (diff) | |
download | illumos-joyent-1426d65aa9264a283c76d271972aeb7f6a070be3.tar.gz |
6642758 Support Shared Context for SPARC64-VII
-rw-r--r-- | usr/src/uts/sfmmu/ml/sfmmu_asm.s | 352 | ||||
-rw-r--r-- | usr/src/uts/sfmmu/vm/hat_sfmmu.c | 18 | ||||
-rw-r--r-- | usr/src/uts/sfmmu/vm/hat_sfmmu.h | 187 | ||||
-rw-r--r-- | usr/src/uts/sun4/ml/swtch.s | 8 | ||||
-rw-r--r-- | usr/src/uts/sun4u/cpu/opl_olympus.c | 34 | ||||
-rw-r--r-- | usr/src/uts/sun4u/cpu/us3_common_mmu.c | 8 | ||||
-rw-r--r-- | usr/src/uts/sun4u/ml/mach_offsets.in | 93 | ||||
-rw-r--r-- | usr/src/uts/sun4u/ml/trap_table.s | 88 | ||||
-rw-r--r-- | usr/src/uts/sun4u/os/mach_cpu_states.c | 4 | ||||
-rw-r--r-- | usr/src/uts/sun4u/sys/machparam.h | 3 | ||||
-rw-r--r-- | usr/src/uts/sun4u/sys/mmu.h | 13 | ||||
-rw-r--r-- | usr/src/uts/sun4u/sys/opl_olympus_regs.h | 9 | ||||
-rw-r--r-- | usr/src/uts/sun4u/vm/mach_sfmmu.h | 423 | ||||
-rw-r--r-- | usr/src/uts/sun4u/vm/mach_sfmmu_asm.s | 317 | ||||
-rw-r--r-- | usr/src/uts/sun4v/vm/mach_sfmmu.h | 198 |
15 files changed, 972 insertions, 783 deletions
diff --git a/usr/src/uts/sfmmu/ml/sfmmu_asm.s b/usr/src/uts/sfmmu/ml/sfmmu_asm.s index 9922254c2a..8c370d099f 100644 --- a/usr/src/uts/sfmmu/ml/sfmmu_asm.s +++ b/usr/src/uts/sfmmu/ml/sfmmu_asm.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -831,11 +831,12 @@ sfmmu_panic10: ldub [%o0 + SFMMU_CEXT], %o2 sll %o2, CTXREG_EXT_SHIFT, %o2 or %o1, %o2, %o1 -#endif - SET_SECCTX(%o1, %g1, %o4, %o5) - - retl - mov %g4, %o0 ! %o0 = ret +#endif /* sun4u */ + + SET_SECCTX(%o1, %g1, %o4, %o5, alloc_ctx_lbl1) + + retl + mov %g4, %o0 ! %o0 = ret SET_SIZE(sfmmu_alloc_ctx) @@ -1196,7 +1197,7 @@ sfmmu_kpm_unload_tsb(caddr_t addr, int vpshift) sethi %hi(tsb_kernel_patch_asi), %o0 call sfmmu_fixup_or or %o0, %lo(tsb_kernel_patch_asi), %o0 -#endif +#endif /* !sun4v */ ldx [%o5], %o4 ! load ktsb base addr (VA or PA) @@ -1466,7 +1467,7 @@ sfmmu_kpm_unload_tsb(caddr_t addr, int vpshift) ld [%o4 + %lo(ktsb_phys)], %o4 movrnz %o4, ASI_MEM, %o3 mov %o3, %asi -#endif +#endif /* !sun4v */ mov %o0, %g1 ! %g1 = vaddr /* GET_KPM_TSBE_POINTER(vpshift, tsbp, vaddr (clobbers), tmp1, tmp2) */ @@ -1498,7 +1499,7 @@ sfmmu_kpm_unload_tsb(caddr_t addr, int vpshift) ld [%o4 + %lo(ktsb_phys)], %o4 movrnz %o4, ASI_MEM, %o3 mov %o3, %asi -#endif +#endif /* !sun4v */ mov %o0, %g1 ! %g1 = vaddr /* GET_KPM_TSBE_POINTER(vpshift, tsbp, vaddr (clobbers), tmp1, tmp2) */ @@ -2701,7 +2702,7 @@ sfmmu_kprot_patch_ktsb4m_szcode: * g4 - g7 = scratch registers */ ALTENTRY(sfmmu_uprot_trap) -#ifdef sun4v +#ifdef sun4v GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5) /* %g1 = first TSB entry ptr now, %g2 preserved */ @@ -2715,7 +2716,7 @@ sfmmu_kprot_patch_ktsb4m_szcode: #else /* sun4v */ #ifdef UTSB_PHYS /* g1 = first TSB entry ptr */ - GET_2ND_TSBREG(%g3) + GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3) brlz,pt %g3, 9f /* check for 2nd TSB */ nop @@ -2938,7 +2939,7 @@ dktsb4m_kpmcheck: */ .align 64 ALTENTRY(sfmmu_uitlb_fastpath) - + PROBE_1ST_ITSB(%g1, %g7, uitlb_fast_8k_probefail) /* g4 - g5 = clobbered by PROBE_1ST_ITSB */ ba,pn %xcc, sfmmu_tsb_miss_tt @@ -2998,7 +2999,15 @@ dktsb4m_kpmcheck: * User instruction miss w/ multiple TSBs (sun4u). * The first probe covers 8K, 64K, and 512K page sizes, * because 64K and 512K mappings are replicated off 8K - * pointer. Second probe covers 4M page size only. + * pointer. Probe of 1st TSB has already been done prior to entry + * into this routine. For the UTSB_PHYS case we probe up to 3 + * valid other TSBs in the following order: + * 1) shared TSB for 4M-256M pages + * 2) private TSB for 4M-256M pages + * 3) shared TSB for 8K-512K pages + * + * For the non UTSB_PHYS case we probe the 2nd TSB here that backs + * 4M-256M pages. * * Just like sfmmu_udtlb_slowpath, except: * o Uses ASI_ITLB_IN @@ -3007,7 +3016,6 @@ dktsb4m_kpmcheck: * * g1 = tsb8k pointer register * g2 = tag access register - * g3 = 2nd tsbreg if defined UTSB_PHYS, else scratch * g4 - g6 = scratch registers * g7 = TSB tag to match */ @@ -3015,51 +3023,157 @@ dktsb4m_kpmcheck: ALTENTRY(sfmmu_uitlb_slowpath) #ifdef UTSB_PHYS - /* - * g1 = 1st TSB entry pointer - * g3 = 2nd TSB base register - * Need 2nd TSB entry pointer for 2nd probe. - */ - PROBE_1ST_ITSB(%g1, %g7, uitlb_8k_probefail) - GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5) + GET_UTSBREG(SCRATCHPAD_UTSBREG4, %g6) + brlz,pt %g6, 1f + nop + GET_4TH_TSBE_PTR(%g2, %g6, %g4, %g5) + PROBE_4TH_ITSB(%g6, %g7, uitlb_4m_scd_probefail) +1: + GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3) + brlz,pt %g3, 2f + nop + GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5) + PROBE_2ND_ITSB(%g3, %g7, uitlb_4m_probefail) +2: + GET_UTSBREG(SCRATCHPAD_UTSBREG3, %g6) + brlz,pt %g6, sfmmu_tsb_miss_tt + nop + GET_3RD_TSBE_PTR(%g2, %g6, %g4, %g5) + PROBE_3RD_ITSB(%g6, %g7, uitlb_8K_scd_probefail) + ba,pn %xcc, sfmmu_tsb_miss_tt + nop + #else /* UTSB_PHYS */ mov %g1, %g3 /* save tsb8k reg in %g3 */ GET_1ST_TSBE_PTR(%g3, %g1, %g5, sfmmu_uitlb) PROBE_1ST_ITSB(%g1, %g7, uitlb_8k_probefail) - mov %g2, %g6 /* GET_2ND_TSBE_PTR clobbers tagacc */ mov %g3, %g7 /* copy tsb8k reg in %g7 */ GET_2ND_TSBE_PTR(%g6, %g7, %g3, %g4, %g5, sfmmu_uitlb) + /* g1 = first TSB pointer, g3 = second TSB pointer */ + srlx %g2, TAG_VALO_SHIFT, %g7 + PROBE_2ND_ITSB(%g3, %g7, isynth) + ba,pn %xcc, sfmmu_tsb_miss_tt + nop + #endif /* UTSB_PHYS */ - /* g1 = first TSB pointer, g3 = second TSB pointer */ - srlx %g2, TAG_VALO_SHIFT, %g7 - PROBE_2ND_ITSB(%g3, %g7, isynth) - /* NOT REACHED */ #endif /* sun4v */ +#if defined(sun4u) && defined(UTSB_PHYS) + + /* + * We come here for ism predict DTLB_MISS case or if + * if probe in first TSB failed. + */ + + .align 64 + ALTENTRY(sfmmu_udtlb_slowpath_noismpred) + /* - * User data miss w/ multiple TSBs. - * The first probe covers 8K, 64K, and 512K page sizes, - * because 64K and 512K mappings are replicated off 8K - * pointer. Second probe covers 4M page size only. - * - * We consider probing for 4M pages first if the VA falls - * in a range that's likely to be ISM. - * - * g1 = tsb8k pointer register - * g2 = tag access register - * g3 = 2nd tsbreg if defined UTSB_PHYS, else scratch - * g4 - g6 = scratch registers - * g7 = TSB tag to match + * g1 = tsb8k pointer register + * g2 = tag access register + * g4 - %g6 = scratch registers + * g7 = TSB tag to match */ + + /* + * ISM non-predict probe order + * probe 1ST_TSB (8K index) + * probe 2ND_TSB (4M index) + * probe 4TH_TSB (4M index) + * probe 3RD_TSB (8K index) + * + * We already probed first TSB in DTLB_MISS handler. + */ + + /* + * Private 2ND TSB 4M-256 pages + */ + GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3) + brlz,pt %g3, 1f + nop + GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5) + PROBE_2ND_DTSB(%g3, %g7, udtlb_4m_probefail) + + /* + * Shared Context 4TH TSB 4M-256 pages + */ +1: + GET_UTSBREG(SCRATCHPAD_UTSBREG4, %g6) + brlz,pt %g6, 2f + nop + GET_4TH_TSBE_PTR(%g2, %g6, %g4, %g5) + PROBE_4TH_DTSB(%g6, %g7, udtlb_4m_shctx_probefail) + + /* + * Shared Context 3RD TSB 8K-512K pages + */ +2: + GET_UTSBREG(SCRATCHPAD_UTSBREG3, %g6) + brlz,pt %g6, sfmmu_tsb_miss_tt + nop + GET_3RD_TSBE_PTR(%g2, %g6, %g4, %g5) + PROBE_3RD_DTSB(%g6, %g7, udtlb_8k_shctx_probefail) + ba,pn %xcc, sfmmu_tsb_miss_tt + nop + .align 64 - ALTENTRY(sfmmu_udtlb_slowpath) + ALTENTRY(sfmmu_udtlb_slowpath_ismpred) + + /* + * g1 = tsb8k pointer register + * g2 = tag access register + * g4 - g6 = scratch registers + * g7 = TSB tag to match + */ + + /* + * ISM predict probe order + * probe 4TH_TSB (4M index) + * probe 2ND_TSB (4M index) + * probe 1ST_TSB (8K index) + * probe 3RD_TSB (8K index) /* - * Check for ISM. If it exists, look for 4M mappings in the second TSB - * first, then probe for other mappings in the first TSB if that fails. + * Shared Context 4TH TSB 4M-256 pages */ + GET_UTSBREG(SCRATCHPAD_UTSBREG4, %g6) + brlz,pt %g6, 4f + nop + GET_4TH_TSBE_PTR(%g2, %g6, %g4, %g5) + PROBE_4TH_DTSB(%g6, %g7, udtlb_4m_shctx_probefail2) + + /* + * Private 2ND TSB 4M-256 pages + */ +4: + GET_UTSBREG(SCRATCHPAD_UTSBREG2, %g3) + brlz,pt %g3, 5f + nop + GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5) + PROBE_2ND_DTSB(%g3, %g7, udtlb_4m_probefail2) + +5: + PROBE_1ST_DTSB(%g1, %g7, udtlb_8k_first_probefail2) + + /* + * Shared Context 3RD TSB 8K-512K pages + */ + GET_UTSBREG(SCRATCHPAD_UTSBREG3, %g6) + brlz,pt %g6, 6f + nop + GET_3RD_TSBE_PTR(%g2, %g6, %g4, %g5) + PROBE_3RD_DTSB(%g6, %g7, udtlb_8k_shctx_probefail2) +6: + ba,pn %xcc, sfmmu_tsb_miss_tt /* ISM Predict and ISM non-predict path */ + nop + +#else /* sun4u && UTSB_PHYS */ + + .align 64 + ALTENTRY(sfmmu_udtlb_slowpath) + srax %g2, PREDISM_BASESHIFT, %g6 /* g6 > 0 : ISM predicted */ brgz,pn %g6, udtlb_miss_probesecond /* check for ISM */ mov %g1, %g3 @@ -3085,10 +3199,8 @@ udtlb_miss_probefirst: brgz,pn %g6, sfmmu_tsb_miss_tt nop #else /* sun4v */ -#ifndef UTSB_PHYS mov %g1, %g4 GET_1ST_TSBE_PTR(%g4, %g1, %g5, sfmmu_udtlb) -#endif UTSB_PHYS PROBE_1ST_DTSB(%g1, %g7, udtlb_first_probefail) /* @@ -3099,9 +3211,7 @@ udtlb_miss_probefirst: */ brgz,pn %g6, sfmmu_tsb_miss_tt nop -#ifndef UTSB_PHYS ldxa [%g0]ASI_DMMU_TSB_8K, %g3 -#endif UTSB_PHYS /* fall through in 8K->4M probe order */ #endif /* sun4v */ @@ -3119,17 +3229,11 @@ udtlb_miss_probesecond: GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5) /* %g2 is okay, no need to reload, %g3 = second tsbe ptr */ #else /* sun4v */ -#ifdef UTSB_PHYS - GET_2ND_TSBREG(%g3) - GET_2ND_TSBE_PTR(%g2, %g3, %g4, %g5) - /* tagacc (%g2) is okay, no need to reload, %g3 = second tsbe ptr */ -#else /* UTSB_PHYS */ mov %g3, %g7 GET_2ND_TSBE_PTR(%g2, %g7, %g3, %g4, %g5, sfmmu_udtlb) /* %g2 clobbered, %g3 =second tsbe ptr */ mov MMU_TAG_ACCESS, %g2 ldxa [%g2]ASI_DMMU, %g2 -#endif /* UTSB_PHYS */ #endif /* sun4v */ srlx %g2, TAG_VALO_SHIFT, %g7 @@ -3139,6 +3243,8 @@ udtlb_miss_probesecond: nop /* fall through to sfmmu_tsb_miss_tt */ +#endif /* sun4u && UTSB_PHYS */ + ALTENTRY(sfmmu_tsb_miss_tt) TT_TRACE(trace_tsbmiss) @@ -3175,9 +3281,8 @@ udtlb_miss_probesecond: wrpr %g7, %tnpc 0: CPU_TSBMISS_AREA(%g6, %g7) - - stn %g1, [%g6 + TSBMISS_TSBPTR] /* save first tsb pointer */ - stn %g3, [%g6 + TSBMISS_TSBPTR4M] /* save second tsb pointer */ + stn %g1, [%g6 + TSBMISS_TSBPTR] /* save 1ST tsb pointer */ + stn %g3, [%g6 + TSBMISS_TSBPTR4M] /* save 2ND tsb pointer */ sllx %g2, TAGACC_CTX_LSHIFT, %g3 brz,a,pn %g3, 1f /* skip ahead if kernel */ @@ -3191,11 +3296,11 @@ udtlb_miss_probesecond: be,pn %icc, tsb_tl0_noctxt /* no ctx miss exception */ stn %g7, [%g6 + (TSBMISS_SCRATCH + TSBMISS_HATID)] -#ifdef sun4v +#if defined(sun4v) || defined(UTSB_PHYS) ldub [%g6 + TSBMISS_URTTEFLAGS], %g7 /* clear ctx1 flag set from */ andn %g7, HAT_CHKCTX1_FLAG, %g7 /* the previous tsb miss */ stub %g7, [%g6 + TSBMISS_URTTEFLAGS] -#endif +#endif /* sun4v || UTSB_PHYS */ ISM_CHECK(%g2, %g6, %g3, %g4, %g5, %g7, %g1, tsb_l1, tsb_ism) /* @@ -3268,11 +3373,11 @@ tsb_4M: tsb_32M: sllx %g2, TAGACC_CTX_LSHIFT, %g5 -#ifdef sun4v +#ifdef sun4v brz,pn %g5, 6f -#else - brz,pn %g5, tsb_pagefault -#endif +#else + brz,pn %g5, tsb_pagefault +#endif ldub [%g6 + TSBMISS_UTTEFLAGS], %g4 and %g4, HAT_32M_FLAG, %g5 brz,pn %g5, tsb_256M @@ -3286,8 +3391,8 @@ tsb_32M: MMU_PAGESHIFT32M, TTE32M, tsb_l32M, tsb_checktte, sfmmu_suspend_tl, tsb_256M) /* NOT REACHED */ - -#ifdef sun4u + +#if defined(sun4u) && !defined(UTSB_PHYS) #define tsb_shme tsb_pagefault #endif tsb_256M: @@ -3318,11 +3423,11 @@ tsb_checktte: brlz,a,pt %g3, tsb_validtte rdpr %tt, %g7 -#ifdef sun4u +#if defined(sun4u) && !defined(UTSB_PHYS) #undef tsb_shme - ba tsb_pagefault - nop -#else + ba tsb_pagefault + nop +#else /* sun4u && !UTSB_PHYS */ tsb_shme: /* @@ -3419,8 +3524,8 @@ tsb_shme_checktte: or %g1, HAT_CHKCTX1_FLAG, %g1 stub %g1, [%g6 + TSBMISS_URTTEFLAGS] - SAVE_CTX1(%g7, %g2, %g1, tsb_shmel) -#endif /* sun4u */ + SAVE_CTX1(%g7, %g2, %g1, tsb_shmel) +#endif /* sun4u && !UTSB_PHYS */ tsb_validtte: /* @@ -3441,15 +3546,16 @@ tsb_validtte: TTE_SET_REFMOD_ML(%g3, %g4, %g5, %g6, %g7, tsb_lset_refmod, tsb_protfault) - rdpr %tt, %g5 GET_MMU_D_TTARGET(%g2, %g7) /* %g2 = ttarget */ #ifdef sun4v MMU_FAULT_STATUS_AREA(%g7) - ldx [%g7 + MMFSA_D_ADDR], %g5 /* save fault addr for later */ -#endif + ldx [%g7 + MMFSA_D_ADDR], %g5 /* load fault addr for later */ +#else /* sun4v */ + mov MMU_TAG_ACCESS, %g5 + ldxa [%g5]ASI_DMMU, %g5 +#endif /* sun4v */ ba,pt %xcc, tsb_update_tl1 - nop - + nop 4: /* * If ITLB miss check exec bit. @@ -3477,13 +3583,13 @@ tsb_validtte: * g4 = patte * g6 = tsbmiss area */ - rdpr %tt, %g5 + rdpr %tt, %g7 #ifdef sun4v MMU_FAULT_STATUS_AREA(%g2) - cmp %g5, T_INSTR_MMU_MISS + cmp %g7, T_INSTR_MMU_MISS be,a,pt %icc, 9f nop - cmp %g5, FAST_IMMU_MISS_TT + cmp %g7, FAST_IMMU_MISS_TT be,a,pt %icc, 9f nop add %g2, MMFSA_D_, %g2 @@ -3491,23 +3597,29 @@ tsb_validtte: ldx [%g2 + MMFSA_CTX_], %g7 sllx %g7, TTARGET_CTX_SHIFT, %g7 ldx [%g2 + MMFSA_ADDR_], %g2 - mov %g2, %g5 ! save the fault addr for later use + mov %g2, %g5 ! load the fault addr for later use srlx %g2, TTARGET_VA_SHIFT, %g2 or %g2, %g7, %g2 -#else - cmp %g5, FAST_IMMU_MISS_TT - be,a,pt %icc, tsb_update_tl1 - ldxa [%g0]ASI_IMMU, %g2 - ldxa [%g0]ASI_DMMU, %g2 -#endif +#else /* sun4v */ + mov MMU_TAG_ACCESS, %g5 + cmp %g7, FAST_IMMU_MISS_TT + be,a,pt %icc, 9f + ldxa [%g0]ASI_IMMU, %g2 + ldxa [%g0]ASI_DMMU, %g2 + ba,pt %icc, tsb_update_tl1 + ldxa [%g5]ASI_DMMU, %g5 +9: + ldxa [%g5]ASI_IMMU, %g5 +#endif /* sun4v */ + tsb_update_tl1: srlx %g2, TTARGET_CTX_SHIFT, %g7 brz,pn %g7, tsb_kernel #ifdef sun4v and %g3, TTE_SZ_BITS, %g7 ! assumes TTE_SZ_SHFT is 0 -#else +#else /* sun4v */ srlx %g3, TTE_SZ_SHFT, %g7 -#endif +#endif /* sun4v */ tsb_user: #ifdef sun4v @@ -3524,35 +3636,34 @@ tsb_user: nop #else /* ITLB_32M_256M_SUPPORT */ bnz,a,pn %icc, tsb_user_pn_synth - cmp %g5, FAST_IMMU_MISS_TT + nop #endif /* ITLB_32M_256M_SUPPORT */ #endif /* sun4v */ tsb_user8k: -#ifdef sun4v +#if defined(sun4v) || defined(UTSB_PHYS) ldub [%g6 + TSBMISS_URTTEFLAGS], %g7 and %g7, HAT_CHKCTX1_FLAG, %g1 brz,a,pn %g1, 1f - ldn [%g6 + TSBMISS_TSBPTR], %g1 ! g1 = first TSB ptr + ldn [%g6 + TSBMISS_TSBPTR], %g1 ! g1 = 1ST TSB ptr GET_UTSBREG_SHCTX(%g6, TSBMISS_TSBSCDPTR, %g1) - brlz,a,pn %g1, ptl1_panic ! if no shared tsb + brlz,a,pn %g1, ptl1_panic ! if no shared 3RD tsb mov PTL1_NO_SCDTSB8K, %g1 ! panic - GET_3RD_TSBE_PTR(%g5, %g1, %g6, %g7) + GET_3RD_TSBE_PTR(%g5, %g1, %g6, %g7) 1: -#else - ldn [%g6 + TSBMISS_TSBPTR], %g1 ! g1 = first TSB ptr +#else /* defined(sun4v) || defined(UTSB_PHYS) */ + ldn [%g6 + TSBMISS_TSBPTR], %g1 ! g1 = 1ST TSB ptr +#endif /* defined(sun4v) || defined(UTSB_PHYS) */ #ifndef UTSB_PHYS mov ASI_N, %g7 ! user TSBs accessed by VA mov %g7, %asi -#endif /* UTSB_PHYS */ - -#endif /* sun4v */ +#endif /* !UTSB_PHYS */ TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, 5) -#ifdef sun4v rdpr %tt, %g5 +#ifdef sun4v cmp %g5, T_INSTR_MMU_MISS be,a,pn %xcc, 9f mov %g3, %g5 @@ -3570,19 +3681,19 @@ tsb_user8k: retry tsb_user4m: -#ifdef sun4v +#if defined(sun4v) || defined(UTSB_PHYS) ldub [%g6 + TSBMISS_URTTEFLAGS], %g7 and %g7, HAT_CHKCTX1_FLAG, %g1 brz,a,pn %g1, 4f - ldn [%g6 + TSBMISS_TSBPTR4M], %g1 ! g1 = TSB ptr - GET_UTSBREG_SHCTX(%g6, TSBMISS_TSBSCDPTR4M, %g1) - brlz,a,pn %g1, 5f ! if no shared 2nd tsb + ldn [%g6 + TSBMISS_TSBPTR4M], %g1 ! g1 = 2ND TSB ptr + GET_UTSBREG_SHCTX(%g6, TSBMISS_TSBSCDPTR4M, %g1)! g1 = 4TH TSB ptr + brlz,a,pn %g1, 5f ! if no shared 4TH TSB nop - GET_4TH_TSBE_PTR(%g5, %g1, %g6, %g7) -#else - ldn [%g6 + TSBMISS_TSBPTR4M], %g1 ! g1 = TSB ptr -#endif + GET_4TH_TSBE_PTR(%g5, %g1, %g6, %g7) 4: +#else /* defined(sun4v) || defined(UTSB_PHYS) */ + ldn [%g6 + TSBMISS_TSBPTR4M], %g1 ! g1 = 2ND TSB ptr +#endif /* defined(sun4v) || defined(UTSB_PHYS) */ brlz,pn %g1, 5f /* Check to see if we have 2nd TSB programmed */ nop @@ -3594,8 +3705,8 @@ tsb_user4m: TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, 6) 5: -#ifdef sun4v rdpr %tt, %g5 +#ifdef sun4v cmp %g5, T_INSTR_MMU_MISS be,a,pn %xcc, 9f mov %g3, %g5 @@ -3631,6 +3742,8 @@ tsb_user4m: * g6 = tsbmiss area */ tsb_user_pn_synth: + rdpr %tt, %g5 + cmp %g5, FAST_IMMU_MISS_TT be,pt %xcc, tsb_user_itlb_synth /* ITLB miss */ andcc %g3, TTE_EXECPRM_INT, %g0 /* is execprm bit set */ bz,pn %icc, 4b /* if not, been here before */ @@ -3650,7 +3763,7 @@ tsb_user_pn_synth: retry tsb_user_itlb_synth: - ldn [%g6 + TSBMISS_TSBPTR4M], %g1 /* g1 = tsbp */ + ldn [%g6 + TSBMISS_TSBPTR4M], %g1 /* g1 = 2ND TSB */ mov MMU_TAG_ACCESS, %g7 ldxa [%g7]ASI_IMMU, %g6 /* get tag access va */ @@ -3668,21 +3781,21 @@ tsb_user_itlb_synth: #endif /* sun4v && ITLB_32M_256M_SUPPORT */ tsb_kernel: -#ifdef sun4v rdpr %tt, %g5 +#ifdef sun4v cmp %g7, TTE4M bge,pn %icc, 5f #else cmp %g7, TTESZ_VALID | TTE4M ! no 32M or 256M support be,pn %icc, 5f -#endif +#endif /* sun4v */ nop - ldn [%g6 + TSBMISS_TSBPTR], %g1 ! g1 = 8k tsbptr + ldn [%g6 + TSBMISS_TSBPTR], %g1 ! g1 = 8K TSB ptr ba,pt %xcc, 6f nop 5: - ldn [%g6 + TSBMISS_TSBPTR4M], %g1 ! g1 = 4m tsbptr - brlz,pn %g1, 3f /* skip programming if 4m TSB ptr is -1 */ + ldn [%g6 + TSBMISS_TSBPTR4M], %g1 ! g1 = 4M TSB ptr + brlz,pn %g1, 3f /* skip programming if 4M TSB ptr is -1 */ nop 6: #ifndef sun4v @@ -3734,7 +3847,7 @@ tsb_ism: or %g2, %g4, %g2 /* g2 = (pseudo-)tagacc */ sub %g5, (IMAP_VB_SHIFT - IMAP_HATFLAGS), %g5 lduha [%g5]ASI_MEM, %g4 /* g5 = pa of imap_hatflags */ -#ifdef sun4v +#if defined(sun4v) || defined(UTSB_PHYS) and %g4, HAT_CTX1_FLAG, %g5 /* g5 = imap_hatflags */ brz,pt %g5, tsb_chk4M_ism nop @@ -3743,7 +3856,8 @@ tsb_ism: stub %g5, [%g6 + TSBMISS_URTTEFLAGS] rdpr %tt, %g5 SAVE_CTX1(%g5, %g3, %g1, tsb_shctxl) -#endif +#endif /* defined(sun4v) || defined(UTSB_PHYS) */ + /* * ISM pages are always locked down. * If we can't find the tte then pagefault @@ -3859,7 +3973,7 @@ tsb_protfault: cmp %g7, T_INSTR_MMU_MISS move %icc, %g5, %g2 sllx %g2, TAGACC_CTX_LSHIFT, %g4 -#endif +#endif /* sun4v */ brnz,pn %g4, 3f /* skip if not kernel */ rdpr %tl, %g5 @@ -3988,7 +4102,7 @@ tsb_protfault: ldxa [%g2]ASI_IMMU, %g3 ldxa [%g2]ASI_DMMU, %g3 2: sllx %g3, TAGACC_CTX_LSHIFT, %g3 -#endif +#endif /* sun4v */ brz,a,pn %g3, ptl1_panic ! panic if called for kernel mov PTL1_BAD_CTX_STEAL, %g1 ! since kernel ctx was stolen rdpr %tl, %g5 @@ -3999,7 +4113,7 @@ tsb_protfault: ba,pt %icc, sfmmu_window_trap nop SET_SIZE(sfmmu_tsb_miss) -#endif /* lint */ +#endif /* lint */ #if defined (lint) /* @@ -4110,7 +4224,7 @@ kvtop_nohblk: cmp %g5, MAX_HASHCNT #else cmp %g5, DEFAULT_MAX_HASHCNT /* no 32/256M kernel pages */ -#endif +#endif /* sun4v */ be,a,pn %icc, 6f mov -1, %o0 /* output = -1 (PFN_INVALID) */ mov %o1, %o4 /* restore hatid */ @@ -4126,7 +4240,7 @@ kvtop_nohblk: move %icc, MMU_PAGESHIFT512K, %g6 ba,pt %icc, 1b movne %icc, MMU_PAGESHIFT4M, %g6 -#endif +#endif /* sun4v */ 6: retl wrpr %g0, %o3, %pstate /* re-enable interrupts */ diff --git a/usr/src/uts/sfmmu/vm/hat_sfmmu.c b/usr/src/uts/sfmmu/vm/hat_sfmmu.c index b81464137f..79dfe1b7d5 100644 --- a/usr/src/uts/sfmmu/vm/hat_sfmmu.c +++ b/usr/src/uts/sfmmu/vm/hat_sfmmu.c @@ -2967,6 +2967,12 @@ sfmmu_tteload_addentry(sfmmu_t *sfmmup, struct hme_blk *hmeblkp, tte_t *ttep, panic("sfmmu_tteload: non cacheable memory tte"); #endif /* DEBUG */ + /* don't simulate dirty bit for writeable ISM/DISM mappings */ + if ((flags & HAT_LOAD_SHARE) && TTE_IS_WRITABLE(ttep)) { + TTE_SET_REF(ttep); + TTE_SET_MOD(ttep); + } + if ((flags & HAT_LOAD_SHARE) || !TTE_IS_REF(ttep) || !TTE_IS_MOD(ttep)) { /* @@ -9678,9 +9684,7 @@ sfmmu_get_ctx(sfmmu_t *sfmmup) { mmu_ctx_t *mmu_ctxp; uint_t pstate_save; -#ifdef sun4v int ret; -#endif ASSERT(sfmmu_hat_lock_held(sfmmup)); ASSERT(sfmmup != ksfmmup); @@ -9721,9 +9725,6 @@ sfmmu_get_ctx(sfmmu_t *sfmmup) */ pstate_save = sfmmu_disable_intrs(); -#ifdef sun4u - (void) sfmmu_alloc_ctx(sfmmup, 1, CPU, SFMMU_PRIVATE); -#else if (sfmmu_alloc_ctx(sfmmup, 1, CPU, SFMMU_PRIVATE) && sfmmup->sfmmu_scdp != NULL) { sf_scd_t *scdp = sfmmup->sfmmu_scdp; @@ -9733,7 +9734,6 @@ sfmmu_get_ctx(sfmmu_t *sfmmup) ASSERT(!ret || scsfmmup->sfmmu_ctxs[CPU_MMU_IDX(CPU)].cnum != INVALID_CONTEXT); } -#endif sfmmu_load_mmustate(sfmmup); sfmmu_enable_intrs(pstate_save); @@ -13953,9 +13953,11 @@ hat_join_region(struct hat *sfmmup, r_type = (r_type == HAT_REGION_ISM) ? SFMMU_REGION_ISM : SFMMU_REGION_HME; /* - * Currently only support shared hmes for the main text region. + * Currently only support shared hmes for the read only main text + * region. */ - if (r_type == SFMMU_REGION_HME && r_obj != srdp->srd_evp) { + if (r_type == SFMMU_REGION_HME && ((r_obj != srdp->srd_evp) || + (r_perm & PROT_WRITE))) { return (HAT_INVALID_REGION_COOKIE); } diff --git a/usr/src/uts/sfmmu/vm/hat_sfmmu.h b/usr/src/uts/sfmmu/vm/hat_sfmmu.h index 16ea7bcfae..92f238aafa 100644 --- a/usr/src/uts/sfmmu/vm/hat_sfmmu.h +++ b/usr/src/uts/sfmmu/vm/hat_sfmmu.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,6 +56,7 @@ extern "C" { * Don't alter these without considering changes to ism_map_t. */ #define DEFAULT_ISM_PAGESIZE MMU_PAGESIZE4M +#define DEFAULT_ISM_PAGESZC TTE4M #define ISM_PG_SIZE(ism_vbshift) (1 << ism_vbshift) #define ISM_SZ_MASK(ism_vbshift) (ISM_PG_SIZE(ism_vbshift) - 1) #define ISM_MAP_SLOTS 8 /* Change this carefully. */ @@ -859,6 +860,188 @@ struct ctx_trace { #ifdef sun4v #define USER_CONTEXT_TYPE NUM_LOCKED_CTXS #endif +#if defined(sun4v) || defined(UTSB_PHYS) +/* + * Get the location in the 4MB base TSB of the tsbe for this fault. + * Assumes that the second TSB only contains 4M mappings. + * + * In: + * tagacc = tag access register (not clobbered) + * tsbe = 2nd TSB base register + * tmp1, tmp2 = scratch registers + * Out: + * tsbe = pointer to the tsbe in the 2nd TSB + */ + +#define GET_4MBASE_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ + and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ + andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ + mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ + sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ + sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ + srlx tagacc, MMU_PAGESHIFT4M, tmp2; \ + and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ + sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ + add tsbe, tmp1, tsbe /* add entry offset to TSB base */ + +#define GET_2ND_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ + GET_4MBASE_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) + +/* + * Get the location in the 3rd TSB of the tsbe for this fault. + * The 3rd TSB corresponds to the shared context, and is used + * for 8K - 512k pages. + * + * In: + * tagacc = tag access register (not clobbered) + * tsbe, tmp1, tmp2 = scratch registers + * Out: + * tsbe = pointer to the tsbe in the 3rd TSB + */ + +#define GET_3RD_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ + and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ + andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ + mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ + sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ + sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ + srlx tagacc, MMU_PAGESHIFT, tmp2; \ + and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ + sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ + add tsbe, tmp1, tsbe /* add entry offset to TSB base */ + +#define GET_4TH_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ + GET_4MBASE_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) +/* + * Copy the sfmmu_region_map or scd_region_map to the tsbmiss + * shmermap or scd_shmermap, from sfmmu_load_mmustate. + */ +#define SET_REGION_MAP(rgn_map, tsbmiss_map, cnt, tmp, label) \ + /* BEGIN CSTYLED */ \ +label: ;\ + ldx [rgn_map], tmp ;\ + dec cnt ;\ + add rgn_map, CLONGSIZE, rgn_map ;\ + stx tmp, [tsbmiss_map] ;\ + brnz,pt cnt, label ;\ + add tsbmiss_map, CLONGSIZE, tsbmiss_map \ + /* END CSTYLED */ + +/* + * If there is no scd, then zero the tsbmiss scd_shmermap, + * from sfmmu_load_mmustate. + */ +#define ZERO_REGION_MAP(tsbmiss_map, cnt, label) \ + /* BEGIN CSTYLED */ \ +label: ;\ + dec cnt ;\ + stx %g0, [tsbmiss_map] ;\ + brnz,pt cnt, label ;\ + add tsbmiss_map, CLONGSIZE, tsbmiss_map + /* END CSTYLED */ + +/* + * Set hmemisc to 1 if the shared hme is also part of an scd. + * In: + * tsbarea = tsbmiss area (not clobbered) + * hmeblkpa = hmeblkpa + hmentoff + SFHME_TTE (not clobbered) + * hmentoff = hmentoff + SFHME_TTE = tte offset(clobbered) + * Out: + * use_shctx = 1 if shme is in scd and 0 otherwise + */ +#define GET_SCDSHMERMAP(tsbarea, hmeblkpa, hmentoff, use_shctx) \ + /* BEGIN CSTYLED */ \ + sub hmeblkpa, hmentoff, hmentoff /* hmentofff = hmeblkpa */ ;\ + add hmentoff, HMEBLK_TAG, hmentoff ;\ + ldxa [hmentoff]ASI_MEM, hmentoff /* read 1st part of tag */ ;\ + and hmentoff, HTAG_RID_MASK, hmentoff /* mask off rid */ ;\ + and hmentoff, BT_ULMASK, use_shctx /* mask bit index */ ;\ + srlx hmentoff, BT_ULSHIFT, hmentoff /* extract word */ ;\ + sllx hmentoff, CLONGSHIFT, hmentoff /* index */ ;\ + add tsbarea, hmentoff, hmentoff /* add to tsbarea */ ;\ + ldx [hmentoff + TSBMISS_SCDSHMERMAP], hmentoff /* scdrgn */ ;\ + srlx hmentoff, use_shctx, use_shctx ;\ + and use_shctx, 0x1, use_shctx \ + /* END CSTYLED */ + +/* + * Synthesize a TSB base register contents for a process. + * + * In: + * tsbinfo = TSB info pointer (ro) + * tsbreg, tmp1 = scratch registers + * Out: + * tsbreg = value to program into TSB base register + */ + +#define MAKE_UTSBREG(tsbinfo, tsbreg, tmp1) \ + ldx [tsbinfo + TSBINFO_PADDR], tsbreg; \ + lduh [tsbinfo + TSBINFO_SZCODE], tmp1; \ + and tmp1, TSB_SOFTSZ_MASK, tmp1; \ + or tsbreg, tmp1, tsbreg; + + +/* + * Load TSB base register to TSBMISS area for privte contexts. + * This register contains utsb_pabase in bits 63:13, and TSB size + * code in bits 2:0. + * + * For private context + * In: + * tsbreg = value to load (ro) + * regnum = constant or register + * tmp1 = scratch register + * Out: + * Specified scratchpad register updated + * + */ +#define SET_UTSBREG(regnum, tsbreg, tmp1) \ + mov regnum, tmp1; \ + stxa tsbreg, [tmp1]ASI_SCRATCHPAD /* save tsbreg */ +/* + * Get TSB base register from the scratchpad for private contexts + * + * In: + * regnum = constant or register + * tsbreg = scratch + * Out: + * tsbreg = tsbreg from the specified scratchpad register + */ +#define GET_UTSBREG(regnum, tsbreg) \ + mov regnum, tsbreg; \ + ldxa [tsbreg]ASI_SCRATCHPAD, tsbreg + +/* + * Load TSB base register to TSBMISS area for shared contexts. + * This register contains utsb_pabase in bits 63:13, and TSB size + * code in bits 2:0. + * + * In: + * tsbmiss = pointer to tsbmiss area + * tsbmissoffset = offset to right tsb pointer + * tsbreg = value to load (ro) + * Out: + * Specified tsbmiss area updated + * + */ +#define SET_UTSBREG_SHCTX(tsbmiss, tsbmissoffset, tsbreg) \ + stx tsbreg, [tsbmiss + tsbmissoffset] /* save tsbreg */ + +/* + * Get TSB base register from the scratchpad for + * shared contexts + * + * In: + * tsbmiss = pointer to tsbmiss area + * tsbmissoffset = offset to right tsb pointer + * tsbreg = scratch + * Out: + * tsbreg = tsbreg from the specified scratchpad register + */ +#define GET_UTSBREG_SHCTX(tsbmiss, tsbmissoffset, tsbreg) \ + ldx [tsbmiss + tsbmissoffset], tsbreg + +#endif /* defined(sun4v) || defined(UTSB_PHYS) */ #ifndef _ASM @@ -1744,7 +1927,7 @@ extern size_t tsb_slab_mask; * sun4u platforms that define UTSB_PHYS use physical addressing to access * the user TSBs at TL>0. The first user TSB base is in the MMU I/D TSB Base * registers. The second TSB base uses a dedicated scratchpad register which - * requires a definition of SCRATCHPAD_UTSBREG in mach_sfmmu.h. The layout for + * requires a definition of SCRATCHPAD_UTSBREG2 in mach_sfmmu.h. The layout for * both registers is equivalent to sun4v below, except the TSB PA range is * [46..13] for sun4u. * diff --git a/usr/src/uts/sun4/ml/swtch.s b/usr/src/uts/sun4/ml/swtch.s index f8892bd0c7..d19606ee84 100644 --- a/usr/src/uts/sun4/ml/swtch.s +++ b/usr/src/uts/sun4/ml/swtch.s @@ -19,10 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - + #pragma ident "%Z%%M% %I% %E% SMI" /* @@ -263,7 +263,7 @@ resume(kthread_id_t t) set SFMMU_PRIVATE, %o3 ! %o3 = sfmmu private flag call sfmmu_alloc_ctx mov %g0, %o1 ! %o1 = allocate flag = 0 -#ifdef sun4v + brz,a,pt %o0, 4f ! %o0 == 0, no private alloc'ed nop @@ -277,8 +277,6 @@ resume(kthread_id_t t) call sfmmu_alloc_ctx mov 1, %o1 ! %o1 = allocate flag = 1 -#endif - 4: call sfmmu_load_mmustate ! program MMU registers mov %i5, %o0 diff --git a/usr/src/uts/sun4u/cpu/opl_olympus.c b/usr/src/uts/sun4u/cpu/opl_olympus.c index 349b198ec3..3a76531e82 100644 --- a/usr/src/uts/sun4u/cpu/opl_olympus.c +++ b/usr/src/uts/sun4u/cpu/opl_olympus.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -103,6 +103,11 @@ int cpu_berr_to_verbose = 0; */ int cpu_alljupiter = 0; +/* + * The sfmmu_cext field to be used by processes in a shared context domain. + */ +static uchar_t shctx_cext = TAGACCEXT_MKSZPAIR(DEFAULT_ISM_PAGESZC, TTE8K); + static int min_ecache_size; static uint_t priv_hcl_1; static uint_t priv_hcl_2; @@ -303,6 +308,11 @@ cpu_fix_alljupiter(void) * hwcap semantics. */ cpu_hwcap_flags |= AV_SPARC_IMA; + + /* + * Enable shared context support. + */ + shctx_on = 1; } #ifdef OLYMPUS_C_REV_B_ERRATA_XCALL @@ -803,7 +813,7 @@ mmu_large_pages_disabled(uint_t flag) /* * mmu_init_large_pages is called with the desired ism_pagesize parameter. - * It may be called from set_platform_defaults, if some value other than 32M + * It may be called from set_platform_defaults, if some value other than 4M * is desired. mmu_ism_pagesize is the tunable. If it has a bad value, * then only warn, since it would be bad form to panic due to a user typo. * @@ -812,12 +822,14 @@ mmu_large_pages_disabled(uint_t flag) void mmu_init_large_pages(size_t ism_pagesize) { + switch (ism_pagesize) { case MMU_PAGESIZE4M: mmu_disable_ism_large_pages = ((1 << TTE64K) | (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M)); mmu_disable_auto_data_large_pages = ((1 << TTE64K) | (1 << TTE512K) | (1 << TTE32M) | (1 << TTE256M)); + shctx_cext = TAGACCEXT_MKSZPAIR(TTE4M, TTE8K); break; case MMU_PAGESIZE32M: mmu_disable_ism_large_pages = ((1 << TTE64K) | @@ -825,6 +837,7 @@ mmu_init_large_pages(size_t ism_pagesize) mmu_disable_auto_data_large_pages = ((1 << TTE64K) | (1 << TTE512K) | (1 << TTE4M) | (1 << TTE256M)); adjust_data_maxlpsize(ism_pagesize); + shctx_cext = TAGACCEXT_MKSZPAIR(TTE32M, TTE8K); break; case MMU_PAGESIZE256M: mmu_disable_ism_large_pages = ((1 << TTE64K) | @@ -832,6 +845,7 @@ mmu_init_large_pages(size_t ism_pagesize) mmu_disable_auto_data_large_pages = ((1 << TTE64K) | (1 << TTE512K) | (1 << TTE4M) | (1 << TTE32M)); adjust_data_maxlpsize(ism_pagesize); + shctx_cext = TAGACCEXT_MKSZPAIR(TTE256M, TTE8K); break; default: cmn_err(CE_WARN, "Unrecognized mmu_ism_pagesize value 0x%lx", @@ -844,7 +858,7 @@ mmu_init_large_pages(size_t ism_pagesize) * Function to reprogram the TLBs when page sizes used * by a process change significantly. */ -void +static void mmu_setup_page_sizes(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz) { uint8_t pgsz0, pgsz1; @@ -909,11 +923,15 @@ mmu_set_ctx_page_sizes(struct hat *hat) /* * If supported, reprogram the TLBs to a larger pagesize. */ - pgsz0 = hat->sfmmu_pgsz[0]; - pgsz1 = hat->sfmmu_pgsz[1]; - ASSERT(pgsz0 < mmu_page_sizes); - ASSERT(pgsz1 < mmu_page_sizes); - new_cext = TAGACCEXT_MKSZPAIR(pgsz1, pgsz0); + if (hat->sfmmu_scdp != NULL) { + new_cext = shctx_cext; + } else { + pgsz0 = hat->sfmmu_pgsz[0]; + pgsz1 = hat->sfmmu_pgsz[1]; + ASSERT(pgsz0 < mmu_page_sizes); + ASSERT(pgsz1 < mmu_page_sizes); + new_cext = TAGACCEXT_MKSZPAIR(pgsz1, pgsz0); + } if (hat->sfmmu_cext != new_cext) { #ifdef DEBUG int i; diff --git a/usr/src/uts/sun4u/cpu/us3_common_mmu.c b/usr/src/uts/sun4u/cpu/us3_common_mmu.c index 892be30295..157d6f7ec9 100644 --- a/usr/src/uts/sun4u/cpu/us3_common_mmu.c +++ b/usr/src/uts/sun4u/cpu/us3_common_mmu.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -134,7 +134,7 @@ int init_mmu_page_sizes = 0; /* * mmu_init_large_pages is called with the desired ism_pagesize parameter, * for Panther-only systems. It may be called from set_platform_defaults, - * if some value other than 32M is desired, for Panther-only systems. + * if some value other than 4M is desired, for Panther-only systems. * mmu_ism_pagesize is the tunable. If it has a bad value, then only warn, * since it would be bad form to panic due * to a user typo. @@ -252,7 +252,7 @@ static uint64_t ttecnt_threshold[MMU_PAGE_SIZES] = { * didn't fault any pages in. This allows the t512_1 to be reprogrammed, * because the T16 does not support the two giant page sizes. ouch. */ -void +static void mmu_fixup_large_pages(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz) { uint_t pgsz0 = tmp_pgsz[0]; @@ -318,7 +318,7 @@ mmu_fixup_large_pages(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz) * Function to set up the page size values used to reprogram the DTLBs, * when page sizes used by a process change significantly. */ -void +static void mmu_setup_page_sizes(struct hat *hat, uint64_t *ttecnt, uint8_t *tmp_pgsz) { uint_t pgsz0, pgsz1; diff --git a/usr/src/uts/sun4u/ml/mach_offsets.in b/usr/src/uts/sun4u/ml/mach_offsets.in index 9ce9aea4fb..7d8df8a635 100644 --- a/usr/src/uts/sun4u/ml/mach_offsets.in +++ b/usr/src/uts/sun4u/ml/mach_offsets.in @@ -18,7 +18,7 @@ \ \ CDDL HEADER END \ -\ Copyright 2007 Sun Microsystems, Inc. All rights reserved. +\ Copyright 2008 Sun Microsystems, Inc. All rights reserved. \ Use is subject to license terms. \ \ offsets.in: input file to produce assym.h using the stabs program @@ -99,47 +99,60 @@ trap_trace_record TRAP_ENT_SIZE tt_f3 TRAP_ENT_F3 tt_f4 TRAP_ENT_F4 -hat HAT_SIZE - sfmmu_cpusran - sfmmu_tsb - sfmmu_ismblkpa - sfmmu_tteflags - sfmmu_cext - sfmmu_ctx_lock - sfmmu_ctxs +hat HAT_SIZE + sfmmu_cpusran + sfmmu_tsb + sfmmu_ismblkpa + sfmmu_tteflags + sfmmu_rtteflags + sfmmu_srdp + sfmmu_region_map.h_rmap_s.hmeregion_map SFMMU_HMERMAP + sfmmu_scdp + sfmmu_cext + sfmmu_ctx_lock + sfmmu_ctxs + +sf_scd SCD_SIZE + scd_sfmmup + scd_region_map.h_rmap_s.hmeregion_map SCD_HMERMAP sfmmu_global_stat HATSTAT_SIZE - sf_pagefaults HATSTAT_PAGEFAULT - sf_uhash_searches HATSTAT_UHASH_SEARCH - sf_uhash_links HATSTAT_UHASH_LINKS - sf_khash_searches HATSTAT_KHASH_SEARCH - sf_khash_links HATSTAT_KHASH_LINKS - -sf_hment SFHME_SIZE SFHME_SHIFT - hme_tte SFHME_TTE - -tsbmiss TSBMISS_SIZE - ksfmmup TSBMISS_KHATID - usfmmup TSBMISS_UHATID - tsbptr TSBMISS_TSBPTR - tsbptr4m TSBMISS_TSBPTR4M - ismblkpa TSBMISS_ISMBLKPA - khashstart TSBMISS_KHASHSTART - uhashstart TSBMISS_UHASHSTART - khashsz TSBMISS_KHASHSZ - uhashsz TSBMISS_UHASHSZ - dcache_line_mask TSBMISS_DMASK - uhat_tteflags TSBMISS_UTTEFLAGS - uhat_rtteflags TSBMISS_URTTEFLAGS - utsb_misses TSBMISS_UTSBMISS - ktsb_misses TSBMISS_KTSBMISS - uprot_traps TSBMISS_UPROTS - kprot_traps TSBMISS_KPROTS - scratch TSBMISS_SCRATCH - -\#define TSB_TAGACC (0 * TSBMISS_SCRATCH_INCR) -\#define TSBMISS_HMEBP (1 * TSBMISS_SCRATCH_INCR) -\#define TSBMISS_HATID (2 * TSBMISS_SCRATCH_INCR) + sf_pagefaults HATSTAT_PAGEFAULT + sf_uhash_searches HATSTAT_UHASH_SEARCH + sf_uhash_links HATSTAT_UHASH_LINKS + sf_khash_searches HATSTAT_KHASH_SEARCH + sf_khash_links HATSTAT_KHASH_LINKS + +sf_hment SFHME_SIZE SFHME_SHIFT + hme_tte SFHME_TTE + +tsbmiss TSBMISS_SIZE + ksfmmup TSBMISS_KHATID + usfmmup TSBMISS_UHATID + usrdp TSBMISS_SHARED_UHATID + tsbptr TSBMISS_TSBPTR + tsbptr4m TSBMISS_TSBPTR4M + tsbscdptr TSBMISS_TSBSCDPTR + tsbscdptr4m TSBMISS_TSBSCDPTR4M + ismblkpa TSBMISS_ISMBLKPA + khashstart TSBMISS_KHASHSTART + uhashstart TSBMISS_UHASHSTART + khashsz TSBMISS_KHASHSZ + uhashsz TSBMISS_UHASHSZ + dcache_line_mask TSBMISS_DMASK + uhat_tteflags TSBMISS_UTTEFLAGS + uhat_rtteflags TSBMISS_URTTEFLAGS + utsb_misses TSBMISS_UTSBMISS + ktsb_misses TSBMISS_KTSBMISS + uprot_traps TSBMISS_UPROTS + kprot_traps TSBMISS_KPROTS + scratch TSBMISS_SCRATCH + shmermap TSBMISS_SHMERMAP + scd_shmermap TSBMISS_SCDSHMERMAP + +\#define TSB_TAGACC (0 * TSBMISS_SCRATCH_INCR) +\#define TSBMISS_HMEBP (1 * TSBMISS_SCRATCH_INCR) +\#define TSBMISS_HATID (2 * TSBMISS_SCRATCH_INCR) kpmtsbm KPMTSBM_SIZE KPMTSBM_SHIFT vbase KPMTSBM_VBASE diff --git a/usr/src/uts/sun4u/ml/trap_table.s b/usr/src/uts/sun4u/ml/trap_table.s index bc20d95bee..8b8e15d926 100644 --- a/usr/src/uts/sun4u/ml/trap_table.s +++ b/usr/src/uts/sun4u/ml/trap_table.s @@ -19,10 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - + #pragma ident "%Z%%M% %I% %E% SMI" #if !defined(lint) @@ -1076,15 +1076,13 @@ table_name/**/_dtlbmiss: ;\ srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ cmp %g3, INVALID_CONTEXT ;\ ble,pn %xcc, sfmmu_kdtlb_miss ;\ + srax %g2, PREDISM_BASESHIFT, %g6 /* g6 > 0 ISM predicted */ ;\ + brgz,pn %g6, sfmmu_udtlb_slowpath_ismpred ;\ srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ - mov SCRATCHPAD_UTSBREG, %g3 ;\ - ldxa [%g3]ASI_SCRATCHPAD, %g3 /* g3 = 2nd tsb reg */ ;\ - brgez,pn %g3, sfmmu_udtlb_slowpath /* branch if 2 TSBs */ ;\ - nop ;\ ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, %g5 data */;\ cmp %g4, %g7 ;\ - bne,pn %xcc, sfmmu_tsb_miss_tt /* no 4M TSB, miss */ ;\ - mov -1, %g3 /* set 4M tsbe ptr to -1 */ ;\ + bne,pn %xcc, sfmmu_udtlb_slowpath_noismpred ;\ + nop ;\ TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ stxa %g5, [%g0]ASI_DTLB_IN /* trapstat expects TTE */ ;\ retry /* in %g5 */ ;\ @@ -1097,10 +1095,13 @@ table_name/**/_dtlbmiss: ;\ unimp 0 ;\ unimp 0 ;\ unimp 0 ;\ - unimp 0 ;\ - unimp 0 ;\ - unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ .align 128 + #else /* UTSB_PHYS */ #define DTLB_MISS(table_name) ;\ .global table_name/**/_dtlbmiss ;\ @@ -1158,41 +1159,42 @@ tt1_itlbmiss: * MUST be EXACTLY 32 instructions or we'll break. */ #ifdef UTSB_PHYS -#define ITLB_MISS(table_name) \ - .global table_name/**/_itlbmiss ;\ -table_name/**/_itlbmiss: ;\ - mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ - ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ - ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\ - sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ - srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ - cmp %g3, INVALID_CONTEXT ;\ - ble,pn %xcc, sfmmu_kitlb_miss ;\ - srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ - mov SCRATCHPAD_UTSBREG, %g3 ;\ - ldxa [%g3]ASI_SCRATCHPAD, %g3 /* g3 = 2nd tsb reg */ ;\ - brgez,pn %g3, sfmmu_uitlb_slowpath /* branch if 2 TSBs */ ;\ - nop ;\ - ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ - cmp %g4, %g7 ;\ - bne,pn %xcc, sfmmu_tsb_miss_tt /* br if 8k ptr miss */ ;\ - mov -1, %g3 /* set 4M TSB ptr to -1 */ ;\ - andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ - bz,pn %icc, exec_fault ;\ - nop ;\ - TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ - stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\ - retry ;\ - unimp 0 ;\ - unimp 0 ;\ - unimp 0 ;\ - unimp 0 ;\ - unimp 0 ;\ - unimp 0 ;\ +#define ITLB_MISS(table_name) \ + .global table_name/**/_itlbmiss ;\ +table_name/**/_itlbmiss: ;\ + mov MMU_TAG_ACCESS, %g6 /* select tag acc */ ;\ + ldxa [%g0]ASI_IMMU_TSB_8K, %g1 /* g1 = tsbe ptr */ ;\ + ldxa [%g6]ASI_IMMU, %g2 /* g2 = tag access */ ;\ + sllx %g2, TAGACC_CTX_LSHIFT, %g3 ;\ + srlx %g3, TAGACC_CTX_LSHIFT, %g3 /* g3 = ctx */ ;\ + cmp %g3, INVALID_CONTEXT ;\ + ble,pn %xcc, sfmmu_kitlb_miss ;\ + srlx %g2, TAG_VALO_SHIFT, %g7 /* g7 = tsb tag */ ;\ + ldda [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */ ;\ + cmp %g4, %g7 ;\ + bne,pn %xcc, sfmmu_uitlb_slowpath ;\ + andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ + bz,pn %icc, exec_fault ;\ + nop ;\ + TT_TRACE(trace_tsbhit) /* 2 instr ifdef TRAPTRACE */ ;\ + stxa %g5, [%g0]ASI_ITLB_IN /* trapstat expects %g5 */ ;\ + retry ;\ unimp 0 ;\ unimp 0 ;\ unimp 0 ;\ - .align 128 + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + unimp 0 ;\ + .align 128 + #else /* UTSB_PHYS */ #define ITLB_MISS(table_name) \ .global table_name/**/_itlbmiss ;\ diff --git a/usr/src/uts/sun4u/os/mach_cpu_states.c b/usr/src/uts/sun4u/os/mach_cpu_states.c index 50c34ed97c..9e14ff1930 100644 --- a/usr/src/uts/sun4u/os/mach_cpu_states.c +++ b/usr/src/uts/sun4u/os/mach_cpu_states.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -396,6 +396,8 @@ ptl1_panic_handler(ptl1_state_t *pstate) "CPU ECC error loop", /* PTL1_BAD_ECC */ "non-kernel context in sys/priv_trap() below or", /* PTL1_BAD_CTX */ + "error raising a TSB exception", /* PTL1_BAD_RAISE_TSBEXCP */ + "missing shared TSB" /* PTL1_NO_SCDTSB8K */ }; uint_t reason = pstate->ptl1_regs.ptl1_g1; diff --git a/usr/src/uts/sun4u/sys/machparam.h b/usr/src/uts/sun4u/sys/machparam.h index c53632a5eb..df9b11b794 100644 --- a/usr/src/uts/sun4u/sys/machparam.h +++ b/usr/src/uts/sun4u/sys/machparam.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -325,6 +325,7 @@ extern "C" { #define PTL1_BAD_ECC 13 #define PTL1_BAD_CTX 14 #define PTL1_BAD_RAISE_TSBEXCP 20 +#define PTL1_NO_SCDTSB8K 21 /* * Defines used for ptl1 related data structs. diff --git a/usr/src/uts/sun4u/sys/mmu.h b/usr/src/uts/sun4u/sys/mmu.h index 8f0f8eb214..98db90182e 100644 --- a/usr/src/uts/sun4u/sys/mmu.h +++ b/usr/src/uts/sun4u/sys/mmu.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -219,6 +219,17 @@ extern "C" { #define CTXREG_NEXT_SHIFT 58 /* + * SPARC64-VII MMU SHARED CONTEXT register Layout + * + * +-----+----+-----+--------------------+-----+----+----+-------------------+ + * | --- | IV | -- | Ishared ctx[44:32] | --- | DV | -- | Dshared ctx[12:0] | + * +-----+----+-----+--------------------+-----+----+----+-------------------+ + * 63 48 47 46 45 44 32 31 16 15 14 13 12 0 + */ +#define SHCTXREG_VALID_BIT 0x8000 +#define SHCTXREG_CTX_LSHIFT 51 + +/* * The kernel always runs in KCONTEXT, and no user mappings * are ever valid in it (so any user access pagefaults). */ diff --git a/usr/src/uts/sun4u/sys/opl_olympus_regs.h b/usr/src/uts/sun4u/sys/opl_olympus_regs.h index ff482ce8a6..89d9689816 100644 --- a/usr/src/uts/sun4u/sys/opl_olympus_regs.h +++ b/usr/src/uts/sun4u/sys/opl_olympus_regs.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -213,7 +213,6 @@ extern "C" { #define ASI_EIDR 0x6E /* Urgent errors */ #define ASI_CACHE_INV 0x74 /* Cache invalidation */ #define ASI_ERR_INJCT 0x76 /* Error injection */ - /* * Address of ASI scratch register. ASI 0x4F */ @@ -222,9 +221,9 @@ extern "C" { #define OPL_SCRATCHPAD_SAVE_AG3 0x10 /* used for saving global registers */ #define OPL_SCRATCHPAD_ERRLOG 0x18 /* keeps EIDR, log's PA & err counter */ #define OPL_SCRATCHPAD_UTSBREG4 0x20 -#define OPL_SCRATCHPAD_UNUSED5 0x28 -#define OPL_SCRATCHPAD_UNUSED6 0x30 -#define OPL_SCRATCHPAD_UNUSED7 0x38 +#define OPL_SCRATCHPAD_UTSBREG5 0x28 +#define OPL_SCRATCHPAD_UTSBREG6 0x30 +#define OPL_SCRATCHPAD_UNUSED7 0x38 /* * Error log scratchpad register format. diff --git a/usr/src/uts/sun4u/vm/mach_sfmmu.h b/usr/src/uts/sun4u/vm/mach_sfmmu.h index 3c5e43f24b..ced9a5729b 100644 --- a/usr/src/uts/sun4u/vm/mach_sfmmu.h +++ b/usr/src/uts/sun4u/vm/mach_sfmmu.h @@ -40,6 +40,7 @@ #include <sys/cheetahregs.h> #include <sys/spitregs.h> #include <sys/opl_olympus_regs.h> +#include <sys/mmu.h> #ifdef __cplusplus extern "C" { @@ -51,7 +52,7 @@ extern "C" { * platform Makefile to access user TSBs via physical address but must also * designate one ASI_SCRATCHPAD register to hold the second user TSB. To * designate the user TSB scratchpad register, platforms must provide a - * definition for SCRATCHPAD_UTSBREG below. + * definition for SCRATCHPAD_UTSBREG2 below. * * Platforms that use UTSB_PHYS do not allocate 2 locked TLB entries to access * the user TSBs. @@ -59,10 +60,12 @@ extern "C" { #if defined(UTSB_PHYS) #if defined(_OPL) -#define SCRATCHPAD_UTSBREG OPL_SCRATCHPAD_UTSBREG4 +#define SCRATCHPAD_UTSBREG2 OPL_SCRATCHPAD_UTSBREG4 /* 4M-256M pages */ +#define SCRATCHPAD_UTSBREG3 OPL_SCRATCHPAD_UTSBREG5 /* 8K-512K pages */ +#define SCRATCHPAD_UTSBREG4 OPL_SCRATCHPAD_UTSBREG6 /* 4M-256M pages */ #else -#error "Compiling UTSB_PHYS but no SCRATCHPAD_UTSBREG specified" -#endif +#error "Compiling UTSB_PHYS but no SCRATCHPAD_UTSBREG2 specified" +#endif /* _OPL */ #endif /* UTSB_PHYS */ @@ -70,17 +73,45 @@ extern "C" { #ifdef _ASM /* - * This macro is used to set private secondary context register in + * This macro is used to set private/shared secondary context register in * sfmmu_alloc_ctx(). + * if is_shctx = 0 then we set the SCONTEXT to cnum and invalidate the + * SHARED_CONTEXT register. If is_shctx = 1 then only the SHARED_CONTEXT + * register is set. + * (See additional comments in sfmmu_alloc_ctx) * Input: - * cnum : cnum - * arg2 : unused - */ -#define SET_SECCTX(cnum, arg2, tmp1, tmp2) \ - mov MMU_SCONTEXT, tmp1; \ - sethi %hi(FLUSH_ADDR), tmp2; \ - stxa cnum, [tmp1]ASI_MMU_CTX; \ - flush tmp2 + * cnum = cnum + * is_shctx = sfmmu private/shared flag (0: private, 1: shared) + * tmp1 : %o4 scratch + * tmp2 : %o5 scratch + * label: used as local branch targets + */ +#define SET_SECCTX(cnum, is_shctx, tmp1, tmp2, label) \ + /* BEGIN CSTYLED */ \ + brnz,pn is_shctx, label/**/1 ;\ + sethi %hi(FLUSH_ADDR), tmp2 ;\ + mov MMU_SCONTEXT, tmp1 ;\ + stxa cnum, [tmp1]ASI_MMU_CTX ;\ + flush tmp2 ;\ + sethi %hi(shctx_on), tmp1 ;\ + ld [tmp1 + %lo(shctx_on)], tmp1 ;\ + brz,pt tmp1, label/**/3 ;\ + mov %g0, cnum ;\ + ba,pt %xcc, label/**/2 ;\ +label/**/1: ;\ + set SHCTXREG_VALID_BIT, tmp1 ;\ + sllx cnum, CTXREG_CTX_SHIFT, cnum ;\ + srlx cnum, CTXREG_CTX_SHIFT, cnum ;\ + or cnum, tmp1, cnum ;\ + mov cnum, tmp1 ;\ + sllx cnum, 32, cnum ;\ + or cnum, tmp1, cnum ;\ +label/**/2: ;\ + mov MMU_SHARED_CONTEXT, tmp1 ;\ + stxa cnum, [tmp1]ASI_MMU_CTX ;\ + flush tmp2 ;\ +label/**/3: + /* END CSTYLED */ /* * This macro is used in the MMU code to check if TL should be lowered from @@ -94,7 +125,7 @@ extern "C" { or scr2, %lo(KERNELBASE), scr2; \ cmp scr1, scr2; \ bgeu %xcc, 9f; \ - nop; \ + nop; \ ba label; \ wrpr %g0, 1, %tl; \ 9: @@ -537,60 +568,9 @@ label/**/_get_2nd_tsb_base: ;\ /* tmp1 = TSB size code */ \ GET_TSBE_POINTER(MMU_PAGESHIFT4M, tsbe_ptr, tagacc, tmp1, tmp2) -#endif /* UTSB_PHYS */ - - -#ifdef UTSB_PHYS - -/* - * Synthesize a TSB base register contents for a process. - * - * In: - * tsbinfo = TSB info pointer (ro) - * tsbreg, tmp1 = scratch registers - * Out: - * tsbreg = value to program into TSB base register - */ - -#define MAKE_UTSBREG_PHYS(tsbinfo, tsbreg, tmp1) \ - ldx [tsbinfo + TSBINFO_PADDR], tsbreg; \ - lduh [tsbinfo + TSBINFO_SZCODE], tmp1; \ - and tmp1, TSB_SOFTSZ_MASK, tmp1; \ - or tsbreg, tmp1, tsbreg; \ - -/* - * Load TSB base register into a dedicated scratchpad register. - * This register contains utsb_pabase in bits 63:13, and TSB size - * code in bits 2:0. - * - * In: - * tsbreg = value to load (ro) - * regnum = constant or register - * tmp1 = scratch register - * Out: - * Specified scratchpad register updated - * - * Note: If this is enabled on Panther, a membar #Sync is required - * following an ASI store to the scratchpad registers. - */ - -#define SET_UTSBREG(regnum, tsbreg, tmp1) \ - mov regnum, tmp1; \ - stxa tsbreg, [tmp1]ASI_SCRATCHPAD; /* save tsbreg */ \ -/* - * Get TSB base register from the scratchpad - * - * In: - * regnum = constant or register - * tsbreg = scratch - * Out: - * tsbreg = tsbreg from the specified scratchpad register - */ +#else /* !UTSB_PHYS */ -#define GET_UTSBREG(regnum, tsbreg) \ - mov regnum, tsbreg; \ - ldxa [tsbreg]ASI_SCRATCHPAD, tsbreg /* * Determine the pointer of the entry in the first TSB to probe given @@ -610,55 +590,7 @@ label/**/_get_2nd_tsb_base: ;\ #define GET_1ST_TSBE_PTR(tagacc, tsbe_ptr, tmp1, tmp2) -/* - * Get the location in the 2nd TSB of the tsbe for this fault. - * Assumes that the second TSB only contains 4M mappings. - * - * In: - * tagacc = tag access register (not clobbered) - * tsbe = 2nd TSB base register - * tmp1, tmp2 = scratch registers - * Out: - * tsbe = pointer to the tsbe in the 2nd TSB - */ - -#define GET_2ND_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ - and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ - andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ - mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ - sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ - sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ - srlx tagacc, MMU_PAGESHIFT4M, tmp2; \ - and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ - sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ - add tsbe, tmp1, tsbe /* add entry offset to TSB base */ - -/* - * Read the 2nd TSB base register. This is not done in GET_2ND_TSBE_PTR as - * an optimization since the TLB miss trap handler entries have potentially - * already loaded the 2nd TSB base reg when we invoke GET_2ND_TSBE_PTR. - * - * Out: - * tsbreg = contents of the 2nd TSB base register - */ -#define GET_2ND_TSBREG(tsbreg) \ - GET_UTSBREG(SCRATCHPAD_UTSBREG, tsbreg); - -/* - * Load the 2nd TSB base into a dedicated scratchpad register which - * is used as a pseudo TSB base register. - * - * In: - * tsbreg = value to load (ro) - * regnum = constant or register - * tmp1 = scratch register - * Out: - * Specified scratchpad register updated - */ -#define LOAD_2ND_TSBREG(tsbreg, tmp1) \ - SET_UTSBREG(SCRATCHPAD_UTSBREG, tsbreg, tmp1); - -#endif /* UTSB_PHYS */ +#endif /* !UTSB_PHYS */ /* @@ -682,135 +614,180 @@ label/**/_get_2nd_tsb_base: ;\ #else #define UTSB_PROBE_ASI ASI_NQUAD_LD #endif - +#define PROBE_TSB(tsbe_ptr, tag, tsbtag, label) \ + /* BEGIN CSTYLED */ \ + ldda [tsbe_ptr]UTSB_PROBE_ASI, tsbtag ;\ + cmp tsbtag, tag /* compare tag w/ TSB */ ;\ + bne,pn %xcc, label/**/1 /* branch if !match */ ;\ + nop \ + /* END CSTYLED */ /* - * Will probe the first TSB, and if it finds a match, will insert it - * into the TLB and retry. + * Probe a TSB. If miss continue from the end of the macro for most probes + * except jump to TSB miss for 3rd ITSB probe. If hit retry faulted + * instruction for DTSB probes. For ITSB probes in case of TSB hit check + * execute bit and branch to exec_fault if the bit is not set otherwise retry + * faulted instruction. Do ITLB synthesis in case of hit in second ITSB if + * synthesis bit is set. * - * tsbe_ptr = precomputed first TSB entry pointer (in, ro) + * tsbe_ptr = precomputed TSB entry pointer (in, ro) * vpg_4m = 4M virtual page number for tag matching (in, ro) * label = where to branch to if this is a miss (text) - * %asi = atomic ASI to use for the TSB access * * For trapstat, we have to explicily use these registers. * g4 = location tag will be retrieved into from TSB (out) * g5 = location data(tte) will be retrieved into from TSB (out) + * + * In case of first tsb probe tsbe_ptr is %g1. For other tsb probes + * move tsbe_ptr into %g1 in case of hit for traptrace. + * + * If the probe fails and we continue from call site %g4-%g5 are clobbered. + * 2nd ITSB probe macro will also clobber %g6 in this case. */ -#define PROBE_1ST_DTSB(tsbe_ptr, vpg_4m, label) /* g4/g5 clobbered */ \ - /* BEGIN CSTYLED */ \ - ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ - cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ - bne,pn %xcc, label/**/1 /* branch if !match */ ;\ - nop ;\ - TT_TRACE(trace_tsbhit) ;\ - DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - /* trapstat expects tte in %g5 */ ;\ - retry /* retry faulted instruction */ ;\ -label/**/1: \ +#define PROBE_1ST_DTSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label) ;\ + TT_TRACE(trace_tsbhit) ;\ + DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/1: \ /* END CSTYLED */ -/* - * Same as above, only if the TTE doesn't have the execute - * bit set, will branch to exec_fault directly. - */ -#define PROBE_1ST_ITSB(tsbe_ptr, vpg_4m, label) \ - /* BEGIN CSTYLED */ \ - ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ - cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ - bne,pn %xcc, label/**/1 /* branch if !match */ ;\ - nop ;\ - andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ - bz,pn %icc, exec_fault ;\ - nop ;\ - TT_TRACE(trace_tsbhit) ;\ - ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - retry /* retry faulted instruction */ ;\ -label/**/1: \ +#define PROBE_2ND_DTSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label) ;\ + mov tsbe_ptr, %g1 /* trace_tsbhit wants ptr in %g1 */ ;\ + TT_TRACE(trace_tsbhit) ;\ + DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/1: \ /* END CSTYLED */ -/* - * vpg_4m = 4M virtual page number for tag matching (in) - * tsbe_ptr = precomputed second TSB entry pointer (in) - * label = label to use to make branch targets unique (text) - * - * For trapstat, we have to explicity use these registers. - * g4 = tag portion of TSBE (out) - * g5 = data portion of TSBE (out) - */ -#define PROBE_2ND_DTSB(tsbe_ptr, vpg_4m, label) \ - /* BEGIN CSTYLED */ \ - ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ - /* since we are looking at 2nd tsb, if it's valid, it must be 4M */ ;\ - cmp %g4, vpg_4m ;\ - bne,pn %xcc, label/**/1 ;\ - nop ;\ - mov tsbe_ptr, %g1 /* trace_tsbhit wants ptr in %g1 */ ;\ - TT_TRACE(trace_tsbhit) ;\ - DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - /* trapstat expects tte in %g5 */ ;\ - retry /* retry faulted instruction */ ;\ -label/**/1: \ +#define PROBE_1ST_ITSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label) ;\ + andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ + bz,pn %icc, exec_fault ;\ + nop ;\ + TT_TRACE(trace_tsbhit) ;\ + ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/1: \ /* END CSTYLED */ -/* - * Macro to get SCD shared hme map on sun4v platforms - * (not applicable to sun4u platforms) - */ -#define GET_SCDSHMERMAP(tsbarea, hmeblkpa, hatid, hmemisc) +#define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ + cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ + bne,pn %xcc, label/**/2 /* branch if !match */ ;\ + or %g0, TTE4M, %g6 ;\ + andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ + bz,a,pn %icc, label/**/1 ;\ + sllx %g6, TTE_SZ_SHFT, %g6 ;\ + mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ + TT_TRACE(trace_tsbhit) ;\ + ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/1: ;\ + andcc %g5, TTE_E_SYNTH_INT, %g0 ;\ + bz,pn %icc, exec_fault ;\ + mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ + or %g5, %g6, %g5 ;\ + TT_TRACE(trace_tsbhit) ;\ + ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/2: + /* END CSTYLED */ + +#ifdef UTSB_PHYS -#ifndef TRAPTRACE /* - * Same as above, with the following additions: - * If the TTE found is not executable, branch directly - * to exec_fault after checking for ITLB synthesis. - * If a TSB miss, branch to TSB miss handler. - */ -#define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label) \ - /* BEGIN CSTYLED */ \ - ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ - cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ - bne,pn %xcc, sfmmu_tsb_miss_tt /* branch if !match */ ;\ - or %g0, TTE4M, %g6 ;\ - andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ - bz,a,pn %icc, label/**/1 ;\ - sllx %g6, TTE_SZ_SHFT, %g6 ;\ - ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - retry /* retry faulted instruction */ ;\ -label/**/1: ;\ - andcc %g5, TTE_E_SYNTH_INT, %g0 ;\ - bz,pn %icc, exec_fault ;\ - or %g5, %g6, %g5 ;\ - ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - retry /* retry faulted instruction */ \ + * Updates the context filed in the tagaccess register with the shared + * context to force the next i/DTLB_STUFF() to load this mapping into + * the TLB with the shared context. + */ +#define SET_SHCTX_TAGACC(tmp1, tmp2, asi) \ + /* BEGIN CSTYLED */ \ + mov MMU_TAG_ACCESS, tmp2 ;\ + ldxa [tmp2]asi, tmp2 /* tmp2 = VA|CTX */ ;\ + srlx tmp2, TAGACC_SHIFT, tmp2 ;\ + sllx tmp2, TAGACC_SHIFT, tmp2 /* tmp2 = VA */ ;\ + mov MMU_SHARED_CONTEXT, tmp1 /* clobber tsbe_ptr */ ;\ + ldxa [tmp1]ASI_MMU_CTX, tmp1 /* tmp2 = shctx reg */ ;\ + sllx tmp1, SHCTXREG_CTX_LSHIFT, tmp1 ;\ + srlx tmp1, SHCTXREG_CTX_LSHIFT, tmp1 /* tmp1 = SHCTX */ ;\ + or tmp1, tmp2, tmp1 /* tmp1 = VA|SHCTX */ ;\ + mov MMU_TAG_ACCESS, tmp2 ;\ + stxa tmp1, [tmp2]asi /* asi = VA|SHCTX */ + /* END CSTYLED */ + +#define PROBE_SHCTX_DTSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label) ;\ + mov tsbe_ptr, %g1 /* trace_tsbhit wants ptr in %g1 */ ;\ + TT_TRACE(trace_tsbhit) ;\ + SET_SHCTX_TAGACC(%g3, %g4, ASI_DMMU) ;\ + DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/1: \ + /* END CSTYLED */ + +#define PROBE_3RD_DTSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_SHCTX_DTSB(tsbe_ptr, vpg_4m, label) ;\ + /* END CSTYLED */ + +#define PROBE_4TH_DTSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_SHCTX_DTSB(tsbe_ptr, vpg_4m, label) ;\ /* END CSTYLED */ -#else /* TRAPTRACE */ + +#define PROBE_SHCTX_ITSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label) ;\ + andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ + bz,pn %icc, exec_fault ;\ + mov tsbe_ptr, %g1 /* for traptrace sake */ ;\ + TT_TRACE(trace_tsbhit) ;\ + SET_SHCTX_TAGACC(%g3, %g4, ASI_IMMU) ;\ + ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ + retry /* retry faulted instruction */ ;\ +label/**/1: + /* END CSTYLED */ + +#define PROBE_3RD_ITSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_SHCTX_ITSB(tsbe_ptr, vpg_4m, sfmmu_tsb_miss_tt) ;\ + /* END CSTYLED */ + +#define PROBE_4TH_ITSB(tsbe_ptr, vpg_4m, label) \ + /* BEGIN CSTYLED */ \ + PROBE_SHCTX_ITSB(tsbe_ptr, vpg_4m, label) ;\ + /* END CSTYLED */ + /* - * Same as above, with the TT_TRACE and mov tsbe_ptr, %g1 additions. - */ -#define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label) \ - /* BEGIN CSTYLED */ \ - ldda [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\ - cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ - bne,pn %xcc, sfmmu_tsb_miss_tt /* branch if !match */ ;\ - or %g0, TTE4M, %g6 ;\ - andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */ ;\ - bz,a,pn %icc, label/**/1 ;\ - sllx %g6, TTE_SZ_SHFT, %g6 ;\ - mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ - TT_TRACE(trace_tsbhit) ;\ - ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - retry /* retry faulted instruction */ ;\ -label/**/1: ;\ - andcc %g5, TTE_E_SYNTH_INT, %g0 ;\ - bz,pn %icc, exec_fault ;\ - mov tsbe_ptr, %g1 /* trap trace wants ptr in %g1 */ ;\ - or %g5, %g6, %g5 ;\ - TT_TRACE(trace_tsbhit) ;\ - ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) ;\ - retry /* retry faulted instruction */ \ + * The traptype is supplied by caller. + * + * If iTSB miss, store shctx into IMMU TAG ACCESS REG + * If dTSB miss, store shctx into DMMU TAG ACCESS REG + * Thus the [D|I]TLB_STUFF will work as expected. + */ +#define SAVE_CTX1(traptype, tmp1, tmp2, label) \ + /* BEGIN CSTYLED */ \ + cmp traptype, FAST_IMMU_MISS_TT ;\ + be,pn %icc, label/**/1 ;\ + nop ;\ + SET_SHCTX_TAGACC(tmp1, tmp2, ASI_DMMU) ;\ + membar #Sync ;\ + ba,a label/**/2 ;\ +label/**/1: ;\ + SET_SHCTX_TAGACC(tmp1, tmp2, ASI_IMMU) ;\ + sethi %hi(FLUSH_ADDR), tmp1 ;\ + flush tmp1 ;\ +label/**/2: /* END CSTYLED */ -#endif /* TRAPTRACE */ +#endif /* UTSB_PHYS */ + #endif /* _ASM */ #ifdef __cplusplus diff --git a/usr/src/uts/sun4u/vm/mach_sfmmu_asm.s b/usr/src/uts/sun4u/vm/mach_sfmmu_asm.s index a9737b13e1..43df08b89e 100644 --- a/usr/src/uts/sun4u/vm/mach_sfmmu_asm.s +++ b/usr/src/uts/sun4u/vm/mach_sfmmu_asm.s @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -96,7 +96,7 @@ sfmmu_load_mmustate(sfmmu_t *sfmmup) } #else /* lint */ - + /* * Invalidate either the context of a specific victim or any process * currently running on this CPU. @@ -107,91 +107,71 @@ sfmmu_load_mmustate(sfmmu_t *sfmmup) */ ENTRY(sfmmu_raise_tsb_exception) ! - ! if (victim == INVALID_CONTEXT) { + ! if (victim == INVALID_CONTEXT || + ! current CPU tsbmiss->usfmmup == victim sfmmup) { + ! if (shctx_on) { + ! shctx = INVALID; + ! } ! if (sec-ctx > INVALID_CONTEXT) { ! write INVALID_CONTEXT to sec-ctx ! } ! if (pri-ctx > INVALID_CONTEXT) { ! write INVALID_CONTEXT to pri-ctx ! } - ! } else if (current CPU tsbmiss->usfmmup != victim sfmmup) { - ! return - ! } else { - ! if (sec-ctx > INVALID_CONTEXT) - ! write INVALID_CONTEXT to sec-ctx - ! - ! if (pri-ctx > INVALID_CONTEXT) - ! write INVALID_CONTEXT to pri-ctx ! } - ! sethi %hi(ksfmmup), %g3 ldx [%g3 + %lo(ksfmmup)], %g3 cmp %g1, %g3 - be,a,pn %xcc, ptl1_panic /* can't invalidate kernel ctx */ + be,a,pn %xcc, ptl1_panic /* can't invalidate kernel ctx */ mov PTL1_BAD_RAISE_TSBEXCP, %g1 set INVALID_CONTEXT, %g2 - cmp %g1, INVALID_CONTEXT - bne,pt %xcc, 1f /* called from wrap_around? */ + be,pn %xcc, 0f /* called from wrap_around? */ mov MMU_SCONTEXT, %g3 + CPU_TSBMISS_AREA(%g5, %g6) /* load cpu tsbmiss area */ + ldx [%g5 + TSBMISS_UHATID], %g5 /* load usfmmup */ + cmp %g5, %g1 /* hat toBe-invalid running? */ + bne,pt %xcc, 3f + nop + +0: + sethi %hi(shctx_on), %g5 + ld [%g5 + %lo(shctx_on)], %g5 + brz %g5, 1f + mov MMU_SHARED_CONTEXT, %g5 + sethi %hi(FLUSH_ADDR), %g4 + stxa %g0, [%g5]ASI_MMU_CTX + flush %g4 + +1: ldxa [%g3]ASI_MMU_CTX, %g5 /* %g5 = pgsz | sec-ctx */ set CTXREG_CTX_MASK, %g4 and %g5, %g4, %g5 /* %g5 = sec-ctx */ cmp %g5, INVALID_CONTEXT /* kernel ctx or invald ctx? */ - ble,pn %xcc, 0f /* yes, no need to change */ - mov MMU_PCONTEXT, %g7 + ble,pn %xcc, 2f /* yes, no need to change */ + mov MMU_PCONTEXT, %g7 stxa %g2, [%g3]ASI_MMU_CTX /* set invalid ctx */ membar #Sync -0: +2: ldxa [%g7]ASI_MMU_CTX, %g3 /* get pgz | pri-ctx */ and %g3, %g4, %g5 /* %g5 = pri-ctx */ cmp %g5, INVALID_CONTEXT /* kernel ctx or invald ctx? */ - ble,pn %xcc, 2f /* yes, no need to change */ + ble,pn %xcc, 3f /* yes, no need to change */ srlx %g3, CTXREG_NEXT_SHIFT, %g3 /* %g3 = nucleus pgsz */ sllx %g3, CTXREG_NEXT_SHIFT, %g3 /* need to preserve nucleus pgsz */ or %g3, %g2, %g2 /* %g2 = nucleus pgsz | INVALID_CONTEXT */ stxa %g2, [%g7]ASI_MMU_CTX /* set pri-ctx to invalid */ - retry - -1: - /* %g3 = MMU_SCONTEXT */ - CPU_TSBMISS_AREA(%g5, %g6) /* load cpu tsbmiss area */ - ldx [%g5 + TSBMISS_UHATID], %g5 /* load usfmmup */ - - cmp %g5, %g1 /* hat toBe-invalid running? */ - bne,pt %xcc, 2f - nop - - ldxa [%g3]ASI_MMU_CTX, %g5 /* %g5 = pgsz | sec-ctx */ - set CTXREG_CTX_MASK, %g4 - and %g5, %g4, %g5 /* %g5 = sec-ctx */ - cmp %g5, INVALID_CONTEXT /* kernel or invalid ctx ? */ - ble,pn %xcc, 0f /* yes, no need to change */ - mov MMU_PCONTEXT, %g7 - - stxa %g2, [%g3]ASI_MMU_CTX /* set sec-ctx to invalid */ - membar #Sync - -0: - ldxa [%g7]ASI_MMU_CTX, %g3 /* %g3 = pgsz | pri-ctx */ - set CTXREG_CTX_MASK, %g6 - and %g3, %g6, %g4 /* %g4 = pri-ctx */ - cmp %g4, INVALID_CONTEXT /* is pri-ctx the victim? */ - ble %icc, 2f /* no, no need to change it */ - srlx %g3, CTXREG_NEXT_SHIFT, %g3 /* %g3 = nucleus pgsz */ - sllx %g3, CTXREG_NEXT_SHIFT, %g3 /* need to preserve nucleus pgsz */ - or %g3, %g2, %g2 /* %g2 = nucleus pgsz | INVALID_CONTEXT */ - stxa %g2, [%g7]ASI_MMU_CTX /* set pri-ctx to invalid */ - /* next instruction is retry so no membar sync */ -2: +3: retry SET_SIZE(sfmmu_raise_tsb_exception) + + /* * %o0 = virtual address @@ -389,16 +369,28 @@ sfmmu_load_mmustate(sfmmu_t *sfmmup) sethi %hi(FLUSH_ADDR), %o4 stxa %o0, [%o1]ASI_MMU_CTX /* set 2nd context reg. */ flush %o4 + sethi %hi(shctx_on), %g3 + ld [%g3 + %lo(shctx_on)], %g3 + brz %g3, 2f + nop + set CTXREG_CTX_MASK, %o4 + and %o0,%o4,%o1 + cmp %o1, INVALID_CONTEXT + bne,pn %icc, 2f + mov MMU_SHARED_CONTEXT, %o1 + sethi %hi(FLUSH_ADDR), %o4 + stxa %g0, [%o1]ASI_MMU_CTX /* set 2nd context reg. */ + flush %o4 /* * if the routine was entered with intr enabled, then enable intr now. * otherwise, keep intr disabled, return without enabing intr. * %g1 - old intr state */ - btst PSTATE_IE, %g1 - bnz,a,pt %icc, 2f +2: btst PSTATE_IE, %g1 + bnz,a,pt %icc, 3f wrpr %g0, %g1, %pstate /* enable interrupts */ -2: retl +3: retl nop SET_SIZE(sfmmu_setctx_sec) @@ -433,93 +425,167 @@ sfmmu_load_mmustate(sfmmu_t *sfmmup) * only be called from TL=0. * * %o0 - hat pointer + * */ ENTRY_NP(sfmmu_load_mmustate) #ifdef DEBUG - PANIC_IF_INTR_ENABLED_PSTR(msfmmu_ei_l3, %g1) + PANIC_IF_INTR_ENABLED_PSTR(msfmmu_ei_l3, %g1) #endif /* DEBUG */ - sethi %hi(ksfmmup), %o3 - ldx [%o3 + %lo(ksfmmup)], %o3 - cmp %o3, %o0 - be,pn %xcc, 3f ! if kernel as, do nothing - nop - - /* - * We need to set up the TSB base register, tsbmiss - * area, and load locked TTE(s) for the TSB. - */ - ldx [%o0 + SFMMU_TSB], %o1 ! %o1 = first tsbinfo - ldx [%o1 + TSBINFO_NEXTPTR], %g2 ! %g2 = second tsbinfo + sethi %hi(ksfmmup), %o3 + ldx [%o3 + %lo(ksfmmup)], %o3 + cmp %o3, %o0 + be,pn %xcc, 8f ! if kernel as, do nothing + nop + /* + * We need to set up the TSB base register, tsbmiss + * area, and load locked TTE(s) for the TSB. + */ + ldx [%o0 + SFMMU_TSB], %o1 ! %o1 = first tsbinfo + ldx [%o1 + TSBINFO_NEXTPTR], %g2 ! %g2 = second tsbinfo #ifdef UTSB_PHYS - /* - * UTSB_PHYS accesses user TSBs via physical addresses. The first - * TSB is in the MMU I/D TSB Base registers. The second TSB uses a - * designated ASI_SCRATCHPAD register as a pseudo TSB base register. + /* + * UTSB_PHYS accesses user TSBs via physical addresses. The first + * TSB is in the MMU I/D TSB Base registers. The 2nd, 3rd and + * 4th TSBs use designated ASI_SCRATCHPAD regs as pseudo TSB base regs. */ - MAKE_UTSBREG_PHYS(%o1, %o2, %o3) ! %o2 = first utsbreg - LOAD_TSBREG(%o2, %o3, %o4) ! write TSB base register + + /* create/set first UTSBREG actually loaded into MMU_TSB */ + MAKE_UTSBREG(%o1, %o2, %o3) ! %o2 = first utsbreg + LOAD_TSBREG(%o2, %o3, %o4) ! write TSB base register - brz,a,pt %g2, 2f - mov -1, %o2 ! use -1 if no second TSB + brz,a,pt %g2, 2f + mov -1, %o2 ! use -1 if no second TSB - MAKE_UTSBREG_PHYS(%g2, %o2, %o3) ! %o2 = second utsbreg + MAKE_UTSBREG(%g2, %o2, %o3) ! %o2 = second utsbreg 2: - LOAD_2ND_TSBREG(%o2, %o3) ! write 2nd pseudo TSB base register -#else /* UTSB_PHYS */ - brz,pt %g2, 4f - nop - /* - * We have a second TSB for this process, so we need to - * encode data for both the first and second TSB in our single - * TSB base register. See hat_sfmmu.h for details on what bits - * correspond to which TSB. - * We also need to load a locked TTE into the TLB for the second TSB - * in this case. - */ - MAKE_TSBREG_SECTSB(%o2, %o1, %g2, %o3, %o4, %g3, sfmmu_tsb_2nd) - ! %o2 = tsbreg - sethi %hi(utsb4m_dtlb_ttenum), %o3 - sethi %hi(utsb4m_vabase), %o4 - ld [%o3 + %lo(utsb4m_dtlb_ttenum)], %o3 - ldx [%o4 + %lo(utsb4m_vabase)], %o4 ! %o4 = TLB tag for sec TSB - sll %o3, DTACC_SHIFT, %o3 ! %o3 = sec TSB TLB index - RESV_OFFSET(%g2, %o4, %g3, sfmmu_tsb_2nd) ! or-in bits of TSB VA - LOAD_TSBTTE(%g2, %o3, %o4, %g3) ! load sec TSB locked TTE - sethi %hi(utsb_vabase), %g3 - ldx [%g3 + %lo(utsb_vabase)], %g3 ! %g3 = TLB tag for first TSB - ba,pt %xcc, 5f - nop + SET_UTSBREG(SCRATCHPAD_UTSBREG2, %o2, %o3) -4: sethi %hi(utsb_vabase), %g3 - ldx [%g3 + %lo(utsb_vabase)], %g3 ! %g3 = TLB tag for first TSB - MAKE_TSBREG(%o2, %o1, %g3, %o3, %o4, sfmmu_tsb_1st) ! %o2 = tsbreg + /* make 3rd and 4th TSB */ + CPU_TSBMISS_AREA(%o4, %o3) ! %o4 = tsbmiss area -5: LOAD_TSBREG(%o2, %o3, %o4) ! write TSB base register + ldx [%o0 + SFMMU_SCDP], %g2 ! %g2 = sfmmu_scd + brz,pt %g2, 3f + mov -1, %o2 ! use -1 if no third TSB - /* - * Load the TTE for the first TSB at the appropriate location in - * the TLB - */ - sethi %hi(utsb_dtlb_ttenum), %o2 - ld [%o2 + %lo(utsb_dtlb_ttenum)], %o2 - sll %o2, DTACC_SHIFT, %o2 ! %o1 = first TSB TLB index - RESV_OFFSET(%o1, %g3, %o3, sfmmu_tsb_1st) ! or-in bits of TSB VA - LOAD_TSBTTE(%o1, %o2, %g3, %o4) ! load first TSB locked TTE -#endif /* UTSB_PHYS */ + ldx [%g2 + SCD_SFMMUP], %g3 ! %g3 = scdp->scd_sfmmup + ldx [%g3 + SFMMU_TSB], %o1 ! %o1 = first scd tsbinfo + brz,pn %o1, 5f + nop ! panic if no third TSB -6: ldx [%o0 + SFMMU_ISMBLKPA], %o1 ! copy members of sfmmu - CPU_TSBMISS_AREA(%o2, %o3) ! we need to access from - stx %o1, [%o2 + TSBMISS_ISMBLKPA] ! sfmmu_tsb_miss into the - ldub [%o0 + SFMMU_TTEFLAGS], %o3 ! per-CPU tsbmiss area. - stx %o0, [%o2 + TSBMISS_UHATID] - stub %o3, [%o2 + TSBMISS_UTTEFLAGS] + /* make 3rd UTSBREG */ + MAKE_UTSBREG(%o1, %o2, %o3) ! %o2 = third utsbreg +3: + SET_UTSBREG(SCRATCHPAD_UTSBREG3, %o2, %o3) + stn %o2, [%o4 + TSBMISS_TSBSCDPTR] -3: retl + brz,pt %g2, 4f + mov -1, %o2 ! use -1 if no 3rd or 4th TSB + + ldx [%o1 + TSBINFO_NEXTPTR], %g2 ! %g2 = second scd tsbinfo + brz,pt %g2, 4f + mov -1, %o2 ! use -1 if no 4th TSB + + /* make 4th UTSBREG */ + MAKE_UTSBREG(%g2, %o2, %o3) ! %o2 = fourth utsbreg +4: + SET_UTSBREG(SCRATCHPAD_UTSBREG4, %o2, %o3) + stn %o2, [%o4 + TSBMISS_TSBSCDPTR4M] + ba,pt %icc, 6f + mov %o4, %o2 ! %o2 = tsbmiss area +5: + sethi %hi(panicstr), %g1 ! panic if no 3rd TSB + ldx [%g1 + %lo(panicstr)], %g1 + tst %g1 + + bnz,pn %xcc, 8f + nop + + sethi %hi(sfmmu_panic10), %o0 + call panic + or %o0, %lo(sfmmu_panic10), %o0 + +#else /* UTSBREG_PHYS */ + + brz,pt %g2, 4f + nop + /* + * We have a second TSB for this process, so we need to + * encode data for both the first and second TSB in our single + * TSB base register. See hat_sfmmu.h for details on what bits + * correspond to which TSB. + * We also need to load a locked TTE into the TLB for the second TSB + * in this case. + */ + MAKE_TSBREG_SECTSB(%o2, %o1, %g2, %o3, %o4, %g3, sfmmu_tsb_2nd) + ! %o2 = tsbreg + sethi %hi(utsb4m_dtlb_ttenum), %o3 + sethi %hi(utsb4m_vabase), %o4 + ld [%o3 + %lo(utsb4m_dtlb_ttenum)], %o3 + ldx [%o4 + %lo(utsb4m_vabase)], %o4 ! %o4 = TLB tag for sec TSB + sll %o3, DTACC_SHIFT, %o3 ! %o3 = sec TSB TLB index + RESV_OFFSET(%g2, %o4, %g3, sfmmu_tsb_2nd) ! or-in bits of TSB VA + LOAD_TSBTTE(%g2, %o3, %o4, %g3) ! load sec TSB locked TTE + sethi %hi(utsb_vabase), %g3 + ldx [%g3 + %lo(utsb_vabase)], %g3 ! %g3 = TLB tag for first TSB + ba,pt %xcc, 5f + nop + +4: sethi %hi(utsb_vabase), %g3 + ldx [%g3 + %lo(utsb_vabase)], %g3 ! %g3 = TLB tag for first TSB + MAKE_TSBREG(%o2, %o1, %g3, %o3, %o4, sfmmu_tsb_1st) ! %o2 = tsbreg + +5: LOAD_TSBREG(%o2, %o3, %o4) ! write TSB base register + + /* + * Load the TTE for the first TSB at the appropriate location in + * the TLB + */ + sethi %hi(utsb_dtlb_ttenum), %o2 + ld [%o2 + %lo(utsb_dtlb_ttenum)], %o2 + sll %o2, DTACC_SHIFT, %o2 ! %o1 = first TSB TLB index + RESV_OFFSET(%o1, %g3, %o3, sfmmu_tsb_1st) ! or-in bits of TSB VA + LOAD_TSBTTE(%o1, %o2, %g3, %o4) ! load first TSB locked TTE + CPU_TSBMISS_AREA(%o2, %o3) +#endif /* UTSB_PHYS */ +6: + ldx [%o0 + SFMMU_ISMBLKPA], %o1 ! copy members of sfmmu + ! we need to access from + stx %o1, [%o2 + TSBMISS_ISMBLKPA] ! sfmmu_tsb_miss into the + ldub [%o0 + SFMMU_TTEFLAGS], %o3 ! per-CPU tsbmiss area. + stx %o0, [%o2 + TSBMISS_UHATID] + stub %o3, [%o2 + TSBMISS_UTTEFLAGS] +#ifdef UTSB_PHYS + ldx [%o0 + SFMMU_SRDP], %o1 + ldub [%o0 + SFMMU_RTTEFLAGS], %o4 + stub %o4, [%o2 + TSBMISS_URTTEFLAGS] + stx %o1, [%o2 + TSBMISS_SHARED_UHATID] + brz,pn %o1, 8f ! check for sfmmu_srdp + add %o0, SFMMU_HMERMAP, %o1 + add %o2, TSBMISS_SHMERMAP, %o2 + mov SFMMU_HMERGNMAP_WORDS, %o3 + ! set tsbmiss shmermap + SET_REGION_MAP(%o1, %o2, %o3, %o4, load_shme_mmustate) + + ldx [%o0 + SFMMU_SCDP], %o4 ! %o4 = sfmmu_scd + CPU_TSBMISS_AREA(%o2, %o3) ! %o2 = tsbmiss area + mov SFMMU_HMERGNMAP_WORDS, %o3 + brnz,pt %o4, 7f ! check for sfmmu_scdp else + add %o2, TSBMISS_SCDSHMERMAP, %o2 ! zero tsbmiss scd_shmermap + ZERO_REGION_MAP(%o2, %o3, zero_scd_mmustate) + ba 8f nop - SET_SIZE(sfmmu_load_mmustate) +7: + add %o4, SCD_HMERMAP, %o1 + SET_REGION_MAP(%o1, %o2, %o3, %o4, load_scd_mmustate) +#endif /* UTSB_PHYS */ + +8: + retl + nop + SET_SIZE(sfmmu_load_mmustate) #endif /* lint */ @@ -657,6 +723,3 @@ prefetch_tsbe_write(struct tsbe *tsbep) SET_SIZE(prefetch_tsbe_write) #endif /* lint */ - -#ifndef lint -#endif /* lint */ diff --git a/usr/src/uts/sun4v/vm/mach_sfmmu.h b/usr/src/uts/sun4v/vm/mach_sfmmu.h index 06ae00fc32..8c6ccbd268 100644 --- a/usr/src/uts/sun4v/vm/mach_sfmmu.h +++ b/usr/src/uts/sun4v/vm/mach_sfmmu.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,7 +73,7 @@ struct hv_tsb_block { * cnum = cnum * is_shctx = sfmmu private/shared flag (0: private, 1: shared) */ -#define SET_SECCTX(cnum, is_shctx, tmp1, tmp2) \ +#define SET_SECCTX(cnum, is_shctx, tmp1, tmp2, label) \ mov MMU_SCONTEXT, tmp1; \ movrnz is_shctx, MMU_SCONTEXT1, tmp1; \ sethi %hi(FLUSH_ADDR), tmp2; \ @@ -376,75 +376,6 @@ label/**/1: \ or tte, TTE_HWWR_INT | TTE_REF_INT, tte; \ label/**/2: \ /* END CSTYLED */ - - -/* - * Synthesize a TSB base register contents for a process. - * - * In: - * tsbinfo = TSB info pointer (ro) - * tsbreg, tmp1 = scratch registers - * Out: - * tsbreg = value to program into TSB base register - */ - -#define MAKE_UTSBREG(tsbinfo, tsbreg, tmp1) \ - ldx [tsbinfo + TSBINFO_PADDR], tsbreg; \ - lduh [tsbinfo + TSBINFO_SZCODE], tmp1; \ - and tmp1, TSB_SOFTSZ_MASK, tmp1; \ - or tsbreg, tmp1, tsbreg; - - -/* - * Load TSB base register into a dedicated scratchpad register - * for private contexts. - * Load TSB base register to TSBMISS area for shared contexts. - * This register contains utsb_pabase in bits 63:13, and TSB size - * code in bits 2:0. - * - * For private context - * In: - * tsbreg = value to load (ro) - * regnum = constant or register - * tmp1 = scratch register - * Out: - * Specified scratchpad register updated - * - */ -#define SET_UTSBREG(regnum, tsbreg, tmp1) \ - mov regnum, tmp1; \ - stxa tsbreg, [tmp1]ASI_SCRATCHPAD /* save tsbreg */ - -/* - * Load TSB base register to TSBMISS area for shared contexts. - * This register contains utsb_pabase in bits 63:13, and TSB size - * code in bits 2:0. - * - * In: - * tsbmiss = pointer to tsbmiss area - * tsbmissoffset = offset to right tsb pointer - * tsbreg = value to load (ro) - * Out: - * Specified tsbmiss area updated - * - */ -#define SET_UTSBREG_SHCTX(tsbmiss, tsbmissoffset, tsbreg) \ - stx tsbreg, [tsbmiss + tsbmissoffset] /* save tsbreg */ - -/* - * Get TSB base register from the scratchpad for - * private contexts - * - * In: - * regnum = constant or register - * tsbreg = scratch - * Out: - * tsbreg = tsbreg from the specified scratchpad register - */ -#define GET_UTSBREG(regnum, tsbreg) \ - mov regnum, tsbreg; \ - ldxa [tsbreg]ASI_SCRATCHPAD, tsbreg - /* * Get TSB base register from the scratchpad for * shared contexts @@ -536,32 +467,6 @@ label/**/1: \ label/**/1: \ /* END CSTYLED */ - -/* - * Get the location in the 2nd TSB of the tsbe for this fault. - * Assumes that the second TSB only contains 4M mappings. - * - * In: - * tagacc = tag access register (not clobbered) - * tsbe, tmp1, tmp2 = scratch registers - * Out: - * tsbe = pointer to the tsbe in the 2nd TSB - */ - -#define GET_2ND_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ - mov SCRATCHPAD_UTSBREG2, tmp1; \ - ldxa [tmp1]ASI_SCRATCHPAD, tsbe; /* get tsbreg */ \ - and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ - andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ - mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ - sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ - sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ - srlx tagacc, MMU_PAGESHIFT4M, tmp2; \ - and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ - sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ - add tsbe, tmp1, tsbe /* add entry offset to TSB base */ - - /* * vpg_4m = 4M virtual page number for tag matching (in) * tsbe_ptr = precomputed second TSB entry pointer (in) @@ -610,105 +515,6 @@ label/**/1: \ retry /* retry faulted instruction */ \ /* END CSTYLED */ - -/* - * Get the location in the 3rd TSB of the tsbe for this fault. - * The 3rd TSB corresponds to the shared context, and is used - * for 8K - 512k pages. - * - * In: - * tagacc = tag access register (not clobbered) - * tsbe = TSB base register - * tmp1, tmp2 = scratch registers - * Out: - * tsbe = pointer to the tsbe in the 3rd TSB - */ -#define GET_3RD_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ - and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ - andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ - mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ - sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ - sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ - srlx tagacc, MMU_PAGESHIFT, tmp2; \ - and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ - sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ - add tsbe, tmp1, tsbe /* add entry offset to TSB base */ - - -/* - * Get the location in the 4th TSB of the tsbe for this fault. - * The 4th TSB is for the shared context. It is used for 4M - 256M pages. - * - * In: - * tagacc = tag access register (not clobbered) - * tsbe = TSB base register - * tmp1, tmp2 = scratch registers - * Out: - * tsbe = pointer to the tsbe in the 4th TSB - */ -#define GET_4TH_TSBE_PTR(tagacc, tsbe, tmp1, tmp2) \ - and tsbe, TSB_SOFTSZ_MASK, tmp2; /* tmp2=szc */ \ - andn tsbe, TSB_SOFTSZ_MASK, tsbe; /* tsbbase */ \ - mov TSB_ENTRIES(0), tmp1; /* nentries in TSB size 0 */ \ - sllx tmp1, tmp2, tmp1; /* tmp1 = nentries in TSB */ \ - sub tmp1, 1, tmp1; /* mask = nentries - 1 */ \ - srlx tagacc, MMU_PAGESHIFT4M, tmp2; \ - and tmp2, tmp1, tmp1; /* tsbent = virtpage & mask */ \ - sllx tmp1, TSB_ENTRY_SHIFT, tmp1; /* entry num --> ptr */ \ - add tsbe, tmp1, tsbe /* add entry offset to TSB base */ - -/* - * Copy the sfmmu_region_map or scd_region_map to the tsbmiss - * shmermap or scd_shmermap, from sfmmu_load_mmustate. - */ -#define SET_REGION_MAP(rgn_map, tsbmiss_map, cnt, tmp, label) \ - /* BEGIN CSTYLED */ \ -label: ;\ - ldx [rgn_map], tmp ;\ - dec cnt ;\ - add rgn_map, CLONGSIZE, rgn_map ;\ - stx tmp, [tsbmiss_map] ;\ - brnz,pt cnt, label ;\ - add tsbmiss_map, CLONGSIZE, tsbmiss_map \ - /* END CSTYLED */ - -/* - * If there is no scd, then zero the tsbmiss scd_shmermap, - * from sfmmu_load_mmustate. - */ -#define ZERO_REGION_MAP(tsbmiss_map, cnt, label) \ - /* BEGIN CSTYLED */ \ -label: ;\ - dec cnt ;\ - stx %g0, [tsbmiss_map] ;\ - brnz,pt cnt, label ;\ - add tsbmiss_map, CLONGSIZE, tsbmiss_map \ - /* END CSTYLED */ - -/* - * Set hmemisc to 1 if the shared hme is also part of an scd. - * In: - * tsbarea = tsbmiss area (not clobbered) - * hmeblkpa = hmeblkpa + hmentoff + SFHME_TTE (not clobbered) - * hmentoff = hmentoff + SFHME_TTE = tte offset(clobbered) - * Out: - * use_shctx = 1 if shme is in scd and 0 otherwise - */ -#define GET_SCDSHMERMAP(tsbarea, hmeblkpa, hmentoff, use_shctx) \ - /* BEGIN CSTYLED */ \ - sub hmeblkpa, hmentoff, hmentoff /* hmentofff = hmeblkpa */ ;\ - add hmentoff, HMEBLK_TAG, hmentoff ;\ - ldxa [hmentoff]ASI_MEM, hmentoff /* read 1st part of tag */ ;\ - and hmentoff, HTAG_RID_MASK, hmentoff /* mask off rid */ ;\ - and hmentoff, BT_ULMASK, use_shctx /* mask bit index */ ;\ - srlx hmentoff, BT_ULSHIFT, hmentoff /* extract word */ ;\ - sllx hmentoff, CLONGSHIFT, hmentoff /* index */ ;\ - add tsbarea, hmentoff, hmentoff /* add to tsbarea */ ;\ - ldx [hmentoff + TSBMISS_SCDSHMERMAP], hmentoff /* scdrgn */ ;\ - srlx hmentoff, use_shctx, use_shctx ;\ - and use_shctx, 0x1, use_shctx \ - /* END CSTYLED */ - /* * 1. Get ctx1. The traptype is supplied by caller. * 2. If iTSB miss, store in MMFSA_I_CTX |