blob: 4ea627d879d6d691abd8beb5baa5d6db81358779 [file] [log] [blame]
Wedson Almeida Filhofed69022018-07-11 15:39:12 +01001#ifndef _ARCH_MM_H
2#define _ARCH_MM_H
3
4#include <stdbool.h>
5#include <stddef.h>
6#include <stdint.h>
7
8/* A phypiscal address. */
9typedef size_t paddr_t;
10
11/* A virtual address. */
12typedef size_t vaddr_t;
13
14/* A page table entry. */
15typedef size_t pte_t;
16
17#define PAGE_LEVEL_BITS 9
18#define PAGE_BITS 12
19
20struct arch_mm_ptable {
21 int max_level;
22};
23
24/**
25 * Initialises the architecture-dependents aspects of the page table.
26 */
27static inline void arch_mm_ptable_init(struct arch_mm_ptable *t)
28{
29 t->max_level = 2;
30}
31
32/**
33 * Determines the maximum level supported by the given page table.
34 */
35static inline int arch_mm_max_level(struct arch_mm_ptable *t)
36{
37 return t->max_level;
38}
39
40/**
41 * Converts a physical address to a table PTE.
42 *
43 * The spec says that 'Table descriptors for stage 2 translations do not
44 * include any attribute field', so we don't take any attributes as arguments.
45 */
46static inline pte_t arch_mm_pa_to_table_pte(paddr_t pa)
47{
48 return pa | 0x3;
49}
50
51/**
52 * Converts a physical address to a block PTE.
53 */
54static inline pte_t arch_mm_pa_to_block_pte(paddr_t pa, uint64_t attrs)
55{
56 return pa | attrs;
57}
58
59/**
60 * Converts a physical address to a page PTE.
61 */
62static inline pte_t arch_mm_pa_to_page_pte(paddr_t pa, uint64_t attrs)
63{
64 return pa | attrs | ((attrs & 1) << 1);
65}
66
67/**
68 * Converts a block PTE to a page PTE.
69 */
70static inline pte_t arch_mm_block_to_page_pte(pte_t pte)
71{
72 return pte | 2;
73}
74
75/**
76 * Specifies whether block mappings are acceptable at the given level.
77 */
78static inline bool arch_mm_is_block_allowed(int level)
79{
80 return level == 1 || level == 2;
81}
82
83/**
84 * Returns the encoding of a page table entry that isn't present.
85 */
86static inline pte_t arch_mm_absent_pte(void)
87{
88 return 0;
89}
90
91/**
92 * Determines if the given pte is present, i.e., if it points to another table,
93 * to a page, or a block of pages.
94 */
95static inline bool arch_mm_pte_is_present(pte_t pte)
96{
97 return (pte & 1) != 0;
98}
99
100/**
101 * Determines if the given pte references another table.
102 */
103static inline bool arch_mm_pte_is_table(pte_t pte)
104{
105 return (pte & 3) == 3;
106}
107
108/**
109 * Determines if the given pte references a block of pages.
110 */
111static inline bool arch_mm_pte_is_block(pte_t pte)
112{
113 return (pte & 3) == 1;
114}
115
116/**
117 * Clears the given virtual address, i.e., sets the ignored bits (from a page
118 * table perspective) to zero.
119 */
120static inline vaddr_t arch_mm_clear_va(vaddr_t addr)
121{
122 return addr & ~((1ull << PAGE_BITS) - 1) & ((1ull << 48) - 1);
123}
124
125/**
126 * Clears the given physical address, i.e., sets the ignored bits (from a page
127 * table perspective) to zero.
128 */
129static inline paddr_t arch_mm_clear_pa(paddr_t addr)
130{
131 return addr & ~((1ull << PAGE_BITS) - 1) & ((1ull << 48) - 1);
132}
133
134/**
135 * Extracts the physical address from a page table entry.
136 */
137static inline paddr_t arch_mm_pte_to_paddr(pte_t pte)
138{
139 return arch_mm_clear_pa(pte);
140}
141
142/**
143 * Extracts a page table pointer from the given page table entry.
144 */
145static inline pte_t *arch_mm_pte_to_table(pte_t pte)
146{
147 return (pte_t *)arch_mm_pte_to_paddr(pte);
148}
149
150/**
151 * Invalidates stage-1 TLB entries referring to the given virtual address range.
152 */
153static inline void arch_mm_invalidate_stage1_range(vaddr_t begin, vaddr_t end)
154{
155 vaddr_t it;
156
157 begin >>= 12;
158 end >>= 12;
159
160 __asm__ volatile("dsb ishst");
161
162 for (it = begin; it < end; it += (1ull << (PAGE_BITS - 12)))
163 __asm__("tlbi vae2is, %0" : : "r"(it));
164
165 __asm__ volatile("dsb ish");
166}
167
168/**
169 * Invalidates stage-2 TLB entries referring to the given virtual address range.
170 */
171static inline void arch_mm_invalidate_stage2_range(vaddr_t begin, vaddr_t end)
172{
173 vaddr_t it;
174
175 begin >>= 12;
176 end >>= 12;
177
178 __asm__ volatile("dsb ishst");
179
180 for (it = begin; it < end; it += (1ull << (PAGE_BITS - 12)))
181 __asm__("tlbi ipas2e1, %0" : : "r"(it));
182
Andrew Scull4f170f52018-07-19 12:58:20 +0100183 __asm__ volatile(
184 "dsb ish\n"
185 "tlbi vmalle1is\n"
186 "dsb ish\n");
Wedson Almeida Filhofed69022018-07-11 15:39:12 +0100187}
188
189uint64_t arch_mm_mode_to_attrs(int mode);
190void arch_mm_init(paddr_t table);
191
Andrew Scull4f170f52018-07-19 12:58:20 +0100192#endif /* _ARCH_MM_H */