2005-09-26 16:04:21 +10:00
/*
* PowerPC version
* Copyright ( C ) 1995 - 1996 Gary Thomas ( gdt @ linuxppc . org )
*
* Modifications by Paul Mackerras ( PowerMac ) ( paulus @ cs . anu . edu . au )
* and Cort Dougan ( PReP ) ( cort @ cs . nmt . edu )
* Copyright ( C ) 1996 Paul Mackerras
*
* Derived from " arch/i386/mm/init.c "
* Copyright ( C ) 1991 , 1992 , 1993 , 1994 Linus Torvalds
*
* Dave Engebretsen < engebret @ us . ibm . com >
* Rework for PPC64 port .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*
*/
2005-11-10 14:53:16 +11:00
# undef DEBUG
2005-09-26 16:04:21 +10:00
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/string.h>
# include <linux/types.h>
# include <linux/mman.h>
# include <linux/mm.h>
# include <linux/swap.h>
# include <linux/stddef.h>
# include <linux/vmalloc.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/bootmem.h>
# include <linux/highmem.h>
# include <linux/idr.h>
# include <linux/nodemask.h>
# include <linux/module.h>
2006-06-27 02:53:52 -07:00
# include <linux/poison.h>
2005-09-26 16:04:21 +10:00
# include <asm/pgalloc.h>
# include <asm/page.h>
# include <asm/prom.h>
# include <asm/lmb.h>
# include <asm/rtas.h>
# include <asm/io.h>
# include <asm/mmu_context.h>
# include <asm/pgtable.h>
# include <asm/mmu.h>
# include <asm/uaccess.h>
# include <asm/smp.h>
# include <asm/machdep.h>
# include <asm/tlb.h>
# include <asm/eeh.h>
# include <asm/processor.h>
# include <asm/mmzone.h>
# include <asm/cputable.h>
# include <asm/sections.h>
# include <asm/system.h>
# include <asm/iommu.h>
# include <asm/abs_addr.h>
# include <asm/vdso.h>
2005-11-16 15:43:48 +11:00
# include "mmu_decl.h"
2005-09-26 16:04:21 +10:00
2005-11-10 14:53:16 +11:00
# ifdef DEBUG
# define DBG(fmt...) printk(fmt)
# else
# define DBG(fmt...)
# endif
2005-09-26 16:04:21 +10:00
# if PGTABLE_RANGE > USER_VSID_RANGE
# warning Limited user VSID range means pagetable space is wasted
# endif
# if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
# warning TASK_SIZE is smaller than it needs to be.
# endif
/* max amount of RAM to use */
unsigned long __max_memory ;
void free_initmem ( void )
{
unsigned long addr ;
addr = ( unsigned long ) __init_begin ;
for ( ; addr < ( unsigned long ) __init_end ; addr + = PAGE_SIZE ) {
2006-06-27 02:53:52 -07:00
memset ( ( void * ) addr , POISON_FREE_INITMEM , PAGE_SIZE ) ;
2005-09-26 16:04:21 +10:00
ClearPageReserved ( virt_to_page ( addr ) ) ;
2006-03-22 00:08:40 -08:00
init_page_count ( virt_to_page ( addr ) ) ;
2005-09-26 16:04:21 +10:00
free_page ( addr ) ;
totalram_pages + + ;
}
printk ( " Freeing unused kernel memory: %luk freed \n " ,
( ( unsigned long ) __init_end - ( unsigned long ) __init_begin ) > > 10 ) ;
}
# ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem ( unsigned long start , unsigned long end )
{
if ( start < end )
printk ( " Freeing initrd memory: %ldk freed \n " , ( end - start ) > > 10 ) ;
for ( ; start < end ; start + = PAGE_SIZE ) {
ClearPageReserved ( virt_to_page ( start ) ) ;
2006-03-22 00:08:40 -08:00
init_page_count ( virt_to_page ( start ) ) ;
2005-09-26 16:04:21 +10:00
free_page ( start ) ;
totalram_pages + + ;
}
}
# endif
static struct kcore_list kcore_vmem ;
static int __init setup_kcore ( void )
{
int i ;
for ( i = 0 ; i < lmb . memory . cnt ; i + + ) {
unsigned long base , size ;
struct kcore_list * kcore_mem ;
base = lmb . memory . region [ i ] . base ;
size = lmb . memory . region [ i ] . size ;
/* GFP_ATOMIC to avoid might_sleep warnings during boot */
kcore_mem = kmalloc ( sizeof ( struct kcore_list ) , GFP_ATOMIC ) ;
if ( ! kcore_mem )
2006-11-17 06:21:12 +01:00
panic ( " %s: kmalloc failed \n " , __FUNCTION__ ) ;
2005-09-26 16:04:21 +10:00
kclist_add ( kcore_mem , __va ( base ) , size ) ;
}
kclist_add ( & kcore_vmem , ( void * ) VMALLOC_START , VMALLOC_END - VMALLOC_START ) ;
return 0 ;
}
module_init ( setup_kcore ) ;
2006-12-06 20:33:20 -08:00
static void zero_ctor ( void * addr , struct kmem_cache * cache , unsigned long flags )
2005-09-26 16:04:21 +10:00
{
memset ( addr , 0 , kmem_cache_size ( cache ) ) ;
}
2005-11-10 14:53:16 +11:00
static const unsigned int pgtable_cache_size [ 2 ] = {
2007-05-09 14:38:48 +10:00
PGD_TABLE_SIZE , PMD_TABLE_SIZE
2005-09-26 16:04:21 +10:00
} ;
static const char * pgtable_cache_name [ ARRAY_SIZE ( pgtable_cache_size ) ] = {
2007-05-09 14:38:48 +10:00
# ifdef CONFIG_PPC_64K_PAGES
" pgd_cache " , " pmd_cache " ,
# else
" pgd_cache " , " pud_pmd_cache " ,
2005-11-07 11:06:55 +11:00
# endif /* CONFIG_PPC_64K_PAGES */
2007-05-09 14:38:48 +10:00
} ;
2005-09-26 16:04:21 +10:00
2006-04-28 15:02:51 +10:00
# ifdef CONFIG_HUGETLB_PAGE
/* Hugepages need one extra cache, initialized in hugetlbpage.c. We
* can ' t put into the tables above , because HPAGE_SHIFT is not compile
* time constant . */
2006-12-06 20:33:20 -08:00
struct kmem_cache * pgtable_cache [ ARRAY_SIZE ( pgtable_cache_size ) + 1 ] ;
2006-04-28 15:02:51 +10:00
# else
2006-12-06 20:33:20 -08:00
struct kmem_cache * pgtable_cache [ ARRAY_SIZE ( pgtable_cache_size ) ] ;
2006-04-28 15:02:51 +10:00
# endif
2005-09-26 16:04:21 +10:00
void pgtable_cache_init ( void )
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( pgtable_cache_size ) ; i + + ) {
int size = pgtable_cache_size [ i ] ;
const char * name = pgtable_cache_name [ i ] ;
2005-11-10 14:53:16 +11:00
DBG ( " Allocating page table cache %s (#%d) "
" for size: %08x... \n " , name , i , size ) ;
2005-09-26 16:04:21 +10:00
pgtable_cache [ i ] = kmem_cache_create ( name ,
size , size ,
2007-05-08 00:23:13 -07:00
SLAB_PANIC ,
2005-09-26 16:04:21 +10:00
zero_ctor ,
NULL ) ;
}
}