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.


188956c246742b0f0eb571cb6a3219580210b978
[palacios.git] / palacios / src / geekos / vmm_shadow_paging.c
1 #include <geekos/vmm_shadow_paging.h>
2
3 #include <geekos/vmm.h>
4
5 extern struct vmm_os_hooks * os_hooks;
6
7
8 int init_shadow_page_state(shadow_page_state_t * state) {
9   state->guest_mode = PDE32;
10   state->shadow_mode = PDE32;
11   
12   state->guest_cr3.r_reg = 0;
13   state->shadow_cr3.r_reg = 0;
14
15   return 0;
16 }
17   
18
19 int wholesale_update_shadow_page_state(shadow_page_state_t * state, shadow_map_t * mem_map) {
20   unsigned i, j;
21   vmm_pde_t * guest_pde;
22   vmm_pde_t * shadow_pde;
23
24
25   // For now, we'll only work with PDE32
26   if (state->guest_mode != PDE32) { 
27     return -1;
28   }
29
30
31   
32   shadow_pde = (vmm_pde_t *)(CR3_TO_PDE(state->shadow_cr3.e_reg.low));  
33   guest_pde = (vmm_pde_t *)(os_hooks->paddr_to_vaddr((void*)CR3_TO_PDE(state->guest_cr3.e_reg.low)));
34
35   // Delete the current page table
36   delete_page_tables_pde32(shadow_pde);
37
38   shadow_pde = os_hooks->allocate_pages(1);
39
40
41   state->shadow_cr3.e_reg.low = (addr_t)shadow_pde;
42
43   state->shadow_mode = PDE32;
44
45   
46   for (i = 0; i < MAX_PDE32_ENTRIES; i++) { 
47     shadow_pde[i] = guest_pde[i];
48
49     // The shadow can be identical to the guest if it's not present
50     if (!shadow_pde[i].present) { 
51       continue;
52     }
53
54     if (shadow_pde[i].large_pages) { 
55       // large page - just map it through shadow map to generate its physical location
56       addr_t guest_addr = PAGE_ADDR(shadow_pde[i].pt_base_addr);
57       addr_t host_addr;
58       shadow_region_t * ent;
59
60       ent = get_shadow_region_by_addr(mem_map, guest_addr);
61       
62       if (!ent) { 
63         // FIXME Panic here - guest is trying to map to physical memory
64         // it does not own in any way!
65         return -1;
66       }
67
68       // FIXME Bounds check here to see if it's trying to trick us
69       
70       switch (ent->host_type) { 
71       case HOST_REGION_PHYSICAL_MEMORY:
72         // points into currently allocated physical memory, so we just
73         // set up the shadow to point to the mapped location
74         if (guest_paddr_to_host_paddr(ent, guest_addr, &host_addr)) { 
75           // Panic here
76           return -1;
77         }
78
79         shadow_pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(host_addr);
80         // FIXME set vmm_info bits here
81         break;
82       case HOST_REGION_UNALLOCATED:
83         // points to physical memory that is *allowed* but that we
84         // have not yet allocated.  We mark as not present and set a
85         // bit to remind us to allocate it later
86         shadow_pde[i].present = 0;
87         // FIXME Set vminfo bits here so that we know that we will be
88         // allocating it later
89         break;
90       case HOST_REGION_NOTHING:
91         // points to physical memory that is NOT ALLOWED.   
92         // We will mark it as not present and set a bit to remind
93         // us that it's bad later and insert a GPF then
94         shadow_pde[i].present = 0;
95         break;
96       case HOST_REGION_MEMORY_MAPPED_DEVICE:
97       case HOST_REGION_REMOTE:
98       case HOST_REGION_SWAPPED:
99       default:
100         // Panic.  Currently unhandled
101         return -1;
102         break;
103       }
104     } else {
105       vmm_pte_t * guest_pte;
106       vmm_pte_t * shadow_pte;
107       addr_t guest_addr;
108       addr_t guest_pte_host_addr;
109       shadow_region_t * ent;
110
111       // small page - set PDE and follow down to the child table
112       shadow_pde[i] = guest_pde[i];
113
114       guest_addr = PAGE_ADDR(guest_pde[i].pt_base_addr);
115
116       // Allocate a new second level page table for the shadow
117       shadow_pte = os_hooks->allocate_pages(1);
118
119       // make our first level page table in the shadow point to it
120       shadow_pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(shadow_pte);
121       
122       ent = get_shadow_region_by_addr(mem_map, guest_addr);
123       
124
125       /* JRL: This is bad.... */
126       // For now the guest Page Table must always be mapped to host physical memory
127       /* If we swap out a page table or if it isn't present for some reason, this turns real ugly */
128
129       if ((!ent) || (ent->host_type != HOST_REGION_PHYSICAL_MEMORY)) { 
130         // FIXME Panic here - guest is trying to map to physical memory
131         // it does not own in any way!
132         return -1;
133       }
134
135       // Address of the relevant second level page table in the guest
136       if (guest_paddr_to_host_paddr(ent, guest_addr, &guest_pte_host_addr)) { 
137         // Panic here
138         return -1;
139       }
140
141
142       // host_addr now contains the host physical address for the guest's 2nd level page table
143       // Now we transform it to relevant virtual address
144       guest_pte = os_hooks->paddr_to_vaddr((void *)guest_pte_host_addr);
145
146       // Now we walk through the second level guest page table
147       // and clone it into the shadow
148       for (j = 0; j < MAX_PTE32_ENTRIES; j++) { 
149         shadow_pte[j] = guest_pte[j];
150
151         addr_t guest_addr = PAGE_ADDR(shadow_pte[j].page_base_addr);
152         
153         shadow_region_t * ent;
154
155         ent = get_shadow_region_by_addr(mem_map, guest_addr);
156       
157         if (!ent) { 
158           // FIXME Panic here - guest is trying to map to physical memory
159           // it does not own in any way!
160           return -1;
161         }
162
163         switch (ent->host_type) { 
164         case HOST_REGION_PHYSICAL_MEMORY:
165           {
166             addr_t host_addr;
167             
168             // points into currently allocated physical memory, so we just
169             // set up the shadow to point to the mapped location
170             if (guest_paddr_to_host_paddr(ent, guest_addr, &host_addr)) { 
171               // Panic here
172               return -1;
173             }
174             
175             shadow_pte[j].page_base_addr = PAGE_ALIGNED_ADDR(host_addr);
176             // FIXME set vmm_info bits here
177             break;
178           }
179         case HOST_REGION_UNALLOCATED:
180           // points to physical memory that is *allowed* but that we
181           // have not yet allocated.  We mark as not present and set a
182           // bit to remind us to allocate it later
183           shadow_pte[j].present = 0;
184           // FIXME Set vminfo bits here so that we know that we will be
185           // allocating it later
186           break;
187         case HOST_REGION_NOTHING:
188           // points to physical memory that is NOT ALLOWED.   
189           // We will mark it as not present and set a bit to remind
190           // us that it's bad later and insert a GPF then
191           shadow_pte[j].present = 0;
192           break;
193         case HOST_REGION_MEMORY_MAPPED_DEVICE:
194         case HOST_REGION_REMOTE:
195         case HOST_REGION_SWAPPED:
196         default:
197           // Panic.  Currently unhandled
198           return -1;
199         break;
200         }
201       }
202     }
203   }
204   return 0;
205 }
206       
207