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.


*** empty log message ***
[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           PrintDebug("Could not convert guest physical address to host virtual address\n");
295           return -1;
296         }
297         
298         first_operand = host_addr;
299       } else {
300         // Register operand
301         // Should be ok??
302       }
303
304       cr0_val = *(char*)cr0 & 0x0f;
305
306       *(char *)first_operand &= 0xf0;
307       *(char *)first_operand |= cr0_val;
308
309       PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
310       info->rip += index;
311       PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
312     } else if ((instr[index] == cr_access_byte) &&
313                (instr[index+1] == mov_from_cr_byte)) {
314       /* Mov from CR0
315        * This can only take a 32 bit register argument in anything less than 64 bit mode.
316        */
317       addr_t first_operand;
318       addr_t second_operand;
319       operand_type_t addr_type;
320
321       struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
322
323       index += 2;
324
325       addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
326      
327       struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
328   
329       if (addr_type != REG_OPERAND) {
330         // invalid opcode to guest
331         PrintDebug("Invalid operand type in mov from CR0\n");
332         return -1;
333       }
334
335       if (info->page_mode == SHADOW_PAGING) {
336         *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
337       } else {
338         *virt_cr0 = *real_cr0;
339       }
340
341       info->rip += index;
342
343     } else {
344       PrintDebug("Unknown read instr from CR0\n");
345       return -1;
346     }
347
348   } else if (info->cpu_mode == PROTECTED) {
349     int index = 0;
350     int ret;
351
352     // The real rip address is actually a combination of the rip + CS base 
353     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
354     if (ret != 15) {
355       // I think we should inject a GPF into the guest
356       PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
357       return -1;
358     }
359
360     while (is_prefix_byte(instr[index])) {
361       index++; 
362     }
363
364
365     if ((instr[index] == cr_access_byte) &&
366         (instr[index+1] == mov_from_cr_byte)) {
367       addr_t first_operand;
368       addr_t second_operand;
369       operand_type_t addr_type;
370       struct cr0_32 * virt_cr0;
371       struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
372
373       index += 2;
374
375       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
376
377       if (addr_type != REG_OPERAND) {
378         PrintDebug("Invalid operand type in mov from CR0\n");
379         return -1;
380       }
381       
382       virt_cr0 = (struct cr0_32 *)first_operand;
383
384       if (info->page_mode == SHADOW_PAGING) {
385         *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
386       } else {
387         *virt_cr0 = *real_cr0;
388       }
389       
390       info->rip += index;
391
392     } else { 
393       PrintDebug("Unknown read instruction from CR0\n");
394       return -1;
395     }
396
397   } else {
398     PrintDebug("Unknown mode read from CR0\n");
399     return -1;
400   }
401
402
403   return 0;
404 }
405
406
407
408
409 int handle_cr3_write(struct guest_info * info) {
410   if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
411     int index = 0;
412     int ret;
413     char instr[15];
414
415
416     /* Isn't the RIP a Guest Virtual Address???????? */
417     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
418     if (ret != 15) {
419       PrintDebug("Could not read instruction (ret=%d)\n", ret);
420       return -1;
421     }
422     
423     while (is_prefix_byte(instr[index])) {
424       index++;
425     }
426
427     if ((instr[index] == cr_access_byte) && 
428         (instr[index + 1] == mov_to_cr_byte)) {
429
430       addr_t first_operand;
431       addr_t second_operand;
432       struct cr3_32 * new_cr3;
433       //      struct cr3_32 * real_cr3;
434       operand_type_t addr_type;
435
436       index += 2;
437
438       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
439
440       if (addr_type != REG_OPERAND) {
441         /* Mov to CR3 can only be a 32 bit register */
442         return -1;
443       }
444
445       new_cr3 = (struct cr3_32 *)first_operand;
446
447       if (info->page_mode == SHADOW_PAGING) {
448         addr_t shadow_pt;
449         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
450         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
451
452
453         *guest_cr3 = *new_cr3;
454
455         // Something like this
456         shadow_pt =  create_new_shadow_pt32(info);
457         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
458
459         /* Copy Various flags */
460         *shadow_cr3 = *new_cr3;
461         
462         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
463
464         if (info->cpu_mode == PROTECTED_PG) {
465           // If we aren't in paged mode then we have to preserve the identity mapped CR3
466           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
467         }
468       }
469
470       info->rip += index;
471
472     } else {
473       PrintDebug("Unknown Instruction\n");
474       return -1;
475     }
476   } else {
477     PrintDebug("Invalid operating Mode\n");
478     return -1;
479   }
480
481   return 0;
482 }
483
484
485
486
487 int handle_cr3_read(struct guest_info * info) {
488   if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
489     int index = 0;
490     int ret;
491     char instr[15];
492
493     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
494     if (ret != 15) {
495       PrintDebug("Could not read instruction (ret=%d)\n", ret);
496       return -1;
497     }
498     
499     while (is_prefix_byte(instr[index])) {
500       index++;
501     }
502
503     if ((instr[index] == cr_access_byte) && 
504         (instr[index + 1] == mov_from_cr_byte)) {
505       addr_t first_operand;
506       addr_t second_operand;
507       struct cr3_32 * virt_cr3;
508       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
509       operand_type_t addr_type;
510
511       index += 2;
512
513       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
514
515       if (addr_type != REG_OPERAND) {
516         /* Mov to CR3 can only be a 32 bit register */
517         return -1;
518       }
519
520       virt_cr3 = (struct cr3_32 *)first_operand;
521
522       if (info->page_mode == SHADOW_PAGING) {
523         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
524       } else {
525         *virt_cr3 = *real_cr3;
526       }
527       
528       info->rip += index;
529     } else {
530       PrintDebug("Unknown Instruction\n");
531       return -1;
532     }
533   } else {
534     PrintDebug("Invalid operating Mode\n");
535     return -1;
536   }
537
538   return 0;
539 }