^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * S390 version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright IBM Corp. 1999, 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author(s): Hartmut Penner (hp@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Martin Schwidefsky (schwidefsky@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Derived from "include/asm-i386/pgalloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 1994 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #ifndef _S390_PGALLOC_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define _S390_PGALLOC_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/threads.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define CRST_ALLOC_ORDER 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned long *crst_table_alloc(struct mm_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void crst_table_free(struct mm_struct *, unsigned long *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned long *page_table_alloc(struct mm_struct *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct page *page_table_alloc_pgste(struct mm_struct *mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) void page_table_free(struct mm_struct *, unsigned long *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) void page_table_free_pgste(struct page *page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) extern int page_table_allocate_pgste;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static inline void crst_table_init(unsigned long *crst, unsigned long entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) memset64((u64 *)crst, entry, _CRST_ENTRIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int crst_table_upgrade(struct mm_struct *mm, unsigned long limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static inline unsigned long check_asce_limit(struct mm_struct *mm, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (addr + len > mm->context.asce_limit &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) addr + len <= TASK_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) rc = crst_table_upgrade(mm, addr + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return (unsigned long) rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned long *table = crst_table_alloc(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) crst_table_init(table, _REGION2_ENTRY_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return (p4d_t *) table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (!mm_p4d_folded(mm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) crst_table_free(mm, (unsigned long *) p4d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned long *table = crst_table_alloc(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) crst_table_init(table, _REGION3_ENTRY_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return (pud_t *) table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static inline void pud_free(struct mm_struct *mm, pud_t *pud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!mm_pud_folded(mm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) crst_table_free(mm, (unsigned long *) pud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) unsigned long *table = crst_table_alloc(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!pgtable_pmd_page_ctor(virt_to_page(table))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) crst_table_free(mm, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return (pmd_t *) table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (mm_pmd_folded(mm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) pgtable_pmd_page_dtor(virt_to_page(pmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) crst_table_free(mm, (unsigned long *) pmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, p4d_t *p4d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pgd_val(*pgd) = _REGION1_ENTRY | __pa(p4d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) p4d_val(*p4d) = _REGION2_ENTRY | __pa(pud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pud_val(*pud) = _REGION3_ENTRY | __pa(pmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline pgd_t *pgd_alloc(struct mm_struct *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return (pgd_t *) crst_table_alloc(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) crst_table_free(mm, (unsigned long *) pgd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static inline void pmd_populate(struct mm_struct *mm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pmd_t *pmd, pgtable_t pte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define pmd_pgtable(pmd) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * page table entry allocation/free routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define pte_alloc_one_kernel(mm) ((pte_t *)page_table_alloc(mm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define pte_alloc_one(mm) ((pte_t *)page_table_alloc(mm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) void vmem_map_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) void *vmem_crst_alloc(unsigned long val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) pte_t *vmem_pte_alloc(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long base_asce_alloc(unsigned long addr, unsigned long num_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) void base_asce_free(unsigned long asce);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #endif /* _S390_PGALLOC_H */