diff options
| -rw-r--r-- | usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c | 36 | ||||
| -rw-r--r-- | usr/src/uts/common/vm/seg_vn.c | 4 | ||||
| -rw-r--r-- | usr/src/uts/sfmmu/ml/sfmmu_asm.s | 169 | ||||
| -rw-r--r-- | usr/src/uts/sun4/io/trapstat.c | 17 | ||||
| -rw-r--r-- | usr/src/uts/sun4u/ml/trap_table.s | 1 | ||||
| -rw-r--r-- | usr/src/uts/sun4u/sys/pte.h | 16 | ||||
| -rw-r--r-- | usr/src/uts/sun4u/vm/mach_sfmmu.h | 41 |
7 files changed, 231 insertions, 53 deletions
diff --git a/usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c b/usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c index 0e8bf6692c..70ce4a7ea5 100644 --- a/usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c +++ b/usr/src/cmd/mdb/sun4u/modules/unix/sfmmu.c @@ -593,6 +593,8 @@ tsbinfo_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { "64K", TSB64K, TSB64K }, { "512K", TSB512K, TSB512K }, { "4M", TSB4M, TSB4M }, + { "32M", TSB32M, TSB32M }, + { "256M", TSB256M, TSB256M }, { NULL, 0, 0 } }; @@ -682,15 +684,15 @@ tsbinfo_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf( "TSB @ %lx (%d entries)\n" "%-?s %-17s %s\n" - "%<u>%-?s %1s %1s %-11s %1s %1s %1s " - "%1s %1s %2s %8s %1s %1s %1s %1s %1s %1s " - "%1s %1s %1s %1s %1s%</u>\n", - tsbinfo.tsb_va, entries, - "", "TAG", "TTE", - "ADDR", "I", "L", "VA 63:22", "V", - "S", "N", "I", "H", "LC", "PA 42:13", "R", - "W", "N", "X", "L", "P", "V", "E", "P", - "W", "G"); + "%<u>%-?s %1s %1s %-11s " + "%1s %1s %1s %1s %1s %1s %8s " + "%1s %1s %1s %1s %1s %1s %1s " + "%1s %1s %1s %1s %1s %1s%</u>\n", + tsbinfo.tsb_va, entries, "", "TAG", "TTE", + "ADDR", "I", "L", "VA 63:22", + "V", "S", "N", "I", "H", "S", "PA 42:13", + "N", "U", "R", "W", "E", "X", "L", + "P", "V", "E", "P", "W", "G"); tsbend = tsbp + entries; for (tsbstart = tsbp; tsbp < tsbend; tsbp++) { @@ -703,9 +705,9 @@ tsbinfo_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) tsbp->tte_tag.tag_valo); pa = (tsbp->tte_data.tte_pahi << 19) + tsbp->tte_data.tte_palo; - mdb_printf("%0?lx %-1u %-1u " - "%011lx %1u %-1u %-1u %-1u %-1u " - "%-2u %08x %1u %1u %1u %1u %1u " + mdb_printf("%0?lx %-1u %-1u %011lx " + "%1u %-1u %-1u %-1u %-1u %1u %08x " + "%1u %1u %1u %1u %1u %1u %1u " "%1u %1u %1u %1u %1u %1u\n", tsbinfo.tsb_va + (tsbp - tsbstart) * sizeof (struct tsbe), @@ -719,12 +721,18 @@ tsbinfo_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) #ifdef sun4v 0, #else - tsbp->tte_data.tte_lckcnt, + tsbp->tte_data.tte_size2, #endif pa, + tsbp->tte_data.tte_no_sync, + tsbp->tte_data.tte_suspend, tsbp->tte_data.tte_ref, tsbp->tte_data.tte_wr_perm, - tsbp->tte_data.tte_no_sync, +#ifdef sun4v + 0, +#else + tsbp->tte_data.tte_exec_synth, +#endif tsbp->tte_data.tte_exec_perm, tsbp->tte_data.tte_lock, tsbp->tte_data.tte_cp, diff --git a/usr/src/uts/common/vm/seg_vn.c b/usr/src/uts/common/vm/seg_vn.c index 5830c81737..33ad8efa5f 100644 --- a/usr/src/uts/common/vm/seg_vn.c +++ b/usr/src/uts/common/vm/seg_vn.c @@ -3374,13 +3374,13 @@ segvn_fault_vnodepages(struct hat *hat, struct seg *seg, caddr_t lpgaddr, } if (btopr(va.va_size) >= btopr(off + pgsz)) { SEGVN_VMSTAT_FLTVNPAGES(21); - err = FC_MAKE_ERR(EIO); + err = FC_MAKE_ERR(ierr); goto out; } if (btopr(va.va_size) < btopr(off + (eaddr - a))) { SEGVN_VMSTAT_FLTVNPAGES(22); - err = FC_MAKE_ERR(EIO); + err = FC_MAKE_ERR(ierr); goto out; } if (brkcow || type == F_SOFTLOCK) { diff --git a/usr/src/uts/sfmmu/ml/sfmmu_asm.s b/usr/src/uts/sfmmu/ml/sfmmu_asm.s index d498188077..575464c8b5 100644 --- a/usr/src/uts/sfmmu/ml/sfmmu_asm.s +++ b/usr/src/uts/sfmmu/ml/sfmmu_asm.s @@ -279,6 +279,83 @@ label: TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget, tmp1) ;\ label: +/* + * Load a 32M/256M Panther TSB entry into the TSB at TL > 0, + * for ITLB synthesis. + * + * tsbep = pointer to the TSBE to load as va (ro) + * tte = 4M pfn offset (in), value of the TTE retrieved and loaded (out) + * with exec_perm turned off and exec_synth turned on + * tagtarget = tag target register. To get TSBE tag to load, + * we need to mask off the context and leave only the va (clobbered) + * ttepa = pointer to the TTE to retrieve/load as pa (ro) + * tmp1, tmp2 = scratch registers + * label = label to use for branch (text) + * %asi = ASI to use for TSB access + */ + +#define TSB_UPDATE_TL_PN(tsbep, tte, tagtarget, ttepa, tmp1, tmp2, label) \ + TSB_LOCK_ENTRY(tsbep, tmp1, tmp2, label) ;\ + /* ;\ + * I don't need to update the TSB then check for the valid tte. ;\ + * TSB invalidate will spin till the entry is unlocked. Note, ;\ + * we always invalidate the hash table before we unload the TSB.;\ + * Or in 4M pfn offset to TTE and set the exec_perm bit to 0 ;\ + * and exec_synth bit to 1. ;\ + */ ;\ + sllx tagtarget, TTARGET_VA_SHIFT, tagtarget ;\ + mov tte, tmp1 ;\ + ldxa [ttepa]ASI_MEM, tte ;\ + srlx tagtarget, TTARGET_VA_SHIFT, tagtarget ;\ + sethi %hi(TSBTAG_INVALID), tmp2 ;\ + brgez,a,pn tte, label/**/f ;\ + sta tmp2, [tsbep + TSBE_TAG]%asi /* unlock */ ;\ + or tte, tmp1, tte ;\ + andn tte, TTE_EXECPRM_INT, tte ;\ + or tte, TTE_E_SYNTH_INT, tte ;\ + TSB_INSERT_UNLOCK_ENTRY(tsbep, tte, tagtarget, tmp1) ;\ +label: + +/* + * Build a 4M pfn offset for a Panther 32M/256M page, for ITLB synthesis. + * + * tte = value of the TTE, used to get tte_size bits (ro) + * tagaccess = tag access register, used to get 4M pfn bits (ro) + * pfn = 4M pfn bits shifted to offset for tte (out) + * tmp1 = scratch register + * label = label to use for branch (text) + */ + +#define GET_4M_PFN_OFF(tte, tagaccess, pfn, tmp, label) \ + /* ;\ + * Get 4M bits from tagaccess for 32M, 256M pagesizes. ;\ + * Return them, shifted, in pfn. ;\ + */ ;\ + srlx tagaccess, MMU_PAGESHIFT4M, tagaccess ;\ + srlx tte, TTE_SZ_SHFT, tmp /* isolate the */ ;\ + andcc tmp, TTE_SZ_BITS, %g0 /* tte_size bits */ ;\ + bz,a,pt %icc, label/**/f /* if 0, is */ ;\ + and tagaccess, 0x7, tagaccess /* 32M page size */ ;\ + and tagaccess, 0x3f, tagaccess /* else 256M page size */ ;\ +label: ;\ + sllx tagaccess, MMU_PAGESHIFT4M, pfn + +/* + * Add 4M TTE size code to a tte for a Panther 32M/256M page, + * for ITLB synthesis. + * + * tte = value of the TTE, used to get tte_size bits (rw) + * tmp1 = scratch register + */ + +#define SET_TTE4M_PN(tte, tmp) \ + /* ;\ + * Set 4M pagesize tte bits. ;\ + */ ;\ + set TTE4M, tmp ;\ + sllx tmp, TTE_SZ_SHFT, tmp ;\ + or tte, tmp, tte + #endif /* UTSB_PHYS */ /* @@ -2366,7 +2443,7 @@ dktsb4m_kpmcheck: 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) + PROBE_2ND_ITSB(%g3, %g7, isynth) /* NOT REACHED */ #endif /* sun4v */ @@ -2725,8 +2802,8 @@ tsb_user: be,pn %icc, tsb_user4m srlx %g3, TTE_SZ2_SHFT, %g7 andcc %g7, TTE_SZ2_BITS, %g7 ! check 32/256MB - bnz,a,pn %icc, tsb_user4m - nop + bnz,a,pn %icc, tsb_user_pn_synth + cmp %g5, FAST_IMMU_MISS_TT #endif tsb_user8k: @@ -2758,33 +2835,89 @@ tsb_user8k: tsb_user4m: ldn [%g6 + TSBMISS_TSBPTR4M], %g1 /* g1 = tsbp */ +4: brz,pn %g1, 5f /* Check to see if we have 2nd TSB programmed */ nop #ifndef sun4v - mov ASI_N, %g7 ! user TSBs always accessed by VA - mov %g7, %asi + mov ASI_N, %g7 ! user TSBs always accessed by VA + mov %g7, %asi #endif - TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, 6) + TSB_UPDATE_TL(%g1, %g3, %g2, %g4, %g7, %g6, 6) 5: #ifdef sun4v - cmp %g5, T_INSTR_MMU_MISS - be,a,pn %xcc, 9f - mov %g3, %g5 + cmp %g5, T_INSTR_MMU_MISS + be,a,pn %xcc, 9f + mov %g3, %g5 #endif /* sun4v */ - cmp %g5, FAST_IMMU_MISS_TT - be,pn %xcc, 9f - mov %g3, %g5 + cmp %g5, FAST_IMMU_MISS_TT + be,pn %xcc, 9f + mov %g3, %g5 - DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) - ! trapstat wants TTE in %g5 - retry + DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) + ! trapstat wants TTE in %g5 + retry 9: - ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) - ! trapstat wants TTE in %g5 - retry + ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) + ! trapstat wants TTE in %g5 + retry + +#ifndef sun4v + /* + * Panther ITLB synthesis. + * The Panther 32M and 256M ITLB code simulates these two large page + * sizes with 4M pages, to provide support for programs, for example + * Java, that may copy instructions into a 32M or 256M data page and + * then execute them. The code below generates the 4M pfn bits and + * saves them in the modified 32M/256M ttes in the TSB. If the tte is + * stored in the DTLB to map a 32M/256M page, the 4M pfn offset bits + * are ignored by the hardware. + * + * Now, load into TSB/TLB. At this point: + * g2 = tagtarget + * g3 = tte + * g4 = patte + * g5 = tt + * g6 = tsbmiss area + */ +tsb_user_pn_synth: + 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 */ + ldn [%g6 + TSBMISS_TSBPTR4M], %g1 /* g1 = tsbp */ + brz,a,pn %g1, 5f /* no 2nd tsb */ + mov %g3, %g5 + + mov MMU_TAG_ACCESS, %g7 + ldxa [%g7]ASI_DMMU, %g6 /* get tag access va */ + GET_4M_PFN_OFF(%g3, %g6, %g5, %g7, 1) /* make 4M pfn offset */ + + mov ASI_N, %g7 /* user TSBs always accessed by VA */ + mov %g7, %asi + TSB_UPDATE_TL_PN(%g1, %g5, %g2, %g4, %g7, %g3, 4) /* update TSB */ +5: + DTLB_STUFF(%g5, %g1, %g2, %g3, %g4) + retry + +tsb_user_itlb_synth: + ldn [%g6 + TSBMISS_TSBPTR4M], %g1 /* g1 = tsbp */ + + mov MMU_TAG_ACCESS, %g7 + ldxa [%g7]ASI_IMMU, %g6 /* get tag access va */ + GET_4M_PFN_OFF(%g3, %g6, %g5, %g7, 2) /* make 4M pfn offset */ + brz,a,pn %g1, 7f /* Check to see if we have 2nd TSB programmed */ + or %g5, %g3, %g5 /* add 4M bits to TTE */ + + mov ASI_N, %g7 /* user TSBs always accessed by VA */ + mov %g7, %asi + TSB_UPDATE_TL_PN(%g1, %g5, %g2, %g4, %g7, %g3, 6) /* update TSB */ +7: + SET_TTE4M_PN(%g5, %g7) /* add TTE4M pagesize to TTE */ + ITLB_STUFF(%g5, %g1, %g2, %g3, %g4) + retry +#endif tsb_kernel: ! no 32M or 256M support #ifdef sun4v diff --git a/usr/src/uts/sun4/io/trapstat.c b/usr/src/uts/sun4/io/trapstat.c index 86665e7a25..0d3d8bb117 100644 --- a/usr/src/uts/sun4/io/trapstat.c +++ b/usr/src/uts/sun4/io/trapstat.c @@ -932,13 +932,13 @@ trapstat_snapshot() #ifndef sun4v #define TSTAT_RETENT_STATHI 1 #define TSTAT_RETENT_STATLO 2 -#define TSTAT_RETENT_SHIFT 8 -#define TSTAT_RETENT_COUNT_LD 10 -#define TSTAT_RETENT_COUNT_ST 12 -#define TSTAT_RETENT_TMPTSHI 13 -#define TSTAT_RETENT_TMPTSLO 14 -#define TSTAT_RETENT_TIME_LD 16 -#define TSTAT_RETENT_TIME_ST 18 +#define TSTAT_RETENT_SHIFT 11 +#define TSTAT_RETENT_COUNT_LD 13 +#define TSTAT_RETENT_COUNT_ST 15 +#define TSTAT_RETENT_TMPTSHI 16 +#define TSTAT_RETENT_TMPTSLO 17 +#define TSTAT_RETENT_TIME_LD 19 +#define TSTAT_RETENT_TIME_ST 21 #else /* sun4v */ #define TSTAT_RETENT_STATHI 1 #define TSTAT_RETENT_STATLO 2 @@ -979,6 +979,9 @@ trapstat_tlbretent(tstat_percpu_t *tcpu, tstat_tlbretent_t *ret, 0x8531702e, /* srlx %g5, 46, %g2 */ 0x8408a004, /* and %g2, 4, %g2 */ 0x88110002, /* or %g4, %g2, %g4 */ + 0x80a12005, /* cmp %g4, 5 */ + 0x34400002, /* bg,a,pn %icc, +8 */ + 0x88102004, /* mov 4, %g4 */ 0x89292000, /* sll %g4, shift, %g4 */ 0x82004004, /* add %g1, %g4, %g1 */ 0xc4586000, /* ldx [%g1 + tmiss_count], %g2 */ diff --git a/usr/src/uts/sun4u/ml/trap_table.s b/usr/src/uts/sun4u/ml/trap_table.s index 06eca3dc50..c3879591a1 100644 --- a/usr/src/uts/sun4u/ml/trap_table.s +++ b/usr/src/uts/sun4u/ml/trap_table.s @@ -1507,7 +1507,6 @@ etrap_table: * g3 - g4 = scratch (clobbered) * g5 = tsbe data (in) * g6 = scratch (clobbered) - * g7 = pc we jumped here from (in) */ ALTENTRY(exec_fault) TRACE_TSBHIT(0x200) diff --git a/usr/src/uts/sun4u/sys/pte.h b/usr/src/uts/sun4u/sys/pte.h index 5127bd676a..988b57fb68 100644 --- a/usr/src/uts/sun4u/sys/pte.h +++ b/usr/src/uts/sun4u/sys/pte.h @@ -54,18 +54,17 @@ typedef union { uint32_t ie:1; /* 1=invert endianness */ uint32_t hmenum:3; /* sw - # of hment in hme_blk */ - uint32_t lckcnt:6; /* sw - tte lock ref cnt */ - uint32_t rsv:1; /* */ + uint32_t rsv:7; /* former rsv:1 lockcnt:6 */ uint32_t sz2:1; /* Panther sz2[48] */ uint32_t diag:5; /* See USII Note above. */ uint32_t pahi:11; /* pa[42:32] */ uint32_t palo:19; /* pa[31:13] */ - uint32_t soft1:1; /* sw bits - unused */ + uint32_t no_sync:1; /* sw - ghost unload */ uint32_t suspend:1; /* sw bits - suspended */ uint32_t ref:1; /* sw - reference */ uint32_t wr_perm:1; /* sw - write permission */ - uint32_t no_sync:1; /* sw - ghost unload */ + uint32_t exec_synth:1; /* sw bits - itlb synthesis */ uint32_t exec_perm:1; /* sw - execute permission */ uint32_t l:1; /* 1=lock in tlb */ @@ -90,13 +89,13 @@ typedef union { #define tte_nfo tte_bit.nfo #define tte_ie tte_bit.ie /* XXX? */ #define tte_hmenum tte_bit.hmenum -#define tte_lckcnt tte_bit.lckcnt #define tte_pahi tte_bit.pahi #define tte_palo tte_bit.palo +#define tte_no_sync tte_bit.no_sync #define tte_suspend tte_bit.suspend #define tte_ref tte_bit.ref #define tte_wr_perm tte_bit.wr_perm -#define tte_no_sync tte_bit.no_sync +#define tte_exec_synth tte_bit.exec_synth #define tte_exec_perm tte_bit.exec_perm #define tte_lock tte_bit.l #define tte_cp tte_bit.cp @@ -182,10 +181,11 @@ typedef union { /* Defines for tte using intlo */ #define TTE_SUSPEND_SHIFT 0 +#define TTE_NOSYNC_INT 0x00001000 #define TTE_SUSPEND 0x00000800 #define TTE_REF_INT 0x00000400 #define TTE_WRPRM_INT 0x00000200 -#define TTE_NOSYNC_INT 0x00000100 +#define TTE_E_SYNTH_INT 0x00000100 #define TTE_EXECPRM_INT 0x00000080 #define TTE_LCK_INT 0x00000040 #define TTE_CP_INT 0x00000020 @@ -264,8 +264,10 @@ typedef union { (ttep)->tte_bit.sz = 3; \ (ttep)->tte_bit.nfo = 1; \ (ttep)->tte_bit.ie = 1; \ + (ttep)->tte_bit.sz2 = 1; \ (ttep)->tte_bit.pahi = 0x7ff; \ (ttep)->tte_bit.palo = 0x7ffff; \ + (ttep)->tte_bit.exec_perm = 1; \ (ttep)->tte_bit.l = 1; \ (ttep)->tte_bit.cp = 1; \ (ttep)->tte_bit.cv = 1; \ diff --git a/usr/src/uts/sun4u/vm/mach_sfmmu.h b/usr/src/uts/sun4u/vm/mach_sfmmu.h index 3026cfaccc..730162e8fe 100644 --- a/usr/src/uts/sun4u/vm/mach_sfmmu.h +++ b/usr/src/uts/sun4u/vm/mach_sfmmu.h @@ -590,26 +590,59 @@ label/**/_get_2nd_tsb_base: ;\ label/**/1: \ /* END CSTYLED */ - +#ifndef TRAPTRACE /* * Same as above, with the following additions: * If the TTE found is not executable, branch directly - * to exec_fault. If a TSB miss, branch to TSB miss handler. + * 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) \ +#define PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label) \ /* BEGIN CSTYLED */ \ ldda [tsbe_ptr]%asi, %g4 /* g4 = tag, g5 = data */ ;\ cmp %g4, vpg_4m /* compare tag w/ TSB */ ;\ bne,pn %xcc, sfmmu_tsb_miss_tt /* branch if !match */ ;\ - nop ;\ + 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 */ \ + /* END CSTYLED */ +#else /* TRAPTRACE */ +/* + * 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]%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 */ \ /* END CSTYLED */ +#endif /* TRAPTRACE */ #endif /* _ASM */ #ifdef __cplusplus |
