2005-09-26 10:04:21 +04:00
/*
* This file contains the routines for initializing the MMU
* on the 4 xx series of chips .
* - - paulus
*
* Derived from arch / ppc / mm / init . c :
* 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
*
* 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 .
*
*/
# 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/ptrace.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/highmem.h>
2010-07-07 02:39:01 +04:00
# include <linux/memblock.h>
2005-09-26 10:04:21 +04:00
# include <asm/pgalloc.h>
# include <asm/prom.h>
# include <asm/io.h>
# include <asm/mmu_context.h>
# include <asm/pgtable.h>
# include <asm/mmu.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2005-09-26 10:04:21 +04:00
# include <asm/smp.h>
# include <asm/bootx.h>
# include <asm/machdep.h>
# include <asm/setup.h>
2010-07-07 02:39:01 +04:00
2005-09-26 10:04:21 +04:00
# include "mmu_decl.h"
extern int __map_without_ltlbs ;
/*
* MMU_init_hw does the chip - specific initialization of the MMU hardware .
*/
void __init MMU_init_hw ( void )
{
/*
* The Zone Protection Register ( ZPR ) defines how protection will
* be applied to every page which is a member of a given zone . At
* present , we utilize only two of the 4 xx ' s zones .
* The zone index bits ( of ZSEL ) in the PTE are used for software
* indicators , except the LSB . For user access , zone 1 is used ,
* for kernel access , zone 0 is used . We set all but zone 1
* to zero , allowing only kernel access as indicated in the PTE .
* For zone 1 , we set a 01 binary ( a value of 10 will not work )
* to allow user access as indicated in the PTE . This also allows
* kernel access as indicated in the PTE .
*/
mtspr ( SPRN_ZPR , 0x10000000 ) ;
flush_instruction_cache ( ) ;
/*
* Set up the real - mode cache parameters for the exception vector
* handlers ( which are run in real - mode ) .
*/
mtspr ( SPRN_DCWR , 0x00000000 ) ; /* All caching is write-back */
/*
* Cache instruction and data space where the exception
* vectors and the kernel live in real - mode .
*/
2010-02-10 06:54:59 +03:00
mtspr ( SPRN_DCCR , 0xFFFF0000 ) ; /* 2GByte of data space at 0x0. */
mtspr ( SPRN_ICCR , 0xFFFF0000 ) ; /* 2GByte of instr. space at 0x0. */
2005-09-26 10:04:21 +04:00
}
# define LARGE_PAGE_SIZE_16M (1<<24)
# define LARGE_PAGE_SIZE_4M (1<<22)
2009-12-14 19:04:24 +03:00
unsigned long __init mmu_mapin_ram ( unsigned long top )
2005-09-26 10:04:21 +04:00
{
2008-10-29 14:41:14 +03:00
unsigned long v , s , mapped ;
2005-09-26 10:04:21 +04:00
phys_addr_t p ;
v = KERNELBASE ;
2008-04-15 23:52:21 +04:00
p = 0 ;
2007-10-31 09:41:20 +03:00
s = total_lowmem ;
2005-09-26 10:04:21 +04:00
2007-10-31 09:41:20 +03:00
if ( __map_without_ltlbs )
return 0 ;
2005-09-26 10:04:21 +04:00
2007-10-31 09:41:20 +03:00
while ( s > = LARGE_PAGE_SIZE_16M ) {
2005-09-26 10:04:21 +04:00
pmd_t * pmdp ;
2009-08-18 23:00:34 +04:00
unsigned long val = p | _PMD_SIZE_16M | _PAGE_EXEC | _PAGE_HWWRITE ;
2005-09-26 10:04:21 +04:00
2007-08-20 16:28:48 +04:00
pmdp = pmd_offset ( pud_offset ( pgd_offset_k ( v ) , v ) , v ) ;
2015-12-01 06:36:35 +03:00
* pmdp + + = __pmd ( val ) ;
* pmdp + + = __pmd ( val ) ;
* pmdp + + = __pmd ( val ) ;
* pmdp + + = __pmd ( val ) ;
2005-09-26 10:04:21 +04:00
v + = LARGE_PAGE_SIZE_16M ;
p + = LARGE_PAGE_SIZE_16M ;
2007-10-31 09:41:20 +03:00
s - = LARGE_PAGE_SIZE_16M ;
2005-09-26 10:04:21 +04:00
}
2007-10-31 09:41:20 +03:00
while ( s > = LARGE_PAGE_SIZE_4M ) {
2005-09-26 10:04:21 +04:00
pmd_t * pmdp ;
2009-08-18 23:00:34 +04:00
unsigned long val = p | _PMD_SIZE_4M | _PAGE_EXEC | _PAGE_HWWRITE ;
2005-09-26 10:04:21 +04:00
2007-08-20 16:28:48 +04:00
pmdp = pmd_offset ( pud_offset ( pgd_offset_k ( v ) , v ) , v ) ;
2015-12-01 06:36:35 +03:00
* pmdp = __pmd ( val ) ;
2005-09-26 10:04:21 +04:00
v + = LARGE_PAGE_SIZE_4M ;
p + = LARGE_PAGE_SIZE_4M ;
2007-10-31 09:41:20 +03:00
s - = LARGE_PAGE_SIZE_4M ;
2005-09-26 10:04:21 +04:00
}
2008-10-29 14:41:14 +03:00
mapped = total_lowmem - s ;
/* If the size of RAM is not an exact power of two, we may not
* have covered RAM in its entirety with 16 and 4 MiB
* pages . Consequently , restrict the top end of RAM currently
2010-07-12 08:36:09 +04:00
* allocable so that calls to the MEMBLOCK to allocate PTEs for " tail "
2008-10-29 14:41:14 +03:00
* coverage with normal - sized pages ( or other reasons ) do not
* attempt to allocate outside the allowed range .
*/
2010-07-07 02:39:02 +04:00
memblock_set_current_limit ( mapped ) ;
2008-10-29 14:41:14 +03:00
return mapped ;
2005-09-26 10:04:21 +04:00
}
2010-07-07 02:39:02 +04:00
void setup_initial_memory_limit ( phys_addr_t first_memblock_base ,
phys_addr_t first_memblock_size )
{
/* We don't currently support the first MEMBLOCK not mapping 0
* physical on those processors
*/
BUG_ON ( first_memblock_base ! = 0 ) ;
/* 40x can only access 16MB at the moment (see head_40x.S) */
memblock_set_current_limit ( min_t ( u64 , first_memblock_size , 0x00800000 ) ) ;
}