1139825Simp/*-
21541Srgrimes * Copyright (c) 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software contributed to Berkeley by
61541Srgrimes * The Mach Operating System project at Carnegie-Mellon University.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes * 1. Redistributions of source code must retain the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer.
131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer in the
151541Srgrimes *    documentation and/or other materials provided with the distribution.
161541Srgrimes * 4. Neither the name of the University nor the names of its contributors
171541Srgrimes *    may be used to endorse or promote products derived from this software
181541Srgrimes *    without specific prior written permission.
191541Srgrimes *
201541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301541Srgrimes * SUCH DAMAGE.
311541Srgrimes *
321817Sdg *	from: @(#)vm_init.c	8.1 (Berkeley) 6/11/93
331541Srgrimes *
341541Srgrimes *
351541Srgrimes * Copyright (c) 1987, 1990 Carnegie-Mellon University.
361541Srgrimes * All rights reserved.
371541Srgrimes *
381541Srgrimes * Authors: Avadis Tevanian, Jr., Michael Wayne Young
395455Sdg *
401541Srgrimes * Permission to use, copy, modify and distribute this software and
411541Srgrimes * its documentation is hereby granted, provided that both the copyright
421541Srgrimes * notice and this permission notice appear in all copies of the
431541Srgrimes * software, derivative works or modified versions, and any portions
441541Srgrimes * thereof, and that both notices appear in supporting documentation.
455455Sdg *
465455Sdg * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
475455Sdg * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
481541Srgrimes * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
495455Sdg *
501541Srgrimes * Carnegie Mellon requests users of this software to return to
511541Srgrimes *
521541Srgrimes *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
531541Srgrimes *  School of Computer Science
541541Srgrimes *  Carnegie Mellon University
551541Srgrimes *  Pittsburgh PA 15213-3890
561541Srgrimes *
571541Srgrimes * any improvements or extensions that they make and grant Carnegie the
581541Srgrimes * rights to redistribute these changes.
591541Srgrimes */
601541Srgrimes
611541Srgrimes/*
621541Srgrimes *	Initialize the Virtual Memory subsystem.
631541Srgrimes */
641541Srgrimes
65116226Sobrien#include <sys/cdefs.h>
66116226Sobrien__FBSDID("$FreeBSD$");
67116226Sobrien
681541Srgrimes#include <sys/param.h>
6910358Sjulian#include <sys/kernel.h>
7076166Smarkm#include <sys/lock.h>
7176166Smarkm#include <sys/proc.h>
72248084Sattilio#include <sys/rwlock.h>
73254025Sjeff#include <sys/malloc.h>
74145530Skris#include <sys/sysctl.h>
753449Sphk#include <sys/systm.h>
76118764Ssilby#include <sys/selinfo.h>
77118764Ssilby#include <sys/pipe.h>
7882127Sdillon#include <sys/bio.h>
7982127Sdillon#include <sys/buf.h>
80252330Sjeff#include <sys/vmem.h>
811541Srgrimes
821541Srgrimes#include <vm/vm.h>
8382127Sdillon#include <vm/vm_param.h>
8482127Sdillon#include <vm/vm_kern.h>
8512662Sdg#include <vm/vm_object.h>
861541Srgrimes#include <vm/vm_page.h>
8712662Sdg#include <vm/vm_map.h>
889507Sdg#include <vm/vm_pager.h>
8912662Sdg#include <vm/vm_extern.h>
901541Srgrimes
91106605Stmmlong physmem;
92106605Stmm
93145530Skrisstatic int exec_map_entries = 16;
94145530SkrisTUNABLE_INT("vm.exec_map_entries", &exec_map_entries);
95145530SkrisSYSCTL_INT(_vm, OID_AUTO, exec_map_entries, CTLFLAG_RD, &exec_map_entries, 0,
96145530Skris    "Maximum number of simultaneous execs");
97145530Skris
981541Srgrimes/*
9910358Sjulian * System initialization
10010358Sjulian */
10192727Salfredstatic void vm_mem_init(void *);
102177253SrwatsonSYSINIT(vm_mem, SI_SUB_VM, SI_ORDER_FIRST, vm_mem_init, NULL);
10310358Sjulian
10410358Sjulian/*
105254025Sjeff * Import kva into the kernel arena.
106254025Sjeff */
107254025Sjeffstatic int
108254025Sjeffkva_import(void *unused, vmem_size_t size, int flags, vmem_addr_t *addrp)
109254025Sjeff{
110254025Sjeff	vm_offset_t addr;
111254025Sjeff	int result;
112254025Sjeff
113254025Sjeff	addr = vm_map_min(kernel_map);
114255426Sjhb	result = vm_map_find(kernel_map, NULL, 0, &addr, size, 0,
115254430Sjhb	    VMFS_SUPER_SPACE, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT);
116254025Sjeff	if (result != KERN_SUCCESS)
117254025Sjeff                return (ENOMEM);
118254025Sjeff
119254025Sjeff	*addrp = addr;
120254025Sjeff
121254025Sjeff	return (0);
122254025Sjeff}
123254025Sjeff
124254025Sjeff/*
1251541Srgrimes *	vm_init initializes the virtual memory system.
1261541Srgrimes *	This is done only by the first cpu up.
1271541Srgrimes *
1281541Srgrimes *	The start and end address of physical memory is passed in.
1291541Srgrimes */
13010358Sjulian/* ARGSUSED*/
13110358Sjulianstatic void
13212569Sbdevm_mem_init(dummy)
13312569Sbde	void *dummy;
1341541Srgrimes{
135254025Sjeff
1361541Srgrimes	/*
1375455Sdg	 * Initializes resident memory structures. From here on, all physical
1385455Sdg	 * memory is accounted for, and we use only virtual addresses.
1391541Srgrimes	 */
1401541Srgrimes	vm_set_page_size();
141127868Salc	virtual_avail = vm_page_startup(virtual_avail);
14271362Sdes
1431541Srgrimes	/*
1441541Srgrimes	 * Initialize other VM packages
1451541Srgrimes	 */
146252330Sjeff	vmem_startup();
14712767Sdyson	vm_object_init();
1481541Srgrimes	vm_map_startup();
1491541Srgrimes	kmem_init(virtual_avail, virtual_end);
150254025Sjeff
151254025Sjeff	/*
152254025Sjeff	 * Initialize the kernel_arena.  This can grow on demand.
153254025Sjeff	 */
154254025Sjeff	vmem_init(kernel_arena, "kernel arena", 0, 0, PAGE_SIZE, 0, 0);
155254025Sjeff	vmem_set_import(kernel_arena, kva_import, NULL, NULL,
156254025Sjeff#if VM_NRESERVLEVEL > 0
157254025Sjeff	    1 << (VM_LEVEL_0_ORDER + PAGE_SHIFT));
158254025Sjeff#else
159254543Sjeff	    /* On non-superpage architectures want large import sizes. */
160254543Sjeff	    PAGE_SIZE * 1024);
161254025Sjeff#endif
162254025Sjeff
163254025Sjeff	kmem_init_zero_region();
164127869Salc	pmap_init();
1651541Srgrimes	vm_pager_init();
1661541Srgrimes}
16782127Sdillon
16882127Sdillonvoid
16982127Sdillonvm_ksubmap_init(struct kva_md_info *kmi)
17082127Sdillon{
17182127Sdillon	vm_offset_t firstaddr;
17282127Sdillon	caddr_t v;
17382127Sdillon	vm_size_t size = 0;
174102600Speter	long physmem_est;
17582127Sdillon	vm_offset_t minaddr;
17682127Sdillon	vm_offset_t maxaddr;
17782127Sdillon
17882127Sdillon	/*
17982127Sdillon	 * Allocate space for system data structures.
18082127Sdillon	 * The first available kernel virtual address is in "v".
18182127Sdillon	 * As pages of kernel virtual memory are allocated, "v" is incremented.
18282127Sdillon	 * As pages of memory are allocated and cleared,
18382127Sdillon	 * "firstaddr" is incremented.
18482127Sdillon	 */
18582127Sdillon
18682127Sdillon	/*
18782127Sdillon	 * Make two passes.  The first pass calculates how much memory is
18882127Sdillon	 * needed and allocates it.  The second pass assigns virtual
18982127Sdillon	 * addresses to the various data structures.
19082127Sdillon	 */
19182127Sdillon	firstaddr = 0;
19282127Sdillonagain:
19382127Sdillon	v = (caddr_t)firstaddr;
19482127Sdillon
19582127Sdillon	/*
19682127Sdillon	 * Discount the physical memory larger than the size of kernel_map
19782127Sdillon	 * to avoid eating up all of KVA space.
19882127Sdillon	 */
199133253Salc	physmem_est = lmin(physmem, btoc(kernel_map->max_offset -
200133253Salc	    kernel_map->min_offset));
20182127Sdillon
20282127Sdillon	v = kern_vfs_bio_buffer_alloc(v, physmem_est);
20382127Sdillon
20482127Sdillon	/*
20582127Sdillon	 * End of first pass, size has been calculated so allocate memory
20682127Sdillon	 */
20782127Sdillon	if (firstaddr == 0) {
208117519Srobert		size = (vm_size_t)v;
209254025Sjeff		firstaddr = kmem_malloc(kernel_arena, round_page(size),
210254025Sjeff		    M_ZERO | M_WAITOK);
21182127Sdillon		if (firstaddr == 0)
21282127Sdillon			panic("startup: no room for tables");
21382127Sdillon		goto again;
21482127Sdillon	}
21582127Sdillon
21682127Sdillon	/*
21782127Sdillon	 * End of second pass, addresses have been assigned
21882127Sdillon	 */
21982127Sdillon	if ((vm_size_t)((char *)v - firstaddr) != size)
22082127Sdillon		panic("startup: table size inconsistency");
22182127Sdillon
222254025Sjeff	/*
223254025Sjeff	 * Allocate the clean map to hold all of the paging and I/O virtual
224254025Sjeff	 * memory.
225254025Sjeff	 */
226252330Sjeff	size = (long)nbuf * BKVASIZE + (long)nswbuf * MAXPHYS +
227252330Sjeff	    (long)bio_transient_maxcnt * MAXPHYS;
228254025Sjeff	kmi->clean_sva = firstaddr = kva_alloc(size);
229254025Sjeff	kmi->clean_eva = firstaddr + size;
230252330Sjeff
231254025Sjeff	/*
232254025Sjeff	 * Allocate the buffer arena.
233254025Sjeff	 */
234252330Sjeff	size = (long)nbuf * BKVASIZE;
235254025Sjeff	kmi->buffer_sva = firstaddr;
236252330Sjeff	kmi->buffer_eva = kmi->buffer_sva + size;
237252330Sjeff	vmem_init(buffer_arena, "buffer arena", kmi->buffer_sva, size,
238252330Sjeff	    PAGE_SIZE, 0, 0);
239254025Sjeff	firstaddr += size;
240252330Sjeff
241254025Sjeff	/*
242254025Sjeff	 * Now swap kva.
243254025Sjeff	 */
244254025Sjeff	swapbkva = firstaddr;
245252330Sjeff	size = (long)nswbuf * MAXPHYS;
246254025Sjeff	firstaddr += size;
247252330Sjeff
248254025Sjeff	/*
249254025Sjeff	 * And optionally transient bio space.
250254025Sjeff	 */
251248569Skib	if (bio_transient_maxcnt != 0) {
252252330Sjeff		size = (long)bio_transient_maxcnt * MAXPHYS;
253252330Sjeff		vmem_init(transient_arena, "transient arena",
254254025Sjeff		    firstaddr, size, PAGE_SIZE, 0, 0);
255254025Sjeff		firstaddr += size;
256248569Skib	}
257254025Sjeff	if (firstaddr != kmi->clean_eva)
258254025Sjeff		panic("Clean map calculation incorrect");
259254025Sjeff
260254025Sjeff	/*
261254025Sjeff 	 * Allocate the pageable submaps.
262254025Sjeff	 */
26382127Sdillon	exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
264210545Salc	    exec_map_entries * round_page(PATH_MAX + ARG_MAX), FALSE);
265178933Salc	pipe_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, maxpipekva,
266178933Salc	    FALSE);
26782127Sdillon}
268