mach_vm_dep.c revision 3177:6d48ee59c4fc
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27/*	All Rights Reserved   */
28
29/*
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
32 */
33
34#pragma ident	"%Z%%M%	%I%	%E% SMI"
35
36/*
37 * UNIX machine dependent virtual memory support.
38 */
39
40#include <sys/vm.h>
41#include <sys/exec.h>
42#include <sys/cmn_err.h>
43#include <sys/cpu_module.h>
44#include <sys/cpu.h>
45#include <sys/elf_SPARC.h>
46#include <sys/archsystm.h>
47#include <vm/hat_sfmmu.h>
48#include <sys/memnode.h>
49#include <sys/mem_cage.h>
50#include <vm/vm_dep.h>
51
52#if defined(__sparcv9) && defined(SF_ERRATA_57)
53caddr_t errata57_limit;
54#endif
55
56uint_t page_colors = 0;
57uint_t page_colors_mask = 0;
58uint_t page_coloring_shift = 0;
59int consistent_coloring;
60
61uint_t mmu_page_sizes = DEFAULT_MMU_PAGE_SIZES;
62uint_t max_mmu_page_sizes = MMU_PAGE_SIZES;
63uint_t mmu_hashcnt = DEFAULT_MAX_HASHCNT;
64uint_t max_mmu_hashcnt = MAX_HASHCNT;
65size_t mmu_ism_pagesize = DEFAULT_ISM_PAGESIZE;
66
67/*
68 * The sun4u hardware mapping sizes which will always be supported are
69 * 8K, 64K, 512K and 4M.  If sun4u based machines need to support other
70 * page sizes, platform or cpu specific routines need to modify the value.
71 * The base pagesize (p_szc == 0) must always be supported by the hardware.
72 */
73int mmu_exported_pagesize_mask = (1 << TTE8K) | (1 << TTE64K) |
74	(1 << TTE512K) | (1 << TTE4M);
75uint_t mmu_exported_page_sizes;
76
77uint_t szc_2_userszc[MMU_PAGE_SIZES];
78uint_t userszc_2_szc[MMU_PAGE_SIZES];
79
80extern uint_t vac_colors_mask;
81extern int vac_shift;
82
83hw_pagesize_t hw_page_array[] = {
84	{MMU_PAGESIZE, MMU_PAGESHIFT, 0, MMU_PAGESIZE >> MMU_PAGESHIFT},
85	{MMU_PAGESIZE64K, MMU_PAGESHIFT64K, 0,
86	    MMU_PAGESIZE64K >> MMU_PAGESHIFT},
87	{MMU_PAGESIZE512K, MMU_PAGESHIFT512K, 0,
88	    MMU_PAGESIZE512K >> MMU_PAGESHIFT},
89	{MMU_PAGESIZE4M, MMU_PAGESHIFT4M, 0, MMU_PAGESIZE4M >> MMU_PAGESHIFT},
90	{MMU_PAGESIZE32M, MMU_PAGESHIFT32M, 0,
91	    MMU_PAGESIZE32M >> MMU_PAGESHIFT},
92	{MMU_PAGESIZE256M, MMU_PAGESHIFT256M, 0,
93	    MMU_PAGESIZE256M >> MMU_PAGESHIFT},
94	{0, 0, 0, 0}
95};
96
97/*
98 * use_text_pgsz64k and use_text_pgsz512k allow the user to turn on these
99 * additional text page sizes for USIII-IV+ and OPL by changing the default
100 * values via /etc/system.
101 */
102int	use_text_pgsz64K = 0;
103int	use_text_pgsz512K = 0;
104
105/*
106 * Maximum and default segment size tunables for user heap, stack, private
107 * and shared anonymous memory, and user text and initialized data.
108 */
109size_t max_uheap_lpsize = MMU_PAGESIZE4M;
110size_t default_uheap_lpsize = MMU_PAGESIZE;
111size_t max_ustack_lpsize = MMU_PAGESIZE4M;
112size_t default_ustack_lpsize = MMU_PAGESIZE;
113size_t max_privmap_lpsize = MMU_PAGESIZE4M;
114size_t max_uidata_lpsize = MMU_PAGESIZE;
115size_t max_utext_lpsize = MMU_PAGESIZE4M;
116size_t max_shm_lpsize = MMU_PAGESIZE4M;
117
118void
119adjust_data_maxlpsize(size_t ismpagesize)
120{
121	if (max_uheap_lpsize == MMU_PAGESIZE4M) {
122		max_uheap_lpsize = ismpagesize;
123	}
124	if (max_ustack_lpsize == MMU_PAGESIZE4M) {
125		max_ustack_lpsize = ismpagesize;
126	}
127	if (max_privmap_lpsize == MMU_PAGESIZE4M) {
128		max_privmap_lpsize = ismpagesize;
129	}
130	if (max_shm_lpsize == MMU_PAGESIZE4M) {
131		max_shm_lpsize = ismpagesize;
132	}
133}
134
135/*
136 * map_addr_proc() is the routine called when the system is to
137 * choose an address for the user.  We will pick an address
138 * range which is just below the current stack limit.  The
139 * algorithm used for cache consistency on machines with virtual
140 * address caches is such that offset 0 in the vnode is always
141 * on a shm_alignment'ed aligned address.  Unfortunately, this
142 * means that vnodes which are demand paged will not be mapped
143 * cache consistently with the executable images.  When the
144 * cache alignment for a given object is inconsistent, the
145 * lower level code must manage the translations so that this
146 * is not seen here (at the cost of efficiency, of course).
147 *
148 * addrp is a value/result parameter.
149 *	On input it is a hint from the user to be used in a completely
150 *	machine dependent fashion.  For MAP_ALIGN, addrp contains the
151 *	minimal alignment.
152 *
153 *	On output it is NULL if no address can be found in the current
154 *	processes address space or else an address that is currently
155 *	not mapped for len bytes with a page of red zone on either side.
156 *	If vacalign is true, then the selected address will obey the alignment
157 *	constraints of a vac machine based on the given off value.
158 */
159/*ARGSUSED4*/
160void
161map_addr_proc(caddr_t *addrp, size_t len, offset_t off, int vacalign,
162    caddr_t userlimit, struct proc *p, uint_t flags)
163{
164	struct as *as = p->p_as;
165	caddr_t addr;
166	caddr_t base;
167	size_t slen;
168	uintptr_t align_amount;
169	int allow_largepage_alignment = 1;
170
171	base = p->p_brkbase;
172	if (userlimit < as->a_userlimit) {
173		/*
174		 * This happens when a program wants to map something in
175		 * a range that's accessible to a program in a smaller
176		 * address space.  For example, a 64-bit program might
177		 * be calling mmap32(2) to guarantee that the returned
178		 * address is below 4Gbytes.
179		 */
180		ASSERT(userlimit > base);
181		slen = userlimit - base;
182	} else {
183		slen = p->p_usrstack - base - (((size_t)rctl_enforced_value(
184		    rctlproc_legacy[RLIMIT_STACK], p->p_rctls, p) + PAGEOFFSET)
185		    & PAGEMASK);
186	}
187	len = (len + PAGEOFFSET) & PAGEMASK;
188
189	/*
190	 * Redzone for each side of the request. This is done to leave
191	 * one page unmapped between segments. This is not required, but
192	 * it's useful for the user because if their program strays across
193	 * a segment boundary, it will catch a fault immediately making
194	 * debugging a little easier.
195	 */
196	len += (2 * PAGESIZE);
197
198	/*
199	 *  If the request is larger than the size of a particular
200	 *  mmu level, then we use that level to map the request.
201	 *  But this requires that both the virtual and the physical
202	 *  addresses be aligned with respect to that level, so we
203	 *  do the virtual bit of nastiness here.
204	 *
205	 *  For 32-bit processes, only those which have specified
206	 *  MAP_ALIGN or an addr will be aligned on a page size > 4MB. Otherwise
207	 *  we can potentially waste up to 256MB of the 4G process address
208	 *  space just for alignment.
209	 */
210	if (p->p_model == DATAMODEL_ILP32 && ((flags & MAP_ALIGN) == 0 ||
211	    ((uintptr_t)*addrp) != 0)) {
212		allow_largepage_alignment = 0;
213	}
214	if ((mmu_page_sizes == max_mmu_page_sizes) &&
215	    allow_largepage_alignment &&
216		(len >= MMU_PAGESIZE256M)) {	/* 256MB mappings */
217		align_amount = MMU_PAGESIZE256M;
218	} else if ((mmu_page_sizes == max_mmu_page_sizes) &&
219	    allow_largepage_alignment &&
220		(len >= MMU_PAGESIZE32M)) {	/* 32MB mappings */
221		align_amount = MMU_PAGESIZE32M;
222	} else if (len >= MMU_PAGESIZE4M) {  /* 4MB mappings */
223		align_amount = MMU_PAGESIZE4M;
224	} else if (len >= MMU_PAGESIZE512K) { /* 512KB mappings */
225		align_amount = MMU_PAGESIZE512K;
226	} else if (len >= MMU_PAGESIZE64K) { /* 64KB mappings */
227		align_amount = MMU_PAGESIZE64K;
228	} else  {
229		/*
230		 * Align virtual addresses on a 64K boundary to ensure
231		 * that ELF shared libraries are mapped with the appropriate
232		 * alignment constraints by the run-time linker.
233		 */
234		align_amount = ELF_SPARC_MAXPGSZ;
235		if ((flags & MAP_ALIGN) && ((uintptr_t)*addrp != 0) &&
236			((uintptr_t)*addrp < align_amount))
237			align_amount = (uintptr_t)*addrp;
238	}
239
240	/*
241	 * 64-bit processes require 1024K alignment of ELF shared libraries.
242	 */
243	if (p->p_model == DATAMODEL_LP64)
244		align_amount = MAX(align_amount, ELF_SPARCV9_MAXPGSZ);
245#ifdef VAC
246	if (vac && vacalign && (align_amount < shm_alignment))
247		align_amount = shm_alignment;
248#endif
249
250	if ((flags & MAP_ALIGN) && ((uintptr_t)*addrp > align_amount)) {
251		align_amount = (uintptr_t)*addrp;
252	}
253	len += align_amount;
254
255	/*
256	 * Look for a large enough hole starting below the stack limit.
257	 * After finding it, use the upper part.  Addition of PAGESIZE is
258	 * for the redzone as described above.
259	 */
260	as_purge(as);
261	if (as_gap(as, len, &base, &slen, AH_HI, NULL) == 0) {
262		caddr_t as_addr;
263
264		addr = base + slen - len + PAGESIZE;
265		as_addr = addr;
266		/*
267		 * Round address DOWN to the alignment amount,
268		 * add the offset, and if this address is less
269		 * than the original address, add alignment amount.
270		 */
271		addr = (caddr_t)((uintptr_t)addr & (~(align_amount - 1l)));
272		addr += (long)(off & (align_amount - 1l));
273		if (addr < as_addr) {
274			addr += align_amount;
275		}
276
277		ASSERT(addr <= (as_addr + align_amount));
278		ASSERT(((uintptr_t)addr & (align_amount - 1l)) ==
279		    ((uintptr_t)(off & (align_amount - 1l))));
280		*addrp = addr;
281
282#if defined(SF_ERRATA_57)
283		if (AS_TYPE_64BIT(as) && addr < errata57_limit) {
284			*addrp = NULL;
285		}
286#endif
287	} else {
288		*addrp = NULL;	/* no more virtual space */
289	}
290}
291
292/*
293 * Platform-dependent page scrub call.
294 */
295void
296pagescrub(page_t *pp, uint_t off, uint_t len)
297{
298	/*
299	 * For now, we rely on the fact that pagezero() will
300	 * always clear UEs.
301	 */
302	pagezero(pp, off, len);
303}
304
305/*ARGSUSED*/
306void
307sync_data_memory(caddr_t va, size_t len)
308{
309	cpu_flush_ecache();
310}
311
312/*
313 * platform specific large pages for kernel heap support
314 */
315void
316mmu_init_kcontext()
317{
318	extern void set_kcontextreg();
319
320	if (kcontextreg)
321		set_kcontextreg();
322}
323
324void
325contig_mem_init(void)
326{
327	/* not applicable to sun4u */
328}
329
330size_t
331exec_get_spslew(void)
332{
333	return (0);
334}
335