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.


added invlpg support
[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_emulate.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
7
8
9 /* Segmentation is a problem here...
10  *
11  * When we get a memory operand, presumably we use the default segment (which is?) 
12  * unless an alternate segment was specfied in the prefix...
13  */
14
15
16 int handle_cr0_write(struct guest_info * info) {
17   char instr[15];
18   
19   
20   if (info->cpu_mode == REAL) {
21     int index = 0;
22     int ret;
23
24     // The real rip address is actually a combination of the rip + CS base 
25     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
26     if (ret != 15) {
27       // I think we should inject a GPF into the guest
28       PrintDebug("Could not read instruction (ret=%d)\n", ret);
29       return -1;
30     }
31
32     while (is_prefix_byte(instr[index])) {
33       index++; 
34     }
35
36     if ((instr[index] == cr_access_byte) && 
37         (instr[index + 1] == lmsw_byte) && 
38         (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
39  
40       addr_t first_operand;
41       addr_t second_operand;
42       struct cr0_real *real_cr0;
43       struct cr0_real *new_cr0;
44       operand_type_t addr_type;
45       char new_cr0_val = 0;
46       // LMSW
47       // decode mod/RM
48       index += 2;
49  
50       real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
51
52       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
53
54
55       if (addr_type == REG_OPERAND) {
56         new_cr0 = (struct cr0_real *)first_operand;
57       } else if (addr_type == MEM_OPERAND) {
58         addr_t host_addr;
59
60         if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
61           // gpf the guest
62           return -1;
63         }
64
65         new_cr0 = (struct cr0_real *)host_addr;
66       } else {
67         // error... don't know what to do
68         return -1;
69       }
70                  
71       if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
72         info->cpu_mode = PROTECTED;
73       } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
74         info->cpu_mode = REAL;
75       }
76       
77       new_cr0_val = *(char*)(new_cr0) & 0x0f;
78
79
80       if (info->page_mode == SHADOW_PAGING) {
81         struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
82
83         PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
84         /* struct cr0_real is only 4 bits wide, 
85          * so we can overwrite the real_cr0 without worrying about the shadow fields
86          */
87         *(char*)real_cr0 &= 0xf0;
88         *(char*)real_cr0 |= new_cr0_val;
89         
90         *(char*)shadow_cr0 &= 0xf0;
91         *(char*)shadow_cr0 |= new_cr0_val;
92
93         PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
94       } else {
95         PrintDebug("Old CR0=%x\n", *real_cr0);  
96         // for now we just pass through....
97         *(char*)real_cr0 &= 0xf0;
98         *(char*)real_cr0 |= new_cr0_val;
99
100         PrintDebug("New CR0=%x\n", *real_cr0);  
101       }
102
103
104       info->rip += index;
105
106     } else if ((instr[index] == cr_access_byte) && 
107                (instr[index + 1] == clts_byte)) {
108       // CLTS
109
110
111     } else if ((instr[index] == cr_access_byte) && 
112                (instr[index + 1] = mov_to_cr_byte)) {
113       addr_t first_operand;
114       addr_t second_operand;
115       struct cr0_32 *real_cr0;
116       struct cr0_32 *new_cr0;
117       operand_type_t addr_type;
118      
119       
120       index += 2;
121  
122       real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
123
124       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
125
126       if (addr_type != REG_OPERAND) {
127         /* Mov to CR0 Can only be a 32 bit register */
128         // FIX ME
129         return -1;
130       }
131
132       new_cr0 = (struct cr0_32 *)first_operand;
133
134       if (new_cr0->pe == 1) {
135         PrintDebug("Entering Protected Mode\n");
136         info->cpu_mode = PROTECTED;
137       }
138
139       if (new_cr0->pg == 1) {
140         // GPF the guest??
141         return -1;
142       }
143
144       if (info->page_mode == SHADOW_PAGING) {
145         struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
146         
147         PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
148         *real_cr0 = *new_cr0;
149         real_cr0->pg = 1;
150
151         *shadow_cr0 = *new_cr0;
152
153         PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
154       } else {
155         PrintDebug("Old CR0=%x\n", *real_cr0);  
156         *real_cr0 = *new_cr0;
157         PrintDebug("New CR0=%x\n", *real_cr0);  
158       }
159
160       info->rip += index;
161
162     } else {
163       PrintDebug("Unsupported Instruction\n");
164       // unsupported instruction, UD the guest
165       return -1;
166     }
167
168
169   } else if (info->cpu_mode == PROTECTED) {
170     int index = 0;
171     int ret;
172
173     PrintDebug("Protected Mode write to CR0\n");
174
175     // The real rip address is actually a combination of the rip + CS base 
176     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
177     if (ret != 15) {
178       // I think we should inject a GPF into the guest
179       PrintDebug("Could not read instruction (ret=%d)\n", ret);
180       return -1;
181     }
182
183     while (is_prefix_byte(instr[index])) {
184       index++; 
185     }
186
187     if ((instr[index] == cr_access_byte) && 
188         (instr[index + 1] == mov_to_cr_byte)) {
189     
190       addr_t first_operand;
191       addr_t second_operand;
192       struct cr0_32 *real_cr0;
193       struct cr0_32 *new_cr0;
194       operand_type_t addr_type;
195
196       index += 2;
197  
198       real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
199
200       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
201
202       if (addr_type != REG_OPERAND) {
203         return -1;
204       }
205
206       new_cr0 = (struct cr0_32 *)first_operand;
207
208
209       if (info->page_mode == SHADOW_PAGING) {
210         struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
211
212         if (new_cr0->pg == 1){
213           struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
214
215           info->cpu_mode = PROTECTED_PG;
216           
217           *shadow_cr0 = *new_cr0;
218           *real_cr0 = *new_cr0;
219
220           //
221           // Activate Shadow Paging
222           //
223           PrintDebug("Turning on paging in the guest\n");
224
225           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
226           
227
228         } else if (new_cr0->pe == 0) {
229           info->cpu_mode = REAL;
230
231           *shadow_cr0 = *new_cr0;
232           *real_cr0 = *new_cr0;
233           real_cr0->pg = 1;
234         }
235
236
237       } else {
238         *real_cr0 = *new_cr0;
239       }
240
241       info->rip += index;
242     }
243     
244   } else { 
245     PrintDebug("Unknown Mode write to CR0\n");
246     return -1;
247   }
248   return 0;
249 }
250
251
252 int handle_cr0_read(struct guest_info * info) {
253   char instr[15];
254
255   if (info->cpu_mode == REAL) {
256     int index = 0;
257     int ret;
258
259     // The real rip address is actually a combination of the rip + CS base 
260     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
261     if (ret != 15) {
262       // I think we should inject a GPF into the guest
263       PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
264       return -1;
265     }
266
267
268     while (is_prefix_byte(instr[index])) {
269       index++; 
270     }
271
272     if ((instr[index] == cr_access_byte) && 
273         (instr[index + 1] == smsw_byte) && 
274         (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
275
276       addr_t first_operand;
277       addr_t second_operand;
278       struct cr0_real *cr0;
279       operand_type_t addr_type;
280       char cr0_val = 0;
281
282       index += 2;
283       
284       cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
285       
286       
287       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
288       
289       if (addr_type == MEM_OPERAND) {
290         addr_t host_addr;
291         
292         if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
293           // gpf the guest
294           return -1;
295         }
296         
297         first_operand = host_addr;
298       } else {
299         // error... don't know what to do
300         return -1;
301       }
302
303       cr0_val = *(char*)cr0 & 0x0f;
304
305       *(char *)first_operand &= 0xf0;
306       *(char *)first_operand |= cr0_val;
307
308       PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
309       info->rip += index;
310       PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
311     } else if ((instr[index] == cr_access_byte) &&
312                (instr[index+1] == mov_from_cr_byte)) {
313       /* Mov from CR0
314        * This can only take a 32 bit register argument in anything less than 64 bit mode.
315        */
316       addr_t first_operand;
317       addr_t second_operand;
318       operand_type_t addr_type;
319
320       struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
321
322       index += 2;
323
324       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
325      
326       struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
327   
328       if (addr_type != REG_OPERAND) {
329         // invalid opcode to guest
330         PrintDebug("Invalid operand type in mov from CR0\n");
331         return -1;
332       }
333
334       if (info->page_mode == SHADOW_PAGING) {
335         *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
336       } else {
337         *virt_cr0 = *real_cr0;
338       }
339
340       info->rip += index;
341
342     } else {
343       PrintDebug("Unknown read instr from CR0\n");
344       return -1;
345     }
346
347   } else if (info->cpu_mode == PROTECTED) {
348     int index = 0;
349     int ret;
350
351     // The real rip address is actually a combination of the rip + CS base 
352     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
353     if (ret != 15) {
354       // I think we should inject a GPF into the guest
355       PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
356       return -1;
357     }
358
359     while (is_prefix_byte(instr[index])) {
360       index++; 
361     }
362
363
364     if ((instr[index] == cr_access_byte) &&
365         (instr[index+1] == mov_from_cr_byte)) {
366       addr_t first_operand;
367       addr_t second_operand;
368       operand_type_t addr_type;
369       struct cr0_32 * virt_cr0;
370       struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
371
372       index += 2;
373
374       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
375
376       if (addr_type != REG_OPERAND) {
377         PrintDebug("Invalid operand type in mov from CR0\n");
378         return -1;
379       }
380       
381       virt_cr0 = (struct cr0_32 *)first_operand;
382
383       if (info->page_mode == SHADOW_PAGING) {
384         *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
385       } else {
386         *virt_cr0 = *real_cr0;
387       }
388       
389       info->rip += index;
390
391     } else { 
392       PrintDebug("Unknown read instruction from CR0\n");
393       return -1;
394     }
395
396   } else {
397     PrintDebug("Unknown mode read from CR0\n");
398     return -1;
399   }
400
401
402   return 0;
403 }
404
405
406
407
408 int handle_cr3_write(struct guest_info * info) {
409   if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
410     int index = 0;
411     int ret;
412     char instr[15];
413
414
415     /* Isn't the RIP a Guest Virtual Address???????? */
416     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
417     if (ret != 15) {
418       PrintDebug("Could not read instruction (ret=%d)\n", ret);
419       return -1;
420     }
421     
422     while (is_prefix_byte(instr[index])) {
423       index++;
424     }
425
426     if ((instr[index] == cr_access_byte) && 
427         (instr[index + 1] == mov_to_cr_byte)) {
428
429       addr_t first_operand;
430       addr_t second_operand;
431       struct cr3_32 * new_cr3;
432       //      struct cr3_32 * real_cr3;
433       operand_type_t addr_type;
434
435       index += 2;
436
437       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
438
439       if (addr_type != REG_OPERAND) {
440         /* Mov to CR3 can only be a 32 bit register */
441         return -1;
442       }
443
444       new_cr3 = (struct cr3_32 *)first_operand;
445
446       if (info->page_mode == SHADOW_PAGING) {
447         addr_t shadow_pt;
448         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
449         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
450
451
452         *guest_cr3 = *new_cr3;
453
454         // Something like this
455         shadow_pt =  create_new_shadow_pt32(info);
456         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
457
458         /* Copy Various flags */
459         *shadow_cr3 = *new_cr3;
460         
461         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
462
463         if (info->cpu_mode == PROTECTED_PG) {
464           // If we aren't in paged mode then we have to preserve the identity mapped CR3
465           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
466         }
467       }
468
469       info->rip += index;
470
471     } else {
472       PrintDebug("Unknown Instruction\n");
473       return -1;
474     }
475   } else {
476     PrintDebug("Invalid operating Mode\n");
477     return -1;
478   }
479
480   return 0;
481 }
482
483
484
485
486 int handle_cr3_read(struct guest_info * info) {
487   if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
488     int index = 0;
489     int ret;
490     char instr[15];
491
492     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
493     if (ret != 15) {
494       PrintDebug("Could not read instruction (ret=%d)\n", ret);
495       return -1;
496     }
497     
498     while (is_prefix_byte(instr[index])) {
499       index++;
500     }
501
502     if ((instr[index] == cr_access_byte) && 
503         (instr[index + 1] == mov_from_cr_byte)) {
504       addr_t first_operand;
505       addr_t second_operand;
506       struct cr3_32 * virt_cr3;
507       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
508       operand_type_t addr_type;
509
510       index += 2;
511
512       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
513
514       if (addr_type != REG_OPERAND) {
515         /* Mov to CR3 can only be a 32 bit register */
516         return -1;
517       }
518
519       virt_cr3 = (struct cr3_32 *)first_operand;
520
521       if (info->page_mode == SHADOW_PAGING) {
522         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
523       } else {
524         *virt_cr3 = *real_cr3;
525       }
526       
527       info->rip += index;
528     } else {
529       PrintDebug("Unknown Instruction\n");
530       return -1;
531     }
532   } else {
533     PrintDebug("Invalid operating Mode\n");
534     return -1;
535   }
536
537   return 0;
538 }