1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#ifndef __ARM64_S2_PGTABLE_H_
20#define __ARM64_S2_PGTABLE_H_
21
22#include <asm/pgtable.h>
23
24
25
26
27
28
29
30
31
32
33
34
35
36#define STAGE2_PGTABLE_LEVELS ARM64_HW_PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52#if STAGE2_PGTABLE_LEVELS > CONFIG_PGTABLE_LEVELS
53#error "Unsupported combination of guest IPA and host VA_BITS."
54#endif
55
56
57#define S2_PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - STAGE2_PGTABLE_LEVELS)
58#define S2_PGDIR_SIZE (_AC(1, UL) << S2_PGDIR_SHIFT)
59#define S2_PGDIR_MASK (~(S2_PGDIR_SIZE - 1))
60
61
62
63
64
65#define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - S2_PGDIR_SHIFT))
66
67
68
69
70
71#define KVM_MMU_CACHE_MIN_PAGES (STAGE2_PGTABLE_LEVELS - 1)
72
73
74#if STAGE2_PGTABLE_LEVELS > 3
75
76#define S2_PUD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
77#define S2_PUD_SIZE (_AC(1, UL) << S2_PUD_SHIFT)
78#define S2_PUD_MASK (~(S2_PUD_SIZE - 1))
79
80#define stage2_pgd_none(pgd) pgd_none(pgd)
81#define stage2_pgd_clear(pgd) pgd_clear(pgd)
82#define stage2_pgd_present(pgd) pgd_present(pgd)
83#define stage2_pgd_populate(pgd, pud) pgd_populate(NULL, pgd, pud)
84#define stage2_pud_offset(pgd, address) pud_offset(pgd, address)
85#define stage2_pud_free(pud) pud_free(NULL, pud)
86
87#define stage2_pud_table_empty(pudp) kvm_page_empty(pudp)
88
89static inline phys_addr_t stage2_pud_addr_end(phys_addr_t addr, phys_addr_t end)
90{
91 phys_addr_t boundary = (addr + S2_PUD_SIZE) & S2_PUD_MASK;
92
93 return (boundary - 1 < end - 1) ? boundary : end;
94}
95
96#endif
97
98
99#if STAGE2_PGTABLE_LEVELS > 2
100
101#define S2_PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
102#define S2_PMD_SIZE (_AC(1, UL) << S2_PMD_SHIFT)
103#define S2_PMD_MASK (~(S2_PMD_SIZE - 1))
104
105#define stage2_pud_none(pud) pud_none(pud)
106#define stage2_pud_clear(pud) pud_clear(pud)
107#define stage2_pud_present(pud) pud_present(pud)
108#define stage2_pud_populate(pud, pmd) pud_populate(NULL, pud, pmd)
109#define stage2_pmd_offset(pud, address) pmd_offset(pud, address)
110#define stage2_pmd_free(pmd) pmd_free(NULL, pmd)
111
112#define stage2_pud_huge(pud) pud_huge(pud)
113#define stage2_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
114
115static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end)
116{
117 phys_addr_t boundary = (addr + S2_PMD_SIZE) & S2_PMD_MASK;
118
119 return (boundary - 1 < end - 1) ? boundary : end;
120}
121
122#endif
123
124#define stage2_pte_table_empty(ptep) kvm_page_empty(ptep)
125
126#if STAGE2_PGTABLE_LEVELS == 2
127#include <asm/stage2_pgtable-nopmd.h>
128#elif STAGE2_PGTABLE_LEVELS == 3
129#include <asm/stage2_pgtable-nopud.h>
130#endif
131
132
133#define stage2_pgd_index(addr) (((addr) >> S2_PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
134
135static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end)
136{
137 phys_addr_t boundary = (addr + S2_PGDIR_SIZE) & S2_PGDIR_MASK;
138
139 return (boundary - 1 < end - 1) ? boundary : end;
140}
141
142#endif
143