Home | History | Annotate | Download | only in vm
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * VM - Hardware Address Translation management.
     28  *
     29  * This file describes the contents of the sun reference mmu (sfmmu)
     30  * specific hat data structures and the sfmmu specific hat procedures.
     31  * The machine independent interface is described in <vm/hat.h>.
     32  */
     33 
     34 #ifndef _VM_MACH_SFMMU_H
     35 #define	_VM_MACH_SFMMU_H
     36 
     37 #include <sys/x_call.h>
     38 #include <sys/cheetahregs.h>
     39 #include <sys/spitregs.h>
     40 #include <sys/opl_olympus_regs.h>
     41 #include <sys/mmu.h>
     42 
     43 #ifdef	__cplusplus
     44 extern "C" {
     45 #endif
     46 
     47 /*
     48  * On sun4u platforms, user TSBs are accessed via virtual address by default.
     49  * Platforms that support ASI_SCRATCHPAD registers can define UTSB_PHYS in the
     50  * platform Makefile to access user TSBs via physical address but must also
     51  * designate one ASI_SCRATCHPAD register to hold the second user TSB.  To
     52  * designate the user TSB scratchpad register, platforms must provide a
     53  * definition for SCRATCHPAD_UTSBREG2 below.
     54  *
     55  * Platforms that use UTSB_PHYS do not allocate 2 locked TLB entries to access
     56  * the user TSBs.
     57  */
     58 #if defined(UTSB_PHYS)
     59 
     60 #if defined(_OPL)
     61 #define	SCRATCHPAD_UTSBREG2	OPL_SCRATCHPAD_UTSBREG4 /* 4M-256M pages */
     62 #define	SCRATCHPAD_UTSBREG3	OPL_SCRATCHPAD_UTSBREG5 /* 8K-512K pages */
     63 #define	SCRATCHPAD_UTSBREG4	OPL_SCRATCHPAD_UTSBREG6 /* 4M-256M pages */
     64 #else
     65 #error "Compiling UTSB_PHYS but no SCRATCHPAD_UTSBREG2 specified"
     66 #endif /* _OPL */
     67 
     68 #endif /* UTSB_PHYS */
     69 
     70 
     71 #ifdef _ASM
     72 
     73 /*
     74  * This macro is used to set private/shared secondary context register in
     75  * sfmmu_alloc_ctx().
     76  * if is_shctx = 0 then we set the SCONTEXT to cnum and invalidate the
     77  * SHARED_CONTEXT register. If is_shctx = 1 then only the SHARED_CONTEXT
     78  * register is set.
     79  *  (See additional comments in sfmmu_alloc_ctx)
     80  * Input:
     81  * cnum     = cnum
     82  * is_shctx = sfmmu private/shared flag (0: private, 1: shared)
     83  * tmp1 :    %o4 scratch
     84  * tmp2 :    %o5 scratch
     85  * label: used as local branch targets
     86  */
     87 #define	SET_SECCTX(cnum, is_shctx, tmp1, tmp2, label)	   \
     88 	/* BEGIN CSTYLED */				   \
     89 	brnz,pn is_shctx, label/**/1			  ;\
     90 	  sethi   %hi(FLUSH_ADDR), tmp2			  ;\
     91 	mov     MMU_SCONTEXT, tmp1			  ;\
     92 	stxa    cnum, [tmp1]ASI_MMU_CTX			  ;\
     93 	flush   tmp2					  ;\
     94 	sethi   %hi(shctx_on), tmp1			  ;\
     95 	ld      [tmp1 + %lo(shctx_on)], tmp1		  ;\
     96 	brz,pt  tmp1, label/**/3			  ;\
     97 	mov    %g0, cnum				  ;\
     98 	ba,pt    %xcc, label/**/2			  ;\
     99 label/**/1:						  ;\
    100 	set     SHCTXREG_VALID_BIT, tmp1		  ;\
    101 	sllx    cnum, CTXREG_CTX_SHIFT, cnum		  ;\
    102 	srlx    cnum, CTXREG_CTX_SHIFT, cnum		  ;\
    103 	or      cnum, tmp1, cnum			  ;\
    104 	mov     cnum, tmp1				  ;\
    105 	sllx    cnum, 32, cnum				  ;\
    106 	or      cnum, tmp1, cnum			  ;\
    107 label/**/2:					          ;\
    108 	mov     MMU_SHARED_CONTEXT, tmp1		  ;\
    109 	stxa    cnum, [tmp1]ASI_MMU_CTX			  ;\
    110 	flush   tmp2					  ;\
    111 label/**/3:
    112 	/* END CSTYLED */
    113 
    114 /*
    115  * This macro is used in the MMU code to check if TL should be lowered from
    116  * 2 to 1 to pop trapstat's state.  See the block comment in trapstat.c
    117  * for details.
    118  */
    119 
    120 #define	TSTAT_CHECK_TL1(label, scr1, scr2)			\
    121 	rdpr	%tpc, scr1;					\
    122 	sethi	%hi(KERNELBASE), scr2;				\
    123 	or	scr2, %lo(KERNELBASE), scr2; 			\
    124 	cmp	scr1, scr2; 					\
    125 	bgeu	%xcc, 9f;					\
    126 	    nop;						\
    127 	ba	label;						\
    128 	wrpr	%g0, 1, %tl;					\
    129 9:
    130 
    131 
    132 /*
    133  * The following macros allow us to share majority of the
    134  * SFMMU code between sun4u and sun4v platforms.
    135  */
    136 
    137 #define	SETUP_TSB_ASI(qlp, tmp)					\
    138 	movrz	qlp, ASI_N, tmp;				\
    139 	movrnz	qlp, ASI_MEM, tmp;				\
    140 	mov	tmp, %asi
    141 
    142 /*
    143  * Macro to swtich to alternate global register on sun4u platforms
    144  * (not applicable to sun4v platforms)
    145  */
    146 #define	USE_ALTERNATE_GLOBALS(scr)				\
    147 	rdpr	%pstate, scr;					\
    148 	wrpr	scr, PSTATE_MG | PSTATE_AG, %pstate
    149 
    150 /*
    151  * Macro to set %gl register value on sun4v platforms
    152  * (not applicable to sun4u platforms)
    153  */
    154 #define	SET_GL_REG(val)
    155 
    156 /*
    157  * Get MMU data tag access register value
    158  *
    159  * In:
    160  *   tagacc, scr1 = scratch registers
    161  * Out:
    162  *   tagacc = MMU data tag access register value
    163  */
    164 #define	GET_MMU_D_TAGACC(tagacc, scr1)				\
    165 	mov	MMU_TAG_ACCESS, scr1;				\
    166 	ldxa	[scr1]ASI_DMMU, tagacc
    167 
    168 /*
    169  * Get MMU data tag target register
    170  *
    171  * In:
    172  *   ttarget, scr1 = scratch registers
    173  * Out:
    174  *   ttarget = MMU data tag target register value
    175  */
    176 #define	GET_MMU_D_TTARGET(ttarget, scr1)			\
    177 	ldxa	[%g0]ASI_DMMU, ttarget
    178 
    179 /*
    180  * Get MMU data/instruction tag access register values
    181  *
    182  * In:
    183  *   dtagacc, itagacc, scr1, scr2 = scratch registers
    184  * Out:
    185  *   dtagacc = MMU data tag access register value
    186  *   itagacc = MMU instruction tag access register value
    187  */
    188 #define	GET_MMU_BOTH_TAGACC(dtagacc, itagacc, scr1, scr2)	\
    189 	mov	MMU_TAG_ACCESS, scr1;				\
    190 	ldxa	[scr1]ASI_DMMU, dtagacc;			\
    191 	ldxa	[scr1]ASI_IMMU, itagacc
    192 
    193 /*
    194  * Get MMU data fault address from the tag access register
    195  *
    196  * In:
    197  *   daddr, scr1 = scratch registers
    198  * Out:
    199  *   daddr = MMU data fault address
    200  */
    201 #define	GET_MMU_D_ADDR(daddr, scr1)				\
    202 	mov	MMU_TAG_ACCESS, scr1;				\
    203 	ldxa	[scr1]ASI_DMMU, daddr;				\
    204 	set	TAGACC_CTX_MASK, scr1;				\
    205 	andn	daddr, scr1, daddr
    206 
    207 
    208 /*
    209  * Load ITLB entry
    210  *
    211  * In:
    212  *   tte = reg containing tte
    213  *   scr1, scr2, scr3, scr4 = scratch registers (not used)
    214  */
    215 #define	ITLB_STUFF(tte, scr1, scr2, scr3, scr4)			\
    216 	stxa	tte, [%g0]ASI_ITLB_IN
    217 
    218 /*
    219  * Load DTLB entry
    220  *
    221  * In:
    222  *   tte = reg containing tte
    223  *   scr1, scr2, scr3, scr4 = scratch register (not used)
    224  */
    225 #define	DTLB_STUFF(tte, scr1, scr2, scr3, scr4)			\
    226 	stxa	tte, [%g0]ASI_DTLB_IN
    227 
    228 
    229 /*
    230  * Returns PFN given the TTE and vaddr
    231  *
    232  * In:
    233  *   tte = reg containing tte
    234  *   vaddr = reg containing vaddr
    235  *   scr1, scr2, scr3 = scratch registers
    236  * Out:
    237  *   tte = PFN value
    238  */
    239 #define	TTETOPFN(tte, vaddr, label, scr1, scr2, scr3)			\
    240 	srlx	tte, TTE_SZ_SHFT, scr1;					\
    241 	and	scr1, TTE_SZ_BITS, scr1;	/* scr1 = tte_size */	\
    242 	srlx	tte, TTE_SZ2_SHFT, scr3;				\
    243 	and	scr3, TTE_SZ2_BITS, scr3;	/* scr3 = tte_size2 */	\
    244 	or	scr1, scr3, scr1;					\
    245 	sllx	scr1, 1, scr2;						\
    246 	add	scr2, scr1, scr2;		/* mulx 3 */		\
    247 	sllx	tte, TTE_PA_LSHIFT, tte;				\
    248 	add	scr2, MMU_PAGESHIFT + TTE_PA_LSHIFT, scr3;		\
    249 	/* BEGIN CSTYLED */						\
    250 	brz,pt	scr2, label/**/1;					\
    251 	  srlx	tte, scr3, tte;						\
    252 	/* END CSTYLED */						\
    253 	sllx	tte, scr2, tte;						\
    254 	set	1, scr1;						\
    255 	add	scr2, MMU_PAGESHIFT, scr3;				\
    256 	sllx	scr1, scr3, scr1;					\
    257 	sub	scr1, 1, scr1;		/* g2=TTE_PAGE_OFFSET(ttesz) */	\
    258 	and	vaddr, scr1, scr2;					\
    259 	srln	scr2, MMU_PAGESHIFT, scr2;				\
    260 	or	tte, scr2, tte;						\
    261 	/* CSTYLED */							\
    262 label/**/1:
    263 
    264 
    265 /*
    266  * TTE_SET_REF_ML is a macro that updates the reference bit if it is
    267  * not already set. Older sun4u platform use the virtual address to
    268  * flush entries from dcache, this is not available here but there are
    269  * only two positions in the 64K dcache where the cache line can reside
    270  * so we need to flush both of them.
    271  *
    272  * Parameters:
    273  * tte      = reg containing tte
    274  * ttepa    = physical pointer to tte
    275  * tsbarea  = tsb miss area
    276  * tmp1     = tmp reg
    277  * tmp2     = tmp reg
    278  * label    = temporary label
    279  */
    280 
    281 #define	TTE_SET_REF_ML(tte, ttepa, tsbarea, tmp1, tmp2, label)	\
    282 	/* BEGIN CSTYLED */						\
    283 	/* check reference bit */					\
    284 	andcc	tte, TTE_REF_INT, %g0;					\
    285 	bnz,pt	%xcc, label/**/4;	/* if ref bit set-skip ahead */	\
    286 	  nop;								\
    287 	GET_CPU_IMPL(tmp1);						\
    288 	cmp	tmp1, SPITFIRE_IMPL;					\
    289 	blt	%icc, label/**/2;	/* skip flush if FJ-OPL cpus */	\
    290 	cmp	tmp1, CHEETAH_IMPL;					\
    291 	bl,a	%icc, label/**/1;					\
    292 	/* update reference bit */					\
    293 	lduh	[tsbarea + TSBMISS_DMASK], tmp1;			\
    294 	stxa	%g0, [ttepa]ASI_DC_INVAL; /* flush line from dcache */	\
    295 	membar	#Sync;							\
    296 	ba	label/**/2;						\
    297 label/**/1:								\
    298 	and	ttepa, tmp1, tmp1;					\
    299 	stxa	%g0, [tmp1]ASI_DC_TAG; /* flush line1 from dcache */	\
    300 	or	%g0, 1, tmp2;						\
    301 	sllx	tmp2, MMU_PAGESHIFT, tmp2;				\
    302 	xor	tmp1, tmp2, tmp1;					\
    303 	stxa	%g0, [tmp1]ASI_DC_TAG; /* flush line2 from dcache */	\
    304 	membar	#Sync;							\
    305 label/**/2:								\
    306 	or	tte, TTE_REF_INT, tmp1;					\
    307 	casxa	[ttepa]ASI_MEM, tte, tmp1; 	/* update ref bit */	\
    308 	cmp	tte, tmp1;						\
    309 	bne,a,pn %xcc, label/**/2;					\
    310 	ldxa	[ttepa]ASI_MEM, tte;	/* MMU_READTTE through pa */	\
    311 	or	tte, TTE_REF_INT, tte;					\
    312 label/**/4:								\
    313 	/* END CSTYLED */
    314 
    315 
    316 /*
    317  * TTE_SET_REFMOD_ML is a macro that updates the reference and modify bits
    318  * if not already set.
    319  *
    320  * Parameters:
    321  * tte      = reg containing tte
    322  * ttepa    = physical pointer to tte
    323  * tsbarea  = tsb miss area
    324  * tmp1     = tmp reg
    325  * tmp2     = tmp reg
    326  * label    = temporary label
    327  * exitlabel = label where to jump to if write perm bit not set.
    328  */
    329 
    330 #define	TTE_SET_REFMOD_ML(tte, ttepa, tsbarea, tmp1, tmp2, label,	\
    331     exitlabel)								\
    332 	/* BEGIN CSTYLED */						\
    333 	/* check reference bit */					\
    334 	andcc	tte, TTE_WRPRM_INT, %g0;				\
    335 	bz,pn	%xcc, exitlabel;	/* exit if wr_perm not set */	\
    336 	  nop;								\
    337 	andcc	tte, TTE_HWWR_INT, %g0;					\
    338 	bnz,pn	%xcc, label/**/4;	/* nothing to do */		\
    339 	  nop;								\
    340 	GET_CPU_IMPL(tmp1);						\
    341 	cmp	tmp1, SPITFIRE_IMPL;					\
    342 	blt	%icc, label/**/2;	/* skip flush if FJ-OPL cpus */	\
    343 	cmp	tmp1, CHEETAH_IMPL;					\
    344 	bl,a	%icc, label/**/1;					\
    345 	/* update reference bit */					\
    346 	lduh	[tsbarea + TSBMISS_DMASK], tmp1;			\
    347 	stxa    %g0, [ttepa]ASI_DC_INVAL; /* flush line from dcache */ 	\
    348 	membar	#Sync;							\
    349 	ba	label/**/2;						\
    350 label/**/1:								\
    351 	and	ttepa, tmp1, tmp1;					\
    352 	stxa	%g0, [tmp1]ASI_DC_TAG; /* flush line1 from dcache */	\
    353 	or	%g0, 1, tmp2;						\
    354 	sllx	tmp2, MMU_PAGESHIFT, tmp2;				\
    355 	xor	tmp1, tmp2, tmp1;					\
    356 	stxa	%g0, [tmp1]ASI_DC_TAG; /* flush line2 from dcache */	\
    357 	membar	#Sync;							\
    358 label/**/2:								\
    359 	or	tte, TTE_HWWR_INT | TTE_REF_INT, tmp1;			\
    360 	casxa	[ttepa]ASI_MEM, tte, tmp1; /* update ref/mod bit */	\
    361 	cmp	tte, tmp1;						\
    362 	bne,a,pn %xcc, label/**/2;					\
    363 	  ldxa	[ttepa]ASI_MEM, tte;	/* MMU_READTTE through pa */	\
    364 	or	tte, TTE_HWWR_INT | TTE_REF_INT, tte;			\
    365 label/**/4:								\
    366 	/* END CSTYLED */
    367 
    368 
    369 #ifndef UTSB_PHYS
    370 
    371 /*
    372  * Synthesize TSB base register contents for a process with
    373  * a single TSB.
    374  *
    375  * We patch the virtual address mask in at runtime since the
    376  * number of significant virtual address bits in the TSB VA
    377  * can vary depending upon the TSB slab size being used on the
    378  * machine.
    379  *
    380  * In:
    381  *   tsbinfo = TSB info pointer (ro)
    382  *   vabase = value of utsb_vabase (ro)
    383  * Out:
    384  *   tsbreg = value to program into TSB base register
    385  */
    386 
    387 #define	MAKE_TSBREG(tsbreg, tsbinfo, vabase, tmp1, tmp2, label)		\
    388 	/* BEGIN CSTYLED */						\
    389 	ldx	[tsbinfo + TSBINFO_VADDR], tmp1;			\
    390 	.global	label/**/_tsbreg_vamask					;\
    391 label/**/_tsbreg_vamask:						\
    392 	or	%g0, RUNTIME_PATCH, tsbreg;				\
    393 	lduh	[tsbinfo + TSBINFO_SZCODE], tmp2;			\
    394 	sllx	tsbreg, TSBREG_VAMASK_SHIFT, tsbreg;			\
    395 	or	vabase, tmp2, tmp2;					\
    396 	and	tmp1, tsbreg, tsbreg;					\
    397 	or	tsbreg, tmp2, tsbreg;					\
    398 	/* END CSTYLED */
    399 
    400 
    401 /*
    402  * Synthesize TSB base register contents for a process with
    403  * two TSBs.  See hat_sfmmu.h for the layout of the TSB base
    404  * register in this case.
    405  *
    406  * In:
    407  *   tsb1 = pointer to first TSB info (ro)
    408  *   tsb2 = pointer to second TSB info (ro)
    409  * Out:
    410  *   tsbreg = value to program into TSB base register
    411  */
    412 #define	MAKE_TSBREG_SECTSB(tsbreg, tsb1, tsb2, tmp1, tmp2, tmp3, label)	\
    413 	/* BEGIN CSTYLED */						\
    414 	set	TSBREG_MSB_CONST, tmp3					;\
    415 	sllx	tmp3, TSBREG_MSB_SHIFT, tsbreg				;\
    416 	.global	label/**/_tsbreg_vamask					;\
    417 label/**/_tsbreg_vamask:						;\
    418 	or	%g0, RUNTIME_PATCH, tmp3				;\
    419 	sll	tmp3, TSBREG_VAMASK_SHIFT, tmp3				;\
    420 	ldx	[tsb1 + TSBINFO_VADDR], tmp1				;\
    421 	ldx	[tsb2 + TSBINFO_VADDR], tmp2				;\
    422 	and	tmp1, tmp3, tmp1					;\
    423 	and	tmp2, tmp3, tmp2					;\
    424 	sllx	tmp2, TSBREG_SECTSB_MKSHIFT, tmp2			;\
    425 	or	tmp1, tmp2, tmp3					;\
    426 	or	tsbreg, tmp3, tsbreg					;\
    427 	lduh	[tsb1 + TSBINFO_SZCODE], tmp1				;\
    428 	lduh	[tsb2 + TSBINFO_SZCODE], tmp2				;\
    429 	and	tmp1, TSB_SOFTSZ_MASK, tmp1				;\
    430 	and	tmp2, TSB_SOFTSZ_MASK, tmp2				;\
    431 	sllx	tmp2, TSBREG_SECSZ_SHIFT, tmp2				;\
    432 	or	tmp1, tmp2, tmp3					;\
    433 	or	tsbreg, tmp3, tsbreg					;\
    434 	/* END CSTYLED */
    435 
    436 
    437 /*
    438  * Load the locked TSB TLB entry.
    439  *
    440  * In:
    441  *   tsbinfo = tsb_info pointer as va (ro)
    442  *   tteidx = shifted index into TLB to load the locked entry (ro)
    443  *   va = virtual address at which to load the locked TSB entry (ro)
    444  * Out:
    445  * Scratch:
    446  *   tmp
    447  */
    448 #define	LOAD_TSBTTE(tsbinfo, tteidx, va, tmp)				\
    449 	mov	MMU_TAG_ACCESS, tmp;					\
    450 	stxa	va, [tmp]ASI_DMMU;		/* set tag access */	\
    451 	membar	#Sync;							\
    452 	ldx	[tsbinfo + TSBINFO_TTE], tmp;	/* fetch locked tte */	\
    453 	stxa	tmp, [tteidx]ASI_DTLB_ACCESS;	/* load locked tte */	\
    454 	membar	#Sync
    455 
    456 
    457 /*
    458  * In the current implementation, TSBs usually come from physically
    459  * contiguous chunks of memory up to 4MB in size, but 8K TSBs may be
    460  * allocated from 8K chunks of memory under certain conditions.  To
    461  * prevent aliasing in the virtual address cache when the TSB slab is
    462  * 8K in size we must align the reserved (TL>0) TSB virtual address to
    463  * have the same low-order bits as the kernel (TL=0) TSB virtual address,
    464  * and map 8K TSBs with an 8K TTE.  In cases where the TSB reserved VA
    465  * range is smaller than the assumed 4M we will patch the shift at
    466  * runtime; otherwise we leave it alone (which is why RUNTIME_PATCH
    467  * constant doesn't appear below).
    468  *
    469  * In:
    470  *   tsbinfo (ro)
    471  *   resva: reserved VA base for this TSB
    472  * Out:
    473  *   resva: corrected VA for this TSB
    474  */
    475 #define	RESV_OFFSET(tsbinfo, resva, tmp1, label)			\
    476 	/* BEGIN CSTYLED */						\
    477 	lduh	[tsbinfo + TSBINFO_SZCODE], tmp1			;\
    478 	brgz,pn	tmp1, label/**/9	 				;\
    479 	  nop								;\
    480 	ldx	[tsbinfo + TSBINFO_VADDR], tmp1				;\
    481 	.global	label/**/_resv_offset					;\
    482 label/**/_resv_offset:							;\
    483 	sllx	tmp1, (64 - MMU_PAGESHIFT4M), tmp1			;\
    484 	srlx	tmp1, (64 - MMU_PAGESHIFT4M), tmp1			;\
    485 	or	tmp1, resva, resva					;\
    486 label/**/9:								\
    487 	/* END CSTYLED */
    488 
    489 /*
    490  * Determine the pointer of the entry in the first TSB to probe given
    491  * the 8K TSB pointer register contents.
    492  *
    493  * In:
    494  *   tsbp8k = 8K TSB pointer register (ro)
    495  *   tmp = scratch register
    496  *   label = label for hot patching of utsb_vabase
    497  *
    498  * Out: tsbe_ptr = TSB entry address
    499  *
    500  * Note: This function is patched at runtime for performance reasons.
    501  *	 Any changes here require sfmmu_patch_utsb fixed.
    502  */
    503 
    504 #define	GET_1ST_TSBE_PTR(tsbp8k, tsbe_ptr, tmp, label)			\
    505 	/* BEGIN CSTYLED */						\
    506 label/**/_get_1st_tsbe_ptr:						;\
    507 	RUNTIME_PATCH_SETX(tsbe_ptr, tmp)				;\
    508 	/* tsbeptr = contents of utsb_vabase */				;\
    509 	/* clear upper bits leaving just bits 21:0 of TSB ptr. */	;\
    510 	sllx	tsbp8k, TSBREG_FIRTSB_SHIFT, tmp			;\
    511 	/* finish clear */						;\
    512 	srlx	tmp, TSBREG_FIRTSB_SHIFT, tmp				;\
    513 	/* or-in bits 41:22 of the VA to form the real pointer. */	;\
    514 	or	tsbe_ptr, tmp, tsbe_ptr					\
    515 	/* END CSTYLED */
    516 
    517 /*
    518  * Determine the base address of the second TSB given the 8K TSB
    519  * pointer register contents.
    520  *
    521  * In:
    522  *   tsbp8k = 8K TSB pointer register (ro)
    523  *   tmp = scratch register
    524  *   label = label for hot patching of utsb_vabase
    525  *
    526  * Out:
    527  *   tsbbase = TSB base address
    528  *
    529  * Note: This function is patched at runtime for performance reasons.
    530  *	 Any changes here require sfmmu_patch_utsb fixed.
    531  */
    532 
    533 #define	GET_2ND_TSB_BASE(tsbp8k, tsbbase, tmp, label)			\
    534 	/* BEGIN CSTYLED */						\
    535 label/**/_get_2nd_tsb_base:						;\
    536 	RUNTIME_PATCH_SETX(tsbbase, tmp)				;\
    537 	/* tsbbase = contents of utsb4m_vabase */			;\
    538 	/* clear upper bits leaving just bits 21:xx of TSB addr. */	;\
    539 	sllx	tsbp8k, TSBREG_SECTSB_LSHIFT, tmp			;\
    540 	/* clear lower bits leaving just 21:13 in 8:0 */		;\
    541 	srlx	tmp, (TSBREG_SECTSB_RSHIFT + MMU_PAGESHIFT), tmp	;\
    542 	/* adjust TSB offset to bits 21:13 */				;\
    543 	sllx	tmp, MMU_PAGESHIFT, tmp					;\
    544 	or	tsbbase, tmp, tsbbase					;\
    545 	/* END CSTYLED */
    546 
    547 /*
    548  * Determine the size code of the second TSB given the 8K TSB
    549  * pointer register contents.
    550  *
    551  * In:
    552  *   tsbp8k = 8K TSB pointer register (ro)
    553  * Out:
    554  *   size = TSB size code
    555  */
    556 
    557 #define	GET_2ND_TSB_SIZE(tsbp8k, size)					\
    558 	srlx	tsbp8k, TSBREG_SECSZ_SHIFT, size;			\
    559 	and	size, TSB_SOFTSZ_MASK, size
    560 
    561 /*
    562  * Get the location in the 2nd TSB of the tsbe for this fault.
    563  * Assumes that the second TSB only contains 4M mappings.
    564  *
    565  * In:
    566  *   tagacc = tag access register (clobbered)
    567  *   tsbp8k = contents of TSB8K pointer register (ro)
    568  *   tmp1, tmp2 = scratch registers
    569  *   label = label at which to patch in reserved TSB 4M VA range
    570  * Out:
    571  *   tsbe_ptr = pointer to the tsbe in the 2nd TSB
    572  */
    573 #define	GET_2ND_TSBE_PTR(tagacc, tsbp8k, tsbe_ptr, tmp1, tmp2, label)	\
    574 	GET_2ND_TSB_BASE(tsbp8k, tsbe_ptr, tmp2, label);		\
    575 	/* tsbe_ptr = TSB base address, tmp2 = junk */			\
    576 	GET_2ND_TSB_SIZE(tsbp8k, tmp1);					\
    577 	/* tmp1 = TSB size code */					\
    578 	GET_TSBE_POINTER(MMU_PAGESHIFT4M, tsbe_ptr, tagacc, tmp1, tmp2)
    579 
    580 
    581 #else /* !UTSB_PHYS */
    582 
    583 
    584 /*
    585  * Determine the pointer of the entry in the first TSB to probe given
    586  * the 8K TSB pointer register contents.
    587  *
    588  * In:
    589  *   tagacc = tag access register
    590  *   tsbe_ptr = 8K TSB pointer register
    591  *   tmp = scratch registers
    592  *
    593  * Out: tsbe_ptr = TSB entry address
    594  *
    595  * Note: This macro is a nop since the 8K TSB pointer register
    596  *	 is the entry pointer and does not need to be decoded.
    597  *	 It is defined to allow for code sharing with sun4v.
    598  */
    599 
    600 #define	GET_1ST_TSBE_PTR(tagacc, tsbe_ptr, tmp1, tmp2)
    601 
    602 #endif /* !UTSB_PHYS */
    603 
    604 
    605 /*
    606  * Load TSB base register.  In the single TSB case this register
    607  * contains utsb_vabase, bits 21:13 of tsbinfo->tsb_va, and the
    608  * TSB size code in bits 2:0.  See hat_sfmmu.h for the layout in
    609  * the case where we have multiple TSBs per process.
    610  *
    611  * In:
    612  *   tsbreg = value to load (ro)
    613  */
    614 #define	LOAD_TSBREG(tsbreg, tmp1, tmp2)					\
    615 	mov	MMU_TSB, tmp1;						\
    616 	sethi	%hi(FLUSH_ADDR), tmp2;					\
    617 	stxa	tsbreg, [tmp1]ASI_DMMU;		/* dtsb reg */		\
    618 	stxa	tsbreg, [tmp1]ASI_IMMU;		/* itsb reg */		\
    619 	flush	tmp2
    620 
    621 #ifdef UTSB_PHYS
    622 #define	UTSB_PROBE_ASI	ASI_QUAD_LDD_PHYS
    623 #else
    624 #define	UTSB_PROBE_ASI	ASI_NQUAD_LD
    625 #endif
    626 #define	PROBE_TSB(tsbe_ptr, tag, tsbtag, label)                            \
    627 	/* BEGIN CSTYLED */                                             \
    628         ldda    [tsbe_ptr]UTSB_PROBE_ASI, tsbtag                        ;\
    629         cmp     tsbtag, tag             /* compare tag w/ TSB */        ;\
    630         bne,pn  %xcc, label/**/1        /* branch if !match */          ;\
    631           nop                                                           \
    632 	/* END CSTYLED */
    633 /*
    634  * Probe a TSB. If miss continue from the end of the macro for most probes
    635  * except jump to TSB miss for 3rd ITSB probe. If hit retry faulted
    636  * instruction for DTSB probes. For ITSB probes in case of TSB hit check
    637  * execute bit and branch to exec_fault if the bit is not set otherwise retry
    638  * faulted instruction. Do ITLB synthesis in case of hit in second ITSB if
    639  * synthesis bit is set.
    640  *
    641  * tsbe_ptr = precomputed TSB entry pointer (in, ro)
    642  * vpg_4m = 4M virtual page number for tag matching  (in, ro)
    643  * label = where to branch to if this is a miss (text)
    644  *
    645  * For trapstat, we have to explicily use these registers.
    646  * g4 = location tag will be retrieved into from TSB (out)
    647  * g5 = location data(tte) will be retrieved into from TSB (out)
    648  *
    649  * In case of first tsb probe tsbe_ptr is %g1. For other tsb probes
    650  * move tsbe_ptr into %g1 in case of hit for traptrace.
    651  *
    652  * If the probe fails and we continue from call site %g4-%g5 are clobbered.
    653  * 2nd ITSB probe macro will also clobber %g6 in this case.
    654  */
    655 #define	PROBE_1ST_DTSB(tsbe_ptr, vpg_4m, label)                         \
    656 	/* BEGIN CSTYLED */                                             \
    657         PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label)                         ;\
    658         TT_TRACE(trace_tsbhit)                                          ;\
    659         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    660         retry                      /* retry faulted instruction */      ;\
    661 label/**/1:                                                             \
    662 	/* END CSTYLED */
    663 
    664 #define	PROBE_2ND_DTSB(tsbe_ptr, vpg_4m, label)                         \
    665 	/* BEGIN CSTYLED */                                             \
    666         PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label)                         ;\
    667         mov     tsbe_ptr, %g1       /* trace_tsbhit wants ptr in %g1 */ ;\
    668         TT_TRACE(trace_tsbhit)                                          ;\
    669         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    670         retry                      /* retry faulted instruction */      ;\
    671 label/**/1:                                                             \
    672 	/* END CSTYLED */
    673 
    674 #define	PROBE_1ST_ITSB(tsbe_ptr, vpg_4m, label)                         \
    675 	/* BEGIN CSTYLED */                                             \
    676         PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label)                         ;\
    677         andcc   %g5, TTE_EXECPRM_INT, %g0  /* check execute bit */      ;\
    678         bz,pn   %icc, exec_fault                                        ;\
    679           nop                                                           ;\
    680         TT_TRACE(trace_tsbhit)                                          ;\
    681         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    682         retry                           /* retry faulted instruction */ ;\
    683 label/**/1:                                                             \
    684 	/* END CSTYLED */
    685 
    686 #define	PROBE_2ND_ITSB(tsbe_ptr, vpg_4m, label)                         \
    687 	/* BEGIN CSTYLED */                                             \
    688         ldda    [tsbe_ptr]UTSB_PROBE_ASI, %g4 /* g4 = tag, g5 = data */ ;\
    689         cmp     %g4, vpg_4m             /* compare tag w/ TSB */        ;\
    690         bne,pn  %xcc, label/**/2        /* branch if !match */          ;\
    691           or    %g0, TTE4M, %g6                                         ;\
    692         andcc   %g5, TTE_EXECPRM_INT, %g0  /* check execute bit */      ;\
    693         bz,a,pn %icc, label/**/1                                        ;\
    694           sllx  %g6, TTE_SZ_SHFT, %g6                                   ;\
    695         mov     tsbe_ptr, %g1         /* trap trace wants ptr in %g1 */ ;\
    696         TT_TRACE(trace_tsbhit)                                          ;\
    697         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    698         retry                        /* retry faulted instruction */    ;\
    699 label/**/1:                                                             ;\
    700         andcc %g5, TTE_E_SYNTH_INT, %g0                                 ;\
    701         bz,pn   %icc, exec_fault                                        ;\
    702           mov   tsbe_ptr, %g1       /* trap trace wants ptr in %g1 */   ;\
    703         or      %g5, %g6, %g5                                           ;\
    704         TT_TRACE(trace_tsbhit)                                          ;\
    705         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    706         retry                      /* retry faulted instruction */      ;\
    707 label/**/2:
    708 	/* END CSTYLED */
    709 
    710 #ifdef UTSB_PHYS
    711 
    712 /*
    713  * Updates the context filed in the tagaccess register with the shared
    714  * context to force the next i/DTLB_STUFF() to load this mapping into
    715  * the TLB with the shared context.
    716  */
    717 #define	SET_SHCTX_TAGACC(tmp1, tmp2, asi)                               \
    718 	/* BEGIN CSTYLED */                                             \
    719         mov     MMU_TAG_ACCESS, tmp2                                    ;\
    720         ldxa    [tmp2]asi, tmp2                 /* tmp2 = VA|CTX */     ;\
    721         srlx    tmp2, TAGACC_SHIFT, tmp2                                ;\
    722         sllx    tmp2, TAGACC_SHIFT, tmp2        /* tmp2 = VA */         ;\
    723         mov     MMU_SHARED_CONTEXT, tmp1        /* clobber tsbe_ptr */  ;\
    724         ldxa    [tmp1]ASI_MMU_CTX, tmp1         /* tmp2 = shctx reg */  ;\
    725         sllx    tmp1, SHCTXREG_CTX_LSHIFT, tmp1                         ;\
    726         srlx    tmp1, SHCTXREG_CTX_LSHIFT, tmp1 /* tmp1 = SHCTX */      ;\
    727         or      tmp1, tmp2, tmp1                /* tmp1  = VA|SHCTX */  ;\
    728         mov     MMU_TAG_ACCESS, tmp2                                    ;\
    729         stxa    tmp1, [tmp2]asi                 /* asi = VA|SHCTX */
    730 	/* END CSTYLED */
    731 
    732 #define	PROBE_SHCTX_DTSB(tsbe_ptr, vpg_4m, label)                       \
    733 	/* BEGIN CSTYLED */                                             \
    734         PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label)                         ;\
    735         mov     tsbe_ptr, %g1       /* trace_tsbhit wants ptr in %g1 */ ;\
    736         TT_TRACE(trace_tsbhit)                                          ;\
    737         SET_SHCTX_TAGACC(%g3, %g4, ASI_DMMU)                            ;\
    738         DTLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    739         retry                      /* retry faulted instruction */      ;\
    740 label/**/1:                                                             \
    741 	/* END CSTYLED */
    742 
    743 #define	PROBE_3RD_DTSB(tsbe_ptr, vpg_4m, label)                         \
    744 	/* BEGIN CSTYLED */                                             \
    745         PROBE_SHCTX_DTSB(tsbe_ptr, vpg_4m, label)                  ;\
    746 	/* END CSTYLED */
    747 
    748 #define	PROBE_4TH_DTSB(tsbe_ptr, vpg_4m, label)                         \
    749 	/* BEGIN CSTYLED */                                             \
    750         PROBE_SHCTX_DTSB(tsbe_ptr, vpg_4m, label)                  ;\
    751 	/* END CSTYLED */
    752 
    753 #define	PROBE_SHCTX_ITSB(tsbe_ptr, vpg_4m, label)                       \
    754 	/* BEGIN CSTYLED */                                             \
    755         PROBE_TSB(tsbe_ptr, vpg_4m, %g4, label)                         ;\
    756         andcc   %g5, TTE_EXECPRM_INT, %g0  /* check execute bit */      ;\
    757         bz,pn %icc, exec_fault                                          ;\
    758          mov     tsbe_ptr, %g1          /* for traptrace sake */        ;\
    759         TT_TRACE(trace_tsbhit)                                          ;\
    760         SET_SHCTX_TAGACC(%g3, %g4, ASI_IMMU)                            ;\
    761         ITLB_STUFF(%g5, %g1, %g2, %g3, %g4)                             ;\
    762         retry                           /* retry faulted instruction */ ;\
    763 label/**/1:
    764 	/* END CSTYLED */
    765 
    766 #define	PROBE_3RD_ITSB(tsbe_ptr, vpg_4m, label)                         \
    767 	/* BEGIN CSTYLED */                                             \
    768         PROBE_SHCTX_ITSB(tsbe_ptr, vpg_4m, sfmmu_tsb_miss_tt)      ;\
    769 	/* END CSTYLED */
    770 
    771 #define	PROBE_4TH_ITSB(tsbe_ptr, vpg_4m, label)                         \
    772 	/* BEGIN CSTYLED */                                             \
    773         PROBE_SHCTX_ITSB(tsbe_ptr, vpg_4m, label)                  ;\
    774 	/* END CSTYLED */
    775 
    776 /*
    777  * The traptype is supplied by caller.
    778  *
    779  * If iTSB miss, store shctx into IMMU TAG ACCESS REG
    780  * If dTSB miss, store shctx into DMMU TAG ACCESS REG
    781  * Thus the [D|I]TLB_STUFF will work as expected.
    782  */
    783 #define	SAVE_CTX1(traptype, tmp1, tmp2, label)                          \
    784 	/* BEGIN CSTYLED */                                             \
    785         cmp     traptype, FAST_IMMU_MISS_TT                             ;\
    786         be,pn %icc, label/**/1                                          ;\
    787           nop                                                           ;\
    788         SET_SHCTX_TAGACC(tmp1, tmp2, ASI_DMMU)                          ;\
    789         membar  #Sync                                                   ;\
    790         ba,a    label/**/2                                              ;\
    791 label/**/1:                                                             ;\
    792         SET_SHCTX_TAGACC(tmp1, tmp2, ASI_IMMU)                          ;\
    793         sethi   %hi(FLUSH_ADDR), tmp1                                   ;\
    794         flush   tmp1                                                    ;\
    795 label/**/2:
    796 	/* END CSTYLED */
    797 
    798 #endif /* UTSB_PHYS */
    799 
    800 #endif /* _ASM */
    801 
    802 #ifdef	__cplusplus
    803 }
    804 #endif
    805 
    806 #endif	/* _VM_MACH_SFMMU_H */
    807