xref: /titanic_51/usr/src/uts/sun4/vm/vm_dep.h (revision 71b4af9b981b0fc179b6c0bab0186b84a2bc2d9c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
516eca74fSstans  * Common Development and Distribution License (the "License").
616eca74fSstans  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*b52a336eSPavel Tatashin  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * UNIX machine dependent virtual memory support.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #ifndef	_VM_DEP_H
307c478bd9Sstevel@tonic-gate #define	_VM_DEP_H
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
337c478bd9Sstevel@tonic-gate extern "C" {
347c478bd9Sstevel@tonic-gate #endif
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
377c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
387c478bd9Sstevel@tonic-gate #include <sys/memnode.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #define	GETTICK()	gettick()
4182c9d5baSVijay Balakrishna, SG-RPE 
42*b52a336eSPavel Tatashin /* tick value that should be used for random values */
43*b52a336eSPavel Tatashin extern u_longlong_t randtick(void);
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * Per page size free lists. Allocated dynamically.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate #define	MAX_MEM_TYPES	2	/* 0 = reloc, 1 = noreloc */
497c478bd9Sstevel@tonic-gate #define	MTYPE_RELOC	0
507c478bd9Sstevel@tonic-gate #define	MTYPE_NORELOC	1
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	PP_2_MTYPE(pp)	(PP_ISNORELOC(pp) ? MTYPE_NORELOC : MTYPE_RELOC)
537c478bd9Sstevel@tonic-gate 
5407ad560dSkchow #define	MTYPE_INIT(mtype, vp, vaddr, flags, pgsz)			\
557c478bd9Sstevel@tonic-gate 	mtype = (flags & PG_NORELOC) ? MTYPE_NORELOC : MTYPE_RELOC;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /* mtype init for page_get_replacement_page */
5807ad560dSkchow #define	MTYPE_PGR_INIT(mtype, flags, pp, mnode, pgcnt)			\
597c478bd9Sstevel@tonic-gate 	mtype = (flags & PG_NORELOC) ? MTYPE_NORELOC : MTYPE_RELOC;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #define	MNODETYPE_2_PFN(mnode, mtype, pfnlo, pfnhi)			\
627c478bd9Sstevel@tonic-gate 	pfnlo = mem_node_config[mnode].physbase;			\
637c478bd9Sstevel@tonic-gate 	pfnhi = mem_node_config[mnode].physmax;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
665d07b933Sdp78419  * candidate counters in vm_pagelist.c are indexed by color and range
675d07b933Sdp78419  */
685d07b933Sdp78419 #define	MAX_MNODE_MRANGES		MAX_MEM_TYPES
695d07b933Sdp78419 #define	MNODE_RANGE_CNT(mnode)		MAX_MNODE_MRANGES
705d07b933Sdp78419 #define	MNODE_MAX_MRANGE(mnode)		(MAX_MEM_TYPES - 1)
715d07b933Sdp78419 #define	MTYPE_2_MRANGE(mnode, mtype)	(mtype)
725d07b933Sdp78419 
735d07b933Sdp78419 /*
747c478bd9Sstevel@tonic-gate  * Internal PG_ flags.
757c478bd9Sstevel@tonic-gate  */
767c478bd9Sstevel@tonic-gate #define	PGI_RELOCONLY	0x10000	/* acts in the opposite sense to PG_NORELOC */
777c478bd9Sstevel@tonic-gate #define	PGI_NOCAGE	0x20000	/* indicates Cage is disabled */
787c478bd9Sstevel@tonic-gate #define	PGI_PGCPHIPRI	0x40000	/* page_get_contig_page priority allocation */
797c478bd9Sstevel@tonic-gate #define	PGI_PGCPSZC0	0x80000	/* relocate base pagesize page */
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * PGI mtype flags - should not overlap PGI flags
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate #define	PGI_MT_RANGE	0x1000000	/* mtype range */
857c478bd9Sstevel@tonic-gate #define	PGI_MT_NEXT	0x2000000	/* get next mtype */
867c478bd9Sstevel@tonic-gate 
87d94ffb28Sjmcp extern page_t ***page_freelists[MMU_PAGE_SIZES][MAX_MEM_TYPES];
887c478bd9Sstevel@tonic-gate extern page_t ***page_cachelists[MAX_MEM_TYPES];
897c478bd9Sstevel@tonic-gate 
90d94ffb28Sjmcp #define	PAGE_FREELISTS(mnode, szc, color, mtype) \
91d94ffb28Sjmcp 	(*(page_freelists[szc][mtype][mnode] + (color)))
92d94ffb28Sjmcp 
937c478bd9Sstevel@tonic-gate #define	PAGE_CACHELISTS(mnode, color, mtype) \
947c478bd9Sstevel@tonic-gate 	(*(page_cachelists[mtype][mnode] + (color)))
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * There are 'page_colors' colors/bins.  Spread them out under a
987c478bd9Sstevel@tonic-gate  * couple of locks.  There are mutexes for both the page freelist
997c478bd9Sstevel@tonic-gate  * and the page cachelist.  We want enough locks to make contention
1007c478bd9Sstevel@tonic-gate  * reasonable, but not too many -- otherwise page_freelist_lock() gets
1017c478bd9Sstevel@tonic-gate  * so expensive that it becomes the bottleneck!
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate #define	NPC_MUTEX	16
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate extern kmutex_t	*fpc_mutex[NPC_MUTEX];
1067c478bd9Sstevel@tonic-gate extern kmutex_t	*cpc_mutex[NPC_MUTEX];
1077c478bd9Sstevel@tonic-gate 
1085d07b933Sdp78419 /*
109ce8eb11aSdp78419  * Iterator provides the info needed to convert RA to PA.
110ce8eb11aSdp78419  * MEM_NODE_ITERATOR_INIT() should be called before
111ce8eb11aSdp78419  * PAGE_NEXT_PFN_FOR_COLOR() if pfn was not obtained via a previous
112ce8eb11aSdp78419  * PAGE_NEXT_PFN_FOR_COLOR() call. Iterator caches color 2 hash
113ce8eb11aSdp78419  * translations requiring initializer call if color or ceq_mask changes,
114ce8eb11aSdp78419  * even if pfn doesn't. MEM_NODE_ITERATOR_INIT() must also be called before
115ce8eb11aSdp78419  * PFN_2_COLOR() that uses a valid iterator argument.
1169853d9e8SJason Beloro  *
1179853d9e8SJason Beloro  * plat_mem_node_iterator_init() starts from last mblock in continuation
1189853d9e8SJason Beloro  * case which may be invalid because memory DR.  To detect this situation
1199853d9e8SJason Beloro  * mi_genid is checked against mpo_genid which is incremented after a
1209853d9e8SJason Beloro  * memory DR operation.  See also plat_slice_add()/plat_slice_del().
121ce8eb11aSdp78419  */
122ce8eb11aSdp78419 #ifdef	sun4v
123ce8eb11aSdp78419 
124ce8eb11aSdp78419 typedef struct mem_node_iterator {
125ce8eb11aSdp78419 	uint_t mi_mnode;		/* mnode in which to iterate */
126ce8eb11aSdp78419 	int mi_init;			/* set to 1 when first init */
1279853d9e8SJason Beloro 	int mi_genid;			/* set/checked against mpo_genid */
128ce8eb11aSdp78419 	int mi_last_mblock;		/* last mblock visited */
129ce8eb11aSdp78419 	uint_t mi_hash_ceq_mask;	/* cached copy of ceq_mask */
130ce8eb11aSdp78419 	uint_t mi_hash_color;		/* cached copy of color */
131ce8eb11aSdp78419 	uint_t mi_mnode_mask;		/* number of mask bits */
132ce8eb11aSdp78419 	uint_t mi_mnode_pfn_shift;	/* mnode position in pfn */
133ce8eb11aSdp78419 	pfn_t mi_mblock_base;		/* first valid pfn in current mblock */
134ce8eb11aSdp78419 	pfn_t mi_mblock_end;		/* last valid pfn in current mblock */
135ce8eb11aSdp78419 	pfn_t mi_ra_to_pa;		/* ra adjustment for current mblock */
136ce8eb11aSdp78419 	pfn_t mi_mnode_pfn_mask;	/* mask to obtain mnode id bits */
137ce8eb11aSdp78419 } mem_node_iterator_t;
138ce8eb11aSdp78419 
139ce8eb11aSdp78419 #define	MEM_NODE_ITERATOR_DECL(it) \
140ce8eb11aSdp78419 	mem_node_iterator_t it
141b779d3e0Sdp78419 #define	MEM_NODE_ITERATOR_INIT(pfn, mnode, szc, it) \
142b779d3e0Sdp78419 	(pfn) = plat_mem_node_iterator_init((pfn), (mnode), (szc), (it), 1)
143ce8eb11aSdp78419 
144b779d3e0Sdp78419 extern pfn_t plat_mem_node_iterator_init(pfn_t, int, uchar_t,
145ce8eb11aSdp78419     mem_node_iterator_t *, int);
146ce8eb11aSdp78419 extern pfn_t plat_rapfn_to_papfn(pfn_t);
147ce8eb11aSdp78419 extern int interleaved_mnodes;
148ce8eb11aSdp78419 
149ce8eb11aSdp78419 #else	/* sun4v */
150ce8eb11aSdp78419 
151ce8eb11aSdp78419 #define	MEM_NODE_ITERATOR_DECL(it) \
152ce8eb11aSdp78419 	void *it = NULL
153b779d3e0Sdp78419 #define	MEM_NODE_ITERATOR_INIT(pfn, mnode, szc, it)
154ce8eb11aSdp78419 
155ce8eb11aSdp78419 #endif	/* sun4v */
156ce8eb11aSdp78419 
157ce8eb11aSdp78419 /*
158ce8eb11aSdp78419  * Return the mnode limits so that hpc_counters length and base
159ce8eb11aSdp78419  * index can be determined. When interleaved_mnodes is set, we
160ce8eb11aSdp78419  * create an array only for the first mnode that exists. All other
161ce8eb11aSdp78419  * mnodes will share the array in this case.
162ce8eb11aSdp78419  * If interleaved_mnodes is not set, simply return the limits for
163ce8eb11aSdp78419  * the given mnode.
164ce8eb11aSdp78419  */
165ce8eb11aSdp78419 #define	HPM_COUNTERS_LIMITS(mnode, physbase, physmax, first)		\
166ce8eb11aSdp78419 	if (!interleaved_mnodes) {					\
167ce8eb11aSdp78419 		(physbase) = mem_node_config[(mnode)].physbase;		\
168ce8eb11aSdp78419 		(physmax) = mem_node_config[(mnode)].physmax;		\
169ce8eb11aSdp78419 		(first) = (mnode);					\
170ce8eb11aSdp78419 	} else if ((first) < 0) {					\
171ce8eb11aSdp78419 		mem_node_max_range(&(physbase), &(physmax));		\
172ce8eb11aSdp78419 		(first) = (mnode);					\
173ce8eb11aSdp78419 	}
174ce8eb11aSdp78419 
175ce8eb11aSdp78419 #define	PAGE_CTRS_WRITE_LOCK(mnode)					\
176ce8eb11aSdp78419 	if (!interleaved_mnodes) {					\
177ce8eb11aSdp78419 		rw_enter(&page_ctrs_rwlock[(mnode)], RW_WRITER);	\
178ce8eb11aSdp78419 		page_freelist_lock(mnode);				\
179ce8eb11aSdp78419 	} else {							\
180ce8eb11aSdp78419 		/* changing shared hpm_counters */			\
181ce8eb11aSdp78419 		int _i;							\
182ce8eb11aSdp78419 		for (_i = 0; _i < max_mem_nodes; _i++) {		\
183ce8eb11aSdp78419 			rw_enter(&page_ctrs_rwlock[_i], RW_WRITER);	\
184ce8eb11aSdp78419 			page_freelist_lock(_i);				\
185ce8eb11aSdp78419 		}							\
186ce8eb11aSdp78419 	}
187ce8eb11aSdp78419 
188ce8eb11aSdp78419 #define	PAGE_CTRS_WRITE_UNLOCK(mnode)					\
189ce8eb11aSdp78419 	if (!interleaved_mnodes) {					\
190ce8eb11aSdp78419 		page_freelist_unlock(mnode);				\
191ce8eb11aSdp78419 		rw_exit(&page_ctrs_rwlock[(mnode)]);			\
192ce8eb11aSdp78419 	} else {							\
193ce8eb11aSdp78419 		int _i;							\
194ce8eb11aSdp78419 		for (_i = 0; _i < max_mem_nodes; _i++) {		\
195ce8eb11aSdp78419 			page_freelist_unlock(_i);			\
196ce8eb11aSdp78419 			rw_exit(&page_ctrs_rwlock[_i]);			\
197ce8eb11aSdp78419 		}							\
198ce8eb11aSdp78419 	}
199ce8eb11aSdp78419 
200ce8eb11aSdp78419 /*
2015d07b933Sdp78419  * cpu specific color conversion functions
2025d07b933Sdp78419  */
2035d07b933Sdp78419 extern uint_t page_get_nsz_color_mask_cpu(uchar_t, uint_t);
2045d07b933Sdp78419 #pragma weak page_get_nsz_color_mask_cpu
2055d07b933Sdp78419 
2065d07b933Sdp78419 extern uint_t page_get_nsz_color_cpu(uchar_t, uint_t);
2075d07b933Sdp78419 #pragma weak page_get_nsz_color_cpu
2085d07b933Sdp78419 
2095d07b933Sdp78419 extern uint_t page_get_color_shift_cpu(uchar_t, uchar_t);
2105d07b933Sdp78419 #pragma weak page_get_color_shift_cpu
2115d07b933Sdp78419 
212ce8eb11aSdp78419 extern uint_t page_convert_color_cpu(uint_t, uchar_t, uchar_t);
213ce8eb11aSdp78419 #pragma weak page_convert_color_cpu
214ce8eb11aSdp78419 
2155d07b933Sdp78419 extern pfn_t page_next_pfn_for_color_cpu(pfn_t,
216ce8eb11aSdp78419     uchar_t, uint_t, uint_t, uint_t, void *);
2175d07b933Sdp78419 #pragma weak page_next_pfn_for_color_cpu
2185d07b933Sdp78419 
219ce8eb11aSdp78419 extern uint_t  page_pfn_2_color_cpu(pfn_t, uchar_t, void *);
2205d07b933Sdp78419 #pragma weak page_pfn_2_color_cpu
2215d07b933Sdp78419 
2225d07b933Sdp78419 #define	PAGE_GET_COLOR_SHIFT(szc, nszc)				\
2235d07b933Sdp78419 	((&page_get_color_shift_cpu != NULL) ?			\
2245d07b933Sdp78419 	    page_get_color_shift_cpu(szc, nszc) :		\
2255d07b933Sdp78419 	    (hw_page_array[(nszc)].hp_shift -			\
2265d07b933Sdp78419 		hw_page_array[(szc)].hp_shift))
2275d07b933Sdp78419 
228ce8eb11aSdp78419 #define	PAGE_CONVERT_COLOR(ncolor, szc, nszc)			\
229ce8eb11aSdp78419 	((&page_convert_color_cpu != NULL) ?			\
230ce8eb11aSdp78419 	    page_convert_color_cpu(ncolor, szc, nszc) :		\
231ce8eb11aSdp78419 	    ((ncolor) << PAGE_GET_COLOR_SHIFT((szc), (nszc))))
232ce8eb11aSdp78419 
233ce8eb11aSdp78419 #define	PFN_2_COLOR(pfn, szc, it)				\
2345d07b933Sdp78419 	((&page_pfn_2_color_cpu != NULL) ?			\
235ce8eb11aSdp78419 	    page_pfn_2_color_cpu(pfn, szc, it) :		\
2365d07b933Sdp78419 	    ((pfn & (hw_page_array[0].hp_colors - 1)) >>	\
2375d07b933Sdp78419 		(hw_page_array[szc].hp_shift -			\
2385d07b933Sdp78419 		    hw_page_array[0].hp_shift)))
2395d07b933Sdp78419 
2405d07b933Sdp78419 #define	PNUM_SIZE(szc)							\
2415d07b933Sdp78419 	(hw_page_array[(szc)].hp_pgcnt)
2425d07b933Sdp78419 #define	PNUM_SHIFT(szc)							\
2435d07b933Sdp78419 	(hw_page_array[(szc)].hp_shift - hw_page_array[0].hp_shift)
2445d07b933Sdp78419 #define	PAGE_GET_SHIFT(szc)						\
2455d07b933Sdp78419 	(hw_page_array[(szc)].hp_shift)
2465d07b933Sdp78419 #define	PAGE_GET_PAGECOLORS(szc)					\
2475d07b933Sdp78419 	(hw_page_array[(szc)].hp_colors)
2485d07b933Sdp78419 
2495d07b933Sdp78419 /*
2505d07b933Sdp78419  * This macro calculates the next sequential pfn with the specified
2515d07b933Sdp78419  * color using color equivalency mask
2525d07b933Sdp78419  */
253ce8eb11aSdp78419 #define	PAGE_NEXT_PFN_FOR_COLOR(pfn, szc, color, ceq_mask, color_mask, it)   \
254a7c3ca36Sdp78419 	{                                                                    \
2555d07b933Sdp78419 		ASSERT(((color) & ~(ceq_mask)) == 0);                        \
2565d07b933Sdp78419 		if (&page_next_pfn_for_color_cpu == NULL) {                  \
2575d07b933Sdp78419 			uint_t	pfn_shift = PAGE_BSZS_SHIFT(szc);            \
2585d07b933Sdp78419 			pfn_t	spfn = pfn >> pfn_shift;                     \
2595d07b933Sdp78419 			pfn_t	stride = (ceq_mask) + 1;                     \
2605d07b933Sdp78419 			ASSERT((((ceq_mask) + 1) & (ceq_mask)) == 0);        \
2615d07b933Sdp78419 			if (((spfn ^ (color)) & (ceq_mask)) == 0) {          \
2625d07b933Sdp78419 				pfn += stride << pfn_shift;                  \
2635d07b933Sdp78419 			} else {                                             \
2645d07b933Sdp78419 				pfn = (spfn & ~(pfn_t)(ceq_mask)) | (color); \
265a7c3ca36Sdp78419 				pfn = (pfn > spfn ? pfn : pfn + stride) <<   \
266a7c3ca36Sdp78419 				    pfn_shift;                               \
2675d07b933Sdp78419 			}                                                    \
2685d07b933Sdp78419 		} else {                                                     \
2695d07b933Sdp78419 		    pfn = page_next_pfn_for_color_cpu(pfn, szc, color,	     \
270ce8eb11aSdp78419 			ceq_mask, color_mask, it);			     \
271a7c3ca36Sdp78419 		}                                                            \
2725d07b933Sdp78419 	}
2735d07b933Sdp78419 
2745d07b933Sdp78419 /* get the color equivalency mask for the next szc */
2755d07b933Sdp78419 #define	PAGE_GET_NSZ_MASK(szc, mask)                                         \
2765d07b933Sdp78419 	((&page_get_nsz_color_mask_cpu == NULL) ?                            \
2775d07b933Sdp78419 	    ((mask) >> (PAGE_GET_SHIFT((szc) + 1) - PAGE_GET_SHIFT(szc))) :  \
2785d07b933Sdp78419 	    page_get_nsz_color_mask_cpu(szc, mask))
2795d07b933Sdp78419 
2805d07b933Sdp78419 /* get the color of the next szc */
2815d07b933Sdp78419 #define	PAGE_GET_NSZ_COLOR(szc, color)                                       \
2825d07b933Sdp78419 	((&page_get_nsz_color_cpu == NULL) ?                                 \
2835d07b933Sdp78419 	    ((color) >> (PAGE_GET_SHIFT((szc) + 1) - PAGE_GET_SHIFT(szc))) : \
2845d07b933Sdp78419 	    page_get_nsz_color_cpu(szc, color))
2855d07b933Sdp78419 
2867c478bd9Sstevel@tonic-gate /* Find the bin for the given page if it was of size szc */
287ce8eb11aSdp78419 #define	PP_2_BIN_SZC(pp, szc)	(PFN_2_COLOR(pp->p_pagenum, szc, (void *)(-1)))
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate #define	PP_2_BIN(pp)		(PP_2_BIN_SZC(pp, pp->p_szc))
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate #define	PP_2_MEM_NODE(pp)	(PFN_2_MEM_NODE(pp->p_pagenum))
2927c478bd9Sstevel@tonic-gate 
293d94ffb28Sjmcp #define	PC_BIN_MUTEX(mnode, bin, flags) ((flags & PG_FREE_LIST) ?	\
2947c478bd9Sstevel@tonic-gate 	&fpc_mutex[(bin) & (NPC_MUTEX - 1)][mnode] :			\
2957c478bd9Sstevel@tonic-gate 	&cpc_mutex[(bin) & (NPC_MUTEX - 1)][mnode])
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate #define	FPC_MUTEX(mnode, i)	(&fpc_mutex[i][mnode])
2987c478bd9Sstevel@tonic-gate #define	CPC_MUTEX(mnode, i)	(&cpc_mutex[i][mnode])
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate #define	PFN_BASE(pfnum, szc)	(pfnum & ~((1 << PAGE_BSZS_SHIFT(szc)) - 1))
3017c478bd9Sstevel@tonic-gate 
3025d07b933Sdp78419 /*
3035d07b933Sdp78419  * this structure is used for walking free page lists
3045d07b933Sdp78419  * controls when to split large pages into smaller pages,
3055d07b933Sdp78419  * and when to coalesce smaller pages into larger pages
3065d07b933Sdp78419  */
3075d07b933Sdp78419 typedef struct page_list_walker {
3085d07b933Sdp78419 	uint_t	plw_colors;		/* num of colors for szc */
3095d07b933Sdp78419 	uint_t  plw_color_mask;		/* colors-1 */
3105d07b933Sdp78419 	uint_t	plw_bin_step;		/* next bin: 1 or 2 */
3115d07b933Sdp78419 	uint_t  plw_count;		/* loop count */
3125d07b933Sdp78419 	uint_t	plw_bin0;		/* starting bin */
3135d07b933Sdp78419 	uint_t  plw_bin_marker;		/* bin after initial jump */
3145d07b933Sdp78419 	uint_t  plw_bin_split_prev;	/* last bin we tried to split */
3155d07b933Sdp78419 	uint_t  plw_do_split;		/* set if OK to split */
3165d07b933Sdp78419 	uint_t  plw_split_next;		/* next bin to split */
3175d07b933Sdp78419 	uint_t	plw_ceq_dif;		/* number of different color groups */
3185d07b933Sdp78419 					/* to check */
3195d07b933Sdp78419 	uint_t	plw_ceq_mask[MMU_PAGE_SIZES + 1]; /* color equiv mask */
3205d07b933Sdp78419 	uint_t	plw_bins[MMU_PAGE_SIZES + 1];	/* num of bins */
3215d07b933Sdp78419 } page_list_walker_t;
3225d07b933Sdp78419 
3235d07b933Sdp78419 void	page_list_walk_init(uchar_t szc, uint_t flags, uint_t bin,
3245d07b933Sdp78419     int can_split, int use_ceq, page_list_walker_t *plw);
3255d07b933Sdp78419 
3267c478bd9Sstevel@tonic-gate typedef	char	hpmctr_t;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate #ifdef DEBUG
3297c478bd9Sstevel@tonic-gate #define	CHK_LPG(pp, szc)	chk_lpg(pp, szc)
3307c478bd9Sstevel@tonic-gate extern void	chk_lpg(page_t *, uchar_t);
3317c478bd9Sstevel@tonic-gate #else
3327c478bd9Sstevel@tonic-gate #define	CHK_LPG(pp, szc)
3337c478bd9Sstevel@tonic-gate #endif
3347c478bd9Sstevel@tonic-gate 
335affbd3ccSkchow /*
336affbd3ccSkchow  * page list count per mnode and type.
337affbd3ccSkchow  */
3387c478bd9Sstevel@tonic-gate typedef	struct {
339affbd3ccSkchow 	pgcnt_t	plc_mt_pgmax;		/* max page cnt */
340affbd3ccSkchow 	pgcnt_t plc_mt_clpgcnt;		/* cache list cnt */
341affbd3ccSkchow 	pgcnt_t plc_mt_flpgcnt;		/* free list cnt - small pages */
342affbd3ccSkchow 	pgcnt_t plc_mt_lgpgcnt;		/* free list cnt - large pages */
343affbd3ccSkchow #ifdef DEBUG
3447c478bd9Sstevel@tonic-gate 	struct {
345affbd3ccSkchow 		pgcnt_t plc_mts_pgcnt;	/* per page size count */
3467c478bd9Sstevel@tonic-gate 		int	plc_mts_colors;
347affbd3ccSkchow 		pgcnt_t	*plc_mtsc_pgcnt; /* per color bin count */
3487c478bd9Sstevel@tonic-gate 	} plc_mts[MMU_PAGE_SIZES];
349affbd3ccSkchow #endif
350affbd3ccSkchow } plcnt_t[MAX_MEM_NODES][MAX_MEM_TYPES];
3517c478bd9Sstevel@tonic-gate 
352affbd3ccSkchow #ifdef DEBUG
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate #define	PLCNT_SZ(ctrs_sz) {						\
3557c478bd9Sstevel@tonic-gate 	int	szc;							\
3565d07b933Sdp78419 	for (szc = 0; szc < mmu_page_sizes; szc++) {			\
3577c478bd9Sstevel@tonic-gate 		int	colors = page_get_pagecolors(szc);		\
3587c478bd9Sstevel@tonic-gate 		ctrs_sz += (max_mem_nodes * MAX_MEM_TYPES *		\
3597c478bd9Sstevel@tonic-gate 		    colors * sizeof (pgcnt_t));				\
3607c478bd9Sstevel@tonic-gate 	}								\
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate #define	PLCNT_INIT(base) {						\
3647c478bd9Sstevel@tonic-gate 	int	mn, mt, szc, colors;					\
3657c478bd9Sstevel@tonic-gate 	for (szc = 0; szc < mmu_page_sizes; szc++) {			\
3667c478bd9Sstevel@tonic-gate 		colors = page_get_pagecolors(szc);			\
3677c478bd9Sstevel@tonic-gate 		for (mn = 0; mn < max_mem_nodes; mn++) {		\
3687c478bd9Sstevel@tonic-gate 			for (mt = 0; mt < MAX_MEM_TYPES; mt++) {	\
369affbd3ccSkchow 				plcnt[mn][mt].plc_mts[szc].		\
3707c478bd9Sstevel@tonic-gate 				    plc_mts_colors = colors;		\
371affbd3ccSkchow 				plcnt[mn][mt].plc_mts[szc].		\
3727c478bd9Sstevel@tonic-gate 				    plc_mtsc_pgcnt = (pgcnt_t *)base;	\
3737c478bd9Sstevel@tonic-gate 				base += (colors * sizeof (pgcnt_t));	\
3747c478bd9Sstevel@tonic-gate 			}						\
3757c478bd9Sstevel@tonic-gate 		}							\
3767c478bd9Sstevel@tonic-gate 	}								\
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate 
379affbd3ccSkchow #define	PLCNT_DO(pp, mn, mtype, szc, cnt, flags) {			\
3807c478bd9Sstevel@tonic-gate 	int	bin = PP_2_BIN(pp);					\
3817c478bd9Sstevel@tonic-gate 	if (flags & PG_CACHE_LIST)					\
382affbd3ccSkchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_clpgcnt, cnt);	\
383affbd3ccSkchow 	else if (szc)							\
384affbd3ccSkchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_lgpgcnt, cnt);	\
385affbd3ccSkchow 	else								\
386affbd3ccSkchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_flpgcnt, cnt);	\
387affbd3ccSkchow 	atomic_add_long(&plcnt[mn][mtype].plc_mts[szc].plc_mts_pgcnt,	\
388affbd3ccSkchow 	    cnt);							\
389affbd3ccSkchow 	atomic_add_long(&plcnt[mn][mtype].plc_mts[szc].			\
3907c478bd9Sstevel@tonic-gate 	    plc_mtsc_pgcnt[bin], cnt);					\
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate #else
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate #define	PLCNT_SZ(ctrs_sz)
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate #define	PLCNT_INIT(base)
3987c478bd9Sstevel@tonic-gate 
399affbd3ccSkchow /* PG_FREE_LIST may not be explicitly set in flags for large pages */
4007c478bd9Sstevel@tonic-gate 
401affbd3ccSkchow #define	PLCNT_DO(pp, mn, mtype, szc, cnt, flags) {			\
402affbd3ccSkchow 	if (flags & PG_CACHE_LIST)					\
403affbd3ccSkchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_clpgcnt, cnt);	\
404affbd3ccSkchow 	else if (szc)							\
405affbd3ccSkchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_lgpgcnt, cnt);	\
406affbd3ccSkchow 	else								\
407affbd3ccSkchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_flpgcnt, cnt);	\
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate #endif
4117c478bd9Sstevel@tonic-gate 
412affbd3ccSkchow #define	PLCNT_INCR(pp, mn, mtype, szc, flags) {				\
413affbd3ccSkchow 	long	cnt = (1 << PAGE_BSZS_SHIFT(szc));			\
414affbd3ccSkchow 	PLCNT_DO(pp, mn, mtype, szc, cnt, flags);			\
415affbd3ccSkchow }
416affbd3ccSkchow 
417affbd3ccSkchow #define	PLCNT_DECR(pp, mn, mtype, szc, flags) {				\
418affbd3ccSkchow 	long	cnt = ((-1) << PAGE_BSZS_SHIFT(szc));			\
419affbd3ccSkchow 	PLCNT_DO(pp, mn, mtype, szc, cnt, flags);			\
420affbd3ccSkchow }
421affbd3ccSkchow 
422affbd3ccSkchow /*
423affbd3ccSkchow  * macros to update page list max counts - done when pages transferred
424e21bae1bSkchow  * from RELOC to NORELOC mtype (kcage_init or kcage_assimilate_page).
425affbd3ccSkchow  */
426e21bae1bSkchow 
427e21bae1bSkchow #define	PLCNT_XFER_NORELOC(pp) {					\
428e21bae1bSkchow 	long	cnt = (1 << PAGE_BSZS_SHIFT((pp)->p_szc));		\
429e21bae1bSkchow 	int	mn = PP_2_MEM_NODE(pp);					\
430e21bae1bSkchow 	atomic_add_long(&plcnt[mn][MTYPE_NORELOC].plc_mt_pgmax, cnt);	\
431e21bae1bSkchow 	atomic_add_long(&plcnt[mn][MTYPE_RELOC].plc_mt_pgmax, -cnt);	\
432affbd3ccSkchow }
433affbd3ccSkchow 
434e21bae1bSkchow /*
435e21bae1bSkchow  * macro to modify the page list max counts when memory is added to
436e21bae1bSkchow  * the page lists during startup (add_physmem) or during a DR operation
437e21bae1bSkchow  * when memory is added (kphysm_add_memory_dynamic) or deleted
438e21bae1bSkchow  * (kphysm_del_cleanup).
439e21bae1bSkchow  */
440ce8eb11aSdp78419 #define	PLCNT_MODIFY_MAX(pfn, cnt) {					       \
441ce8eb11aSdp78419 	spgcnt_t _cnt = (spgcnt_t)(cnt);				       \
442ce8eb11aSdp78419 	pgcnt_t _acnt = ABS(_cnt);					       \
443ce8eb11aSdp78419 	int _mn;							       \
444ce8eb11aSdp78419 	pgcnt_t _np;							       \
445ce8eb11aSdp78419 	if (&plat_mem_node_intersect_range != NULL) {			       \
446ce8eb11aSdp78419 		for (_mn = 0; _mn < max_mem_nodes; _mn++) {		       \
447ce8eb11aSdp78419 			plat_mem_node_intersect_range((pfn), _acnt, _mn, &_np);\
448ce8eb11aSdp78419 			if (_np == 0)					       \
449ce8eb11aSdp78419 				continue;				       \
450ce8eb11aSdp78419 			atomic_add_long(&plcnt[_mn][MTYPE_RELOC].plc_mt_pgmax, \
451ce8eb11aSdp78419 			    (_cnt < 0) ? -_np : _np);			       \
452ce8eb11aSdp78419 		}							       \
453ce8eb11aSdp78419 	} else {							       \
454ce8eb11aSdp78419 		pfn_t _pfn = (pfn);					       \
455ce8eb11aSdp78419 		pfn_t _endpfn = _pfn + _acnt;				       \
456ce8eb11aSdp78419 		while (_pfn < _endpfn) {				       \
457ce8eb11aSdp78419 			_mn = PFN_2_MEM_NODE(_pfn);			       \
458ce8eb11aSdp78419 			_np = MIN(_endpfn, mem_node_config[_mn].physmax + 1) - \
459ce8eb11aSdp78419 			    _pfn;					       \
460ce8eb11aSdp78419 			_pfn += _np;					       \
461ce8eb11aSdp78419 			atomic_add_long(&plcnt[_mn][MTYPE_RELOC].plc_mt_pgmax, \
462ce8eb11aSdp78419 			    (_cnt < 0) ? -_np : _np);			       \
463ce8eb11aSdp78419 		}							       \
4644c36ab88Skchow 	}								       \
465affbd3ccSkchow }
466affbd3ccSkchow 
4679853d9e8SJason Beloro /*
4689853d9e8SJason Beloro  * macro to call page_ctrs_adjust() when memory is added
4699853d9e8SJason Beloro  * during a DR operation.
4709853d9e8SJason Beloro  */
4719853d9e8SJason Beloro #define	PAGE_CTRS_ADJUST(pfn, cnt, rv) {				       \
4729853d9e8SJason Beloro 	spgcnt_t _cnt = (spgcnt_t)(cnt);				       \
4739853d9e8SJason Beloro 	int _mn;							       \
4749853d9e8SJason Beloro 	pgcnt_t _np;							       \
4759853d9e8SJason Beloro 	if (&plat_mem_node_intersect_range != NULL) {			       \
4769853d9e8SJason Beloro 		for (_mn = 0; _mn < max_mem_nodes; _mn++) {		       \
4779853d9e8SJason Beloro 			plat_mem_node_intersect_range((pfn), _cnt, _mn, &_np); \
4789853d9e8SJason Beloro 			if (_np == 0)					       \
4799853d9e8SJason Beloro 				continue;				       \
4809853d9e8SJason Beloro 			if ((rv = page_ctrs_adjust(_mn)) != 0)		       \
4819853d9e8SJason Beloro 				break;					       \
4829853d9e8SJason Beloro 		}							       \
4839853d9e8SJason Beloro 	} else {							       \
4849853d9e8SJason Beloro 		pfn_t _pfn = (pfn);					       \
4859853d9e8SJason Beloro 		pfn_t _endpfn = _pfn + _cnt;				       \
4869853d9e8SJason Beloro 		while (_pfn < _endpfn) {				       \
4879853d9e8SJason Beloro 			_mn = PFN_2_MEM_NODE(_pfn);			       \
4889853d9e8SJason Beloro 			_np = MIN(_endpfn, mem_node_config[_mn].physmax + 1) - \
4899853d9e8SJason Beloro 			    _pfn;					       \
4909853d9e8SJason Beloro 			_pfn += _np;					       \
4919853d9e8SJason Beloro 			if ((rv = page_ctrs_adjust(_mn)) != 0)		       \
4929853d9e8SJason Beloro 				break;					       \
4939853d9e8SJason Beloro 		}							       \
4949853d9e8SJason Beloro 	}								       \
4959853d9e8SJason Beloro }
4969853d9e8SJason Beloro 
497affbd3ccSkchow extern plcnt_t	plcnt;
498affbd3ccSkchow 
499affbd3ccSkchow #define	MNODE_PGCNT(mn)							\
500affbd3ccSkchow 	(plcnt[mn][MTYPE_RELOC].plc_mt_clpgcnt +			\
501affbd3ccSkchow 	    plcnt[mn][MTYPE_NORELOC].plc_mt_clpgcnt +			\
502affbd3ccSkchow 	    plcnt[mn][MTYPE_RELOC].plc_mt_flpgcnt +			\
503affbd3ccSkchow 	    plcnt[mn][MTYPE_NORELOC].plc_mt_flpgcnt +			\
504affbd3ccSkchow 	    plcnt[mn][MTYPE_RELOC].plc_mt_lgpgcnt +			\
505affbd3ccSkchow 	    plcnt[mn][MTYPE_NORELOC].plc_mt_lgpgcnt)
506affbd3ccSkchow 
507affbd3ccSkchow #define	MNODETYPE_PGCNT(mn, mtype)					\
508affbd3ccSkchow 	(plcnt[mn][mtype].plc_mt_clpgcnt +				\
509affbd3ccSkchow 	    plcnt[mn][mtype].plc_mt_flpgcnt +				\
510affbd3ccSkchow 	    plcnt[mn][mtype].plc_mt_lgpgcnt)
511affbd3ccSkchow 
512affbd3ccSkchow /*
513affbd3ccSkchow  * macros to loop through the mtype range - MTYPE_START returns -1 in
514affbd3ccSkchow  * mtype if no pages in mnode/mtype and possibly NEXT mtype.
515affbd3ccSkchow  */
516affbd3ccSkchow #define	MTYPE_START(mnode, mtype, flags) {				\
517affbd3ccSkchow 	if (plcnt[mnode][mtype].plc_mt_pgmax == 0) {			\
518102033aaSdp78419 		ASSERT(mtype == MTYPE_RELOC ||				\
519102033aaSdp78419 		    MNODETYPE_PGCNT(mnode, mtype) == 0 ||		\
520102033aaSdp78419 		    plcnt[mnode][mtype].plc_mt_pgmax != 0);		\
521affbd3ccSkchow 		MTYPE_NEXT(mnode, mtype, flags);			\
522affbd3ccSkchow 	}								\
523affbd3ccSkchow }
524affbd3ccSkchow 
525affbd3ccSkchow /*
526affbd3ccSkchow  * if allocation from the RELOC pool failed and there is sufficient cage
527affbd3ccSkchow  * memory, attempt to allocate from the NORELOC pool.
528affbd3ccSkchow  */
529affbd3ccSkchow #define	MTYPE_NEXT(mnode, mtype, flags) { 				\
530affbd3ccSkchow 	if (!(flags & (PG_NORELOC | PGI_NOCAGE | PGI_RELOCONLY)) &&	\
531affbd3ccSkchow 	    (kcage_freemem >= kcage_lotsfree)) {			\
53216eca74fSstans 		if (plcnt[mnode][MTYPE_NORELOC].plc_mt_pgmax == 0) {	\
533102033aaSdp78419 			ASSERT(MNODETYPE_PGCNT(mnode, MTYPE_NORELOC) == 0 || \
534102033aaSdp78419 			    plcnt[mnode][MTYPE_NORELOC].plc_mt_pgmax != 0);  \
535affbd3ccSkchow 			mtype = -1;					\
536affbd3ccSkchow 		} else {						\
537affbd3ccSkchow 			mtype = MTYPE_NORELOC;				\
538affbd3ccSkchow 			flags |= PG_NORELOC;				\
539affbd3ccSkchow 		}							\
540affbd3ccSkchow 	} else {							\
541affbd3ccSkchow 		mtype = -1;						\
542affbd3ccSkchow 	}								\
543affbd3ccSkchow }
544affbd3ccSkchow 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  * get the ecache setsize for the current cpu.
5477c478bd9Sstevel@tonic-gate  */
5487c478bd9Sstevel@tonic-gate #define	CPUSETSIZE()	(cpunodes[CPU->cpu_id].ecache_setsize)
5497c478bd9Sstevel@tonic-gate 
550affbd3ccSkchow extern struct cpu	cpu0;
551affbd3ccSkchow #define	CPU0		&cpu0
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate #define	PAGE_BSZS_SHIFT(szc)	TTE_BSZS_SHIFT(szc)
5547c478bd9Sstevel@tonic-gate /*
5557c478bd9Sstevel@tonic-gate  * For sfmmu each larger page is 8 times the size of the previous
5567c478bd9Sstevel@tonic-gate  * size page.
5577c478bd9Sstevel@tonic-gate  */
5587c478bd9Sstevel@tonic-gate #define	FULL_REGION_CNT(rg_szc)	(8)
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate  * The counter base must be per page_counter element to prevent
5627c478bd9Sstevel@tonic-gate  * races when re-indexing, and the base page size element should
5637c478bd9Sstevel@tonic-gate  * be aligned on a boundary of the given region size.
5647c478bd9Sstevel@tonic-gate  *
5657c478bd9Sstevel@tonic-gate  * We also round up the number of pages spanned by the counters
5667c478bd9Sstevel@tonic-gate  * for a given region to PC_BASE_ALIGN in certain situations to simplify
5677c478bd9Sstevel@tonic-gate  * the coding for some non-performance critical routines.
5687c478bd9Sstevel@tonic-gate  */
5697c478bd9Sstevel@tonic-gate #define	PC_BASE_ALIGN		((pfn_t)1 << PAGE_BSZS_SHIFT(mmu_page_sizes-1))
5707c478bd9Sstevel@tonic-gate #define	PC_BASE_ALIGN_MASK	(PC_BASE_ALIGN - 1)
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate extern int ecache_alignsize;
5737c478bd9Sstevel@tonic-gate #define	L2CACHE_ALIGN		ecache_alignsize
5746061ce8aSkchow #define	L2CACHE_ALIGN_MAX	512
5757c478bd9Sstevel@tonic-gate 
57685f58038Sdp78419 extern int update_proc_pgcolorbase_after_fork;
5777c478bd9Sstevel@tonic-gate extern int consistent_coloring;
5787c478bd9Sstevel@tonic-gate extern uint_t vac_colors_mask;
5797c478bd9Sstevel@tonic-gate extern int vac_size;
5807c478bd9Sstevel@tonic-gate extern int vac_shift;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate /*
583bb121940Sdp78419  * Kernel mem segment in 64-bit space
584bb121940Sdp78419  */
585bb121940Sdp78419 extern caddr_t kmem64_base, kmem64_end, kmem64_aligned_end;
586bb121940Sdp78419 extern int kmem64_alignsize, kmem64_szc;
587bb121940Sdp78419 extern uint64_t kmem64_pabase;
588bb121940Sdp78419 extern int max_bootlp_tteszc;
589bb121940Sdp78419 
590bb121940Sdp78419 /*
591ec25b48fSsusans  * Maximum and default values for user heap, stack, private and shared
592ec25b48fSsusans  * anonymous memory, and user text and initialized data.
593ec25b48fSsusans  *
594ec25b48fSsusans  * Initial values are defined in architecture specific mach_vm_dep.c file.
595ec25b48fSsusans  * Used by map_pgsz*() routines.
5967c478bd9Sstevel@tonic-gate  */
597ec25b48fSsusans extern size_t max_uheap_lpsize;
598ec25b48fSsusans extern size_t default_uheap_lpsize;
599ec25b48fSsusans extern size_t max_ustack_lpsize;
600ec25b48fSsusans extern size_t default_ustack_lpsize;
601ec25b48fSsusans extern size_t max_privmap_lpsize;
602ec25b48fSsusans extern size_t max_uidata_lpsize;
603ec25b48fSsusans extern size_t max_utext_lpsize;
604ec25b48fSsusans extern size_t max_shm_lpsize;
605ec25b48fSsusans 
606ec25b48fSsusans /*
607ec25b48fSsusans  * For adjusting the default lpsize, for DTLB-limited page sizes.
608ec25b48fSsusans  */
609ec25b48fSsusans extern void adjust_data_maxlpsize(size_t ismpagesize);
610ec25b48fSsusans 
611ec25b48fSsusans /*
612ec25b48fSsusans  * Sanity control. Don't use large pages regardless of user
613ec25b48fSsusans  * settings if there's less than priv or shm_lpg_min_physmem memory installed.
614ec25b48fSsusans  * The units for this variable are 8K pages.
615ec25b48fSsusans  */
616ec25b48fSsusans extern pgcnt_t privm_lpg_min_physmem;
617ec25b48fSsusans extern pgcnt_t shm_lpg_min_physmem;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate  * AS_2_BIN macro controls the page coloring policy.
6217c478bd9Sstevel@tonic-gate  * 0 (default) uses various vaddr bits
6227c478bd9Sstevel@tonic-gate  * 1 virtual=paddr
6237c478bd9Sstevel@tonic-gate  * 2 bin hopping
6247c478bd9Sstevel@tonic-gate  */
625d94ffb28Sjmcp #define	AS_2_BIN(as, seg, vp, addr, bin, szc)				\
6267c478bd9Sstevel@tonic-gate switch (consistent_coloring) {						\
6277c478bd9Sstevel@tonic-gate 	default:                                                        \
6287c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN,					\
6297c478bd9Sstevel@tonic-gate 			"AS_2_BIN: bad consistent coloring value");	\
6307c478bd9Sstevel@tonic-gate 		/* assume default algorithm -> continue */		\
6317c478bd9Sstevel@tonic-gate 	case 0: {                                                       \
6327c478bd9Sstevel@tonic-gate 		uint32_t ndx, new;					\
6337c478bd9Sstevel@tonic-gate 		int slew = 0;						\
6345d07b933Sdp78419 		pfn_t pfn;                                              \
6357c478bd9Sstevel@tonic-gate                                                                         \
6367c478bd9Sstevel@tonic-gate 		if (vp != NULL && IS_SWAPVP(vp) &&			\
6377c478bd9Sstevel@tonic-gate 		    seg->s_ops == &segvn_ops)				\
6387c478bd9Sstevel@tonic-gate 			slew = as_color_bin(as);			\
6397c478bd9Sstevel@tonic-gate                                                                         \
6405d07b933Sdp78419 		pfn = ((uintptr_t)addr >> MMU_PAGESHIFT) +		\
6417c478bd9Sstevel@tonic-gate 			(((uintptr_t)addr >> page_coloring_shift) <<	\
6425d07b933Sdp78419 			(vac_shift - MMU_PAGESHIFT));			\
643102033aaSdp78419 		if ((szc) == 0 || &page_pfn_2_color_cpu == NULL) {	\
6445d07b933Sdp78419 			pfn += slew;					\
645ce8eb11aSdp78419 			bin = PFN_2_COLOR(pfn, szc, NULL);		\
6465d07b933Sdp78419 		} else {						\
647ce8eb11aSdp78419 			bin = PFN_2_COLOR(pfn, szc, NULL);		\
6485d07b933Sdp78419 			bin += slew >> (vac_shift - MMU_PAGESHIFT);	\
6495d07b933Sdp78419 			bin &= hw_page_array[(szc)].hp_colors - 1;	\
6505d07b933Sdp78419 		}							\
6517c478bd9Sstevel@tonic-gate 		break;                                                  \
6527c478bd9Sstevel@tonic-gate 	}                                                               \
6537c478bd9Sstevel@tonic-gate 	case 1:                                                         \
6545d07b933Sdp78419 		bin = PFN_2_COLOR(((uintptr_t)addr >> MMU_PAGESHIFT),	\
655ce8eb11aSdp78419 		    szc, NULL);						\
6567c478bd9Sstevel@tonic-gate 		break;                                                  \
6577c478bd9Sstevel@tonic-gate 	case 2: {                                                       \
6587c478bd9Sstevel@tonic-gate 		int cnt = as_color_bin(as);				\
6595d07b933Sdp78419 		uint_t color_mask = page_get_pagecolors(0) - 1;		\
6605d07b933Sdp78419                                                                         \
6617c478bd9Sstevel@tonic-gate 		/* make sure physical color aligns with vac color */	\
6627c478bd9Sstevel@tonic-gate 		while ((cnt & vac_colors_mask) !=			\
6637c478bd9Sstevel@tonic-gate 		    addr_to_vcolor(addr)) {				\
6647c478bd9Sstevel@tonic-gate 			cnt++;						\
6657c478bd9Sstevel@tonic-gate 		}                                                       \
6665d07b933Sdp78419 		bin = cnt = cnt & color_mask;			        \
6675d07b933Sdp78419 		bin >>= PAGE_GET_COLOR_SHIFT(0, szc);                   \
6687c478bd9Sstevel@tonic-gate 		/* update per as page coloring fields */		\
6695d07b933Sdp78419 		cnt = (cnt + 1) & color_mask;			        \
6705d07b933Sdp78419 		if (cnt == (as_color_start(as) & color_mask)) {	        \
6717c478bd9Sstevel@tonic-gate 			cnt = as_color_start(as) = as_color_start(as) + \
6727c478bd9Sstevel@tonic-gate 				PGCLR_LOOPFACTOR;			\
6737c478bd9Sstevel@tonic-gate 		}                                                       \
6745d07b933Sdp78419 		as_color_bin(as) = cnt & color_mask;		        \
6757c478bd9Sstevel@tonic-gate 		break;                                                  \
6767c478bd9Sstevel@tonic-gate 	}								\
6777c478bd9Sstevel@tonic-gate }									\
6785d07b933Sdp78419 	ASSERT(bin < page_get_pagecolors(szc));
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
681affbd3ccSkchow  * cpu private vm data - accessed thru CPU->cpu_vm_data
682affbd3ccSkchow  *	vc_pnum_memseg: tracks last memseg visited in page_numtopp_nolock()
683affbd3ccSkchow  *	vc_pnext_memseg: tracks last memseg visited in page_nextn()
684affbd3ccSkchow  *	vc_kmptr: unaligned kmem pointer for this vm_cpu_data_t
6856061ce8aSkchow  *	vc_kmsize: orignal kmem size for this vm_cpu_data_t
686affbd3ccSkchow  */
687affbd3ccSkchow 
688affbd3ccSkchow typedef struct {
689affbd3ccSkchow 	struct memseg	*vc_pnum_memseg;
690affbd3ccSkchow 	struct memseg	*vc_pnext_memseg;
691affbd3ccSkchow 	void		*vc_kmptr;
6926061ce8aSkchow 	size_t		vc_kmsize;
693affbd3ccSkchow } vm_cpu_data_t;
694affbd3ccSkchow 
695affbd3ccSkchow /* allocation size to ensure vm_cpu_data_t resides in its own cache line */
696affbd3ccSkchow #define	VM_CPU_DATA_PADSIZE						\
697affbd3ccSkchow 	(P2ROUNDUP(sizeof (vm_cpu_data_t), L2CACHE_ALIGN_MAX))
698affbd3ccSkchow 
699affbd3ccSkchow /*
7007c478bd9Sstevel@tonic-gate  * Function to get an ecache color bin: F(as, cnt, vcolor).
7017c478bd9Sstevel@tonic-gate  * the goal of this function is to:
7027c478bd9Sstevel@tonic-gate  * - to spread a processes' physical pages across the entire ecache to
7037c478bd9Sstevel@tonic-gate  *	maximize its use.
7047c478bd9Sstevel@tonic-gate  * - to minimize vac flushes caused when we reuse a physical page on a
7057c478bd9Sstevel@tonic-gate  *	different vac color than it was previously used.
7067c478bd9Sstevel@tonic-gate  * - to prevent all processes to use the same exact colors and trash each
7077c478bd9Sstevel@tonic-gate  *	other.
7087c478bd9Sstevel@tonic-gate  *
7097c478bd9Sstevel@tonic-gate  * cnt is a bin ptr kept on a per as basis.  As we page_create we increment
7107c478bd9Sstevel@tonic-gate  * the ptr so we spread out the physical pages to cover the entire ecache.
7117c478bd9Sstevel@tonic-gate  * The virtual color is made a subset of the physical color in order to
7127c478bd9Sstevel@tonic-gate  * in minimize virtual cache flushing.
7137c478bd9Sstevel@tonic-gate  * We add in the as to spread out different as.	 This happens when we
7147c478bd9Sstevel@tonic-gate  * initialize the start count value.
7157c478bd9Sstevel@tonic-gate  * sizeof(struct as) is 60 so we shift by 3 to get into the bit range
7167c478bd9Sstevel@tonic-gate  * that will tend to change.  For example, on spitfire based machines
7177c478bd9Sstevel@tonic-gate  * (vcshft == 1) contigous as are spread bu ~6 bins.
7187c478bd9Sstevel@tonic-gate  * vcshft provides for proper virtual color alignment.
7197c478bd9Sstevel@tonic-gate  * In theory cnt should be updated using cas only but if we are off by one
7207c478bd9Sstevel@tonic-gate  * or 2 it is no big deal.
7217c478bd9Sstevel@tonic-gate  * We also keep a start value which is used to randomize on what bin we
7227c478bd9Sstevel@tonic-gate  * start counting when it is time to start another loop. This avoids
7237c478bd9Sstevel@tonic-gate  * contigous allocations of ecache size to point to the same bin.
7247c478bd9Sstevel@tonic-gate  * Why 3? Seems work ok. Better than 7 or anything larger.
7257c478bd9Sstevel@tonic-gate  */
7267c478bd9Sstevel@tonic-gate #define	PGCLR_LOOPFACTOR 3
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate /*
7297c478bd9Sstevel@tonic-gate  * When a bin is empty, and we can't satisfy a color request correctly,
7307c478bd9Sstevel@tonic-gate  * we scan.  If we assume that the programs have reasonable spatial
7317c478bd9Sstevel@tonic-gate  * behavior, then it will not be a good idea to use the adjacent color.
7327c478bd9Sstevel@tonic-gate  * Using the adjacent color would result in virtually adjacent addresses
7337c478bd9Sstevel@tonic-gate  * mapping into the same spot in the cache.  So, if we stumble across
7347c478bd9Sstevel@tonic-gate  * an empty bin, skip a bunch before looking.  After the first skip,
7357c478bd9Sstevel@tonic-gate  * then just look one bin at a time so we don't miss our cache on
7367c478bd9Sstevel@tonic-gate  * every look. Be sure to check every bin.  Page_create() will panic
7377c478bd9Sstevel@tonic-gate  * if we miss a page.
7387c478bd9Sstevel@tonic-gate  *
7397c478bd9Sstevel@tonic-gate  * This also explains the `<=' in the for loops in both page_get_freelist()
7407c478bd9Sstevel@tonic-gate  * and page_get_cachelist().  Since we checked the target bin, skipped
7417c478bd9Sstevel@tonic-gate  * a bunch, then continued one a time, we wind up checking the target bin
7427c478bd9Sstevel@tonic-gate  * twice to make sure we get all of them bins.
7437c478bd9Sstevel@tonic-gate  */
7447c478bd9Sstevel@tonic-gate #define	BIN_STEP	20
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate #ifdef VM_STATS
7477c478bd9Sstevel@tonic-gate struct vmm_vmstats_str {
748d94ffb28Sjmcp 	ulong_t pgf_alloc[MMU_PAGE_SIZES];	/* page_get_freelist */
749d94ffb28Sjmcp 	ulong_t pgf_allocok[MMU_PAGE_SIZES];
750d94ffb28Sjmcp 	ulong_t pgf_allocokrem[MMU_PAGE_SIZES];
751d94ffb28Sjmcp 	ulong_t pgf_allocfailed[MMU_PAGE_SIZES];
7527c478bd9Sstevel@tonic-gate 	ulong_t pgf_allocdeferred;
753d94ffb28Sjmcp 	ulong_t	pgf_allocretry[MMU_PAGE_SIZES];
754affbd3ccSkchow 	ulong_t pgc_alloc;			/* page_get_cachelist */
7557c478bd9Sstevel@tonic-gate 	ulong_t pgc_allocok;
7567c478bd9Sstevel@tonic-gate 	ulong_t pgc_allocokrem;
7577c478bd9Sstevel@tonic-gate 	ulong_t	pgc_allocokdeferred;
7587c478bd9Sstevel@tonic-gate 	ulong_t pgc_allocfailed;
759affbd3ccSkchow 	ulong_t	pgcp_alloc[MMU_PAGE_SIZES];	/* page_get_contig_pages */
7607c478bd9Sstevel@tonic-gate 	ulong_t	pgcp_allocfailed[MMU_PAGE_SIZES];
7617c478bd9Sstevel@tonic-gate 	ulong_t	pgcp_allocempty[MMU_PAGE_SIZES];
7627c478bd9Sstevel@tonic-gate 	ulong_t	pgcp_allocok[MMU_PAGE_SIZES];
763affbd3ccSkchow 	ulong_t	ptcp[MMU_PAGE_SIZES];		/* page_trylock_contig_pages */
7647c478bd9Sstevel@tonic-gate 	ulong_t	ptcpfreethresh[MMU_PAGE_SIZES];
7657c478bd9Sstevel@tonic-gate 	ulong_t	ptcpfailexcl[MMU_PAGE_SIZES];
7667c478bd9Sstevel@tonic-gate 	ulong_t	ptcpfailszc[MMU_PAGE_SIZES];
7677c478bd9Sstevel@tonic-gate 	ulong_t	ptcpfailcage[MMU_PAGE_SIZES];
7687c478bd9Sstevel@tonic-gate 	ulong_t	ptcpok[MMU_PAGE_SIZES];
769affbd3ccSkchow 	ulong_t	pgmf_alloc[MMU_PAGE_SIZES];	/* page_get_mnode_freelist */
7707c478bd9Sstevel@tonic-gate 	ulong_t	pgmf_allocfailed[MMU_PAGE_SIZES];
7717c478bd9Sstevel@tonic-gate 	ulong_t	pgmf_allocempty[MMU_PAGE_SIZES];
7727c478bd9Sstevel@tonic-gate 	ulong_t	pgmf_allocok[MMU_PAGE_SIZES];
773affbd3ccSkchow 	ulong_t	pgmc_alloc;			/* page_get_mnode_cachelist */
7747c478bd9Sstevel@tonic-gate 	ulong_t	pgmc_allocfailed;
7757c478bd9Sstevel@tonic-gate 	ulong_t	pgmc_allocempty;
7767c478bd9Sstevel@tonic-gate 	ulong_t	pgmc_allocok;
777affbd3ccSkchow 	ulong_t	pladd_free[MMU_PAGE_SIZES];	/* page_list_add/sub */
778affbd3ccSkchow 	ulong_t	plsub_free[MMU_PAGE_SIZES];
779affbd3ccSkchow 	ulong_t	pladd_cache;
780affbd3ccSkchow 	ulong_t	plsub_cache;
781affbd3ccSkchow 	ulong_t	plsubpages_szcbig;
782affbd3ccSkchow 	ulong_t	plsubpages_szc0;
7835d07b933Sdp78419 	ulong_t	pfs_req[MMU_PAGE_SIZES];	/* page_freelist_split */
7845d07b933Sdp78419 	ulong_t	pfs_demote[MMU_PAGE_SIZES];
7855d07b933Sdp78419 	ulong_t	pfc_coalok[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
786affbd3ccSkchow 	ulong_t ppr_reloc[MMU_PAGE_SIZES];	/* page_relocate */
787d94ffb28Sjmcp 	ulong_t ppr_relocok[MMU_PAGE_SIZES];
7887c478bd9Sstevel@tonic-gate 	ulong_t ppr_relocnoroot[MMU_PAGE_SIZES];
7897c478bd9Sstevel@tonic-gate 	ulong_t ppr_reloc_replnoroot[MMU_PAGE_SIZES];
7907c478bd9Sstevel@tonic-gate 	ulong_t ppr_relocnolock[MMU_PAGE_SIZES];
7917c478bd9Sstevel@tonic-gate 	ulong_t ppr_relocnomem[MMU_PAGE_SIZES];
7927c478bd9Sstevel@tonic-gate 	ulong_t ppr_krelocfail[MMU_PAGE_SIZES];
7938b464eb8Smec 	ulong_t ppr_copyfail;
7945d07b933Sdp78419 	/* page coalesce counter */
7955d07b933Sdp78419 	ulong_t	page_ctrs_coalesce[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
7965d07b933Sdp78419 	/* candidates useful */
7975d07b933Sdp78419 	ulong_t	page_ctrs_cands_skip[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
7985d07b933Sdp78419 	/* ctrs changed after locking */
7995d07b933Sdp78419 	ulong_t	page_ctrs_changed[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
8005d07b933Sdp78419 	/* page_freelist_coalesce failed */
8015d07b933Sdp78419 	ulong_t	page_ctrs_failed[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
8027c478bd9Sstevel@tonic-gate 	ulong_t	page_ctrs_coalesce_all;	/* page coalesce all counter */
8037c478bd9Sstevel@tonic-gate 	ulong_t	page_ctrs_cands_skip_all; /* candidates useful for all func */
8047c478bd9Sstevel@tonic-gate };
8057c478bd9Sstevel@tonic-gate extern struct vmm_vmstats_str vmm_vmstats;
8067c478bd9Sstevel@tonic-gate #endif	/* VM_STATS */
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate /*
8097c478bd9Sstevel@tonic-gate  * Used to hold off page relocations into the cage until OBP has completed
8107c478bd9Sstevel@tonic-gate  * its boot-time handoff of its resources to the kernel.
8117c478bd9Sstevel@tonic-gate  */
8127c478bd9Sstevel@tonic-gate extern int page_relocate_ready;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate /*
8157c478bd9Sstevel@tonic-gate  * cpu/mmu-dependent vm variables may be reset at bootup.
8167c478bd9Sstevel@tonic-gate  */
8177c478bd9Sstevel@tonic-gate extern uint_t mmu_page_sizes;
8187c478bd9Sstevel@tonic-gate extern uint_t max_mmu_page_sizes;
8197c478bd9Sstevel@tonic-gate extern uint_t mmu_hashcnt;
8207c478bd9Sstevel@tonic-gate extern uint_t max_mmu_hashcnt;
8217c478bd9Sstevel@tonic-gate extern size_t mmu_ism_pagesize;
8227c478bd9Sstevel@tonic-gate extern int mmu_exported_pagesize_mask;
8237c478bd9Sstevel@tonic-gate extern uint_t mmu_exported_page_sizes;
8247c478bd9Sstevel@tonic-gate extern uint_t szc_2_userszc[];
8257c478bd9Sstevel@tonic-gate extern uint_t userszc_2_szc[];
8267c478bd9Sstevel@tonic-gate 
82702bc52beSkchow #define	mmu_legacy_page_sizes	mmu_exported_page_sizes
8287c478bd9Sstevel@tonic-gate #define	USERSZC_2_SZC(userszc)	(userszc_2_szc[userszc])
8297c478bd9Sstevel@tonic-gate #define	SZC_2_USERSZC(szc)	(szc_2_userszc[szc])
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate  * Platform specific page routines
8337c478bd9Sstevel@tonic-gate  */
8347c478bd9Sstevel@tonic-gate extern void mach_page_add(page_t **, page_t *);
8357c478bd9Sstevel@tonic-gate extern void mach_page_sub(page_t **, page_t *);
8367c478bd9Sstevel@tonic-gate extern uint_t page_get_pagecolors(uint_t);
8377c478bd9Sstevel@tonic-gate extern void ppcopy_kernel__relocatable(page_t *, page_t *);
8387c478bd9Sstevel@tonic-gate #define	ppcopy_kernel(p1, p2)	ppcopy_kernel__relocatable(p1, p2)
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate /*
8417c478bd9Sstevel@tonic-gate  * platform specific large pages for kernel heap support
8427c478bd9Sstevel@tonic-gate  */
8437c478bd9Sstevel@tonic-gate extern size_t get_segkmem_lpsize(size_t lpsize);
8447c478bd9Sstevel@tonic-gate extern size_t mmu_get_kernel_lpsize(size_t lpsize);
8457c478bd9Sstevel@tonic-gate extern void mmu_init_kernel_pgsz(struct hat *hat);
8467c478bd9Sstevel@tonic-gate extern void mmu_init_kcontext();
8477c478bd9Sstevel@tonic-gate extern uint64_t kcontextreg;
8487c478bd9Sstevel@tonic-gate 
8491e45ea5aSblakej /*
8501e45ea5aSblakej  * Nucleus data page allocator routines
8511e45ea5aSblakej  */
8521e45ea5aSblakej extern void ndata_alloc_init(struct memlist *, uintptr_t, uintptr_t);
8531e45ea5aSblakej extern void *ndata_alloc(struct memlist *, size_t, size_t);
8541e45ea5aSblakej extern void *ndata_extra_base(struct memlist *, size_t, caddr_t);
8551e45ea5aSblakej extern size_t ndata_maxsize(struct memlist *);
8561e45ea5aSblakej extern size_t ndata_spare(struct memlist *, size_t, size_t);
8571e45ea5aSblakej 
8587c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate #endif
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate #endif	/* _VM_DEP_H */
863