ARC: mm: support 3 levels of page tables
[linux-2.6-microblaze.git] / arch / arc / include / asm / pgtable-levels.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2020 Synopsys, Inc. (www.synopsys.com)
4  */
5
6 /*
7  * Helpers for implemenintg paging levels
8  */
9
10 #ifndef _ASM_ARC_PGTABLE_LEVELS_H
11 #define _ASM_ARC_PGTABLE_LEVELS_H
12
13 #if CONFIG_PGTABLE_LEVELS == 2
14
15 /*
16  * 2 level paging setup for software walked MMUv3 (ARC700) and MMUv4 (HS)
17  *
18  * [31]            32 bit virtual address              [0]
19  * -------------------------------------------------------
20  * |               | <---------- PGDIR_SHIFT ----------> |
21  * |               |                | <-- PAGE_SHIFT --> |
22  * -------------------------------------------------------
23  *       |                  |                |
24  *       |                  |                --> off in page frame
25  *       |                  ---> index into Page Table
26  *       ----> index into Page Directory
27  *
28  * Given software walk, the vaddr split is arbitrary set to 11:8:13
29  * However enabling of super page in a 2 level regime pegs PGDIR_SHIFT to
30  * super page size.
31  */
32
33 #if defined(CONFIG_ARC_HUGEPAGE_16M)
34 #define PGDIR_SHIFT             24
35 #elif defined(CONFIG_ARC_HUGEPAGE_2M)
36 #define PGDIR_SHIFT             21
37 #else
38 /*
39  * No Super page case
40  * Default value provides 11:8:13 (8K), 10:10:12 (4K)
41  * Limits imposed by pgtable_t only PAGE_SIZE long
42  * (so 4K page can only have 1K entries: or 10 bits)
43  */
44 #ifdef CONFIG_ARC_PAGE_SIZE_4K
45 #define PGDIR_SHIFT             22
46 #else
47 #define PGDIR_SHIFT             21
48 #endif
49
50 #endif
51
52 #else /* CONFIG_PGTABLE_LEVELS != 2 */
53
54 /*
55  * A default 3 level paging testing setup in software walked MMU
56  *   MMUv4 (8K page): <4> : <7> : <8> : <13>
57  */
58 #define PGDIR_SHIFT             28
59 #if CONFIG_PGTABLE_LEVELS > 2
60 #define PMD_SHIFT               21
61 #endif
62
63 #endif /* CONFIG_PGTABLE_LEVELS */
64
65 #define PGDIR_SIZE              BIT(PGDIR_SHIFT)
66 #define PGDIR_MASK              (~(PGDIR_SIZE - 1))
67 #define PTRS_PER_PGD            BIT(32 - PGDIR_SHIFT)
68
69 #if CONFIG_PGTABLE_LEVELS > 2
70 #define PMD_SIZE                BIT(PMD_SHIFT)
71 #define PMD_MASK                (~(PMD_SIZE - 1))
72 #define PTRS_PER_PMD            BIT(PGDIR_SHIFT - PMD_SHIFT)
73 #endif
74
75 #define PTRS_PER_PTE            BIT(PMD_SHIFT - PAGE_SHIFT)
76
77 #ifndef __ASSEMBLY__
78
79 #if CONFIG_PGTABLE_LEVELS > 2
80 #include <asm-generic/pgtable-nopud.h>
81 #else
82 #include <asm-generic/pgtable-nopmd.h>
83 #endif
84
85 /*
86  * 1st level paging: pgd
87  */
88 #define pgd_index(addr)         ((addr) >> PGDIR_SHIFT)
89 #define pgd_offset(mm, addr)    (((mm)->pgd) + pgd_index(addr))
90 #define pgd_offset_k(addr)      pgd_offset(&init_mm, addr)
91 #define pgd_ERROR(e) \
92         pr_crit("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
93
94 #if CONFIG_PGTABLE_LEVELS > 2
95
96 /* In 3 level paging, pud_* macros work on pgd */
97 #define pud_none(x)             (!pud_val(x))
98 #define pud_bad(x)              ((pud_val(x) & ~PAGE_MASK))
99 #define pud_present(x)          (pud_val(x))
100 #define pud_clear(xp)           do { pud_val(*(xp)) = 0; } while (0)
101 #define pud_pgtable(pud)        ((pmd_t *)(pud_val(pud) & PAGE_MASK))
102 #define pud_page(pud)           virt_to_page(pud_pgtable(pud))
103 #define set_pud(pudp, pud)      (*(pudp) = pud)
104
105 /*
106  * 2nd level paging: pmd
107  */
108 #define pmd_ERROR(e) \
109         pr_crit("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
110
111 #define pmd_pfn(pmd)            ((pmd_val(pmd) & PMD_MASK) >> PAGE_SHIFT)
112 #define pfn_pmd(pfn,prot)       __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
113 #define mk_pmd(page,prot)       pfn_pmd(page_to_pfn(page),prot)
114
115 #endif
116
117 /*
118  * Due to the strange way generic pgtable level folding works, the pmd_* macros
119  *  - are valid even for 2 levels (which supposedly only has pgd - pte)
120  *  - behave differently for 2 vs. 3
121  * In 2  level paging        (pgd -> pte), pmd_* macros work on pgd
122  * In 3+ level paging (pgd -> pmd -> pte), pmd_* macros work on pmd
123  */
124 #define pmd_none(x)             (!pmd_val(x))
125 #define pmd_bad(x)              ((pmd_val(x) & ~PAGE_MASK))
126 #define pmd_present(x)          (pmd_val(x))
127 #define pmd_clear(xp)           do { pmd_val(*(xp)) = 0; } while (0)
128 #define pmd_page_vaddr(pmd)     (pmd_val(pmd) & PAGE_MASK)
129 #define pmd_page(pmd)           virt_to_page(pmd_page_vaddr(pmd))
130 #define set_pmd(pmdp, pmd)      (*(pmdp) = pmd)
131 #define pmd_pgtable(pmd)        ((pgtable_t) pmd_page_vaddr(pmd))
132
133 /*
134  * 3rd level paging: pte
135  */
136 #define pte_ERROR(e) \
137         pr_crit("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
138
139 #define pte_none(x)             (!pte_val(x))
140 #define pte_present(x)          (pte_val(x) & _PAGE_PRESENT)
141 #define pte_clear(mm,addr,ptep) set_pte_at(mm, addr, ptep, __pte(0))
142 #define pte_page(pte)           pfn_to_page(pte_pfn(pte))
143 #define set_pte(ptep, pte)      ((*(ptep)) = (pte))
144 #define pte_pfn(pte)            (pte_val(pte) >> PAGE_SHIFT)
145 #define pfn_pte(pfn, prot)      __pte(__pfn_to_phys(pfn) | pgprot_val(prot))
146 #define mk_pte(page, prot)      pfn_pte(page_to_pfn(page), prot)
147
148 #ifdef CONFIG_ISA_ARCV2
149 #define pmd_leaf(x)             (pmd_val(x) & _PAGE_HW_SZ)
150 #endif
151
152 #endif  /* !__ASSEMBLY__ */
153
154 #endif