xref: /onnv-gate/usr/src/uts/sun4/vm/vm_dep.h (revision 12908:80a39220b451)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52090Sstans  * Common Development and Distribution License (the "License").
62090Sstans  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12908SPavel.Tatashin@Sun.COM  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * UNIX machine dependent virtual memory support.
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #ifndef	_VM_DEP_H
300Sstevel@tonic-gate #define	_VM_DEP_H
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #ifdef	__cplusplus
330Sstevel@tonic-gate extern "C" {
340Sstevel@tonic-gate #endif
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <vm/hat_sfmmu.h>
370Sstevel@tonic-gate #include <sys/archsystm.h>
380Sstevel@tonic-gate #include <sys/memnode.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #define	GETTICK()	gettick()
418898SVijay.Balakrishna@Sun.COM 
42*12908SPavel.Tatashin@Sun.COM /* tick value that should be used for random values */
43*12908SPavel.Tatashin@Sun.COM extern u_longlong_t randtick(void);
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate  * Per page size free lists. Allocated dynamically.
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate #define	MAX_MEM_TYPES	2	/* 0 = reloc, 1 = noreloc */
490Sstevel@tonic-gate #define	MTYPE_RELOC	0
500Sstevel@tonic-gate #define	MTYPE_NORELOC	1
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #define	PP_2_MTYPE(pp)	(PP_ISNORELOC(pp) ? MTYPE_NORELOC : MTYPE_RELOC)
530Sstevel@tonic-gate 
541385Skchow #define	MTYPE_INIT(mtype, vp, vaddr, flags, pgsz)			\
550Sstevel@tonic-gate 	mtype = (flags & PG_NORELOC) ? MTYPE_NORELOC : MTYPE_RELOC;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /* mtype init for page_get_replacement_page */
581385Skchow #define	MTYPE_PGR_INIT(mtype, flags, pp, mnode, pgcnt)			\
590Sstevel@tonic-gate 	mtype = (flags & PG_NORELOC) ? MTYPE_NORELOC : MTYPE_RELOC;
600Sstevel@tonic-gate 
610Sstevel@tonic-gate #define	MNODETYPE_2_PFN(mnode, mtype, pfnlo, pfnhi)			\
620Sstevel@tonic-gate 	pfnlo = mem_node_config[mnode].physbase;			\
630Sstevel@tonic-gate 	pfnhi = mem_node_config[mnode].physmax;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
662961Sdp78419  * candidate counters in vm_pagelist.c are indexed by color and range
672961Sdp78419  */
682961Sdp78419 #define	MAX_MNODE_MRANGES		MAX_MEM_TYPES
692961Sdp78419 #define	MNODE_RANGE_CNT(mnode)		MAX_MNODE_MRANGES
702961Sdp78419 #define	MNODE_MAX_MRANGE(mnode)		(MAX_MEM_TYPES - 1)
712961Sdp78419 #define	MTYPE_2_MRANGE(mnode, mtype)	(mtype)
722961Sdp78419 
732961Sdp78419 /*
740Sstevel@tonic-gate  * Internal PG_ flags.
750Sstevel@tonic-gate  */
760Sstevel@tonic-gate #define	PGI_RELOCONLY	0x10000	/* acts in the opposite sense to PG_NORELOC */
770Sstevel@tonic-gate #define	PGI_NOCAGE	0x20000	/* indicates Cage is disabled */
780Sstevel@tonic-gate #define	PGI_PGCPHIPRI	0x40000	/* page_get_contig_page priority allocation */
790Sstevel@tonic-gate #define	PGI_PGCPSZC0	0x80000	/* relocate base pagesize page */
800Sstevel@tonic-gate 
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate  * PGI mtype flags - should not overlap PGI flags
830Sstevel@tonic-gate  */
840Sstevel@tonic-gate #define	PGI_MT_RANGE	0x1000000	/* mtype range */
850Sstevel@tonic-gate #define	PGI_MT_NEXT	0x2000000	/* get next mtype */
860Sstevel@tonic-gate 
8712293SJames.McPherson@Sun.COM extern page_t ***page_freelists[MMU_PAGE_SIZES][MAX_MEM_TYPES];
880Sstevel@tonic-gate extern page_t ***page_cachelists[MAX_MEM_TYPES];
890Sstevel@tonic-gate 
9012293SJames.McPherson@Sun.COM #define	PAGE_FREELISTS(mnode, szc, color, mtype) \
9112293SJames.McPherson@Sun.COM 	(*(page_freelists[szc][mtype][mnode] + (color)))
9212293SJames.McPherson@Sun.COM 
930Sstevel@tonic-gate #define	PAGE_CACHELISTS(mnode, color, mtype) \
940Sstevel@tonic-gate 	(*(page_cachelists[mtype][mnode] + (color)))
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate  * There are 'page_colors' colors/bins.  Spread them out under a
980Sstevel@tonic-gate  * couple of locks.  There are mutexes for both the page freelist
990Sstevel@tonic-gate  * and the page cachelist.  We want enough locks to make contention
1000Sstevel@tonic-gate  * reasonable, but not too many -- otherwise page_freelist_lock() gets
1010Sstevel@tonic-gate  * so expensive that it becomes the bottleneck!
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate #define	NPC_MUTEX	16
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate extern kmutex_t	*fpc_mutex[NPC_MUTEX];
1060Sstevel@tonic-gate extern kmutex_t	*cpc_mutex[NPC_MUTEX];
1070Sstevel@tonic-gate 
1082961Sdp78419 /*
1094769Sdp78419  * Iterator provides the info needed to convert RA to PA.
1104769Sdp78419  * MEM_NODE_ITERATOR_INIT() should be called before
1114769Sdp78419  * PAGE_NEXT_PFN_FOR_COLOR() if pfn was not obtained via a previous
1124769Sdp78419  * PAGE_NEXT_PFN_FOR_COLOR() call. Iterator caches color 2 hash
1134769Sdp78419  * translations requiring initializer call if color or ceq_mask changes,
1144769Sdp78419  * even if pfn doesn't. MEM_NODE_ITERATOR_INIT() must also be called before
1154769Sdp78419  * PFN_2_COLOR() that uses a valid iterator argument.
11610106SJason.Beloro@Sun.COM  *
11710106SJason.Beloro@Sun.COM  * plat_mem_node_iterator_init() starts from last mblock in continuation
11810106SJason.Beloro@Sun.COM  * case which may be invalid because memory DR.  To detect this situation
11910106SJason.Beloro@Sun.COM  * mi_genid is checked against mpo_genid which is incremented after a
12010106SJason.Beloro@Sun.COM  * memory DR operation.  See also plat_slice_add()/plat_slice_del().
1214769Sdp78419  */
1224769Sdp78419 #ifdef	sun4v
1234769Sdp78419 
1244769Sdp78419 typedef struct mem_node_iterator {
1254769Sdp78419 	uint_t mi_mnode;		/* mnode in which to iterate */
1264769Sdp78419 	int mi_init;			/* set to 1 when first init */
12710106SJason.Beloro@Sun.COM 	int mi_genid;			/* set/checked against mpo_genid */
1284769Sdp78419 	int mi_last_mblock;		/* last mblock visited */
1294769Sdp78419 	uint_t mi_hash_ceq_mask;	/* cached copy of ceq_mask */
1304769Sdp78419 	uint_t mi_hash_color;		/* cached copy of color */
1314769Sdp78419 	uint_t mi_mnode_mask;		/* number of mask bits */
1324769Sdp78419 	uint_t mi_mnode_pfn_shift;	/* mnode position in pfn */
1334769Sdp78419 	pfn_t mi_mblock_base;		/* first valid pfn in current mblock */
1344769Sdp78419 	pfn_t mi_mblock_end;		/* last valid pfn in current mblock */
1354769Sdp78419 	pfn_t mi_ra_to_pa;		/* ra adjustment for current mblock */
1364769Sdp78419 	pfn_t mi_mnode_pfn_mask;	/* mask to obtain mnode id bits */
1374769Sdp78419 } mem_node_iterator_t;
1384769Sdp78419 
1394769Sdp78419 #define	MEM_NODE_ITERATOR_DECL(it) \
1404769Sdp78419 	mem_node_iterator_t it
1416041Sdp78419 #define	MEM_NODE_ITERATOR_INIT(pfn, mnode, szc, it) \
1426041Sdp78419 	(pfn) = plat_mem_node_iterator_init((pfn), (mnode), (szc), (it), 1)
1434769Sdp78419 
1446041Sdp78419 extern pfn_t plat_mem_node_iterator_init(pfn_t, int, uchar_t,
1454769Sdp78419     mem_node_iterator_t *, int);
1464769Sdp78419 extern pfn_t plat_rapfn_to_papfn(pfn_t);
1474769Sdp78419 extern int interleaved_mnodes;
1484769Sdp78419 
1494769Sdp78419 #else	/* sun4v */
1504769Sdp78419 
1514769Sdp78419 #define	MEM_NODE_ITERATOR_DECL(it) \
1524769Sdp78419 	void *it = NULL
1536041Sdp78419 #define	MEM_NODE_ITERATOR_INIT(pfn, mnode, szc, it)
1544769Sdp78419 
1554769Sdp78419 #endif	/* sun4v */
1564769Sdp78419 
1574769Sdp78419 /*
1584769Sdp78419  * Return the mnode limits so that hpc_counters length and base
1594769Sdp78419  * index can be determined. When interleaved_mnodes is set, we
1604769Sdp78419  * create an array only for the first mnode that exists. All other
1614769Sdp78419  * mnodes will share the array in this case.
1624769Sdp78419  * If interleaved_mnodes is not set, simply return the limits for
1634769Sdp78419  * the given mnode.
1644769Sdp78419  */
1654769Sdp78419 #define	HPM_COUNTERS_LIMITS(mnode, physbase, physmax, first)		\
1664769Sdp78419 	if (!interleaved_mnodes) {					\
1674769Sdp78419 		(physbase) = mem_node_config[(mnode)].physbase;		\
1684769Sdp78419 		(physmax) = mem_node_config[(mnode)].physmax;		\
1694769Sdp78419 		(first) = (mnode);					\
1704769Sdp78419 	} else if ((first) < 0) {					\
1714769Sdp78419 		mem_node_max_range(&(physbase), &(physmax));		\
1724769Sdp78419 		(first) = (mnode);					\
1734769Sdp78419 	}
1744769Sdp78419 
1754769Sdp78419 #define	PAGE_CTRS_WRITE_LOCK(mnode)					\
1764769Sdp78419 	if (!interleaved_mnodes) {					\
1774769Sdp78419 		rw_enter(&page_ctrs_rwlock[(mnode)], RW_WRITER);	\
1784769Sdp78419 		page_freelist_lock(mnode);				\
1794769Sdp78419 	} else {							\
1804769Sdp78419 		/* changing shared hpm_counters */			\
1814769Sdp78419 		int _i;							\
1824769Sdp78419 		for (_i = 0; _i < max_mem_nodes; _i++) {		\
1834769Sdp78419 			rw_enter(&page_ctrs_rwlock[_i], RW_WRITER);	\
1844769Sdp78419 			page_freelist_lock(_i);				\
1854769Sdp78419 		}							\
1864769Sdp78419 	}
1874769Sdp78419 
1884769Sdp78419 #define	PAGE_CTRS_WRITE_UNLOCK(mnode)					\
1894769Sdp78419 	if (!interleaved_mnodes) {					\
1904769Sdp78419 		page_freelist_unlock(mnode);				\
1914769Sdp78419 		rw_exit(&page_ctrs_rwlock[(mnode)]);			\
1924769Sdp78419 	} else {							\
1934769Sdp78419 		int _i;							\
1944769Sdp78419 		for (_i = 0; _i < max_mem_nodes; _i++) {		\
1954769Sdp78419 			page_freelist_unlock(_i);			\
1964769Sdp78419 			rw_exit(&page_ctrs_rwlock[_i]);			\
1974769Sdp78419 		}							\
1984769Sdp78419 	}
1994769Sdp78419 
2004769Sdp78419 /*
2012961Sdp78419  * cpu specific color conversion functions
2022961Sdp78419  */
2032961Sdp78419 extern uint_t page_get_nsz_color_mask_cpu(uchar_t, uint_t);
2042961Sdp78419 #pragma weak page_get_nsz_color_mask_cpu
2052961Sdp78419 
2062961Sdp78419 extern uint_t page_get_nsz_color_cpu(uchar_t, uint_t);
2072961Sdp78419 #pragma weak page_get_nsz_color_cpu
2082961Sdp78419 
2092961Sdp78419 extern uint_t page_get_color_shift_cpu(uchar_t, uchar_t);
2102961Sdp78419 #pragma weak page_get_color_shift_cpu
2112961Sdp78419 
2124769Sdp78419 extern uint_t page_convert_color_cpu(uint_t, uchar_t, uchar_t);
2134769Sdp78419 #pragma weak page_convert_color_cpu
2144769Sdp78419 
2152961Sdp78419 extern pfn_t page_next_pfn_for_color_cpu(pfn_t,
2164769Sdp78419     uchar_t, uint_t, uint_t, uint_t, void *);
2172961Sdp78419 #pragma weak page_next_pfn_for_color_cpu
2182961Sdp78419 
2194769Sdp78419 extern uint_t  page_pfn_2_color_cpu(pfn_t, uchar_t, void *);
2202961Sdp78419 #pragma weak page_pfn_2_color_cpu
2212961Sdp78419 
2222961Sdp78419 #define	PAGE_GET_COLOR_SHIFT(szc, nszc)				\
2232961Sdp78419 	((&page_get_color_shift_cpu != NULL) ?			\
2242961Sdp78419 	    page_get_color_shift_cpu(szc, nszc) :		\
2252961Sdp78419 	    (hw_page_array[(nszc)].hp_shift -			\
2262961Sdp78419 		hw_page_array[(szc)].hp_shift))
2272961Sdp78419 
2284769Sdp78419 #define	PAGE_CONVERT_COLOR(ncolor, szc, nszc)			\
2294769Sdp78419 	((&page_convert_color_cpu != NULL) ?			\
2304769Sdp78419 	    page_convert_color_cpu(ncolor, szc, nszc) :		\
2314769Sdp78419 	    ((ncolor) << PAGE_GET_COLOR_SHIFT((szc), (nszc))))
2324769Sdp78419 
2334769Sdp78419 #define	PFN_2_COLOR(pfn, szc, it)				\
2342961Sdp78419 	((&page_pfn_2_color_cpu != NULL) ?			\
2354769Sdp78419 	    page_pfn_2_color_cpu(pfn, szc, it) :		\
2362961Sdp78419 	    ((pfn & (hw_page_array[0].hp_colors - 1)) >>	\
2372961Sdp78419 		(hw_page_array[szc].hp_shift -			\
2382961Sdp78419 		    hw_page_array[0].hp_shift)))
2392961Sdp78419 
2402961Sdp78419 #define	PNUM_SIZE(szc)							\
2412961Sdp78419 	(hw_page_array[(szc)].hp_pgcnt)
2422961Sdp78419 #define	PNUM_SHIFT(szc)							\
2432961Sdp78419 	(hw_page_array[(szc)].hp_shift - hw_page_array[0].hp_shift)
2442961Sdp78419 #define	PAGE_GET_SHIFT(szc)						\
2452961Sdp78419 	(hw_page_array[(szc)].hp_shift)
2462961Sdp78419 #define	PAGE_GET_PAGECOLORS(szc)					\
2472961Sdp78419 	(hw_page_array[(szc)].hp_colors)
2482961Sdp78419 
2492961Sdp78419 /*
2502961Sdp78419  * This macro calculates the next sequential pfn with the specified
2512961Sdp78419  * color using color equivalency mask
2522961Sdp78419  */
2535847Sdp78419 #define	PAGE_NEXT_PFN_FOR_COLOR(pfn, szc, color, ceq_mask, color_mask, it)   \
2545847Sdp78419 	{                                                                    \
2555847Sdp78419 		ASSERT(((color) & ~(ceq_mask)) == 0);                        \
2565847Sdp78419 		if (&page_next_pfn_for_color_cpu == NULL) {                  \
2575847Sdp78419 			uint_t	pfn_shift = PAGE_BSZS_SHIFT(szc);            \
2585847Sdp78419 			pfn_t	spfn = pfn >> pfn_shift;                     \
2595847Sdp78419 			pfn_t	stride = (ceq_mask) + 1;                     \
2605847Sdp78419 			ASSERT((((ceq_mask) + 1) & (ceq_mask)) == 0);        \
2615847Sdp78419 			if (((spfn ^ (color)) & (ceq_mask)) == 0) {          \
2625847Sdp78419 				pfn += stride << pfn_shift;                  \
2635847Sdp78419 			} else {                                             \
2645847Sdp78419 				pfn = (spfn & ~(pfn_t)(ceq_mask)) | (color); \
2655847Sdp78419 				pfn = (pfn > spfn ? pfn : pfn + stride) <<   \
2665847Sdp78419 				    pfn_shift;                               \
2675847Sdp78419 			}                                                    \
2685847Sdp78419 		} else {                                                     \
2695847Sdp78419 		    pfn = page_next_pfn_for_color_cpu(pfn, szc, color,	     \
2705847Sdp78419 			ceq_mask, color_mask, it);			     \
2715847Sdp78419 		}                                                            \
2722961Sdp78419 	}
2732961Sdp78419 
2742961Sdp78419 /* get the color equivalency mask for the next szc */
2752961Sdp78419 #define	PAGE_GET_NSZ_MASK(szc, mask)                                         \
2762961Sdp78419 	((&page_get_nsz_color_mask_cpu == NULL) ?                            \
2772961Sdp78419 	    ((mask) >> (PAGE_GET_SHIFT((szc) + 1) - PAGE_GET_SHIFT(szc))) :  \
2782961Sdp78419 	    page_get_nsz_color_mask_cpu(szc, mask))
2792961Sdp78419 
2802961Sdp78419 /* get the color of the next szc */
2812961Sdp78419 #define	PAGE_GET_NSZ_COLOR(szc, color)                                       \
2822961Sdp78419 	((&page_get_nsz_color_cpu == NULL) ?                                 \
2832961Sdp78419 	    ((color) >> (PAGE_GET_SHIFT((szc) + 1) - PAGE_GET_SHIFT(szc))) : \
2842961Sdp78419 	    page_get_nsz_color_cpu(szc, color))
2852961Sdp78419 
2860Sstevel@tonic-gate /* Find the bin for the given page if it was of size szc */
2874769Sdp78419 #define	PP_2_BIN_SZC(pp, szc)	(PFN_2_COLOR(pp->p_pagenum, szc, (void *)(-1)))
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate #define	PP_2_BIN(pp)		(PP_2_BIN_SZC(pp, pp->p_szc))
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate #define	PP_2_MEM_NODE(pp)	(PFN_2_MEM_NODE(pp->p_pagenum))
2920Sstevel@tonic-gate 
29312293SJames.McPherson@Sun.COM #define	PC_BIN_MUTEX(mnode, bin, flags) ((flags & PG_FREE_LIST) ?	\
29412293SJames.McPherson@Sun.COM 	&fpc_mutex[(bin) & (NPC_MUTEX - 1)][mnode] :			\
2950Sstevel@tonic-gate 	&cpc_mutex[(bin) & (NPC_MUTEX - 1)][mnode])
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate #define	FPC_MUTEX(mnode, i)	(&fpc_mutex[i][mnode])
2980Sstevel@tonic-gate #define	CPC_MUTEX(mnode, i)	(&cpc_mutex[i][mnode])
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate #define	PFN_BASE(pfnum, szc)	(pfnum & ~((1 << PAGE_BSZS_SHIFT(szc)) - 1))
3010Sstevel@tonic-gate 
3022961Sdp78419 /*
3032961Sdp78419  * this structure is used for walking free page lists
3042961Sdp78419  * controls when to split large pages into smaller pages,
3052961Sdp78419  * and when to coalesce smaller pages into larger pages
3062961Sdp78419  */
3072961Sdp78419 typedef struct page_list_walker {
3082961Sdp78419 	uint_t	plw_colors;		/* num of colors for szc */
3092961Sdp78419 	uint_t  plw_color_mask;		/* colors-1 */
3102961Sdp78419 	uint_t	plw_bin_step;		/* next bin: 1 or 2 */
3112961Sdp78419 	uint_t  plw_count;		/* loop count */
3122961Sdp78419 	uint_t	plw_bin0;		/* starting bin */
3132961Sdp78419 	uint_t  plw_bin_marker;		/* bin after initial jump */
3142961Sdp78419 	uint_t  plw_bin_split_prev;	/* last bin we tried to split */
3152961Sdp78419 	uint_t  plw_do_split;		/* set if OK to split */
3162961Sdp78419 	uint_t  plw_split_next;		/* next bin to split */
3172961Sdp78419 	uint_t	plw_ceq_dif;		/* number of different color groups */
3182961Sdp78419 					/* to check */
3192961Sdp78419 	uint_t	plw_ceq_mask[MMU_PAGE_SIZES + 1]; /* color equiv mask */
3202961Sdp78419 	uint_t	plw_bins[MMU_PAGE_SIZES + 1];	/* num of bins */
3212961Sdp78419 } page_list_walker_t;
3222961Sdp78419 
3232961Sdp78419 void	page_list_walk_init(uchar_t szc, uint_t flags, uint_t bin,
3242961Sdp78419     int can_split, int use_ceq, page_list_walker_t *plw);
3252961Sdp78419 
3260Sstevel@tonic-gate typedef	char	hpmctr_t;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate #ifdef DEBUG
3290Sstevel@tonic-gate #define	CHK_LPG(pp, szc)	chk_lpg(pp, szc)
3300Sstevel@tonic-gate extern void	chk_lpg(page_t *, uchar_t);
3310Sstevel@tonic-gate #else
3320Sstevel@tonic-gate #define	CHK_LPG(pp, szc)
3330Sstevel@tonic-gate #endif
3340Sstevel@tonic-gate 
335414Skchow /*
336414Skchow  * page list count per mnode and type.
337414Skchow  */
3380Sstevel@tonic-gate typedef	struct {
339414Skchow 	pgcnt_t	plc_mt_pgmax;		/* max page cnt */
340414Skchow 	pgcnt_t plc_mt_clpgcnt;		/* cache list cnt */
341414Skchow 	pgcnt_t plc_mt_flpgcnt;		/* free list cnt - small pages */
342414Skchow 	pgcnt_t plc_mt_lgpgcnt;		/* free list cnt - large pages */
343414Skchow #ifdef DEBUG
3440Sstevel@tonic-gate 	struct {
345414Skchow 		pgcnt_t plc_mts_pgcnt;	/* per page size count */
346414Skchow 		int	plc_mts_colors;
347414Skchow 		pgcnt_t	*plc_mtsc_pgcnt; /* per color bin count */
348414Skchow 	} plc_mts[MMU_PAGE_SIZES];
349414Skchow #endif
350414Skchow } plcnt_t[MAX_MEM_NODES][MAX_MEM_TYPES];
3510Sstevel@tonic-gate 
352414Skchow #ifdef DEBUG
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate #define	PLCNT_SZ(ctrs_sz) {						\
3550Sstevel@tonic-gate 	int	szc;							\
3562961Sdp78419 	for (szc = 0; szc < mmu_page_sizes; szc++) {			\
3570Sstevel@tonic-gate 		int	colors = page_get_pagecolors(szc);		\
3580Sstevel@tonic-gate 		ctrs_sz += (max_mem_nodes * MAX_MEM_TYPES *		\
3590Sstevel@tonic-gate 		    colors * sizeof (pgcnt_t));				\
3600Sstevel@tonic-gate 	}								\
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate #define	PLCNT_INIT(base) {						\
3640Sstevel@tonic-gate 	int	mn, mt, szc, colors;					\
3650Sstevel@tonic-gate 	for (szc = 0; szc < mmu_page_sizes; szc++) {			\
3660Sstevel@tonic-gate 		colors = page_get_pagecolors(szc);			\
3670Sstevel@tonic-gate 		for (mn = 0; mn < max_mem_nodes; mn++) {		\
3680Sstevel@tonic-gate 			for (mt = 0; mt < MAX_MEM_TYPES; mt++) {	\
3691385Skchow 				plcnt[mn][mt].plc_mts[szc].		\
3700Sstevel@tonic-gate 				    plc_mts_colors = colors;		\
3711385Skchow 				plcnt[mn][mt].plc_mts[szc].		\
3720Sstevel@tonic-gate 				    plc_mtsc_pgcnt = (pgcnt_t *)base;	\
3730Sstevel@tonic-gate 				base += (colors * sizeof (pgcnt_t));	\
3740Sstevel@tonic-gate 			}						\
3750Sstevel@tonic-gate 		}							\
3760Sstevel@tonic-gate 	}								\
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate 
379414Skchow #define	PLCNT_DO(pp, mn, mtype, szc, cnt, flags) {			\
3800Sstevel@tonic-gate 	int	bin = PP_2_BIN(pp);					\
3810Sstevel@tonic-gate 	if (flags & PG_CACHE_LIST)					\
382414Skchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_clpgcnt, cnt);	\
383414Skchow 	else if (szc)							\
384414Skchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_lgpgcnt, cnt);	\
385414Skchow 	else								\
386414Skchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_flpgcnt, cnt);	\
387414Skchow 	atomic_add_long(&plcnt[mn][mtype].plc_mts[szc].plc_mts_pgcnt,	\
388414Skchow 	    cnt);							\
389414Skchow 	atomic_add_long(&plcnt[mn][mtype].plc_mts[szc].			\
3900Sstevel@tonic-gate 	    plc_mtsc_pgcnt[bin], cnt);					\
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate #else
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate #define	PLCNT_SZ(ctrs_sz)
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate #define	PLCNT_INIT(base)
3980Sstevel@tonic-gate 
399414Skchow /* PG_FREE_LIST may not be explicitly set in flags for large pages */
4000Sstevel@tonic-gate 
401414Skchow #define	PLCNT_DO(pp, mn, mtype, szc, cnt, flags) {			\
402414Skchow 	if (flags & PG_CACHE_LIST)					\
403414Skchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_clpgcnt, cnt);	\
404414Skchow 	else if (szc)							\
405414Skchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_lgpgcnt, cnt);	\
406414Skchow 	else								\
407414Skchow 		atomic_add_long(&plcnt[mn][mtype].plc_mt_flpgcnt, cnt);	\
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate #endif
4110Sstevel@tonic-gate 
412414Skchow #define	PLCNT_INCR(pp, mn, mtype, szc, flags) {				\
413414Skchow 	long	cnt = (1 << PAGE_BSZS_SHIFT(szc));			\
414414Skchow 	PLCNT_DO(pp, mn, mtype, szc, cnt, flags);			\
415414Skchow }
416414Skchow 
417414Skchow #define	PLCNT_DECR(pp, mn, mtype, szc, flags) {				\
418414Skchow 	long	cnt = ((-1) << PAGE_BSZS_SHIFT(szc));			\
419414Skchow 	PLCNT_DO(pp, mn, mtype, szc, cnt, flags);			\
420414Skchow }
421414Skchow 
422414Skchow /*
423414Skchow  * macros to update page list max counts - done when pages transferred
4241373Skchow  * from RELOC to NORELOC mtype (kcage_init or kcage_assimilate_page).
425414Skchow  */
4261373Skchow 
4271373Skchow #define	PLCNT_XFER_NORELOC(pp) {					\
4281373Skchow 	long	cnt = (1 << PAGE_BSZS_SHIFT((pp)->p_szc));		\
4291373Skchow 	int	mn = PP_2_MEM_NODE(pp);					\
4301373Skchow 	atomic_add_long(&plcnt[mn][MTYPE_NORELOC].plc_mt_pgmax, cnt);	\
4311373Skchow 	atomic_add_long(&plcnt[mn][MTYPE_RELOC].plc_mt_pgmax, -cnt);	\
432414Skchow }
433414Skchow 
4341373Skchow /*
4351373Skchow  * macro to modify the page list max counts when memory is added to
4361373Skchow  * the page lists during startup (add_physmem) or during a DR operation
4371373Skchow  * when memory is added (kphysm_add_memory_dynamic) or deleted
4381373Skchow  * (kphysm_del_cleanup).
4391373Skchow  */
4404769Sdp78419 #define	PLCNT_MODIFY_MAX(pfn, cnt) {					       \
4414769Sdp78419 	spgcnt_t _cnt = (spgcnt_t)(cnt);				       \
4424769Sdp78419 	pgcnt_t _acnt = ABS(_cnt);					       \
4434769Sdp78419 	int _mn;							       \
4444769Sdp78419 	pgcnt_t _np;							       \
4454769Sdp78419 	if (&plat_mem_node_intersect_range != NULL) {			       \
4464769Sdp78419 		for (_mn = 0; _mn < max_mem_nodes; _mn++) {		       \
4474769Sdp78419 			plat_mem_node_intersect_range((pfn), _acnt, _mn, &_np);\
4484769Sdp78419 			if (_np == 0)					       \
4494769Sdp78419 				continue;				       \
4504769Sdp78419 			atomic_add_long(&plcnt[_mn][MTYPE_RELOC].plc_mt_pgmax, \
4514769Sdp78419 			    (_cnt < 0) ? -_np : _np);			       \
4524769Sdp78419 		}							       \
4534769Sdp78419 	} else {							       \
4544769Sdp78419 		pfn_t _pfn = (pfn);					       \
4554769Sdp78419 		pfn_t _endpfn = _pfn + _acnt;				       \
4564769Sdp78419 		while (_pfn < _endpfn) {				       \
4574769Sdp78419 			_mn = PFN_2_MEM_NODE(_pfn);			       \
4584769Sdp78419 			_np = MIN(_endpfn, mem_node_config[_mn].physmax + 1) - \
4594769Sdp78419 			    _pfn;					       \
4604769Sdp78419 			_pfn += _np;					       \
4614769Sdp78419 			atomic_add_long(&plcnt[_mn][MTYPE_RELOC].plc_mt_pgmax, \
4624769Sdp78419 			    (_cnt < 0) ? -_np : _np);			       \
4634769Sdp78419 		}							       \
4644769Sdp78419 	}								       \
465414Skchow }
466414Skchow 
46710106SJason.Beloro@Sun.COM /*
46810106SJason.Beloro@Sun.COM  * macro to call page_ctrs_adjust() when memory is added
46910106SJason.Beloro@Sun.COM  * during a DR operation.
47010106SJason.Beloro@Sun.COM  */
47110106SJason.Beloro@Sun.COM #define	PAGE_CTRS_ADJUST(pfn, cnt, rv) {				       \
47210106SJason.Beloro@Sun.COM 	spgcnt_t _cnt = (spgcnt_t)(cnt);				       \
47310106SJason.Beloro@Sun.COM 	int _mn;							       \
47410106SJason.Beloro@Sun.COM 	pgcnt_t _np;							       \
47510106SJason.Beloro@Sun.COM 	if (&plat_mem_node_intersect_range != NULL) {			       \
47610106SJason.Beloro@Sun.COM 		for (_mn = 0; _mn < max_mem_nodes; _mn++) {		       \
47710106SJason.Beloro@Sun.COM 			plat_mem_node_intersect_range((pfn), _cnt, _mn, &_np); \
47810106SJason.Beloro@Sun.COM 			if (_np == 0)					       \
47910106SJason.Beloro@Sun.COM 				continue;				       \
48010106SJason.Beloro@Sun.COM 			if ((rv = page_ctrs_adjust(_mn)) != 0)		       \
48110106SJason.Beloro@Sun.COM 				break;					       \
48210106SJason.Beloro@Sun.COM 		}							       \
48310106SJason.Beloro@Sun.COM 	} else {							       \
48410106SJason.Beloro@Sun.COM 		pfn_t _pfn = (pfn);					       \
48510106SJason.Beloro@Sun.COM 		pfn_t _endpfn = _pfn + _cnt;				       \
48610106SJason.Beloro@Sun.COM 		while (_pfn < _endpfn) {				       \
48710106SJason.Beloro@Sun.COM 			_mn = PFN_2_MEM_NODE(_pfn);			       \
48810106SJason.Beloro@Sun.COM 			_np = MIN(_endpfn, mem_node_config[_mn].physmax + 1) - \
48910106SJason.Beloro@Sun.COM 			    _pfn;					       \
49010106SJason.Beloro@Sun.COM 			_pfn += _np;					       \
49110106SJason.Beloro@Sun.COM 			if ((rv = page_ctrs_adjust(_mn)) != 0)		       \
49210106SJason.Beloro@Sun.COM 				break;					       \
49310106SJason.Beloro@Sun.COM 		}							       \
49410106SJason.Beloro@Sun.COM 	}								       \
49510106SJason.Beloro@Sun.COM }
49610106SJason.Beloro@Sun.COM 
497414Skchow extern plcnt_t	plcnt;
498414Skchow 
499414Skchow #define	MNODE_PGCNT(mn)							\
500414Skchow 	(plcnt[mn][MTYPE_RELOC].plc_mt_clpgcnt +			\
501414Skchow 	    plcnt[mn][MTYPE_NORELOC].plc_mt_clpgcnt +			\
502414Skchow 	    plcnt[mn][MTYPE_RELOC].plc_mt_flpgcnt +			\
503414Skchow 	    plcnt[mn][MTYPE_NORELOC].plc_mt_flpgcnt +			\
504414Skchow 	    plcnt[mn][MTYPE_RELOC].plc_mt_lgpgcnt +			\
505414Skchow 	    plcnt[mn][MTYPE_NORELOC].plc_mt_lgpgcnt)
506414Skchow 
507414Skchow #define	MNODETYPE_PGCNT(mn, mtype)					\
508414Skchow 	(plcnt[mn][mtype].plc_mt_clpgcnt +				\
509414Skchow 	    plcnt[mn][mtype].plc_mt_flpgcnt +				\
510414Skchow 	    plcnt[mn][mtype].plc_mt_lgpgcnt)
511414Skchow 
512414Skchow /*
513414Skchow  * macros to loop through the mtype range - MTYPE_START returns -1 in
514414Skchow  * mtype if no pages in mnode/mtype and possibly NEXT mtype.
515414Skchow  */
516414Skchow #define	MTYPE_START(mnode, mtype, flags) {				\
517414Skchow 	if (plcnt[mnode][mtype].plc_mt_pgmax == 0) {			\
5183177Sdp78419 		ASSERT(mtype == MTYPE_RELOC ||				\
5193177Sdp78419 		    MNODETYPE_PGCNT(mnode, mtype) == 0 ||		\
5203177Sdp78419 		    plcnt[mnode][mtype].plc_mt_pgmax != 0);		\
521414Skchow 		MTYPE_NEXT(mnode, mtype, flags);			\
522414Skchow 	}								\
523414Skchow }
524414Skchow 
525414Skchow /*
526414Skchow  * if allocation from the RELOC pool failed and there is sufficient cage
527414Skchow  * memory, attempt to allocate from the NORELOC pool.
528414Skchow  */
529414Skchow #define	MTYPE_NEXT(mnode, mtype, flags) { 				\
530414Skchow 	if (!(flags & (PG_NORELOC | PGI_NOCAGE | PGI_RELOCONLY)) &&	\
531414Skchow 	    (kcage_freemem >= kcage_lotsfree)) {			\
5322090Sstans 		if (plcnt[mnode][MTYPE_NORELOC].plc_mt_pgmax == 0) {	\
5333177Sdp78419 			ASSERT(MNODETYPE_PGCNT(mnode, MTYPE_NORELOC) == 0 || \
5343177Sdp78419 			    plcnt[mnode][MTYPE_NORELOC].plc_mt_pgmax != 0);  \
535414Skchow 			mtype = -1;					\
536414Skchow 		} else {						\
537414Skchow 			mtype = MTYPE_NORELOC;				\
538414Skchow 			flags |= PG_NORELOC;				\
539414Skchow 		}							\
540414Skchow 	} else {							\
541414Skchow 		mtype = -1;						\
542414Skchow 	}								\
543414Skchow }
544414Skchow 
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate  * get the ecache setsize for the current cpu.
5470Sstevel@tonic-gate  */
5480Sstevel@tonic-gate #define	CPUSETSIZE()	(cpunodes[CPU->cpu_id].ecache_setsize)
5490Sstevel@tonic-gate 
550414Skchow extern struct cpu	cpu0;
551414Skchow #define	CPU0		&cpu0
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate #define	PAGE_BSZS_SHIFT(szc)	TTE_BSZS_SHIFT(szc)
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate  * For sfmmu each larger page is 8 times the size of the previous
5560Sstevel@tonic-gate  * size page.
5570Sstevel@tonic-gate  */
5580Sstevel@tonic-gate #define	FULL_REGION_CNT(rg_szc)	(8)
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate /*
5610Sstevel@tonic-gate  * The counter base must be per page_counter element to prevent
5620Sstevel@tonic-gate  * races when re-indexing, and the base page size element should
5630Sstevel@tonic-gate  * be aligned on a boundary of the given region size.
5640Sstevel@tonic-gate  *
5650Sstevel@tonic-gate  * We also round up the number of pages spanned by the counters
5660Sstevel@tonic-gate  * for a given region to PC_BASE_ALIGN in certain situations to simplify
5670Sstevel@tonic-gate  * the coding for some non-performance critical routines.
5680Sstevel@tonic-gate  */
5690Sstevel@tonic-gate #define	PC_BASE_ALIGN		((pfn_t)1 << PAGE_BSZS_SHIFT(mmu_page_sizes-1))
5700Sstevel@tonic-gate #define	PC_BASE_ALIGN_MASK	(PC_BASE_ALIGN - 1)
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate extern int ecache_alignsize;
5730Sstevel@tonic-gate #define	L2CACHE_ALIGN		ecache_alignsize
574450Skchow #define	L2CACHE_ALIGN_MAX	512
5750Sstevel@tonic-gate 
5764266Sdp78419 extern int update_proc_pgcolorbase_after_fork;
5770Sstevel@tonic-gate extern int consistent_coloring;
5780Sstevel@tonic-gate extern uint_t vac_colors_mask;
5790Sstevel@tonic-gate extern int vac_size;
5800Sstevel@tonic-gate extern int vac_shift;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate /*
5833764Sdp78419  * Kernel mem segment in 64-bit space
5843764Sdp78419  */
5853764Sdp78419 extern caddr_t kmem64_base, kmem64_end, kmem64_aligned_end;
5863764Sdp78419 extern int kmem64_alignsize, kmem64_szc;
5873764Sdp78419 extern uint64_t kmem64_pabase;
5883764Sdp78419 extern int max_bootlp_tteszc;
5893764Sdp78419 
5903764Sdp78419 /*
5912991Ssusans  * Maximum and default values for user heap, stack, private and shared
5922991Ssusans  * anonymous memory, and user text and initialized data.
5932991Ssusans  *
5942991Ssusans  * Initial values are defined in architecture specific mach_vm_dep.c file.
5952991Ssusans  * Used by map_pgsz*() routines.
5960Sstevel@tonic-gate  */
5972991Ssusans extern size_t max_uheap_lpsize;
5982991Ssusans extern size_t default_uheap_lpsize;
5992991Ssusans extern size_t max_ustack_lpsize;
6002991Ssusans extern size_t default_ustack_lpsize;
6012991Ssusans extern size_t max_privmap_lpsize;
6022991Ssusans extern size_t max_uidata_lpsize;
6032991Ssusans extern size_t max_utext_lpsize;
6042991Ssusans extern size_t max_shm_lpsize;
6052991Ssusans 
6062991Ssusans /*
6072991Ssusans  * For adjusting the default lpsize, for DTLB-limited page sizes.
6082991Ssusans  */
6092991Ssusans extern void adjust_data_maxlpsize(size_t ismpagesize);
6102991Ssusans 
6112991Ssusans /*
6122991Ssusans  * Sanity control. Don't use large pages regardless of user
6132991Ssusans  * settings if there's less than priv or shm_lpg_min_physmem memory installed.
6142991Ssusans  * The units for this variable are 8K pages.
6152991Ssusans  */
6162991Ssusans extern pgcnt_t privm_lpg_min_physmem;
6172991Ssusans extern pgcnt_t shm_lpg_min_physmem;
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate /*
6200Sstevel@tonic-gate  * AS_2_BIN macro controls the page coloring policy.
6210Sstevel@tonic-gate  * 0 (default) uses various vaddr bits
6220Sstevel@tonic-gate  * 1 virtual=paddr
6230Sstevel@tonic-gate  * 2 bin hopping
6240Sstevel@tonic-gate  */
62512293SJames.McPherson@Sun.COM #define	AS_2_BIN(as, seg, vp, addr, bin, szc)				\
6260Sstevel@tonic-gate switch (consistent_coloring) {						\
6270Sstevel@tonic-gate 	default:                                                        \
6280Sstevel@tonic-gate 		cmn_err(CE_WARN,					\
6290Sstevel@tonic-gate 			"AS_2_BIN: bad consistent coloring value");	\
6300Sstevel@tonic-gate 		/* assume default algorithm -> continue */		\
6310Sstevel@tonic-gate 	case 0: {                                                       \
6320Sstevel@tonic-gate 		uint32_t ndx, new;					\
6330Sstevel@tonic-gate 		int slew = 0;						\
6342961Sdp78419 		pfn_t pfn;                                              \
6350Sstevel@tonic-gate                                                                         \
6360Sstevel@tonic-gate 		if (vp != NULL && IS_SWAPVP(vp) &&			\
6372961Sdp78419 		    seg->s_ops == &segvn_ops)				\
6380Sstevel@tonic-gate 			slew = as_color_bin(as);			\
6390Sstevel@tonic-gate                                                                         \
6402961Sdp78419 		pfn = ((uintptr_t)addr >> MMU_PAGESHIFT) +		\
6410Sstevel@tonic-gate 			(((uintptr_t)addr >> page_coloring_shift) <<	\
6422961Sdp78419 			(vac_shift - MMU_PAGESHIFT));			\
6433177Sdp78419 		if ((szc) == 0 || &page_pfn_2_color_cpu == NULL) {	\
6442961Sdp78419 			pfn += slew;					\
6454769Sdp78419 			bin = PFN_2_COLOR(pfn, szc, NULL);		\
6462961Sdp78419 		} else {						\
6474769Sdp78419 			bin = PFN_2_COLOR(pfn, szc, NULL);		\
6482961Sdp78419 			bin += slew >> (vac_shift - MMU_PAGESHIFT);	\
6492961Sdp78419 			bin &= hw_page_array[(szc)].hp_colors - 1;	\
6502961Sdp78419 		}							\
6510Sstevel@tonic-gate 		break;                                                  \
6520Sstevel@tonic-gate 	}                                                               \
6530Sstevel@tonic-gate 	case 1:                                                         \
6544769Sdp78419 		bin = PFN_2_COLOR(((uintptr_t)addr >> MMU_PAGESHIFT),	\
6554769Sdp78419 		    szc, NULL);						\
6560Sstevel@tonic-gate 		break;                                                  \
6570Sstevel@tonic-gate 	case 2: {                                                       \
6580Sstevel@tonic-gate 		int cnt = as_color_bin(as);				\
6592961Sdp78419 		uint_t color_mask = page_get_pagecolors(0) - 1;		\
6602961Sdp78419                                                                         \
6610Sstevel@tonic-gate 		/* make sure physical color aligns with vac color */	\
6620Sstevel@tonic-gate 		while ((cnt & vac_colors_mask) !=			\
6630Sstevel@tonic-gate 		    addr_to_vcolor(addr)) {				\
6640Sstevel@tonic-gate 			cnt++;						\
6650Sstevel@tonic-gate 		}                                                       \
6662961Sdp78419 		bin = cnt = cnt & color_mask;			        \
6672961Sdp78419 		bin >>= PAGE_GET_COLOR_SHIFT(0, szc);                   \
6680Sstevel@tonic-gate 		/* update per as page coloring fields */		\
6692961Sdp78419 		cnt = (cnt + 1) & color_mask;			        \
6702961Sdp78419 		if (cnt == (as_color_start(as) & color_mask)) {	        \
6710Sstevel@tonic-gate 			cnt = as_color_start(as) = as_color_start(as) + \
6720Sstevel@tonic-gate 				PGCLR_LOOPFACTOR;			\
6730Sstevel@tonic-gate 		}                                                       \
6742961Sdp78419 		as_color_bin(as) = cnt & color_mask;		        \
6750Sstevel@tonic-gate 		break;                                                  \
6760Sstevel@tonic-gate 	}								\
6770Sstevel@tonic-gate }									\
6782961Sdp78419 	ASSERT(bin < page_get_pagecolors(szc));
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate /*
681414Skchow  * cpu private vm data - accessed thru CPU->cpu_vm_data
682414Skchow  *	vc_pnum_memseg: tracks last memseg visited in page_numtopp_nolock()
683414Skchow  *	vc_pnext_memseg: tracks last memseg visited in page_nextn()
684414Skchow  *	vc_kmptr: unaligned kmem pointer for this vm_cpu_data_t
685450Skchow  *	vc_kmsize: orignal kmem size for this vm_cpu_data_t
686414Skchow  */
687414Skchow 
688414Skchow typedef struct {
689414Skchow 	struct memseg	*vc_pnum_memseg;
690414Skchow 	struct memseg	*vc_pnext_memseg;
691414Skchow 	void		*vc_kmptr;
692450Skchow 	size_t		vc_kmsize;
693414Skchow } vm_cpu_data_t;
694414Skchow 
695414Skchow /* allocation size to ensure vm_cpu_data_t resides in its own cache line */
696414Skchow #define	VM_CPU_DATA_PADSIZE						\
697414Skchow 	(P2ROUNDUP(sizeof (vm_cpu_data_t), L2CACHE_ALIGN_MAX))
698414Skchow 
699414Skchow /* for boot cpu before kmem is initialized */
700414Skchow extern char	vm_cpu_data0[];
701414Skchow 
702414Skchow /*
7030Sstevel@tonic-gate  * Function to get an ecache color bin: F(as, cnt, vcolor).
7040Sstevel@tonic-gate  * the goal of this function is to:
7050Sstevel@tonic-gate  * - to spread a processes' physical pages across the entire ecache to
7060Sstevel@tonic-gate  *	maximize its use.
7070Sstevel@tonic-gate  * - to minimize vac flushes caused when we reuse a physical page on a
7080Sstevel@tonic-gate  *	different vac color than it was previously used.
7090Sstevel@tonic-gate  * - to prevent all processes to use the same exact colors and trash each
7100Sstevel@tonic-gate  *	other.
7110Sstevel@tonic-gate  *
7120Sstevel@tonic-gate  * cnt is a bin ptr kept on a per as basis.  As we page_create we increment
7130Sstevel@tonic-gate  * the ptr so we spread out the physical pages to cover the entire ecache.
7140Sstevel@tonic-gate  * The virtual color is made a subset of the physical color in order to
7150Sstevel@tonic-gate  * in minimize virtual cache flushing.
7160Sstevel@tonic-gate  * We add in the as to spread out different as.	 This happens when we
7170Sstevel@tonic-gate  * initialize the start count value.
7180Sstevel@tonic-gate  * sizeof(struct as) is 60 so we shift by 3 to get into the bit range
7190Sstevel@tonic-gate  * that will tend to change.  For example, on spitfire based machines
7200Sstevel@tonic-gate  * (vcshft == 1) contigous as are spread bu ~6 bins.
7210Sstevel@tonic-gate  * vcshft provides for proper virtual color alignment.
7220Sstevel@tonic-gate  * In theory cnt should be updated using cas only but if we are off by one
7230Sstevel@tonic-gate  * or 2 it is no big deal.
7240Sstevel@tonic-gate  * We also keep a start value which is used to randomize on what bin we
7250Sstevel@tonic-gate  * start counting when it is time to start another loop. This avoids
7260Sstevel@tonic-gate  * contigous allocations of ecache size to point to the same bin.
7270Sstevel@tonic-gate  * Why 3? Seems work ok. Better than 7 or anything larger.
7280Sstevel@tonic-gate  */
7290Sstevel@tonic-gate #define	PGCLR_LOOPFACTOR 3
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate /*
7320Sstevel@tonic-gate  * When a bin is empty, and we can't satisfy a color request correctly,
7330Sstevel@tonic-gate  * we scan.  If we assume that the programs have reasonable spatial
7340Sstevel@tonic-gate  * behavior, then it will not be a good idea to use the adjacent color.
7350Sstevel@tonic-gate  * Using the adjacent color would result in virtually adjacent addresses
7360Sstevel@tonic-gate  * mapping into the same spot in the cache.  So, if we stumble across
7370Sstevel@tonic-gate  * an empty bin, skip a bunch before looking.  After the first skip,
7380Sstevel@tonic-gate  * then just look one bin at a time so we don't miss our cache on
7390Sstevel@tonic-gate  * every look. Be sure to check every bin.  Page_create() will panic
7400Sstevel@tonic-gate  * if we miss a page.
7410Sstevel@tonic-gate  *
7420Sstevel@tonic-gate  * This also explains the `<=' in the for loops in both page_get_freelist()
7430Sstevel@tonic-gate  * and page_get_cachelist().  Since we checked the target bin, skipped
7440Sstevel@tonic-gate  * a bunch, then continued one a time, we wind up checking the target bin
7450Sstevel@tonic-gate  * twice to make sure we get all of them bins.
7460Sstevel@tonic-gate  */
7470Sstevel@tonic-gate #define	BIN_STEP	20
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate #ifdef VM_STATS
7500Sstevel@tonic-gate struct vmm_vmstats_str {
75112293SJames.McPherson@Sun.COM 	ulong_t pgf_alloc[MMU_PAGE_SIZES];	/* page_get_freelist */
75212293SJames.McPherson@Sun.COM 	ulong_t pgf_allocok[MMU_PAGE_SIZES];
75312293SJames.McPherson@Sun.COM 	ulong_t pgf_allocokrem[MMU_PAGE_SIZES];
75412293SJames.McPherson@Sun.COM 	ulong_t pgf_allocfailed[MMU_PAGE_SIZES];
75512293SJames.McPherson@Sun.COM 	ulong_t pgf_allocdeferred;
75612293SJames.McPherson@Sun.COM 	ulong_t	pgf_allocretry[MMU_PAGE_SIZES];
757414Skchow 	ulong_t pgc_alloc;			/* page_get_cachelist */
7580Sstevel@tonic-gate 	ulong_t pgc_allocok;
7590Sstevel@tonic-gate 	ulong_t pgc_allocokrem;
76012293SJames.McPherson@Sun.COM 	ulong_t	pgc_allocokdeferred;
7610Sstevel@tonic-gate 	ulong_t pgc_allocfailed;
762414Skchow 	ulong_t	pgcp_alloc[MMU_PAGE_SIZES];	/* page_get_contig_pages */
7630Sstevel@tonic-gate 	ulong_t	pgcp_allocfailed[MMU_PAGE_SIZES];
7640Sstevel@tonic-gate 	ulong_t	pgcp_allocempty[MMU_PAGE_SIZES];
7650Sstevel@tonic-gate 	ulong_t	pgcp_allocok[MMU_PAGE_SIZES];
766414Skchow 	ulong_t	ptcp[MMU_PAGE_SIZES];		/* page_trylock_contig_pages */
7670Sstevel@tonic-gate 	ulong_t	ptcpfreethresh[MMU_PAGE_SIZES];
7680Sstevel@tonic-gate 	ulong_t	ptcpfailexcl[MMU_PAGE_SIZES];
7690Sstevel@tonic-gate 	ulong_t	ptcpfailszc[MMU_PAGE_SIZES];
7700Sstevel@tonic-gate 	ulong_t	ptcpfailcage[MMU_PAGE_SIZES];
7710Sstevel@tonic-gate 	ulong_t	ptcpok[MMU_PAGE_SIZES];
772414Skchow 	ulong_t	pgmf_alloc[MMU_PAGE_SIZES];	/* page_get_mnode_freelist */
7730Sstevel@tonic-gate 	ulong_t	pgmf_allocfailed[MMU_PAGE_SIZES];
7740Sstevel@tonic-gate 	ulong_t	pgmf_allocempty[MMU_PAGE_SIZES];
7750Sstevel@tonic-gate 	ulong_t	pgmf_allocok[MMU_PAGE_SIZES];
776414Skchow 	ulong_t	pgmc_alloc;			/* page_get_mnode_cachelist */
7770Sstevel@tonic-gate 	ulong_t	pgmc_allocfailed;
7780Sstevel@tonic-gate 	ulong_t	pgmc_allocempty;
7790Sstevel@tonic-gate 	ulong_t	pgmc_allocok;
780414Skchow 	ulong_t	pladd_free[MMU_PAGE_SIZES];	/* page_list_add/sub */
781414Skchow 	ulong_t	plsub_free[MMU_PAGE_SIZES];
782414Skchow 	ulong_t	pladd_cache;
783414Skchow 	ulong_t	plsub_cache;
784414Skchow 	ulong_t	plsubpages_szcbig;
785414Skchow 	ulong_t	plsubpages_szc0;
7862961Sdp78419 	ulong_t	pfs_req[MMU_PAGE_SIZES];	/* page_freelist_split */
7872961Sdp78419 	ulong_t	pfs_demote[MMU_PAGE_SIZES];
7882961Sdp78419 	ulong_t	pfc_coalok[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
78912293SJames.McPherson@Sun.COM 	ulong_t ppr_reloc[MMU_PAGE_SIZES];	/* page_relocate */
79012293SJames.McPherson@Sun.COM 	ulong_t ppr_relocok[MMU_PAGE_SIZES];
7910Sstevel@tonic-gate 	ulong_t ppr_relocnoroot[MMU_PAGE_SIZES];
7920Sstevel@tonic-gate 	ulong_t ppr_reloc_replnoroot[MMU_PAGE_SIZES];
7930Sstevel@tonic-gate 	ulong_t ppr_relocnolock[MMU_PAGE_SIZES];
7940Sstevel@tonic-gate 	ulong_t ppr_relocnomem[MMU_PAGE_SIZES];
7950Sstevel@tonic-gate 	ulong_t ppr_krelocfail[MMU_PAGE_SIZES];
7963253Smec 	ulong_t ppr_copyfail;
7972961Sdp78419 	/* page coalesce counter */
79812293SJames.McPherson@Sun.COM 	ulong_t	page_ctrs_coalesce[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
7992961Sdp78419 	/* candidates useful */
80012293SJames.McPherson@Sun.COM 	ulong_t	page_ctrs_cands_skip[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
8012961Sdp78419 	/* ctrs changed after locking */
80212293SJames.McPherson@Sun.COM 	ulong_t	page_ctrs_changed[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
8032961Sdp78419 	/* page_freelist_coalesce failed */
80412293SJames.McPherson@Sun.COM 	ulong_t	page_ctrs_failed[MMU_PAGE_SIZES][MAX_MNODE_MRANGES];
80512293SJames.McPherson@Sun.COM 	ulong_t	page_ctrs_coalesce_all;	/* page coalesce all counter */
80612293SJames.McPherson@Sun.COM 	ulong_t	page_ctrs_cands_skip_all; /* candidates useful for all func */
8070Sstevel@tonic-gate };
8080Sstevel@tonic-gate extern struct vmm_vmstats_str vmm_vmstats;
8090Sstevel@tonic-gate #endif	/* VM_STATS */
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate /*
8120Sstevel@tonic-gate  * Used to hold off page relocations into the cage until OBP has completed
8130Sstevel@tonic-gate  * its boot-time handoff of its resources to the kernel.
8140Sstevel@tonic-gate  */
8150Sstevel@tonic-gate extern int page_relocate_ready;
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate /*
8180Sstevel@tonic-gate  * cpu/mmu-dependent vm variables may be reset at bootup.
8190Sstevel@tonic-gate  */
8200Sstevel@tonic-gate extern uint_t mmu_page_sizes;
8210Sstevel@tonic-gate extern uint_t max_mmu_page_sizes;
8220Sstevel@tonic-gate extern uint_t mmu_hashcnt;
8230Sstevel@tonic-gate extern uint_t max_mmu_hashcnt;
8240Sstevel@tonic-gate extern size_t mmu_ism_pagesize;
8250Sstevel@tonic-gate extern int mmu_exported_pagesize_mask;
8260Sstevel@tonic-gate extern uint_t mmu_exported_page_sizes;
8270Sstevel@tonic-gate extern uint_t szc_2_userszc[];
8280Sstevel@tonic-gate extern uint_t userszc_2_szc[];
8290Sstevel@tonic-gate 
8305349Skchow #define	mmu_legacy_page_sizes	mmu_exported_page_sizes
8310Sstevel@tonic-gate #define	USERSZC_2_SZC(userszc)	(userszc_2_szc[userszc])
8320Sstevel@tonic-gate #define	SZC_2_USERSZC(szc)	(szc_2_userszc[szc])
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate /*
8350Sstevel@tonic-gate  * Platform specific page routines
8360Sstevel@tonic-gate  */
8370Sstevel@tonic-gate extern void mach_page_add(page_t **, page_t *);
8380Sstevel@tonic-gate extern void mach_page_sub(page_t **, page_t *);
8390Sstevel@tonic-gate extern uint_t page_get_pagecolors(uint_t);
8400Sstevel@tonic-gate extern void ppcopy_kernel__relocatable(page_t *, page_t *);
8410Sstevel@tonic-gate #define	ppcopy_kernel(p1, p2)	ppcopy_kernel__relocatable(p1, p2)
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate /*
8440Sstevel@tonic-gate  * platform specific large pages for kernel heap support
8450Sstevel@tonic-gate  */
8460Sstevel@tonic-gate extern size_t get_segkmem_lpsize(size_t lpsize);
8470Sstevel@tonic-gate extern size_t mmu_get_kernel_lpsize(size_t lpsize);
8480Sstevel@tonic-gate extern void mmu_init_kernel_pgsz(struct hat *hat);
8490Sstevel@tonic-gate extern void mmu_init_kcontext();
8500Sstevel@tonic-gate extern uint64_t kcontextreg;
8510Sstevel@tonic-gate 
8524104Sblakej /*
8534104Sblakej  * Nucleus data page allocator routines
8544104Sblakej  */
8554104Sblakej extern void ndata_alloc_init(struct memlist *, uintptr_t, uintptr_t);
8564104Sblakej extern void *ndata_alloc(struct memlist *, size_t, size_t);
8574104Sblakej extern void *ndata_extra_base(struct memlist *, size_t, caddr_t);
8584104Sblakej extern size_t ndata_maxsize(struct memlist *);
8594104Sblakej extern size_t ndata_spare(struct memlist *, size_t, size_t);
8604104Sblakej 
8610Sstevel@tonic-gate #ifdef	__cplusplus
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate #endif
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate #endif	/* _VM_DEP_H */
866