2005-04-16 15:20:36 -07:00
/*
* include / asm - s390 / pgalloc . h
*
* S390 version
* Copyright ( C ) 1999 , 2000 IBM Deutschland Entwicklung GmbH , IBM Corporation
* Author ( s ) : Hartmut Penner ( hp @ de . ibm . com )
* Martin Schwidefsky ( schwidefsky @ de . ibm . com )
*
* Derived from " include/asm-i386/pgalloc.h "
* Copyright ( C ) 1994 Linus Torvalds
*/
# ifndef _S390_PGALLOC_H
# define _S390_PGALLOC_H
# include <linux/threads.h>
# include <linux/gfp.h>
# include <linux/mm.h>
# define check_pgt_cache() do {} while (0)
2007-10-22 12:52:47 +02:00
unsigned long * crst_table_alloc ( struct mm_struct * , int ) ;
2008-02-09 18:24:35 +01:00
void crst_table_free ( struct mm_struct * , unsigned long * ) ;
2006-09-20 15:59:37 +02:00
2008-02-09 18:24:35 +01:00
unsigned long * page_table_alloc ( struct mm_struct * ) ;
void page_table_free ( struct mm_struct * , unsigned long * ) ;
void disable_noexec ( struct mm_struct * , struct task_struct * ) ;
2005-04-16 15:20:36 -07:00
2007-10-22 12:52:47 +02:00
static inline void clear_table ( unsigned long * s , unsigned long val , size_t n )
2005-04-16 15:20:36 -07:00
{
2008-12-25 13:39:26 +01:00
typedef struct { char _ [ n ] ; } addrtype ;
2007-10-22 12:52:47 +02:00
* s = val ;
n = ( n / 256 ) - 1 ;
asm volatile (
# ifdef CONFIG_64BIT
" mvc 8(248,%0),0(%0) \n "
2006-09-20 15:59:37 +02:00
# else
2007-10-22 12:52:47 +02:00
" mvc 4(252,%0),0(%0) \n "
2006-09-20 15:59:37 +02:00
# endif
2007-10-22 12:52:47 +02:00
" 0: mvc 256(256,%0),0(%0) \n "
" la %0,256(%0) \n "
" brct %1,0b \n "
2008-12-25 13:39:26 +01:00
: " +a " ( s ) , " +d " ( n ) , " =m " ( * ( addrtype * ) s )
: " m " ( * ( addrtype * ) s ) ) ;
2005-04-16 15:20:36 -07:00
}
2007-10-22 12:52:47 +02:00
static inline void crst_table_init ( unsigned long * crst , unsigned long entry )
2005-04-16 15:20:36 -07:00
{
2007-10-22 12:52:47 +02:00
clear_table ( crst , entry , sizeof ( unsigned long ) * 2048 ) ;
crst = get_shadow_table ( crst ) ;
if ( crst )
clear_table ( crst , entry , sizeof ( unsigned long ) * 2048 ) ;
2005-04-16 15:20:36 -07:00
}
# ifndef __s390x__
2007-10-22 12:52:47 +02:00
static inline unsigned long pgd_entry_type ( struct mm_struct * mm )
{
return _SEGMENT_ENTRY_EMPTY ;
}
2007-10-22 12:52:48 +02:00
# define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
2008-02-04 22:29:14 -08:00
# define pud_free(mm, x) do { } while (0)
2007-10-22 12:52:48 +02:00
2007-10-22 12:52:47 +02:00
# define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
2008-02-04 22:29:14 -08:00
# define pmd_free(mm, x) do { } while (0)
2007-10-22 12:52:47 +02:00
2007-10-22 12:52:48 +02:00
# define pgd_populate(mm, pgd, pud) BUG()
# define pgd_populate_kernel(mm, pgd, pud) BUG()
# define pud_populate(mm, pud, pmd) BUG()
# define pud_populate_kernel(mm, pud, pmd) BUG()
2007-10-22 12:52:47 +02:00
2005-04-16 15:20:36 -07:00
# else /* __s390x__ */
2007-10-22 12:52:47 +02:00
static inline unsigned long pgd_entry_type ( struct mm_struct * mm )
2005-04-16 15:20:36 -07:00
{
2008-02-09 18:24:37 +01:00
if ( mm - > context . asce_limit < = ( 1UL < < 31 ) )
return _SEGMENT_ENTRY_EMPTY ;
if ( mm - > context . asce_limit < = ( 1UL < < 42 ) )
return _REGION3_ENTRY_EMPTY ;
2008-02-09 18:24:36 +01:00
return _REGION2_ENTRY_EMPTY ;
2005-04-16 15:20:36 -07:00
}
2008-02-09 18:24:37 +01:00
int crst_table_upgrade ( struct mm_struct * , unsigned long limit ) ;
void crst_table_downgrade ( struct mm_struct * , unsigned long limit ) ;
2008-02-09 18:24:36 +01:00
static inline pud_t * pud_alloc_one ( struct mm_struct * mm , unsigned long address )
{
unsigned long * table = crst_table_alloc ( mm , mm - > context . noexec ) ;
if ( table )
crst_table_init ( table , _REGION3_ENTRY_EMPTY ) ;
return ( pud_t * ) table ;
}
# define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud)
2007-10-22 12:52:48 +02:00
2007-10-22 12:52:47 +02:00
static inline pmd_t * pmd_alloc_one ( struct mm_struct * mm , unsigned long vmaddr )
2005-04-16 15:20:36 -07:00
{
2008-02-09 18:24:35 +01:00
unsigned long * table = crst_table_alloc ( mm , mm - > context . noexec ) ;
if ( table )
crst_table_init ( table , _SEGMENT_ENTRY_EMPTY ) ;
return ( pmd_t * ) table ;
2005-04-16 15:20:36 -07:00
}
2008-02-09 18:24:35 +01:00
# define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
2005-04-16 15:20:36 -07:00
2008-02-09 18:24:36 +01:00
static inline void pgd_populate_kernel ( struct mm_struct * mm ,
pgd_t * pgd , pud_t * pud )
{
pgd_val ( * pgd ) = _REGION2_ENTRY | __pa ( pud ) ;
}
static inline void pgd_populate ( struct mm_struct * mm , pgd_t * pgd , pud_t * pud )
{
pgd_populate_kernel ( mm , pgd , pud ) ;
2008-02-09 18:24:37 +01:00
if ( mm - > context . noexec ) {
pgd = get_shadow_table ( pgd ) ;
pud = get_shadow_table ( pud ) ;
pgd_populate_kernel ( mm , pgd , pud ) ;
}
2008-02-09 18:24:36 +01:00
}
2007-10-22 12:52:48 +02:00
static inline void pud_populate_kernel ( struct mm_struct * mm ,
pud_t * pud , pmd_t * pmd )
2005-04-16 15:20:36 -07:00
{
2007-10-22 12:52:48 +02:00
pud_val ( * pud ) = _REGION3_ENTRY | __pa ( pmd ) ;
2005-04-16 15:20:36 -07:00
}
2007-10-22 12:52:48 +02:00
static inline void pud_populate ( struct mm_struct * mm , pud_t * pud , pmd_t * pmd )
2007-02-05 21:18:17 +01:00
{
2007-10-22 12:52:48 +02:00
pud_populate_kernel ( mm , pud , pmd ) ;
2008-02-09 18:24:35 +01:00
if ( mm - > context . noexec ) {
pud = get_shadow_table ( pud ) ;
pmd = get_shadow_table ( pmd ) ;
pud_populate_kernel ( mm , pud , pmd ) ;
}
2007-02-05 21:18:17 +01:00
}
2005-04-16 15:20:36 -07:00
# endif /* __s390x__ */
2007-10-22 12:52:47 +02:00
static inline pgd_t * pgd_alloc ( struct mm_struct * mm )
{
2009-09-11 10:28:57 +02:00
spin_lock_init ( & mm - > context . list_lock ) ;
2008-02-09 18:24:35 +01:00
INIT_LIST_HEAD ( & mm - > context . crst_list ) ;
INIT_LIST_HEAD ( & mm - > context . pgtable_list ) ;
2009-12-07 12:51:43 +01:00
return ( pgd_t * )
crst_table_alloc ( mm , user_mode = = SECONDARY_SPACE_MODE ) ;
2007-10-22 12:52:47 +02:00
}
2008-02-09 18:24:35 +01:00
# define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
2007-10-22 12:52:47 +02:00
2008-02-09 18:24:35 +01:00
static inline void pmd_populate_kernel ( struct mm_struct * mm ,
pmd_t * pmd , pte_t * pte )
2005-04-16 15:20:36 -07:00
{
2007-10-22 12:52:47 +02:00
pmd_val ( * pmd ) = _SEGMENT_ENTRY + __pa ( pte ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-09 18:24:35 +01:00
static inline void pmd_populate ( struct mm_struct * mm ,
pmd_t * pmd , pgtable_t pte )
2005-04-16 15:20:36 -07:00
{
2007-02-05 21:18:17 +01:00
pmd_populate_kernel ( mm , pmd , pte ) ;
2008-02-09 18:24:35 +01:00
if ( mm - > context . noexec ) {
pmd = get_shadow_table ( pmd ) ;
pmd_populate_kernel ( mm , pmd , pte + PTRS_PER_PTE ) ;
}
2005-04-16 15:20:36 -07:00
}
2008-02-09 18:24:35 +01:00
# define pmd_pgtable(pmd) \
( pgtable_t ) ( pmd_val ( pmd ) & - sizeof ( pte_t ) * PTRS_PER_PTE )
2005-04-16 15:20:36 -07:00
/*
* page table entry allocation / free routines .
*/
2008-02-09 18:24:35 +01:00
# define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
# define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
# define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
# define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
2005-04-16 15:20:36 -07:00
# endif /* _S390_PGALLOC_H */