1/* init.c: memory initialisation for FRV 2 * 3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 * 11 * Derived from: 12 * - linux/arch/m68knommu/mm/init.c 13 * - Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, Kenneth Albanowski <kjahds@kjahds.com>, 14 * - Copyright (C) 2000 Lineo, Inc. (www.lineo.com) 15 * - linux/arch/m68k/mm/init.c 16 * - Copyright (C) 1995 Hamish Macdonald 17 */ 18 19#include <linux/signal.h> 20#include <linux/sched.h> 21#include <linux/pagemap.h> 22#include <linux/swap.h> 23#include <linux/mm.h> 24#include <linux/kernel.h> 25#include <linux/string.h> 26#include <linux/types.h> 27#include <linux/bootmem.h> 28#include <linux/highmem.h> 29 30#include <asm/setup.h> 31#include <asm/segment.h> 32#include <asm/page.h> 33#include <asm/pgtable.h> 34#include <asm/system.h> 35#include <asm/mmu_context.h> 36#include <asm/virtconvert.h> 37#include <asm/sections.h> 38#include <asm/tlb.h> 39 40#undef DEBUG 41 42DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 43 44/* 45 * BAD_PAGE is the page that is used for page faults when linux 46 * is out-of-memory. Older versions of linux just did a 47 * do_exit(), but using this instead means there is less risk 48 * for a process dying in kernel mode, possibly leaving a inode 49 * unused etc.. 50 * 51 * BAD_PAGETABLE is the accompanying page-table: it is initialized 52 * to point to BAD_PAGE entries. 53 * 54 * ZERO_PAGE is a special page that is used for zero-initialized 55 * data and COW. 56 */ 57static unsigned long empty_bad_page_table; 58static unsigned long empty_bad_page; 59unsigned long empty_zero_page; 60 61/*****************************************************************************/ 62/* 63 * 64 */ 65void show_mem(void) 66{ 67 unsigned long i; 68 int free = 0, total = 0, reserved = 0, shared = 0; 69 70 printk("\nMem-info:\n"); 71 show_free_areas(); 72 i = max_mapnr; 73 while (i-- > 0) { 74 struct page *page = &mem_map[i]; 75 76 total++; 77 if (PageReserved(page)) 78 reserved++; 79 else if (!page_count(page)) 80 free++; 81 else 82 shared += page_count(page) - 1; 83 } 84 85 printk("%d pages of RAM\n",total); 86 printk("%d free pages\n",free); 87 printk("%d reserved pages\n",reserved); 88 printk("%d pages shared\n",shared); 89 90} /* end show_mem() */ 91 92/*****************************************************************************/ 93/* 94 * paging_init() continues the virtual memory environment setup which 95 * was begun by the code in arch/head.S. 96 * The parameters are pointers to where to stick the starting and ending 97 * addresses of available kernel virtual memory. 98 */ 99void __init paging_init(void) 100{ 101 unsigned long zones_size[MAX_NR_ZONES] = {0, }; 102 103 /* allocate some pages for kernel housekeeping tasks */ 104 empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); 105 empty_bad_page = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); 106 empty_zero_page = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); 107 108 memset((void *) empty_zero_page, 0, PAGE_SIZE); 109 110#ifdef CONFIG_HIGHMEM 111 if (num_physpages - num_mappedpages) { 112 pgd_t *pge; 113 pud_t *pue; 114 pmd_t *pme; 115 116 pkmap_page_table = alloc_bootmem_pages(PAGE_SIZE); 117 118 memset(pkmap_page_table, 0, PAGE_SIZE); 119 120 pge = swapper_pg_dir + pgd_index_k(PKMAP_BASE); 121 pue = pud_offset(pge, PKMAP_BASE); 122 pme = pmd_offset(pue, PKMAP_BASE); 123 __set_pmd(pme, virt_to_phys(pkmap_page_table) | _PAGE_TABLE); 124 } 125#endif 126 127 /* distribute the allocatable pages across the various zones and pass them to the allocator 128 */ 129 zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; 130#ifdef CONFIG_HIGHMEM 131 zones_size[ZONE_HIGHMEM] = num_physpages - num_mappedpages; 132#endif 133 134 free_area_init(zones_size); 135 136#ifdef CONFIG_MMU 137 /* initialise init's MMU context */ 138 init_new_context(&init_task, &init_mm); 139#endif 140 141} /* end paging_init() */ 142 143/*****************************************************************************/ 144/* 145 * 146 */ 147void __init mem_init(void) 148{ 149 unsigned long npages = (memory_end - memory_start) >> PAGE_SHIFT; 150 unsigned long tmp; 151#ifdef CONFIG_MMU 152 unsigned long loop, pfn; 153 int datapages = 0; 154#endif 155 int codek = 0, datak = 0; 156 157 /* this will put all memory onto the freelists */ 158 totalram_pages = free_all_bootmem(); 159 160#ifdef CONFIG_MMU 161 for (loop = 0 ; loop < npages ; loop++) 162 if (PageReserved(&mem_map[loop])) 163 datapages++; 164 165#ifdef CONFIG_HIGHMEM 166 for (pfn = num_physpages - 1; pfn >= num_mappedpages; pfn--) { 167 struct page *page = &mem_map[pfn]; 168 169 ClearPageReserved(page); 170 init_page_count(page); 171 __free_page(page); 172 totalram_pages++; 173 } 174#endif 175 176 codek = ((unsigned long) &_etext - (unsigned long) &_stext) >> 10; 177 datak = datapages << (PAGE_SHIFT - 10); 178 179#else 180 codek = (_etext - _stext) >> 10; 181 datak = 0; //(_ebss - _sdata) >> 10; 182#endif 183 184 tmp = nr_free_pages() << PAGE_SHIFT; 185 printk("Memory available: %luKiB/%luKiB RAM, %luKiB/%luKiB ROM (%dKiB kernel code, %dKiB data)\n", 186 tmp >> 10, 187 npages << (PAGE_SHIFT - 10), 188 (rom_length > 0) ? ((rom_length >> 10) - codek) : 0, 189 rom_length >> 10, 190 codek, 191 datak 192 ); 193 194} /* end mem_init() */ 195 196/*****************************************************************************/ 197/* 198 * free the memory that was only required for initialisation 199 */ 200void __init free_initmem(void) 201{ 202#if defined(CONFIG_RAMKERNEL) && !defined(CONFIG_PROTECT_KERNEL) 203 unsigned long start, end, addr; 204 205 start = PAGE_ALIGN((unsigned long) &__init_begin); /* round up */ 206 end = ((unsigned long) &__init_end) & PAGE_MASK; /* round down */ 207 208 /* next to check that the page we free is not a partial page */ 209 for (addr = start; addr < end; addr += PAGE_SIZE) { 210 ClearPageReserved(virt_to_page(addr)); 211 init_page_count(virt_to_page(addr)); 212 free_page(addr); 213 totalram_pages++; 214 } 215 216 printk("Freeing unused kernel memory: %ldKiB freed (0x%lx - 0x%lx)\n", 217 (end - start) >> 10, start, end); 218#endif 219} /* end free_initmem() */ 220 221/*****************************************************************************/ 222/* 223 * free the initial ramdisk memory 224 */ 225#ifdef CONFIG_BLK_DEV_INITRD 226void __init free_initrd_mem(unsigned long start, unsigned long end) 227{ 228 int pages = 0; 229 for (; start < end; start += PAGE_SIZE) { 230 ClearPageReserved(virt_to_page(start)); 231 init_page_count(virt_to_page(start)); 232 free_page(start); 233 totalram_pages++; 234 pages++; 235 } 236 printk("Freeing initrd memory: %dKiB freed\n", (pages * PAGE_SIZE) >> 10); 237} /* end free_initrd_mem() */ 238#endif 239