1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
3  * Copyright (c) 2015-2018 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #pragma once
25 
26 /* top level defines for the x86 mmu */
27 /* NOTE: the top part can be included from assembly */
28 #define KB                (1024UL)
29 #define MB                (1024UL*1024UL)
30 #define GB                (1024UL*1024UL*1024UL)
31 
32 #define X86_MMU_PG_P        0x001           /* P    Valid                   */
33 #define X86_MMU_PG_RW       0x002           /* R/W  Read/Write              */
34 #define X86_MMU_PG_U        0x004           /* U/S  User/Supervisor         */
35 #define X86_MMU_PG_PS       0x080           /* PS   Page size (0=4k,1=4M)   */
36 #define X86_MMU_PG_PTE_PAT  0x080           /* PAT  PAT index               */
37 #define X86_MMU_PG_G        0x100           /* G    Global                  */
38 #define X86_MMU_CLEAR       0x0
39 #define X86_DIRTY_ACCESS_MASK   0xf9f
40 #define X86_MMU_CACHE_DISABLE   0x010       /* C Cache disable */
41 
42 /* default flags for inner page directory entries */
43 #define X86_KERNEL_PD_FLAGS (X86_MMU_PG_RW | X86_MMU_PG_P | X86_MMU_PG_U)
44 
45 /* default flags for 2MB/4MB/1GB page directory entries */
46 #define X86_KERNEL_PD_LP_FLAGS (X86_MMU_PG_G | X86_MMU_PG_PS | X86_MMU_PG_RW | X86_MMU_PG_P)
47 
48 /* default flags for 4K page table entries */
49 #define X86_KERNEL_PT_FLAGS (X86_MMU_PG_G | X86_MMU_PG_RW | X86_MMU_PG_P)
50 
51 #if !defined(PAGE_SIZE)
52 #define PAGE_SIZE       4096
53 #elif PAGE_SIZE != 4096
54 #error "Found multiple incompatible definitions for PAGE_SIZE"
55 #endif
56 #define PAGE_DIV_SHIFT      12
57 
58 #if defined(PAE_MODE_ENABLED) || ARCH_X86_64
59 /* PAE mode */
60 #define X86_PDPT_ADDR_MASK      (0x00000000ffffffe0ul)
61 #define X86_PG_FRAME            (0xfffffffffffff000ul)
62 /* ISDM:4.1.4 MAXPHYADDR is at most 52 */
63 #define X86_PG_PHY_ADDR_MASK    (0x000ffffffffff000ul)
64 /* NX Bit is ignored in the PAE mode */
65 #define X86_FLAGS_MASK          (0x8000000000000ffful)
66 #define X86_PTE_NOT_PRESENT     (0xFFFFFFFFFFFFFFFEul)
67 #define X86_2MB_PAGE_FRAME      (0x000fffffffe00000ul)
68 #define PAGE_OFFSET_MASK_4KB    (0x0000000000000ffful)
69 #define PAGE_OFFSET_MASK_2MB    (0x00000000001ffffful)
70 #define X86_MMU_PG_NX           (1ul << 63)
71 
72 #if ARCH_X86_64
73 #define X86_PAGING_LEVELS   4
74 #define PML4_SHIFT      39
75 #else
76 #define X86_PAGING_LEVELS   3
77 #endif
78 
79 #define PDP_SHIFT       30
80 #define PD_SHIFT        21
81 #define PT_SHIFT        12
82 #define ADDR_OFFSET     9
83 #define PDPT_ADDR_OFFSET    2
84 #define NO_OF_PT_ENTRIES    512
85 
86 #define X86_SET_FLAG(x)     (x=1)
87 
88 #else
89 /* non PAE mode */
90 #define X86_PG_FRAME        (0xfffff000)
91 #define X86_FLAGS_MASK          (0x00000fff)
92 #define X86_PTE_NOT_PRESENT     (0xfffffffe)
93 #define X86_4MB_PAGE_FRAME      (0xffc00000)
94 #define PAGE_OFFSET_MASK_4KB    (0x00000fff)
95 #define PAGE_OFFSET_MASK_4MB    (0x003fffff)
96 #define NO_OF_PT_ENTRIES    1024
97 #define X86_PAGING_LEVELS   2
98 #define PD_SHIFT        22
99 #define PT_SHIFT        12
100 #define ADDR_OFFSET     10
101 
102 #endif
103 
104 /* on both x86-32 and x86-64 physical memory is mapped at the base of the kernel address space */
105 #define X86_PHYS_TO_VIRT(x)     ((uintptr_t)(x) + KERNEL_BASE - MEMBASE)
106 #define X86_VIRT_TO_PHYS(x)     ((uintptr_t)(x) - KERNEL_BASE + MEMBASE)
107 
108 /* C defines below */
109 #ifndef ASSEMBLY
110 
111 #include <sys/types.h>
112 #include <compiler.h>
113 
114 __BEGIN_CDECLS
115 
116 /* Different page table levels in the page table mgmt hirerachy */
117 enum page_table_levels {
118     PF_L,
119     PT_L,
120     PD_L,
121 #if defined(PAE_MODE_ENABLED) || ARCH_X86_64
122     PDP_L,
123 #endif
124 #if ARCH_X86_64
125     PML4_L
126 #endif
127 };
128 
129 
130 struct map_range {
131     vaddr_t start_vaddr;
132 #if defined(PAE_MODE_ENABLED) || ARCH_X86_64
133     uint64_t start_paddr; /* Physical address in the PAE mode is 64 bits wide */
134 #else
135     paddr_t start_paddr; /* Physical address in the PAE mode is 32 bits wide */
136 #endif
137     uint32_t size;
138 };
139 
140 #if defined(PAE_MODE_ENABLED) || ARCH_X86_64
141 typedef uint64_t map_addr_t;
142 typedef uint64_t arch_flags_t;
143 #define PRIxMAP_ADDR PRIx64
144 #define PRIxARCH_FLAGS PRIx64
145 #define PRIxMAP_RANGE_PADDR PRIx64
146 #else
147 typedef uint32_t map_addr_t;
148 typedef uint32_t arch_flags_t;
149 #define PRIxMAP_ADDR PRIx32
150 #define PRIxARCH_FLAGS PRIx32
151 #define PRIxMAP_RANGE_PADDR PRIxPADDR
152 #endif
153 
154 #if ARCH_X86_64
155 status_t x86_mmu_check_mapping (addr_t pml4, paddr_t paddr,
156                                 vaddr_t vaddr, arch_flags_t in_flags,
157                                 uint32_t *ret_level, arch_flags_t *ret_flags,
158                                 map_addr_t *last_valid_entry);
159 #endif
160 
161 status_t x86_mmu_get_mapping(map_addr_t init_table, vaddr_t vaddr, uint32_t *ret_level,
162                              arch_flags_t *mmu_flags, map_addr_t *last_valid_entry);
163 
164 status_t x86_mmu_map_range (map_addr_t pt, struct map_range *range, arch_flags_t flags);
165 status_t x86_mmu_add_mapping(map_addr_t init_table, map_addr_t paddr,
166                              vaddr_t vaddr, arch_flags_t flags);
167 status_t x86_mmu_unmap(map_addr_t init_table, vaddr_t vaddr, size_t count);
168 
169 void x86_mmu_early_init(void);
170 void x86_mmu_init(void);
171 
172 __END_CDECLS
173 
174 #endif // !ASSEMBLY
175