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.


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