1 /*
2 * Copyright (C) 2018-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 /**
7 * @file mmu.h
8 *
9 * @brief APIs for Memory Management module
10 */
11 #ifndef MMU_H
12 #define MMU_H
13 /**
14 * @brief Memory Management
15 *
16 * @defgroup acrn_mem ACRN Memory Management
17 * @{
18 */
19 /** The flag that indicates that the page fault was caused by a non present
20 * page.
21 */
22 #define PAGE_FAULT_P_FLAG 0x00000001U
23 /** The flag that indicates that the page fault was caused by a write access. */
24 #define PAGE_FAULT_WR_FLAG 0x00000002U
25 /** The flag that indicates that the page fault was caused in user mode. */
26 #define PAGE_FAULT_US_FLAG 0x00000004U
27 /** The flag that indicates that the page fault was caused by a reserved bit
28 * violation.
29 */
30 #define PAGE_FAULT_RSVD_FLAG 0x00000008U
31 /** The flag that indicates that the page fault was caused by an instruction
32 * fetch.
33 */
34 #define PAGE_FAULT_ID_FLAG 0x00000010U
35
36 /* Defines used for common memory sizes */
37 #define MEM_1K 1024U
38 #define MEM_2K (MEM_1K * 2U)
39 #define MEM_4K (MEM_1K * 4U)
40 #define MEM_1M (MEM_1K * 1024U)
41 #define MEM_2M (MEM_1M * 2U)
42 #define MEM_1G (MEM_1M * 1024U)
43 #define MEM_2G (MEM_1G * 2UL)
44 #define MEM_4G (MEM_1G * 4UL)
45
46 #ifndef ASSEMBLER
47
48 #include <asm/page.h>
49 #include <asm/pgtable.h>
50
51 /* Define cache line size (in bytes) */
52 #define CACHE_LINE_SIZE 64U
53
54 /* IA32E Paging constants */
55 #define IA32E_REF_MASK ((get_pcpu_info())->physical_address_mask)
56 #define INVEPT_TYPE_SINGLE_CONTEXT 1UL
57 #define INVEPT_TYPE_ALL_CONTEXTS 2UL
58 #define VMFAIL_INVALID_EPT_VPID \
59 " jnc 1f\n" \
60 " mov $1, %0\n" /* CF: error = 1 */ \
61 " jmp 3f\n" \
62 "1: jnz 2f\n" \
63 " mov $2, %0\n" /* ZF: error = 2 */ \
64 " jmp 3f\n" \
65 "2: mov $0, %0\n" \
66 "3:"
67
68 struct invvpid_operand {
69 uint32_t vpid : 16;
70 uint32_t rsvd1 : 16;
71 uint32_t rsvd2 : 32;
72 uint64_t gva;
73 };
74
asm_invvpid(const struct invvpid_operand operand,uint64_t type)75 static inline int32_t asm_invvpid(const struct invvpid_operand operand, uint64_t type)
76 {
77 int32_t error;
78 asm volatile ("invvpid %1, %2\n"
79 VMFAIL_INVALID_EPT_VPID
80 : "=r" (error)
81 : "m" (operand), "r" (type)
82 : "memory");
83 return error;
84 }
85
86 struct invept_desc {
87 uint64_t eptp;
88 uint64_t res;
89 };
90
asm_invept(uint64_t type,struct invept_desc desc)91 static inline int32_t asm_invept(uint64_t type, struct invept_desc desc)
92 {
93 int32_t error;
94 asm volatile ("invept %1, %2\n"
95 VMFAIL_INVALID_EPT_VPID
96 : "=r" (error)
97 : "m" (desc), "r" (type)
98 : "memory");
99 return error;
100 }
101
102 struct acrn_vcpu;
round_page_up(uint64_t addr)103 static inline uint64_t round_page_up(uint64_t addr)
104 {
105 return (((addr + (uint64_t)PAGE_SIZE) - 1UL) & PAGE_MASK);
106 }
107
round_page_down(uint64_t addr)108 static inline uint64_t round_page_down(uint64_t addr)
109 {
110 return (addr & PAGE_MASK);
111 }
112
round_pde_up(uint64_t val)113 static inline uint64_t round_pde_up(uint64_t val)
114 {
115 return (((val + (uint64_t)PDE_SIZE) - 1UL) & PDE_MASK);
116 }
117
round_pde_down(uint64_t val)118 static inline uint64_t round_pde_down(uint64_t val)
119 {
120 return (val & PDE_MASK);
121 }
122
123 /* Page size */
124 #define PAGE_SIZE_4K MEM_4K
125 #define PAGE_SIZE_2M MEM_2M
126 #define PAGE_SIZE_1G MEM_1G
127
128 /**
129 * @brief MMU paging enable
130 */
131 void enable_paging(void);
132 /**
133 * @brief Supervisor-mode execution prevention (SMEP) enable
134 */
135 void enable_smep(void);
136
137 /**
138 * @brief Supervisor-mode Access Prevention (SMAP) enable
139 */
140 void enable_smap(void);
141
142 /**
143 * @brief MMU page tables initialization
144 */
145 void init_paging(void);
146
147 /*
148 * set paging attribute for primary page tables
149 */
150 void set_paging_supervisor(uint64_t base, uint64_t size);
151 void set_paging_x(uint64_t base, uint64_t size);
152 void set_paging_nx(uint64_t base, uint64_t size);
153
154 /**
155 * @brief Specified signle VPID flush
156 *
157 * @param[in] vpid the specified VPID
158 */
159 void flush_vpid_single(uint16_t vpid);
160 /**
161 * @brief All VPID flush
162 */
163 void flush_vpid_global(void);
164
165 /**
166 * @brief Guest-physical mappings and combined mappings invalidation
167 *
168 * @param[in] eptp the pointer that points the eptp
169 */
170 void invept(const void *eptp);
171
172 /* get PDPT address from CR3 vaule in PAE mode */
get_pae_pdpt_addr(uint64_t cr3)173 static inline uint64_t get_pae_pdpt_addr(uint64_t cr3)
174 {
175 return (cr3 & 0xFFFFFFE0UL);
176 }
177
178 /*
179 * flush TLB only for the specified page with the address
180 */
181 void flush_tlb(uint64_t addr);
182 void flush_tlb_range(uint64_t addr, uint64_t size);
183
184 void flush_invalidate_all_cache(void);
185 void flush_cacheline(const volatile void *p);
186 void flush_cache_range(const volatile void *p, uint64_t size);
187 void allocate_ppt_pages(void);
188
189 /**
190 * @}
191 */
192 #endif /* ASSEMBLER not defined */
193
194 #endif /* MMU_H */
195