Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


moved further along in the boot process....
[palacios.git] / palacios / src / palacios / vmm_paging.c
1 #include <palacios/vmm_paging.h>
2
3 #include <palacios/vmm.h>
4
5 #include <palacios/vm_guest_mem.h>
6
7
8 extern struct vmm_os_hooks * os_hooks;
9
10 void delete_page_tables_pde32(pde32_t * pde) {
11   int i;//, j;
12
13   if (pde == NULL) { 
14     return;
15   }
16
17   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
18     if (pde[i].present) {
19       pte32_t * pte = (pte32_t *)(pde[i].pt_base_addr << PAGE_POWER);
20
21       /*
22         for (j = 0; (j < MAX_PTE32_ENTRIES); j++) {
23         if ((pte[j].present)) {
24         os_hooks->free_page((void *)(pte[j].page_base_addr << PAGE_POWER));
25         }
26         }
27       */
28       //PrintDebug("Deleting PTE %d (%x)\n", i, pte);
29       os_hooks->free_page(pte);
30     }
31   }
32
33   //  PrintDebug("Deleting PDE (%x)\n", pde);
34   os_hooks->free_page(pde);
35 }
36
37
38
39
40
41 int pt32_lookup(pde32_t * pd, addr_t vaddr, addr_t * paddr) {
42   addr_t pde_entry;
43   pde32_entry_type_t pde_entry_type;
44
45   if (pd == 0) {
46     return -1;
47   }
48
49   pde_entry_type = pde32_lookup(pd, vaddr, &pde_entry);
50
51   if (pde_entry_type == PDE32_ENTRY_PTE32) {
52     return pte32_lookup((pte32_t *)pde_entry, vaddr, paddr);
53   } else if (pde_entry_type == PDE32_ENTRY_LARGE_PAGE) {
54     *paddr = pde_entry;
55     return 0;
56   }
57
58   return -1;
59 }
60
61
62
63 /* We can't do a full lookup because we don't know what context the page tables are in...
64  * The entry addresses could be pointing to either guest physical memory or host physical memory
65  * Instead we just return the entry address, and a flag to show if it points to a pte or a large page...
66  */
67 pde32_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
68   pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
69
70   if (!pde_entry->present) {
71     *entry = 0;
72     return PDE32_ENTRY_NOT_PRESENT;
73   } else  {
74     *entry = PAGE_ADDR(pde_entry->pt_base_addr);
75     
76     if (pde_entry->large_page) {
77       *entry += PAGE_OFFSET(addr);
78       return PDE32_ENTRY_LARGE_PAGE;
79     } else {
80       *entry = PDE32_T_ADDR(*pde_entry);
81       return PDE32_ENTRY_PTE32;
82     }
83   }  
84   return PDE32_ENTRY_NOT_PRESENT;
85 }
86
87
88
89 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
90  */
91 int pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
92   pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
93
94   if (!pte_entry->present) {
95     *entry = 0;
96     PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
97     return -1;
98   } else {
99     *entry = PTE32_T_ADDR(*pte_entry) + PT32_PAGE_OFFSET(addr);
100     return 0;
101   }
102
103   return -1;
104 }
105
106
107
108 pt_access_status_t can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
109   pde32_t * entry = &pde[PDE32_INDEX(addr)];
110
111   if (entry->present == 0) {
112     return PT_ENTRY_NOT_PRESENT;
113   } else if ((entry->writable == 0) && (access_type.write == 1)) {
114     return PT_WRITE_ERROR;
115   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
116     // Check CR0.WP
117     return PT_USER_ERROR;
118   }
119
120   return PT_ACCESS_OK;
121 }
122
123
124 pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
125   pte32_t * entry = &pte[PTE32_INDEX(addr)];
126
127   if (entry->present == 0) {
128     return PT_ENTRY_NOT_PRESENT;
129   } else if ((entry->writable == 0) && (access_type.write == 1)) {
130     return PT_WRITE_ERROR;
131   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
132     // Check CR0.WP
133     return PT_USER_ERROR;
134   }
135
136   return PT_ACCESS_OK;
137 }
138
139
140
141
142 /* We generate a page table to correspond to a given memory layout
143  * pulling pages from the mem_list when necessary
144  * If there are any gaps in the layout, we add them as unmapped pages
145  */
146 pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) {
147   ullong_t current_page_addr = 0;
148   int i, j;
149   struct shadow_map * map = &(guest_info->mem_map);
150
151   pde32_t * pde = os_hooks->allocate_pages(1);
152
153   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
154     int pte_present = 0;
155     pte32_t * pte = os_hooks->allocate_pages(1);
156     
157
158     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
159       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
160
161       if (!region || 
162           (region->host_type == HOST_REGION_HOOK) || 
163           (region->host_type == HOST_REGION_UNALLOCATED) || 
164           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
165           (region->host_type == HOST_REGION_REMOTE) ||
166           (region->host_type == HOST_REGION_SWAPPED)) {
167         pte[j].present = 0;
168         pte[j].writable = 0;
169         pte[j].user_page = 0;
170         pte[j].write_through = 0;
171         pte[j].cache_disable = 0;
172         pte[j].accessed = 0;
173         pte[j].dirty = 0;
174         pte[j].pte_attr = 0;
175         pte[j].global_page = 0;
176         pte[j].vmm_info = 0;
177         pte[j].page_base_addr = 0;
178       } else {
179         addr_t host_addr;
180         pte[j].present = 1;
181         pte[j].writable = 1;
182         pte[j].user_page = 1;
183         pte[j].write_through = 0;
184         pte[j].cache_disable = 0;
185         pte[j].accessed = 0;
186         pte[j].dirty = 0;
187         pte[j].pte_attr = 0;
188         pte[j].global_page = 0;
189         pte[j].vmm_info = 0;
190
191         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
192           // BIG ERROR
193           // PANIC
194           return NULL;
195         }
196         
197         pte[j].page_base_addr = host_addr >> 12;
198         
199         pte_present = 1;
200       }
201
202       current_page_addr += PAGE_SIZE;
203     }
204
205     if (pte_present == 0) { 
206       os_hooks->free_page(pte);
207
208       pde[i].present = 0;
209       pde[i].writable = 0;
210       pde[i].user_page = 0;
211       pde[i].write_through = 0;
212       pde[i].cache_disable = 0;
213       pde[i].accessed = 0;
214       pde[i].reserved = 0;
215       pde[i].large_page = 0;
216       pde[i].global_page = 0;
217       pde[i].vmm_info = 0;
218       pde[i].pt_base_addr = 0;
219     } else {
220       pde[i].present = 1;
221       pde[i].writable = 1;
222       pde[i].user_page = 1;
223       pde[i].write_through = 0;
224       pde[i].cache_disable = 0;
225       pde[i].accessed = 0;
226       pde[i].reserved = 0;
227       pde[i].large_page = 0;
228       pde[i].global_page = 0;
229       pde[i].vmm_info = 0;
230       pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(pte);
231     }
232
233   }
234
235   return pde;
236 }
237
238
239
240
241
242
243 void PrintPDE32(addr_t virtual_address, pde32_t * pde)
244 {
245   PrintDebug("PDE %p -> %p : present=%x, writable=%x, user=%x, wt=%x, cd=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
246              virtual_address,
247              (void *) (pde->pt_base_addr << PAGE_POWER),
248              pde->present,
249              pde->writable,
250              pde->user_page, 
251              pde->write_through,
252              pde->cache_disable,
253              pde->accessed,
254              pde->reserved,
255              pde->large_page,
256              pde->global_page,
257              pde->vmm_info);
258 }
259   
260 void PrintPTE32(addr_t virtual_address, pte32_t * pte)
261 {
262   PrintDebug("PTE %p -> %p : present=%x, writable=%x, user=%x, wt=%x, cd=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, vmm_info=%x\n",
263              virtual_address,
264              (void*)(pte->page_base_addr << PAGE_POWER),
265              pte->present,
266              pte->writable,
267              pte->user_page,
268              pte->write_through,
269              pte->cache_disable,
270              pte->accessed,
271              pte->dirty,
272              pte->pte_attr,
273              pte->global_page,
274              pte->vmm_info);
275 }
276
277
278
279 void PrintPD32(pde32_t * pde)
280 {
281   int i;
282
283   PrintDebug("Page Directory at %p:\n", pde);
284   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { 
285     if ( pde[i].present) {
286       PrintPDE32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
287     }
288   }
289 }
290
291 void PrintPT32(addr_t starting_address, pte32_t * pte) 
292 {
293   int i;
294
295   PrintDebug("Page Table at %p:\n", pte);
296   for (i = 0; (i < MAX_PTE32_ENTRIES) ; i++) { 
297     if (pte[i].present) {
298       PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i]));
299     }
300   }
301 }
302
303
304
305
306
307 void PrintDebugPageTables(pde32_t * pde)
308 {
309   int i;
310   
311   PrintDebug("Dumping the pages starting with the pde page at %p\n", pde);
312
313   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { 
314     if (pde[i].present) {
315       PrintPDE32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
316       PrintPT32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (pte32_t *)(pde[i].pt_base_addr << PAGE_POWER));
317     }
318   }
319 }
320