More work on x86_64 port, also cleaned up a little of the API.
[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 /**
80  * \brief Allocate a block of memory at the specified virtual address
81  */
82 tPAddr MM_Allocate(tVAddr VAddr)
83 {
84         tPAddr  ret;
85         
86         ret = MM_AllocPhys();
87         if(!ret)        return 0;
88         
89         if( !MM_Map(VAddr, ret) )
90         {
91                 MM_DerefPhys(ret);
92                 return 0;
93         }
94         
95         return ret;
96 }
97
98 /**
99  * \brief Get the physical address of a virtual location
100  */
101 tPAddr MM_GetPhysAddr(tVAddr Addr)
102 {
103         if( !(PAGEMAPLVL4(Addr >> 39) & 1) )
104                 return 0;
105         if( !(PAGEDIRPTR(Addr >> 30) & 1) )
106                 return 0;
107         if( !(PAGEDIR(Addr >> 21) & 1) )
108                 return 0;
109         if( !(PAGETABLE(Addr >> 12) & 1) )
110                 return 0;
111         
112         return (PAGETABLE(Addr >> 12) & ~0xFFF) | (Addr & 0xFFF);
113 }
114
115 /**
116  * \brief Sets the flags on a page
117  */
118 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
119 {
120         tPAddr  *ent;
121         
122         // Validity Check
123         if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
124                 return ;
125         if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
126                 return ;
127         if( !(PAGEDIR(VAddr >> 21) & 1) )
128                 return ;
129         if( !(PAGETABLE(VAddr >> 12) & 1) )
130                 return ;
131         
132         // Set Flags
133         ent = &PAGETABLE(VAddr >> 12);
134         
135         // Read-Only
136         if( Mask & MM_PFLAG_RO )
137         {
138                 if( Flags & MM_PFLAG_RO ) {
139                         *ent &= ~PF_WRITE;
140                 }
141                 else {
142                         *ent |= PF_WRITE;
143                 }
144         }
145         
146         // Kernel
147         if( Mask & MM_PFLAG_KERNEL )
148         {
149                 if( Flags & MM_PFLAG_KERNEL ) {
150                         *ent &= ~PF_USER;
151                 }
152                 else {
153                         *ent |= PF_USER;
154                 }
155         }
156         
157         // Copy-On-Write
158         if( Mask & MM_PFLAG_COW )
159         {
160                 if( Flags & MM_PFLAG_COW ) {
161                         *ent &= ~PF_WRITE;
162                         *ent |= PF_COW;
163                 }
164                 else {
165                         *ent &= ~PF_COW;
166                         *ent |= PF_WRITE;
167                 }
168         }
169         
170         // Execute
171         if( Mask & MM_PFLAG_EXEC )
172         {
173                 if( Flags & MM_PFLAG_EXEC ) {
174                         *ent &= ~PF_NX;
175                 }
176                 else {
177                         *ent |= PF_NX;
178                 }
179         }
180 }
181
182 Uint MM_GetFlags(tVAddr VAddr)
183 {
184         tPAddr  *ent;
185         Uint    ret = 0;
186         
187         // Validity Check
188         if( !(PAGEMAPLVL4(VAddr >> 39) & 1) )
189                 return 0;
190         if( !(PAGEDIRPTR(VAddr >> 30) & 1) )
191                 return 0;
192         if( !(PAGEDIR(VAddr >> 21) & 1) )
193                 return 0;
194         if( !(PAGETABLE(VAddr >> 12) & 1) )
195                 return 0;
196         
197         // Set Flags
198         ent = &PAGETABLE(VAddr >> 12);
199         
200         // Read-Only
201         if( !(*ent & PF_WRITE) )        ret |= MM_PFLAG_RO;
202         // Kernel
203         if( !(*ent & PF_USER) ) ret |= MM_PFLAG_KERNEL;
204         // Copy-On-Write
205         if( *ent & PF_COW )     ret |= MM_PFLAG_COW;    
206         // Execute
207         if( !(*ent & PF_NX) )   ret |= MM_PFLAG_EXEC;
208         
209         return ret;
210 }

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