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 paging debug functions to a separate file that gets included only into vmm_paging.c
[palacios.git] / palacios / src / palacios / vmm_paging.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_paging.h>
21
22 #include <palacios/vmm.h>
23
24 #include <palacios/vm_guest_mem.h>
25
26
27
28 #define USE_VMM_PAGING_DEBUG
29 // All of the debug functions defined in vmm_paging.h are implemented in this file
30 #include "vmm_paging_debug.h"
31 #undef USE_VMM_PAGING_DEBUG
32
33
34 void delete_page_tables_32(pde32_t * pde) {
35   int i;
36
37   if (pde == NULL) { 
38     return;
39   }
40
41   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
42     if (pde[i].present) {
43       // We double cast, first to an addr_t to handle 64 bit issues, then to the pointer
44       PrintDebug("PTE base addr %x \n", pde[i].pt_base_addr);
45       pte32_t * pte = (pte32_t *)((addr_t)(uint_t)(pde[i].pt_base_addr << PAGE_POWER));
46
47       PrintDebug("Deleting PTE %d (%p)\n", i, pte);
48       V3_FreePage(pte);
49     }
50   }
51
52   PrintDebug("Deleting PDE (%p)\n", pde);
53   V3_FreePage(V3_PAddr(pde));
54 }
55
56 void delete_page_tables_32PAE(pdpe32pae_t * pdpe) { 
57   PrintError("Unimplemented function\n");
58 }
59
60 void delete_page_tables_64(pml4e64_t * pml4) {
61   PrintError("Unimplemented function\n");
62 }
63
64
65 int translate_guest_pt_32(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * paddr) {
66   addr_t guest_pde_pa = CR3_TO_PDE32_PA((void *)guest_cr3);
67   pde32_t * guest_pde = 0;
68
69   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) {
70     PrintError("In GVA->GPA: Invalid GPA(%p)->HVA PDE32 lookup\n", 
71                (void *)guest_pde);
72     return -1;
73   }
74   
75
76   return -1;
77 }
78
79
80 int translate_host_pt_32(addr_t host_cr3, addr_t vaddr, addr_t * paddr) {
81
82   return -1;
83 }
84
85
86
87
88
89
90 int pt32_lookup(pde32_t * pd, addr_t vaddr, addr_t * paddr) {
91   addr_t pde_entry;
92   pde32_entry_type_t pde_entry_type;
93
94   if (pd == 0) {
95     return -1;
96   }
97
98   pde_entry_type = pde32_lookup(pd, vaddr, &pde_entry);
99
100   if (pde_entry_type == PDE32_ENTRY_PTE32) {
101     return pte32_lookup((pte32_t *)pde_entry, vaddr, paddr);
102   } else if (pde_entry_type == PDE32_ENTRY_LARGE_PAGE) {
103     *paddr = pde_entry;
104     return 0;
105   }
106
107   return -1;
108 }
109
110
111
112 /* We can't do a full lookup because we don't know what context the page tables are in...
113  * The entry addresses could be pointing to either guest physical memory or host physical memory
114  * Instead we just return the entry address, and a flag to show if it points to a pte or a large page...
115  */
116 pde32_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
117   pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
118
119   if (!pde_entry->present) {
120     *entry = 0;
121     return PDE32_ENTRY_NOT_PRESENT;
122   } else  {
123
124     if (pde_entry->large_page) {
125       pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry;
126
127       *entry = PDE32_4MB_T_ADDR(*large_pde);
128       *entry += PD32_4MB_PAGE_OFFSET(addr);
129       return PDE32_ENTRY_LARGE_PAGE;
130     } else {
131       *entry = PDE32_T_ADDR(*pde_entry);
132       return PDE32_ENTRY_PTE32;
133     }
134   }  
135   return PDE32_ENTRY_NOT_PRESENT;
136 }
137
138
139
140 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
141  */
142 int pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
143   pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
144
145   if (!pte_entry->present) {
146     *entry = 0;
147     PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
148     return -1;
149   } else {
150     *entry = PTE32_T_ADDR(*pte_entry) + PT32_PAGE_OFFSET(addr);
151     return 0;
152   }
153
154   return -1;
155 }
156
157
158
159 pt_access_status_t can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
160   pde32_t * entry = &pde[PDE32_INDEX(addr)];
161
162   if (entry->present == 0) {
163     return PT_ENTRY_NOT_PRESENT;
164   } else if ((entry->writable == 0) && (access_type.write == 1)) {
165     return PT_WRITE_ERROR;
166   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
167     // Check CR0.WP?
168     return PT_USER_ERROR;
169   }
170
171   return PT_ACCESS_OK;
172 }
173
174
175 pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
176   pte32_t * entry = &pte[PTE32_INDEX(addr)];
177
178   if (entry->present == 0) {
179     return PT_ENTRY_NOT_PRESENT;
180   } else if ((entry->writable == 0) && (access_type.write == 1)) {
181     return PT_WRITE_ERROR;
182   } else if ((entry->user_page == 0) && (access_type.user == 1)) {
183     // Check CR0.WP?
184     return PT_USER_ERROR;
185   }
186
187   return PT_ACCESS_OK;
188 }
189
190
191
192
193 /* We generate a page table to correspond to a given memory layout
194  * pulling pages from the mem_list when necessary
195  * If there are any gaps in the layout, we add them as unmapped pages
196  */
197 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
198   addr_t current_page_addr = 0;
199   int i, j;
200   struct shadow_map * map = &(guest_info->mem_map);
201
202   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
203
204   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
205     int pte_present = 0;
206     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
207     
208
209     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
210       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
211
212       if (!region || 
213           (region->host_type == HOST_REGION_HOOK) || 
214           (region->host_type == HOST_REGION_UNALLOCATED) || 
215           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
216           (region->host_type == HOST_REGION_REMOTE) ||
217           (region->host_type == HOST_REGION_SWAPPED)) {
218         pte[j].present = 0;
219         pte[j].writable = 0;
220         pte[j].user_page = 0;
221         pte[j].write_through = 0;
222         pte[j].cache_disable = 0;
223         pte[j].accessed = 0;
224         pte[j].dirty = 0;
225         pte[j].pte_attr = 0;
226         pte[j].global_page = 0;
227         pte[j].vmm_info = 0;
228         pte[j].page_base_addr = 0;
229       } else {
230         addr_t host_addr;
231         pte[j].present = 1;
232         pte[j].writable = 1;
233         pte[j].user_page = 1;
234         pte[j].write_through = 0;
235         pte[j].cache_disable = 0;
236         pte[j].accessed = 0;
237         pte[j].dirty = 0;
238         pte[j].pte_attr = 0;
239         pte[j].global_page = 0;
240         pte[j].vmm_info = 0;
241
242         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
243           // BIG ERROR
244           // PANIC
245           return NULL;
246         }
247         
248         pte[j].page_base_addr = host_addr >> 12;
249         
250         pte_present = 1;
251       }
252
253       current_page_addr += PAGE_SIZE;
254     }
255
256     if (pte_present == 0) { 
257       V3_FreePage(V3_PAddr(pte));
258
259       pde[i].present = 0;
260       pde[i].writable = 0;
261       pde[i].user_page = 0;
262       pde[i].write_through = 0;
263       pde[i].cache_disable = 0;
264       pde[i].accessed = 0;
265       pde[i].reserved = 0;
266       pde[i].large_page = 0;
267       pde[i].global_page = 0;
268       pde[i].vmm_info = 0;
269       pde[i].pt_base_addr = 0;
270     } else {
271       pde[i].present = 1;
272       pde[i].writable = 1;
273       pde[i].user_page = 1;
274       pde[i].write_through = 0;
275       pde[i].cache_disable = 0;
276       pde[i].accessed = 0;
277       pde[i].reserved = 0;
278       pde[i].large_page = 0;
279       pde[i].global_page = 0;
280       pde[i].vmm_info = 0;
281       pde[i].pt_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pte));
282     }
283
284   }
285
286   return pde;
287 }
288
289
290 /* We generate a page table to correspond to a given memory layout
291  * pulling pages from the mem_list when necessary
292  * If there are any gaps in the layout, we add them as unmapped pages
293  */
294 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
295   addr_t current_page_addr = 0;
296   int i, j, k;
297   struct shadow_map * map = &(guest_info->mem_map);
298
299   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
300   memset(pdpe, 0, PAGE_SIZE);
301
302   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
303     int pde_present = 0;
304     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
305
306     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
307
308
309       int pte_present = 0;
310       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
311       
312       
313       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
314         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
315         
316         if (!region || 
317             (region->host_type == HOST_REGION_HOOK) || 
318             (region->host_type == HOST_REGION_UNALLOCATED) || 
319             (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
320             (region->host_type == HOST_REGION_REMOTE) ||
321             (region->host_type == HOST_REGION_SWAPPED)) {
322           pte[k].present = 0;
323           pte[k].writable = 0;
324           pte[k].user_page = 0;
325           pte[k].write_through = 0;
326           pte[k].cache_disable = 0;
327           pte[k].accessed = 0;
328           pte[k].dirty = 0;
329           pte[k].pte_attr = 0;
330           pte[k].global_page = 0;
331           pte[k].vmm_info = 0;
332           pte[k].page_base_addr = 0;
333           pte[k].rsvd = 0;
334         } else {
335           addr_t host_addr;
336           pte[k].present = 1;
337           pte[k].writable = 1;
338           pte[k].user_page = 1;
339           pte[k].write_through = 0;
340           pte[k].cache_disable = 0;
341           pte[k].accessed = 0;
342           pte[k].dirty = 0;
343           pte[k].pte_attr = 0;
344           pte[k].global_page = 0;
345           pte[k].vmm_info = 0;
346           
347           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
348             // BIG ERROR
349             // PANIC
350             return NULL;
351           }
352           
353           pte[k].page_base_addr = host_addr >> 12;
354           pte[k].rsvd = 0;
355
356           pte_present = 1;
357         }
358         
359         current_page_addr += PAGE_SIZE;
360       }
361       
362       if (pte_present == 0) { 
363         V3_FreePage(V3_PAddr(pte));
364         
365         pde[j].present = 0;
366         pde[j].writable = 0;
367         pde[j].user_page = 0;
368         pde[j].write_through = 0;
369         pde[j].cache_disable = 0;
370         pde[j].accessed = 0;
371         pde[j].avail = 0;
372         pde[j].large_page = 0;
373         pde[j].global_page = 0;
374         pde[j].vmm_info = 0;
375         pde[j].pt_base_addr = 0;
376         pde[j].rsvd = 0;
377       } else {
378         pde[j].present = 1;
379         pde[j].writable = 1;
380         pde[j].user_page = 1;
381         pde[j].write_through = 0;
382         pde[j].cache_disable = 0;
383         pde[j].accessed = 0;
384         pde[j].avail = 0;
385         pde[j].large_page = 0;
386         pde[j].global_page = 0;
387         pde[j].vmm_info = 0;
388         pde[j].pt_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pte));
389         pde[j].rsvd = 0;
390
391         pde_present = 1;
392       }
393       
394     }
395     
396     if (pde_present == 0) { 
397       V3_FreePage(V3_PAddr(pde));
398       
399       pdpe[i].present = 0;
400       pdpe[i].rsvd = 0;
401       pdpe[i].write_through = 0;
402       pdpe[i].cache_disable = 0;
403       pdpe[i].accessed = 0;
404       pdpe[i].avail = 0;
405       pdpe[i].rsvd2 = 0;
406       pdpe[i].vmm_info = 0;
407       pdpe[i].pd_base_addr = 0;
408       pdpe[i].rsvd3 = 0;
409     } else {
410       pdpe[i].present = 1;
411       pdpe[i].rsvd = 0;
412       pdpe[i].write_through = 0;
413       pdpe[i].cache_disable = 0;
414       pdpe[i].accessed = 0;
415       pdpe[i].avail = 0;
416       pdpe[i].rsvd2 = 0;
417       pdpe[i].vmm_info = 0;
418       pdpe[i].pd_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pde));
419       pdpe[i].rsvd3 = 0;
420     }
421     
422   }
423
424
425   return pdpe;
426 }
427
428
429
430
431
432
433 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
434   addr_t current_page_addr = 0;
435   int i, j, k, m;
436   struct shadow_map * map = &(info->mem_map);
437   
438   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
439
440   for (i = 0; i < 1; i++) {
441     int pdpe_present = 0;
442     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
443
444     for (j = 0; j < 20; j++) {
445       int pde_present = 0;
446       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
447
448       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
449         int pte_present = 0;
450         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
451
452
453         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
454           struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
455           
456
457           
458           if (!region || 
459               (region->host_type == HOST_REGION_HOOK) || 
460               (region->host_type == HOST_REGION_UNALLOCATED) || 
461               (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
462               (region->host_type == HOST_REGION_REMOTE) ||
463               (region->host_type == HOST_REGION_SWAPPED)) {
464             pte[m].present = 0;
465             pte[m].writable = 0;
466             pte[m].user_page = 0;
467             pte[m].write_through = 0;
468             pte[m].cache_disable = 0;
469             pte[m].accessed = 0;
470             pte[m].dirty = 0;
471             pte[m].pte_attr = 0;
472             pte[m].global_page = 0;
473             pte[m].vmm_info = 0;
474             pte[m].page_base_addr = 0;
475           } else {
476             addr_t host_addr;
477             pte[m].present = 1;
478             pte[m].writable = 1;
479             pte[m].user_page = 1;
480             pte[m].write_through = 0;
481             pte[m].cache_disable = 0;
482             pte[m].accessed = 0;
483             pte[m].dirty = 0;
484             pte[m].pte_attr = 0;
485             pte[m].global_page = 0;
486             pte[m].vmm_info = 0;
487             
488             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
489               // BIG ERROR
490               // PANIC
491               return NULL;
492             }
493
494             pte[m].page_base_addr = PTE64_BASE_ADDR(host_addr);
495
496             //PrintPTE64(current_page_addr, &(pte[m]));
497
498             pte_present = 1;      
499           }
500
501
502
503
504           current_page_addr += PAGE_SIZE;
505         }
506         
507         if (pte_present == 0) {
508           V3_FreePage(V3_PAddr(pte));
509
510           pde[k].present = 0;
511           pde[k].writable = 0;
512           pde[k].user_page = 0;
513           pde[k].write_through = 0;
514           pde[k].cache_disable = 0;
515           pde[k].accessed = 0;
516           pde[k].reserved = 0;
517           pde[k].large_page = 0;
518           //pde[k].global_page = 0;
519           pde[k].vmm_info = 0;
520           pde[k].pt_base_addr = 0;
521         } else {
522           pde[k].present = 1;
523           pde[k].writable = 1;
524           pde[k].user_page = 1;
525           pde[k].write_through = 0;
526           pde[k].cache_disable = 0;
527           pde[k].accessed = 0;
528           pde[k].reserved = 0;
529           pde[k].large_page = 0;
530           //pde[k].global_page = 0;
531           pde[k].vmm_info = 0;
532           pde[k].pt_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pte));
533
534           pde_present = 1;
535         }
536       }
537
538       if (pde_present == 0) {
539         V3_FreePage(V3_PAddr(pde));
540         
541         pdpe[j].present = 0;
542         pdpe[j].writable = 0;
543         pdpe[j].user_page = 0;
544         pdpe[j].write_through = 0;
545         pdpe[j].cache_disable = 0;
546         pdpe[j].accessed = 0;
547         pdpe[j].reserved = 0;
548         pdpe[j].large_page = 0;
549         //pdpe[j].global_page = 0;
550         pdpe[j].vmm_info = 0;
551         pdpe[j].pd_base_addr = 0;
552       } else {
553         pdpe[j].present = 1;
554         pdpe[j].writable = 1;
555         pdpe[j].user_page = 1;
556         pdpe[j].write_through = 0;
557         pdpe[j].cache_disable = 0;
558         pdpe[j].accessed = 0;
559         pdpe[j].reserved = 0;
560         pdpe[j].large_page = 0;
561         //pdpe[j].global_page = 0;
562         pdpe[j].vmm_info = 0;
563         pdpe[j].pd_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pde));
564
565
566         pdpe_present = 1;
567       }
568
569     }
570
571     PrintDebug("PML index=%d\n", i);
572
573     if (pdpe_present == 0) {
574       V3_FreePage(V3_PAddr(pdpe));
575       
576       pml[i].present = 0;
577       pml[i].writable = 0;
578       pml[i].user_page = 0;
579       pml[i].write_through = 0;
580       pml[i].cache_disable = 0;
581       pml[i].accessed = 0;
582       pml[i].reserved = 0;
583       //pml[i].large_page = 0;
584       //pml[i].global_page = 0;
585       pml[i].vmm_info = 0;
586       pml[i].pdp_base_addr = 0;
587     } else {
588       pml[i].present = 1;
589       pml[i].writable = 1;
590       pml[i].user_page = 1;
591       pml[i].write_through = 0;
592       pml[i].cache_disable = 0;
593       pml[i].accessed = 0;
594       pml[i].reserved = 0;
595       //pml[i].large_page = 0;
596       //pml[i].global_page = 0;
597       pml[i].vmm_info = 0;
598       pml[i].pdp_base_addr = PAGE_ALIGNED_ADDR((addr_t)V3_PAddr(pdpe));
599     }
600   }
601
602   return pml;
603 }
604
605
606
607