2022-05-31 18:04:11 +08:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( C ) 2020 - 2022 Loongson Technology Corporation Limited
*/
# include <linux/init.h>
# include <linux/export.h>
# include <linux/mm.h>
# include <asm/pgalloc.h>
# include <asm/pgtable.h>
# include <asm/tlbflush.h>
pgd_t * pgd_alloc ( struct mm_struct * mm )
{
pgd_t * ret , * init ;
2022-07-03 17:12:01 +03:00
ret = ( pgd_t * ) __get_free_page ( GFP_KERNEL ) ;
2022-05-31 18:04:11 +08:00
if ( ret ) {
init = pgd_offset ( & init_mm , 0UL ) ;
2022-10-27 20:52:50 +08:00
pgd_init ( ret ) ;
2022-05-31 18:04:11 +08:00
memcpy ( ret + USER_PTRS_PER_PGD , init + USER_PTRS_PER_PGD ,
( PTRS_PER_PGD - USER_PTRS_PER_PGD ) * sizeof ( pgd_t ) ) ;
}
return ret ;
}
EXPORT_SYMBOL_GPL ( pgd_alloc ) ;
2022-10-27 20:52:50 +08:00
void pgd_init ( void * addr )
2022-05-31 18:04:11 +08:00
{
unsigned long * p , * end ;
unsigned long entry ;
# if !defined(__PAGETABLE_PUD_FOLDED)
entry = ( unsigned long ) invalid_pud_table ;
# elif !defined(__PAGETABLE_PMD_FOLDED)
entry = ( unsigned long ) invalid_pmd_table ;
# else
entry = ( unsigned long ) invalid_pte_table ;
# endif
2022-10-27 20:52:50 +08:00
p = ( unsigned long * ) addr ;
2022-05-31 18:04:11 +08:00
end = p + PTRS_PER_PGD ;
do {
p [ 0 ] = entry ;
p [ 1 ] = entry ;
p [ 2 ] = entry ;
p [ 3 ] = entry ;
p [ 4 ] = entry ;
p + = 8 ;
p [ - 3 ] = entry ;
p [ - 2 ] = entry ;
p [ - 1 ] = entry ;
} while ( p ! = end ) ;
}
EXPORT_SYMBOL_GPL ( pgd_init ) ;
# ifndef __PAGETABLE_PMD_FOLDED
2022-10-27 20:52:50 +08:00
void pmd_init ( void * addr )
2022-05-31 18:04:11 +08:00
{
unsigned long * p , * end ;
2022-10-27 20:52:50 +08:00
unsigned long pagetable = ( unsigned long ) invalid_pte_table ;
2022-05-31 18:04:11 +08:00
2022-10-27 20:52:50 +08:00
p = ( unsigned long * ) addr ;
2022-05-31 18:04:11 +08:00
end = p + PTRS_PER_PMD ;
do {
p [ 0 ] = pagetable ;
p [ 1 ] = pagetable ;
p [ 2 ] = pagetable ;
p [ 3 ] = pagetable ;
p [ 4 ] = pagetable ;
p + = 8 ;
p [ - 3 ] = pagetable ;
p [ - 2 ] = pagetable ;
p [ - 1 ] = pagetable ;
} while ( p ! = end ) ;
}
EXPORT_SYMBOL_GPL ( pmd_init ) ;
# endif
# ifndef __PAGETABLE_PUD_FOLDED
2022-10-27 20:52:50 +08:00
void pud_init ( void * addr )
2022-05-31 18:04:11 +08:00
{
unsigned long * p , * end ;
2022-10-27 20:52:50 +08:00
unsigned long pagetable = ( unsigned long ) invalid_pmd_table ;
2022-05-31 18:04:11 +08:00
p = ( unsigned long * ) addr ;
end = p + PTRS_PER_PUD ;
do {
p [ 0 ] = pagetable ;
p [ 1 ] = pagetable ;
p [ 2 ] = pagetable ;
p [ 3 ] = pagetable ;
p [ 4 ] = pagetable ;
p + = 8 ;
p [ - 3 ] = pagetable ;
p [ - 2 ] = pagetable ;
p [ - 1 ] = pagetable ;
} while ( p ! = end ) ;
}
2022-10-27 20:52:50 +08:00
EXPORT_SYMBOL_GPL ( pud_init ) ;
2022-05-31 18:04:11 +08:00
# endif
pmd_t mk_pmd ( struct page * page , pgprot_t prot )
{
pmd_t pmd ;
pmd_val ( pmd ) = ( page_to_pfn ( page ) < < _PFN_SHIFT ) | pgprot_val ( prot ) ;
return pmd ;
}
void set_pmd_at ( struct mm_struct * mm , unsigned long addr ,
pmd_t * pmdp , pmd_t pmd )
{
* pmdp = pmd ;
flush_tlb_all ( ) ;
}
void __init pagetable_init ( void )
{
/* Initialize the entire pgd. */
2022-10-27 20:52:50 +08:00
pgd_init ( swapper_pg_dir ) ;
pgd_init ( invalid_pg_dir ) ;
2022-05-31 18:04:11 +08:00
# ifndef __PAGETABLE_PUD_FOLDED
2022-10-27 20:52:50 +08:00
pud_init ( invalid_pud_table ) ;
2022-05-31 18:04:11 +08:00
# endif
# ifndef __PAGETABLE_PMD_FOLDED
2022-10-27 20:52:50 +08:00
pmd_init ( invalid_pmd_table ) ;
2022-05-31 18:04:11 +08:00
# endif
}