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.


reworked the hash table implementation
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
1 #include <palacios/vmm_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmcb.h>
4 #include <palacios/vmm_decoder.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
7
8
9
10 /* Segmentation is a problem here...
11  *
12  * When we get a memory operand, presumably we use the default segment (which is?) 
13  * unless an alternate segment was specfied in the prefix...
14  */
15
16
17 #ifndef DEBUG_CTRL_REGS
18 #undef PrintDebug
19 #define PrintDebug(fmt, args...)
20 #endif
21
22
23
24
25
26 // First Attempt = 494 lines
27 // current = 106 lines
28 int handle_cr0_write(struct guest_info * info) {
29   char instr[15];
30   int ret;
31   struct x86_instr dec_instr;
32
33   if (info->mem_mode == PHYSICAL_MEM) { 
34     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
35   } else { 
36     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
37   }
38
39   /* The IFetch will already have faulted in the necessary bytes for the full instruction
40     if (ret != 15) {
41     // I think we should inject a GPF into the guest
42     PrintError("Could not read instruction (ret=%d)\n", ret);
43     return -1;
44     }
45   */
46
47   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
48     PrintError("Could not decode instruction\n");
49     return -1;
50   }
51
52
53   if (opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
54     struct cr0_real *real_cr0  = (struct cr0_real*)&(info->ctrl_regs.cr0);
55     struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.src_operand.operand);      
56     uchar_t new_cr0_val;
57
58     PrintDebug("LMSW\n");
59
60     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
61     
62     PrintDebug("OperandVal = %x\n", new_cr0_val);
63
64     PrintDebug("Old CR0=%x\n", *real_cr0);      
65     *(uchar_t*)real_cr0 &= 0xf0;
66     *(uchar_t*)real_cr0 |= new_cr0_val;
67     PrintDebug("New CR0=%x\n", *real_cr0);      
68       
69
70     if (info->shdw_pg_mode == SHADOW_PAGING) {
71       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
72       
73       PrintDebug(" Old Shadow CR0=%x\n", *shadow_cr0);  
74       *(uchar_t*)shadow_cr0 &= 0xf0;
75       *(uchar_t*)shadow_cr0 |= new_cr0_val;
76       PrintDebug("New Shadow CR0=%x\n", *shadow_cr0);   
77     }
78   } else if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
79     PrintDebug("MOV2CR0\n");
80
81     if (info->cpu_mode == LONG) {
82       // 64 bit registers
83     } else {
84       // 32 bit registers
85         struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
86         struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
87
88         PrintDebug("OperandVal = %x, length=%d\n", *new_cr0, dec_instr.src_operand.size);
89
90
91         PrintDebug("Old CR0=%x\n", *real_cr0);
92         *real_cr0 = *new_cr0;
93         
94
95         if (info->shdw_pg_mode == SHADOW_PAGING) {
96           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
97           
98           PrintDebug("Old Shadow CR0=%x\n", *shadow_cr0);       
99           
100           real_cr0->et = 1;
101           
102           *shadow_cr0 = *new_cr0;
103           shadow_cr0->et = 1;
104           
105           if (get_mem_mode(info) == VIRTUAL_MEM) {
106             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
107             
108             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
109           } else  {
110             info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
111             real_cr0->pg = 1;
112           }
113           
114           PrintDebug("New Shadow CR0=%x\n",*shadow_cr0);
115         }
116         PrintDebug("New CR0=%x\n", *real_cr0);
117     }
118
119   } else if (opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
120     // CLTS
121     struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
122         
123     real_cr0->ts = 0;
124
125     if (info->shdw_pg_mode == SHADOW_PAGING) {
126       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
127       shadow_cr0->ts = 0;
128     }
129   } else {
130     PrintError("Unhandled opcode in handle_cr0_write\n");
131     return -1;
132   }
133
134   info->rip += dec_instr.instr_length;
135
136   return 0;
137 }
138
139
140 // First attempt = 253 lines
141 // current = 51 lines
142 int handle_cr0_read(struct guest_info * info) {
143   char instr[15];
144   int ret;
145   struct x86_instr dec_instr;
146
147   if (info->mem_mode == PHYSICAL_MEM) { 
148     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
149   } else { 
150     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
151   }
152
153   /* The IFetch will already have faulted in the necessary bytes for the full instruction
154      if (ret != 15) {
155      // I think we should inject a GPF into the guest
156      PrintError("Could not read instruction (ret=%d)\n", ret);
157      return -1;
158      }
159   */
160
161   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
162     PrintError("Could not decode instruction\n");
163     return -1;
164   }
165   
166   if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
167     struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
168     struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
169     
170     PrintDebug("MOVCR2\n");
171     PrintDebug("CR0 at 0x%x\n", real_cr0);
172
173     if (info->shdw_pg_mode == SHADOW_PAGING) {
174       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
175     } else {
176       *virt_cr0 = *real_cr0;
177     }
178     
179     PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
180     PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
181   } else if (opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
182     struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
183     struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
184     char cr0_val = *(char*)real_cr0 & 0x0f;
185     
186     PrintDebug("SMSW\n");
187
188     PrintDebug("CR0 at 0x%x\n", real_cr0);
189
190     *(char *)virt_cr0 &= 0xf0;
191     *(char *)virt_cr0 |= cr0_val;
192     
193   } else {
194     PrintError("Unhandled opcode in handle_cr0_read\n");
195     return -1;
196   }
197
198   info->rip += dec_instr.instr_length;
199
200   return 0;
201 }
202
203
204
205 // First Attemp = 256 lines
206 // current = 65 lines
207 int handle_cr3_write(struct guest_info * info) {
208   int ret;
209   char instr[15];
210   struct x86_instr dec_instr;
211
212   if (info->mem_mode == PHYSICAL_MEM) { 
213     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
214   } else { 
215     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
216   }
217
218   /* The IFetch will already have faulted in the necessary bytes for the full instruction
219      if (ret != 15) {
220      // I think we should inject a GPF into the guest
221      PrintError("Could not read instruction (ret=%d)\n", ret);
222      return -1;
223      }
224   */
225
226   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
227     PrintError("Could not decode instruction\n");
228     return -1;
229   }
230
231   if (opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
232
233     PrintDebug("MOV2CR3\n");
234
235     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
236
237     if (info->shdw_pg_mode == SHADOW_PAGING) {
238       struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);       
239       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
240       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
241       int cached = 0;
242       
243
244       PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
245                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
246       
247
248       cached = cache_page_tables32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
249       if (cached == -1) {
250         PrintError("CR3 Cache failed\n");
251         return -1;
252       } else if (cached == 0) {
253
254
255         addr_t shadow_pt;
256
257         
258         PrintDebug("New CR3 is different - flushing shadow page table\n");      
259         
260         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
261         
262         shadow_pt =  create_new_shadow_pt32();
263         
264         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);    
265       } else {
266         PrintDebug("Reusing cached shadow Page table\n");
267       }
268       
269       shadow_cr3->pwt = new_cr3->pwt;
270       shadow_cr3->pcd = new_cr3->pcd;
271       
272       // What the hell...
273       *guest_cr3 = *new_cr3;
274       
275       PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
276                  *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
277
278       if (info->mem_mode == VIRTUAL_MEM) {
279         // If we aren't in paged mode then we have to preserve the identity mapped CR3
280         info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
281       }
282     }
283   } else {
284     PrintError("Unhandled opcode in handle_cr3_write\n");
285     return -1;
286   }
287
288   info->rip += dec_instr.instr_length;
289
290   return 0;
291 }
292
293
294
295 // first attempt = 156 lines
296 // current = 36 lines
297 int handle_cr3_read(struct guest_info * info) {
298   char instr[15];
299   int ret;
300   struct x86_instr dec_instr;
301
302   if (info->mem_mode == PHYSICAL_MEM) { 
303     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
304   } else { 
305     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
306   }
307
308   /* The IFetch will already have faulted in the necessary bytes for the full instruction
309      if (ret != 15) {
310      // I think we should inject a GPF into the guest
311      PrintError("Could not read instruction (ret=%d)\n", ret);
312      return -1;
313      }
314   */
315
316   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
317     PrintError("Could not decode instruction\n");
318     return -1;
319   }
320
321   if (opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
322     PrintDebug("MOVCR32\n");
323     struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
324
325     PrintDebug("CR3 at 0x%x\n", &(info->ctrl_regs.cr3));
326
327     if (info->shdw_pg_mode == SHADOW_PAGING) {
328       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
329     } else {
330       *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
331     }
332   } else {
333     PrintError("Unhandled opcode in handle_cr3_read\n");
334     return -1;
335   }
336
337
338   info->rip += dec_instr.instr_length;
339
340   return 0;
341 }
342
343
344
345