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