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