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.


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