985fa8446202f8571d5605869f2c0e56b85b647a
[tpg/acess2.git] / Kernel / arch / x86_64 / mm_virt.c
1 /*
2  * Acess2 x86_64 Port
3  * 
4  * Virtual Memory Manager
5  */
6 #include <acess.h>
7 #include <mm_virt.h>
8
9 // === CONSTANTS ===
10 #define PML4_SHIFT      39
11 #define PDP_SHIFT       30
12 #define PDIR_SHIFT      21
13 #define PTAB_SHIFT      12
14
15 #define PF_PRESENT      0x1
16 #define PF_WRITE        0x2
17 #define PF_USER         0x4
18 #define PF_NX           0x80000000##00000000
19 #define PF_COW          0x200
20 #define PF_PAGED        0x400
21
22 // === MACROS ===
23 #define PAGETABLE(idx)  (*((tPAddr*)MM_FRACTAL_BASE+(idx)))
24 #define PAGEDIR(idx)    PAGETABLE((MM_FRACTAL_BASE>>12)+((idx)&0x7FFFFFF))
25 #define PAGEDIRPTR(idx) PAGETABLE((MM_FRACTAL_BASE>>21)+((idx)&0x3FFFF))
26 #define PAGEMAPLVL4(idx)        PAGETABLE((MM_FRACTAL_BASE>>30)+((idx)&0x1FF))
27
28 // === GLOBALS ===
29
30 // === CODE ===
31 void MM_InitVirt(void)
32 {
33         
34 }
35
36 /**
37  * \brief Map a physical page to a virtual one
38  */
39 int MM_Map(tVAddr VAddr, tPAddr PAddr)
40 {
41         tPAddr  tmp;
42         
43         // Check PML4
44         if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
45         {
46                 tmp = MM_AllocPhys();
47                 if(!tmp)        return 0;
48                 PAGEMAPLVL4(VAddr >> 39) = tmp | 3;
49                 memset( &PAGEDIRPTR( (VAddr>>39)<<9 ), 0, 4096 );
50         }
51         
52         // Check PDP
53         if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
54         {
55                 tmp = MM_AllocPhys();
56                 if(!tmp)        return 0;
57                 PAGEDIRPTR(VAddr >> 30) = tmp | 3;
58                 memset( &PAGEDIR( (VAddr>>30)<<9 ), 0, 4096 );
59         }
60         
61         // Check Page Dir
62         if( !(PAGEDIR(VAddr >> 21) & 1) )
63         {
64                 tmp = MM_AllocPhys();
65                 if(!tmp)        return 0;
66                 PAGEDIR(VAddr >> 21) = tmp | 3;
67                 memset( &PAGETABLE( (VAddr>>21)<<9 ), 0, 4096 );
68         }
69         
70         // Check if this virtual address is already mapped
71         if( PAGETABLE(VAddr >> 12) & 1 )
72                 return 0;
73         
74         PAGETABLE(VAddr >> 12) = PAddr | 3;
75         
76         return 1;
77 }
78
79 void MM_Unmap(tVAddr VAddr)
80 {
81         // Check PML4
82         if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )   return ;
83         // Check PDP
84         if( !(PAGEDIRPTR(VAddr >> 30) & 1) )    return ;
85         // Check Page Dir
86         if( !(PAGEDIR(VAddr >> 21) & 1) )       return ;
87         
88         PAGETABLE(VAddr >> 12) = 0;
89 }
90
91 /**
92  * \brief Allocate a block of memory at the specified virtual address
93  */
94 tPAddr MM_Allocate(tVAddr VAddr)
95 {
96         tPAddr  ret;
97         
98         ret = MM_AllocPhys();
99         if(!ret)        return 0;
100         
101         if( !MM_Map(VAddr, ret) )
102         {
103                 MM_DerefPhys(ret);
104                 return 0;
105         }
106         
107         return ret;
108 }
109
110 void MM_Deallocate(tVAddr VAddr)
111 {
112         tPAddr  phys;
113         
114         phys = MM_GetPhysAddr(VAddr);
115         if(!phys)       return ;
116         
117         MM_Unmap(VAddr);
118         
119         MM_DerefPhys(phys);
120 }
121
122 /**
123  * \brief Get the physical address of a virtual location
124  */
125 tPAddr MM_GetPhysAddr(tVAddr Addr)
126 {
127         if( !(PAGEMAPLVL4(Addr >> 39) & 1) )
128                 return 0;
129         if( !(PAGEDIRPTR(Addr >> 30) & 1) )
130                 return 0;
131         if( !(PAGEDIR(Addr >> 21) & 1) )
132                 return 0;
133         if( !(PAGETABLE(Addr >> 12) & 1) )
134                 return 0;
135         
136         return (PAGETABLE(Addr >> 12) & ~0xFFF) | (Addr & 0xFFF);
137 }
138
139 /**
140  * \brief Sets the flags on a page
141  */
142 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
143 {
144         tPAddr  *ent;
145         
146         // Validity Check
147         if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
148                 return ;
149         if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
150                 return ;
151         if( !(PAGEDIR(VAddr >> 21) & 1) )
152                 return ;
153         if( !(PAGETABLE(VAddr >> 12) & 1) )
154                 return ;
155         
156         // Set Flags
157         ent = &PAGETABLE(VAddr >> 12);
158         
159         // Read-Only
160         if( Mask & MM_PFLAG_RO )
161         {
162                 if( Flags & MM_PFLAG_RO ) {
163                         *ent &= ~PF_WRITE;
164                 }
165                 else {
166                         *ent |= PF_WRITE;
167                 }
168         }
169         
170         // Kernel
171         if( Mask & MM_PFLAG_KERNEL )
172         {
173                 if( Flags & MM_PFLAG_KERNEL ) {
174                         *ent &= ~PF_USER;
175                 }
176                 else {
177                         *ent |= PF_USER;
178                 }
179         }
180         
181         // Copy-On-Write
182         if( Mask & MM_PFLAG_COW )
183         {
184                 if( Flags & MM_PFLAG_COW ) {
185                         *ent &= ~PF_WRITE;
186                         *ent |= PF_COW;
187                 }
188                 else {
189                         *ent &= ~PF_COW;
190                         *ent |= PF_WRITE;
191                 }
192         }
193         
194         // Execute
195         if( Mask & MM_PFLAG_EXEC )
196         {
197                 if( Flags & MM_PFLAG_EXEC ) {
198                         *ent &= ~PF_NX;
199                 }
200                 else {
201                         *ent |= PF_NX;
202                 }
203         }
204 }
205
206 /**
207  * \brief Get the flags applied to a page
208  */
209 Uint MM_GetFlags(tVAddr VAddr)
210 {
211         tPAddr  *ent;
212         Uint    ret = 0;
213         
214         // Validity Check
215         if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
216                 return 0;
217         if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
218                 return 0;
219         if( !(PAGEDIR(VAddr >> 21) & 1) )
220                 return 0;
221         if( !(PAGETABLE(VAddr >> 12) & 1) )
222                 return 0;
223         
224         // Set Flags
225         ent = &PAGETABLE(VAddr >> 12);
226         
227         // Read-Only
228         if( !(*ent & PF_WRITE) )        ret |= MM_PFLAG_RO;
229         // Kernel
230         if( !(*ent & PF_USER) ) ret |= MM_PFLAG_KERNEL;
231         // Copy-On-Write
232         if( *ent & PF_COW )     ret |= MM_PFLAG_COW;    
233         // Execute
234         if( !(*ent & PF_NX) )   ret |= MM_PFLAG_EXEC;
235         
236         return ret;
237 }
238
239 // --- Hardware Mappings ---
240 /**
241  * \brief Map a range of hardware pages
242  */
243 tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
244 {
245         Log_KernelPanic("MM", "TODO: Implement MM_MapHWPages");
246         return 0;
247 }
248
249 /**
250  * \brief Free a range of hardware pages
251  */
252 void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
253 {
254         Log_KernelPanic("MM", "TODO: Implement MM_UnmapHWPages");
255 }
256
257 // --- Tempory Mappings ---
258 tVAddr MM_MapTemp(tPAddr PAddr)
259 {
260         Log_KernelPanic("MM", "TODO: Implement MM_MapTemp");
261         return 0;
262 }
263
264 void MM_FreeTemp(tVAddr VAddr)
265 {
266         Log_KernelPanic("MM", "TODO: Implement MM_FreeTemp");
267         return ;
268 }
269
270
271 // --- Address Space Clone --
272 tPAddr MM_Clone(void)
273 {
274         tPAddr  ret;
275         
276         // #1 Create a copy of the PML4
277         ret = MM_AllocPhys();
278         if(!ret)        return 0;
279         
280         // #2 Alter the fractal pointer
281         // #3 Set Copy-On-Write to all user pages
282         // #4 Return
283         return 0;
284 }

UCC git Repository :: git.ucc.asn.au