2019-06-03 07:44:50 +02:00
/* SPDX-License-Identifier: GPL-2.0-only */
2012-03-05 11:49:27 +00:00
/*
* Based on arch / arm / include / asm / pgalloc . h
*
* Copyright ( C ) 2000 - 2001 Russell King
* Copyright ( C ) 2012 ARM Ltd .
*/
# ifndef __ASM_PGALLOC_H
# define __ASM_PGALLOC_H
# include <asm/pgtable-hwdef.h>
# include <asm/processor.h>
# include <asm/cacheflush.h>
# include <asm/tlbflush.h>
2019-07-11 20:58:02 -07:00
# include <asm-generic/pgalloc.h> /* for pte_{alloc,free}_one */
2015-10-12 18:52:57 +03:00
# define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
2014-11-19 17:44:12 +00:00
2015-04-14 15:45:39 -07:00
# if CONFIG_PGTABLE_LEVELS > 2
2012-03-05 11:49:27 +00:00
static inline pmd_t * pmd_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
2019-07-11 20:58:02 -07:00
gfp_t gfp = GFP_PGTABLE_USER ;
2019-03-11 18:57:49 -06:00
struct page * page ;
2019-07-11 20:58:02 -07:00
if ( mm = = & init_mm )
gfp = GFP_PGTABLE_KERNEL ;
page = alloc_page ( gfp ) ;
2019-03-11 18:57:49 -06:00
if ( ! page )
return NULL ;
if ( ! pgtable_pmd_page_ctor ( page ) ) {
__free_page ( page ) ;
return NULL ;
}
return page_address ( page ) ;
2012-03-05 11:49:27 +00:00
}
2018-02-15 11:14:56 +00:00
static inline void pmd_free ( struct mm_struct * mm , pmd_t * pmdp )
2012-03-05 11:49:27 +00:00
{
2018-02-15 11:14:56 +00:00
BUG_ON ( ( unsigned long ) pmdp & ( PAGE_SIZE - 1 ) ) ;
2019-03-11 18:57:49 -06:00
pgtable_pmd_page_dtor ( virt_to_page ( pmdp ) ) ;
2018-02-15 11:14:56 +00:00
free_page ( ( unsigned long ) pmdp ) ;
2012-03-05 11:49:27 +00:00
}
2018-02-15 11:14:56 +00:00
static inline void __pud_populate ( pud_t * pudp , phys_addr_t pmdp , pudval_t prot )
2012-03-05 11:49:27 +00:00
{
2018-02-15 11:14:56 +00:00
set_pud ( pudp , __pud ( __phys_to_pud_val ( pmdp ) | prot ) ) ;
2012-03-05 11:49:27 +00:00
}
2018-02-15 11:14:56 +00:00
static inline void pud_populate ( struct mm_struct * mm , pud_t * pudp , pmd_t * pmdp )
2016-01-25 11:45:06 +00:00
{
2018-02-15 11:14:56 +00:00
__pud_populate ( pudp , __pa ( pmdp ) , PMD_TYPE_TABLE ) ;
2016-01-25 11:45:06 +00:00
}
# else
2018-02-15 11:14:56 +00:00
static inline void __pud_populate ( pud_t * pudp , phys_addr_t pmdp , pudval_t prot )
2016-01-25 11:45:06 +00:00
{
BUILD_BUG ( ) ;
}
2015-04-14 15:45:39 -07:00
# endif /* CONFIG_PGTABLE_LEVELS > 2 */
2012-03-05 11:49:27 +00:00
2015-04-14 15:45:39 -07:00
# if CONFIG_PGTABLE_LEVELS > 3
2014-05-12 18:40:51 +09:00
static inline pud_t * pud_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
2019-07-11 20:58:02 -07:00
return ( pud_t * ) __get_free_page ( GFP_PGTABLE_USER ) ;
2014-05-12 18:40:51 +09:00
}
2018-02-15 11:14:56 +00:00
static inline void pud_free ( struct mm_struct * mm , pud_t * pudp )
2014-05-12 18:40:51 +09:00
{
2018-02-15 11:14:56 +00:00
BUG_ON ( ( unsigned long ) pudp & ( PAGE_SIZE - 1 ) ) ;
free_page ( ( unsigned long ) pudp ) ;
2014-05-12 18:40:51 +09:00
}
2018-02-15 11:14:56 +00:00
static inline void __pgd_populate ( pgd_t * pgdp , phys_addr_t pudp , pgdval_t prot )
2014-05-12 18:40:51 +09:00
{
2018-02-15 11:14:56 +00:00
set_pgd ( pgdp , __pgd ( __phys_to_pgd_val ( pudp ) | prot ) ) ;
2014-05-12 18:40:51 +09:00
}
2018-02-15 11:14:56 +00:00
static inline void pgd_populate ( struct mm_struct * mm , pgd_t * pgdp , pud_t * pudp )
2016-01-25 11:45:06 +00:00
{
2018-02-15 11:14:56 +00:00
__pgd_populate ( pgdp , __pa ( pudp ) , PUD_TYPE_TABLE ) ;
2016-01-25 11:45:06 +00:00
}
# else
2018-02-15 11:14:56 +00:00
static inline void __pgd_populate ( pgd_t * pgdp , phys_addr_t pudp , pgdval_t prot )
2016-01-25 11:45:06 +00:00
{
BUILD_BUG ( ) ;
}
2015-04-14 15:45:39 -07:00
# endif /* CONFIG_PGTABLE_LEVELS > 3 */
2014-05-12 18:40:51 +09:00
2012-03-05 11:49:27 +00:00
extern pgd_t * pgd_alloc ( struct mm_struct * mm ) ;
2018-02-15 11:14:56 +00:00
extern void pgd_free ( struct mm_struct * mm , pgd_t * pgdp ) ;
2012-03-05 11:49:27 +00:00
2018-02-15 11:14:56 +00:00
static inline void __pmd_populate ( pmd_t * pmdp , phys_addr_t ptep ,
2012-03-05 11:49:27 +00:00
pmdval_t prot )
{
2018-02-15 11:14:56 +00:00
set_pmd ( pmdp , __pmd ( __phys_to_pmd_val ( ptep ) | prot ) ) ;
2012-03-05 11:49:27 +00:00
}
/*
* Populate the pmdp entry with a pointer to the pte . This pmd is part
* of the mm address space .
*/
static inline void
pmd_populate_kernel ( struct mm_struct * mm , pmd_t * pmdp , pte_t * ptep )
{
/*
* The pmd must be loaded with the physical address of the PTE table
*/
__pmd_populate ( pmdp , __pa ( ptep ) , PMD_TYPE_TABLE ) ;
}
static inline void
pmd_populate ( struct mm_struct * mm , pmd_t * pmdp , pgtable_t ptep )
{
__pmd_populate ( pmdp , page_to_phys ( ptep ) , PMD_TYPE_TABLE ) ;
}
# define pmd_pgtable(pmd) pmd_page(pmd)
# endif