linux/arch/s390/include/asm/pgalloc.h
<<
>>
Prefs
   1/*
   2 *  include/asm-s390/pgalloc.h
   3 *
   4 *  S390 version
   5 *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
   6 *    Author(s): Hartmut Penner (hp@de.ibm.com)
   7 *               Martin Schwidefsky (schwidefsky@de.ibm.com)
   8 *
   9 *  Derived from "include/asm-i386/pgalloc.h"
  10 *    Copyright (C) 1994  Linus Torvalds
  11 */
  12
  13#ifndef _S390_PGALLOC_H
  14#define _S390_PGALLOC_H
  15
  16#include <linux/threads.h>
  17#include <linux/gfp.h>
  18#include <linux/mm.h>
  19
  20unsigned long *crst_table_alloc(struct mm_struct *);
  21void crst_table_free(struct mm_struct *, unsigned long *);
  22
  23unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
  24void page_table_free(struct mm_struct *, unsigned long *);
  25void page_table_free_rcu(struct mmu_gather *, unsigned long *);
  26
  27static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
  28{
  29        typedef struct { char _[n]; } addrtype;
  30
  31        *s = val;
  32        n = (n / 256) - 1;
  33        asm volatile(
  34#ifdef CONFIG_64BIT
  35                "       mvc     8(248,%0),0(%0)\n"
  36#else
  37                "       mvc     4(252,%0),0(%0)\n"
  38#endif
  39                "0:     mvc     256(256,%0),0(%0)\n"
  40                "       la      %0,256(%0)\n"
  41                "       brct    %1,0b\n"
  42                : "+a" (s), "+d" (n), "=m" (*(addrtype *) s)
  43                : "m" (*(addrtype *) s));
  44}
  45
  46static inline void crst_table_init(unsigned long *crst, unsigned long entry)
  47{
  48        clear_table(crst, entry, sizeof(unsigned long)*2048);
  49}
  50
  51#ifndef CONFIG_64BIT
  52
  53static inline unsigned long pgd_entry_type(struct mm_struct *mm)
  54{
  55        return _SEGMENT_ENTRY_EMPTY;
  56}
  57
  58#define pud_alloc_one(mm,address)               ({ BUG(); ((pud_t *)2); })
  59#define pud_free(mm, x)                         do { } while (0)
  60
  61#define pmd_alloc_one(mm,address)               ({ BUG(); ((pmd_t *)2); })
  62#define pmd_free(mm, x)                         do { } while (0)
  63
  64#define pgd_populate(mm, pgd, pud)              BUG()
  65#define pud_populate(mm, pud, pmd)              BUG()
  66
  67#else /* CONFIG_64BIT */
  68
  69static inline unsigned long pgd_entry_type(struct mm_struct *mm)
  70{
  71        if (mm->context.asce_limit <= (1UL << 31))
  72                return _SEGMENT_ENTRY_EMPTY;
  73        if (mm->context.asce_limit <= (1UL << 42))
  74                return _REGION3_ENTRY_EMPTY;
  75        return _REGION2_ENTRY_EMPTY;
  76}
  77
  78int crst_table_upgrade(struct mm_struct *, unsigned long limit);
  79void crst_table_downgrade(struct mm_struct *, unsigned long limit);
  80
  81static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
  82{
  83        unsigned long *table = crst_table_alloc(mm);
  84        if (table)
  85                crst_table_init(table, _REGION3_ENTRY_EMPTY);
  86        return (pud_t *) table;
  87}
  88#define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud)
  89
  90static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
  91{
  92        unsigned long *table = crst_table_alloc(mm);
  93        if (table)
  94                crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
  95        return (pmd_t *) table;
  96}
  97#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
  98
  99static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 100{
 101        pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud);
 102}
 103
 104static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 105{
 106        pud_val(*pud) = _REGION3_ENTRY | __pa(pmd);
 107}
 108
 109#endif /* CONFIG_64BIT */
 110
 111static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 112{
 113        spin_lock_init(&mm->context.list_lock);
 114        INIT_LIST_HEAD(&mm->context.pgtable_list);
 115        INIT_LIST_HEAD(&mm->context.gmap_list);
 116        return (pgd_t *) crst_table_alloc(mm);
 117}
 118#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
 119
 120static inline void pmd_populate(struct mm_struct *mm,
 121                                pmd_t *pmd, pgtable_t pte)
 122{
 123        pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);
 124}
 125
 126#define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte)
 127
 128#define pmd_pgtable(pmd) \
 129        (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)
 130
 131/*
 132 * page table entry allocation/free routines.
 133 */
 134#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
 135#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
 136
 137#define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
 138#define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
 139
 140extern void rcu_table_freelist_finish(void);
 141
 142#endif /* _S390_PGALLOC_H */
 143