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.


architecture independence work
[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     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
415     if (ret != 15) {
416       PrintDebug("Could not read instruction (ret=%d)\n", ret);
417       return -1;
418     }
419     
420     while (is_prefix_byte(instr[index])) {
421       index++;
422     }
423
424     if ((instr[index] == cr_access_byte) && 
425         (instr[index + 1] == mov_to_cr_byte)) {
426
427       addr_t first_operand;
428       addr_t second_operand;
429       struct cr3_32 * new_cr3;
430       //      struct cr3_32 * real_cr3;
431       operand_type_t addr_type;
432
433       index += 2;
434
435       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
436
437       if (addr_type != REG_OPERAND) {
438         /* Mov to CR3 can only be a 32 bit register */
439         return -1;
440       }
441
442       new_cr3 = (struct cr3_32 *)first_operand;
443
444       if (info->page_mode == SHADOW_PAGING) {
445         addr_t shadow_pt;
446         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
447         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
448
449
450         *guest_cr3 = *new_cr3;
451
452         // Something like this
453         shadow_pt =  create_new_shadow_pt32(info);
454         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
455
456         /* Copy Various flags */
457         *shadow_cr3 = *new_cr3;
458         
459         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
460
461         if (info->cpu_mode == PROTECTED_PG) {
462           // If we aren't in paged mode then we have to preserve the identity mapped CR3
463           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
464         }
465       }
466
467       info->rip += index;
468
469     } else {
470       PrintDebug("Unknown Instruction\n");
471       return -1;
472     }
473   } else {
474     PrintDebug("Invalid operating Mode\n");
475     return -1;
476   }
477
478   return 0;
479 }
480
481
482
483
484 int handle_cr3_read(struct guest_info * info) {
485   if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
486     int index = 0;
487     int ret;
488     char instr[15];
489
490     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
491     if (ret != 15) {
492       PrintDebug("Could not read instruction (ret=%d)\n", ret);
493       return -1;
494     }
495     
496     while (is_prefix_byte(instr[index])) {
497       index++;
498     }
499
500     if ((instr[index] == cr_access_byte) && 
501         (instr[index + 1] == mov_from_cr_byte)) {
502       addr_t first_operand;
503       addr_t second_operand;
504       struct cr3_32 * virt_cr3;
505       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
506       operand_type_t addr_type;
507
508       index += 2;
509
510       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
511
512       if (addr_type != REG_OPERAND) {
513         /* Mov to CR3 can only be a 32 bit register */
514         return -1;
515       }
516
517       virt_cr3 = (struct cr3_32 *)first_operand;
518
519       if (info->page_mode == SHADOW_PAGING) {
520         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
521       } else {
522         *virt_cr3 = *real_cr3;
523       }
524       
525       info->rip += index;
526     } else {
527       PrintDebug("Unknown Instruction\n");
528       return -1;
529     }
530   } else {
531     PrintDebug("Invalid operating Mode\n");
532     return -1;
533   }
534
535   return 0;
536 }