2019-05-27 08:55:01 +02:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
2005-09-26 16:04:21 +10:00
/*
* Declarations of procedures and variables shared between files
* in arch / ppc / mm / .
*
* 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
*/
2007-04-24 13:09:12 +10:00
# include <linux/mm.h>
2005-09-26 16:04:21 +10:00
# include <asm/mmu.h>
2008-12-18 19:13:42 +00:00
# ifdef CONFIG_PPC_MMU_NOHASH
2018-03-21 15:16:58 +01:00
# include <asm/trace.h>
2008-12-18 19:13:42 +00:00
/*
* On 40 x and 8 xx , we directly inline tlbia and tlbivax
*/
2017-08-08 13:58:54 +02:00
# if defined(CONFIG_40x) || defined(CONFIG_PPC_8xx)
2008-12-18 19:13:42 +00:00
static inline void _tlbil_all ( void )
{
2009-01-06 17:56:51 +00:00
asm volatile ( " sync; tlbia; isync " : : : " memory " ) ;
2018-03-21 15:17:00 +01:00
trace_tlbia ( MMU_NO_CONTEXT ) ;
2008-12-18 19:13:42 +00:00
}
static inline void _tlbil_pid ( unsigned int pid )
{
2009-01-06 17:56:51 +00:00
asm volatile ( " sync; tlbia; isync " : : : " memory " ) ;
2018-03-21 15:17:00 +01:00
trace_tlbia ( pid ) ;
2008-12-18 19:13:42 +00:00
}
2009-07-23 23:15:24 +00:00
# define _tlbil_pid_noind(pid) _tlbil_pid(pid)
2017-08-08 13:58:54 +02:00
# else /* CONFIG_40x || CONFIG_PPC_8xx */
2008-12-18 19:13:42 +00:00
extern void _tlbil_all ( void ) ;
extern void _tlbil_pid ( unsigned int pid ) ;
2009-07-23 23:15:47 +00:00
# ifdef CONFIG_PPC_BOOK3E
extern void _tlbil_pid_noind ( unsigned int pid ) ;
# else
2009-07-23 23:15:24 +00:00
# define _tlbil_pid_noind(pid) _tlbil_pid(pid)
2009-07-23 23:15:47 +00:00
# endif
2017-08-08 13:58:54 +02:00
# endif /* !(CONFIG_40x || CONFIG_PPC_8xx) */
2008-12-18 19:13:42 +00:00
/*
* On 8 xx , we directly inline tlbie , on others , it ' s extern
*/
2017-08-08 13:58:54 +02:00
# ifdef CONFIG_PPC_8xx
2009-07-23 23:15:24 +00:00
static inline void _tlbil_va ( unsigned long address , unsigned int pid ,
unsigned int tsize , unsigned int ind )
2008-12-18 19:13:42 +00:00
{
2009-01-06 17:56:51 +00:00
asm volatile ( " tlbie %0; sync " : : " r " ( address ) : " memory " ) ;
2018-03-21 15:16:58 +01:00
trace_tlbie ( 0 , 0 , address , pid , 0 , 0 , 0 ) ;
2008-12-18 19:13:42 +00:00
}
2009-07-23 23:15:47 +00:00
# elif defined(CONFIG_PPC_BOOK3E)
extern void _tlbil_va ( unsigned long address , unsigned int pid ,
unsigned int tsize , unsigned int ind ) ;
# else
2009-07-23 23:15:24 +00:00
extern void __tlbil_va ( unsigned long address , unsigned int pid ) ;
static inline void _tlbil_va ( unsigned long address , unsigned int pid ,
unsigned int tsize , unsigned int ind )
{
__tlbil_va ( address , pid ) ;
}
2017-08-08 13:58:54 +02:00
# endif /* CONFIG_PPC_8xx */
2008-12-18 19:13:42 +00:00
2010-03-05 10:43:12 +00:00
# if defined(CONFIG_PPC_BOOK3E) || defined(CONFIG_PPC_47x)
2009-07-23 23:15:47 +00:00
extern void _tlbivax_bcast ( unsigned long address , unsigned int pid ,
unsigned int tsize , unsigned int ind ) ;
# else
2009-07-23 23:15:24 +00:00
static inline void _tlbivax_bcast ( unsigned long address , unsigned int pid ,
unsigned int tsize , unsigned int ind )
2008-12-18 19:13:42 +00:00
{
BUG ( ) ;
}
2009-07-23 23:15:47 +00:00
# endif
2008-12-18 19:13:42 +00:00
2019-04-26 16:36:39 +00:00
static inline void print_system_hash_info ( void ) { }
2008-12-18 19:13:42 +00:00
# else /* CONFIG_PPC_MMU_NOHASH */
2019-04-26 16:36:39 +00:00
void print_system_hash_info ( void ) ;
2008-12-18 19:13:42 +00:00
# endif /* CONFIG_PPC_MMU_NOHASH */
2005-10-10 21:58:35 +10:00
# ifdef CONFIG_PPC32
2008-12-08 19:34:55 -08:00
2005-09-26 16:04:21 +10:00
extern void mapin_ram ( void ) ;
2008-06-14 09:41:42 +10:00
extern void setbat ( int index , unsigned long virt , phys_addr_t phys ,
2015-03-25 20:11:55 +11:00
unsigned int size , pgprot_t prot ) ;
2005-09-26 16:04:21 +10:00
extern int __map_without_bats ;
extern unsigned int rtas_data , rtas_size ;
2007-06-13 14:52:56 +10:00
struct hash_pte ;
2019-04-26 16:23:36 +00:00
extern u8 early_hash [ ] ;
2009-07-23 23:15:58 +00:00
# endif /* CONFIG_PPC32 */
2005-10-10 21:58:35 +10:00
extern unsigned long __max_low_memory ;
2008-04-16 05:52:25 +10:00
extern phys_addr_t __initial_memory_limit_addr ;
2008-07-10 01:09:23 +10:00
extern phys_addr_t total_memory ;
extern phys_addr_t total_lowmem ;
2008-04-16 05:52:21 +10:00
extern phys_addr_t memstart_addr ;
2008-04-16 05:52:22 +10:00
extern phys_addr_t lowmem_end_addr ;
2005-09-26 16:04:21 +10:00
2009-12-12 06:31:53 +00:00
# ifdef CONFIG_WII
extern unsigned long wii_hole_start ;
extern unsigned long wii_hole_size ;
extern unsigned long wii_mmu_mapin_mem2 ( unsigned long top ) ;
extern void wii_memory_fixups ( void ) ;
# endif
2005-09-26 16:04:21 +10:00
/* ...and now those things that may be slightly different between processor
* architectures . - - Dan
*/
powerpc/8xx: Map linear kernel RAM with 8M pages
On a live running system (VoIP gateway for Air Trafic Control), over
a 10 minutes period (with 277s idle), we get 87 millions DTLB misses
and approximatly 35 secondes are spent in DTLB handler.
This represents 5.8% of the overall time and even 10.8% of the
non-idle time.
Among those 87 millions DTLB misses, 15% are on user addresses and
85% are on kernel addresses. And within the kernel addresses, 93%
are on addresses from the linear address space and only 7% are on
addresses from the virtual address space.
MPC8xx has no BATs but it has 8Mb page size. This patch implements
mapping of kernel RAM using 8Mb pages, on the same model as what is
done on the 40x.
In 4k pages mode, each PGD entry maps a 4Mb area: we map every two
entries to the same 8Mb physical page. In each second entry, we add
4Mb to the page physical address to ease life of the FixupDAR
routine. This is just ignored by HW.
In 16k pages mode, each PGD entry maps a 64Mb area: each PGD entry
will point to the first page of the area. The DTLB handler adds
the 3 bits from EPN to map the correct page.
With this patch applied, we now get only 13 millions TLB misses
during the 10 minutes period. The idle time has increased to 313s
and the overall time spent in DTLB miss handler is 6.3s, which
represents 1% of the overall time and 2.2% of non-idle time.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Scott Wood <oss@buserror.net>
2016-02-09 17:07:50 +01:00
# ifdef CONFIG_PPC32
2005-09-26 16:04:21 +10:00
extern void MMU_init_hw ( void ) ;
2019-04-26 16:23:35 +00:00
void MMU_init_hw_patch ( void ) ;
2019-02-21 19:08:38 +00:00
unsigned long mmu_mapin_ram ( unsigned long base , unsigned long top ) ;
powerpc/8xx: Map linear kernel RAM with 8M pages
On a live running system (VoIP gateway for Air Trafic Control), over
a 10 minutes period (with 277s idle), we get 87 millions DTLB misses
and approximatly 35 secondes are spent in DTLB handler.
This represents 5.8% of the overall time and even 10.8% of the
non-idle time.
Among those 87 millions DTLB misses, 15% are on user addresses and
85% are on kernel addresses. And within the kernel addresses, 93%
are on addresses from the linear address space and only 7% are on
addresses from the virtual address space.
MPC8xx has no BATs but it has 8Mb page size. This patch implements
mapping of kernel RAM using 8Mb pages, on the same model as what is
done on the 40x.
In 4k pages mode, each PGD entry maps a 4Mb area: we map every two
entries to the same 8Mb physical page. In each second entry, we add
4Mb to the page physical address to ease life of the FixupDAR
routine. This is just ignored by HW.
In 16k pages mode, each PGD entry maps a 64Mb area: each PGD entry
will point to the first page of the area. The DTLB handler adds
the 3 bits from EPN to map the correct page.
With this patch applied, we now get only 13 millions TLB misses
during the 10 minutes period. The idle time has increased to 313s
and the overall time spent in DTLB miss handler is 6.3s, which
represents 1% of the overall time and 2.2% of non-idle time.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Scott Wood <oss@buserror.net>
2016-02-09 17:07:50 +01:00
# endif
2005-09-26 16:04:21 +10:00
powerpc/8xx: Map linear kernel RAM with 8M pages
On a live running system (VoIP gateway for Air Trafic Control), over
a 10 minutes period (with 277s idle), we get 87 millions DTLB misses
and approximatly 35 secondes are spent in DTLB handler.
This represents 5.8% of the overall time and even 10.8% of the
non-idle time.
Among those 87 millions DTLB misses, 15% are on user addresses and
85% are on kernel addresses. And within the kernel addresses, 93%
are on addresses from the linear address space and only 7% are on
addresses from the virtual address space.
MPC8xx has no BATs but it has 8Mb page size. This patch implements
mapping of kernel RAM using 8Mb pages, on the same model as what is
done on the 40x.
In 4k pages mode, each PGD entry maps a 4Mb area: we map every two
entries to the same 8Mb physical page. In each second entry, we add
4Mb to the page physical address to ease life of the FixupDAR
routine. This is just ignored by HW.
In 16k pages mode, each PGD entry maps a 64Mb area: each PGD entry
will point to the first page of the area. The DTLB handler adds
the 3 bits from EPN to map the correct page.
With this patch applied, we now get only 13 millions TLB misses
during the 10 minutes period. The idle time has increased to 313s
and the overall time spent in DTLB miss handler is 6.3s, which
represents 1% of the overall time and 2.2% of non-idle time.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Scott Wood <oss@buserror.net>
2016-02-09 17:07:50 +01:00
# ifdef CONFIG_PPC_FSL_BOOK3E
2015-10-06 22:48:10 -05:00
extern unsigned long map_mem_in_cams ( unsigned long ram , int max_cam_idx ,
bool dryrun ) ;
2011-09-16 10:39:59 -05:00
extern unsigned long calc_cam_sz ( unsigned long ram , unsigned long virt ,
phys_addr_t phys ) ;
2009-10-16 18:48:40 -05:00
# ifdef CONFIG_PPC32
2005-09-26 16:04:21 +10:00
extern void adjust_total_lowmem ( void ) ;
2013-12-24 15:12:07 +08:00
extern int switch_to_as1 ( void ) ;
2013-12-24 15:12:11 +08:00
extern void restore_to_as0 ( int esel , int offset , void * dt_ptr , int bootcpu ) ;
2019-09-20 17:45:38 +08:00
void create_kaslr_tlb_entry ( int entry , unsigned long virt , phys_addr_t phys ) ;
2019-09-20 17:45:39 +08:00
void reloc_kernel_entry ( void * fdt , int addr ) ;
2019-09-20 17:45:40 +08:00
extern int is_second_reloc ;
2009-10-16 18:48:40 -05:00
# endif
2010-05-13 14:38:21 -05:00
extern void loadcam_entry ( unsigned int index ) ;
2015-10-06 22:48:09 -05:00
extern void loadcam_multi ( int first_idx , int num , int tmp_idx ) ;
2010-05-13 14:38:21 -05:00
2019-09-20 17:45:40 +08:00
# ifdef CONFIG_RANDOMIZE_BASE
void kaslr_early_init ( void * dt_ptr , phys_addr_t size ) ;
2019-09-20 17:45:42 +08:00
void kaslr_late_init ( void ) ;
2019-09-20 17:45:40 +08:00
# else
static inline void kaslr_early_init ( void * dt_ptr , phys_addr_t size ) { }
2019-09-20 17:45:42 +08:00
static inline void kaslr_late_init ( void ) { }
2019-09-20 17:45:40 +08:00
# endif
2010-05-13 14:38:21 -05:00
struct tlbcam {
u32 MAS0 ;
u32 MAS1 ;
unsigned long MAS2 ;
u32 MAS3 ;
u32 MAS7 ;
} ;
2005-09-26 16:04:21 +10:00
# endif
2016-02-09 17:07:58 +01:00
2018-11-17 10:24:56 +00:00
# if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_FSL_BOOKE) || defined(CONFIG_PPC_8xx)
2016-02-09 17:07:58 +01:00
/* 6xx have BATS */
/* FSL_BOOKE have TLBCAM */
2016-05-17 09:02:45 +02:00
/* 8xx have LTLB */
2016-02-09 17:07:58 +01:00
phys_addr_t v_block_mapped ( unsigned long va ) ;
unsigned long p_block_mapped ( phys_addr_t pa ) ;
# else
static inline phys_addr_t v_block_mapped ( unsigned long va ) { return 0 ; }
static inline unsigned long p_block_mapped ( phys_addr_t pa ) { return 0 ; }
# endif
2019-02-21 19:08:49 +00:00
2019-02-21 19:08:51 +00:00
# if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx)
2019-02-21 19:08:49 +00:00
void mmu_mark_initmem_nx ( void ) ;
void mmu_mark_rodata_ro ( void ) ;
# else
static inline void mmu_mark_initmem_nx ( void ) { }
static inline void mmu_mark_rodata_ro ( void ) { }
# endif
2020-01-14 07:14:40 +00:00
2020-05-19 05:49:14 +00:00
# ifdef CONFIG_PPC_8xx
void __init mmu_mapin_immr ( void ) ;
# endif
2020-01-14 07:14:40 +00:00
# ifdef CONFIG_PPC_DEBUG_WX
void ptdump_check_wx ( void ) ;
# else
static inline void ptdump_check_wx ( void ) { }
# endif