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.


ac4fbbf12eb741b2c02afdc94ce045e0d3f1a0ab
[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       for (j = 0; (j < MAX_PTE32_ENTRIES); j++) {
22         if ((pte[j].present)) {
23           os_hooks->free_page((void *)(pte[j].page_base_addr << PAGE_POWER));
24         }
25       }
26       
27       os_hooks->free_page(pte);
28     }
29   }
30
31   os_hooks->free_page(pde);
32 }
33
34
35
36
37
38
39
40 /* We can't do a full lookup because we don't know what context the page tables are in...
41  * The entry addresses could be pointing to either guest physical memory or host physical memory
42  * Instead we just return the entry address, and a flag to show if it points to a pte or a large page...
43  */
44 pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) {
45   pde32_t * pde_entry = &(pde[PDE32_INDEX(addr)]);
46
47   if (!pde_entry->present) {
48     *entry = 0;
49     return NOT_PRESENT;
50   } else  {
51     *entry = PAGE_ADDR(pde_entry->pt_base_addr);
52     
53     if (pde_entry->large_pages) {
54       *entry += PAGE_OFFSET(addr);
55       return LARGE_PAGE;
56     } else {
57       return PTE32;
58     }
59   }  
60   return NOT_PRESENT;
61 }
62
63
64 int pte32_lookup(pte32_t * pte, addr_t addr, addr_t * entry) {
65   pte32_t * pte_entry = &(pte[PTE32_INDEX(addr)]);
66
67   if (!pte_entry->present) {
68     *entry = 0;
69     return -1;
70   } else {
71     *entry = PAGE_ADDR(pte_entry->page_base_addr);
72     *entry += PAGE_OFFSET(addr);
73     return 0;
74   }
75
76   return -1;
77 }
78
79
80
81
82
83
84
85
86 /* We generate a page table to correspond to a given memory layout
87  * pulling pages from the mem_list when necessary
88  * If there are any gaps in the layout, we add them as unmapped pages
89  */
90 pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) {
91   ullong_t current_page_addr = 0;
92   int i, j;
93   struct shadow_map * map = &(guest_info->mem_map);
94
95
96   pde32_t * pde = os_hooks->allocate_pages(1);
97
98   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
99     int pte_present = 0;
100     pte32_t * pte = os_hooks->allocate_pages(1);
101     
102
103     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
104       shadow_region_t * region = get_shadow_region_by_addr(map, current_page_addr);
105
106       if (!region || 
107           (region->host_type == HOST_REGION_NOTHING) || 
108           (region->host_type == HOST_REGION_UNALLOCATED) || 
109           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
110           (region->host_type == HOST_REGION_REMOTE) ||
111           (region->host_type == HOST_REGION_SWAPPED)) {
112         pte[j].present = 0;
113         pte[j].flags = 0;
114         pte[j].accessed = 0;
115         pte[j].dirty = 0;
116         pte[j].pte_attr = 0;
117         pte[j].global_page = 0;
118         pte[j].vmm_info = 0;
119         pte[j].page_base_addr = 0;
120       } else {
121         addr_t host_addr;
122         pte[j].present = 1;
123         pte[j].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER;   
124         
125         pte[j].accessed = 0;
126         pte[j].dirty = 0;
127         pte[j].pte_attr = 0;
128         pte[j].global_page = 0;
129         pte[j].vmm_info = 0;
130
131         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
132           // BIG ERROR
133           // PANIC
134           return NULL;
135         }
136         
137         pte[j].page_base_addr = host_addr >> 12;
138         
139         pte_present = 1;
140       }
141
142       current_page_addr += PAGE_SIZE;
143     }
144
145     if (pte_present == 0) { 
146       os_hooks->free_page(pte);
147
148       pde[i].present = 0;
149       pde[i].flags = 0;
150       pde[i].accessed = 0;
151       pde[i].reserved = 0;
152       pde[i].large_pages = 0;
153       pde[i].global_page = 0;
154       pde[i].vmm_info = 0;
155       pde[i].pt_base_addr = 0;
156     } else {
157       pde[i].present = 1;
158       pde[i].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER;
159       pde[i].accessed = 0;
160       pde[i].reserved = 0;
161       pde[i].large_pages = 0;
162       pde[i].global_page = 0;
163       pde[i].vmm_info = 0;
164       pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(pte);
165     }
166
167   }
168
169   return pde;
170 }
171
172
173
174
175
176
177 void PrintPDE32(void * virtual_address, pde32_t * pde)
178 {
179   PrintDebug("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
180               virtual_address,
181               (void *) (pde->pt_base_addr << PAGE_POWER),
182               pde->present,
183               pde->flags,
184               pde->accessed,
185               pde->reserved,
186               pde->large_pages,
187               pde->global_page,
188               pde->vmm_info);
189 }
190   
191 void PrintPTE32(void * virtual_address, pte32_t * pte)
192 {
193   PrintDebug("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, vmm_info=%x\n",
194               virtual_address,
195               (void*)(pte->page_base_addr << PAGE_POWER),
196               pte->present,
197               pte->flags,
198               pte->accessed,
199               pte->dirty,
200               pte->pte_attr,
201               pte->global_page,
202               pte->vmm_info);
203 }
204
205
206
207 void PrintPD32(pde32_t * pde)
208 {
209   int i;
210
211   PrintDebug("Page Directory at %p:\n", pde);
212   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { 
213     if ( pde[i].present) {
214       PrintPDE32((void*)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
215     }
216   }
217 }
218
219 void PrintPT32(void * starting_address, pte32_t * pte) 
220 {
221   int i;
222
223   PrintDebug("Page Table at %p:\n", pte);
224   for (i = 0; (i < MAX_PTE32_ENTRIES) ; i++) { 
225     if (pte[i].present) {
226       PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i]));
227     }
228   }
229 }
230
231
232
233
234
235 void PrintDebugPageTables(pde32_t * pde)
236 {
237   int i;
238   
239   PrintDebug("Dumping the pages starting with the pde page at %p\n", pde);
240
241   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { 
242     if (pde[i].present) {
243       PrintPDE32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i]));
244       PrintPT32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (void *)(pde[i].pt_base_addr << PAGE_POWER));
245     }
246   }
247 }
248