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_decoder.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
7
8
9
10 extern void SerialMemDump(unsigned char *start, int n);
11
12 /* Segmentation is a problem here...
13  *
14  * When we get a memory operand, presumably we use the default segment (which is?) 
15  * unless an alternate segment was specfied in the prefix...
16  */
17
18
19 int handle_cr0_write(struct guest_info * info) {
20   char instr[15];
21   
22   
23   switch (info->cpu_mode) { 
24   case REAL: 
25     {
26       int index = 0;
27       int ret;
28       
29       PrintDebug("Real Mode write to CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
30
31       // The real rip address is actually a combination of the rip + CS base 
32       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
33       if (ret != 15) {
34         // I think we should inject a GPF into the guest
35         PrintDebug("Could not read instruction (ret=%d)\n", ret);
36         return -1;
37       }
38
39       while (is_prefix_byte(instr[index])) {
40         index++; 
41       }
42
43       if ((instr[index] == cr_access_byte) && 
44           (instr[index + 1] == lmsw_byte) && 
45           (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
46  
47         addr_t first_operand;
48         addr_t second_operand;
49         struct cr0_real *real_cr0;
50         struct cr0_real *new_cr0;
51         operand_type_t addr_type;
52         char new_cr0_val = 0;
53         // LMSW
54         // decode mod/RM
55         index += 2;
56  
57         real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
58
59         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
60
61
62         if (addr_type == REG_OPERAND) {
63           new_cr0 = (struct cr0_real *)first_operand;
64         } else if (addr_type == MEM_OPERAND) {
65           addr_t host_addr;
66
67           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
68             // gpf the guest
69             return -1;
70           }
71
72           new_cr0 = (struct cr0_real *)host_addr;
73         } else {
74           PrintDebug("Memory operand in real mode write to CR0 is UNIMPLEMENTED\n");
75           // error... don't know what to do
76           return -1;
77         }
78                  
79         if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
80           info->cpu_mode = PROTECTED;
81         } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
82           info->cpu_mode = REAL;
83         }
84       
85         new_cr0_val = *(char*)(new_cr0) & 0x0f;
86
87
88         if (info->shdw_pg_mode == SHADOW_PAGING) {
89           struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
90
91           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
92           /* struct cr0_real is only 4 bits wide, 
93            * so we can overwrite the real_cr0 without worrying about the shadow fields
94            */
95           *(char*)real_cr0 &= 0xf0;
96           *(char*)real_cr0 |= new_cr0_val;
97         
98           *(char*)shadow_cr0 &= 0xf0;
99           *(char*)shadow_cr0 |= new_cr0_val;
100
101           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
102         } else {
103           PrintDebug("Old CR0=%x\n", *real_cr0);        
104           // for now we just pass through....
105           *(char*)real_cr0 &= 0xf0;
106           *(char*)real_cr0 |= new_cr0_val;
107
108           PrintDebug("New CR0=%x\n", *real_cr0);        
109         }
110
111
112         info->rip += index;
113
114       } else if ((instr[index] == cr_access_byte) && 
115                  (instr[index + 1] == clts_byte)) {
116         // CLTS
117         PrintDebug("CLTS unhandled in CR0 write\n");
118         return -1;
119
120       } else if ((instr[index] == cr_access_byte) && 
121                  (instr[index + 1] = mov_to_cr_byte)) {
122         addr_t first_operand;
123         addr_t second_operand;
124         struct cr0_32 *real_cr0;
125         struct cr0_32 *new_cr0;
126         operand_type_t addr_type;
127      
128       
129         index += 2;
130  
131         real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
132
133         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
134
135         if (addr_type != REG_OPERAND) {
136           PrintDebug("Moving to CR0 from non-register operand in CR0 write\n");
137           /* Mov to CR0 Can only be a 32 bit register */
138           // FIX ME
139           return -1;
140         }
141
142         new_cr0 = (struct cr0_32 *)first_operand;
143
144         if (new_cr0->pe == 1) {
145           PrintDebug("Entering Protected Mode\n");
146           info->cpu_mode = PROTECTED;
147         }
148
149         if (new_cr0->pg == 1) {
150           PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n");
151
152           // GPF the guest??
153           return -1;
154         }
155
156         if (info->shdw_pg_mode == SHADOW_PAGING) {
157           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
158         
159           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
160           *real_cr0 = *new_cr0;
161           real_cr0->pg = 1;
162
163           *shadow_cr0 = *new_cr0;
164
165           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
166         } else {
167           PrintDebug("Old CR0=%x\n", *real_cr0);        
168           *real_cr0 = *new_cr0;
169           PrintDebug("New CR0=%x\n", *real_cr0);        
170         }
171
172         info->rip += index;
173
174       } else {
175         PrintDebug("Unsupported Instruction\n");
176         // unsupported instruction, UD the guest
177         return -1;
178       }
179
180     } 
181     break;
182  
183   case PROTECTED: 
184     {
185
186       int index = 0;
187       int ret;
188
189       PrintDebug("Protected %s Mode write to CR0 at guest %s linear rip 0x%x\n", 
190                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
191                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
192                  get_addr_linear(info, info->rip, &(info->segments.cs)));
193
194       // OK, now we will read the instruction
195       // The only difference between PROTECTED and PROTECTED_PG is whether we read
196       // from guest_pa or guest_va
197       if (info->mem_mode == PHYSICAL_MEM) { 
198         // The real rip address is actually a combination of the rip + CS base 
199         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
200       } else { 
201         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
202       }
203         
204       if (ret != 15) {
205         // I think we should inject a GPF into the guest
206         PrintDebug("Could not read instruction (ret=%d)\n", ret);
207         return -1;
208       }
209
210       while (is_prefix_byte(instr[index])) {
211         index++; 
212       }
213
214       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
215
216       struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
217
218       if ((instr[index] == cr_access_byte) && 
219           (instr[index + 1] == mov_to_cr_byte)) {
220
221         // MOV to CR0
222     
223         addr_t first_operand;
224         addr_t second_operand;
225         struct cr0_32 *new_cr0;
226         operand_type_t addr_type;
227
228         index += 2;
229  
230
231         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
232
233         if (addr_type != REG_OPERAND) {
234           PrintDebug("Non-register operand in write to CR0\n");
235           return -1;
236         }
237
238         new_cr0 = (struct cr0_32 *)first_operand;
239
240
241
242         if (info->shdw_pg_mode == SHADOW_PAGING) {
243           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
244
245           if (new_cr0->pg == 1){
246             // This should be new_cr0->pg && !(old_cr->pg), right?
247             // and then a case for turning paging off?
248
249             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
250
251             info->mem_mode = VIRTUAL_MEM;
252           
253             *shadow_cr0 = *new_cr0;
254             *real_cr0 = *new_cr0;
255
256             //
257             // Activate Shadow Paging
258             //
259             PrintDebug("Turning on paging in the guest\n");
260
261             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
262           
263
264           } else if (new_cr0->pe == 0) {
265             info->cpu_mode = REAL;
266
267             *shadow_cr0 = *new_cr0;
268             *real_cr0 = *new_cr0;
269             real_cr0->pg = 1;
270           }
271
272
273         } else {
274           *real_cr0 = *new_cr0;
275         }
276
277         info->rip += index;
278
279       } else if ((instr[index] == 0x0f) &&
280                  (instr[index + 1] == 0x06)) { 
281         // CLTS instruction
282         PrintDebug("CLTS instruction - clearing TS flag of real and shadow CR0\n");
283         shadow_cr0->ts=0;
284         real_cr0->ts=0;
285         
286         index+=2;
287         
288         info->rip+=index;
289
290       } else {
291         PrintDebug("Unkown instruction: \n");
292         SerialMemDump(instr,15);
293         return -1;
294       }
295     }
296     break;
297     
298   case PROTECTED_PAE:
299     PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n");
300     return -1;
301
302   case LONG:
303     PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n");
304     return -1;
305
306   default: 
307     {
308       PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode);
309       return -1;
310     }
311     break;
312
313   }
314
315   return 0;
316 }
317
318
319 int handle_cr0_read(struct guest_info * info) {
320   char instr[15];
321
322   switch (info->cpu_mode) { 
323
324   case REAL: 
325     {
326
327       int index = 0;
328       int ret;
329
330       PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
331
332       // The real rip address is actually a combination of the rip + CS base 
333       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
334       if (ret != 15) {
335         // I think we should inject a GPF into the guest
336         PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
337         return -1;
338       }
339
340
341       while (is_prefix_byte(instr[index])) {
342         index++; 
343       }
344
345       if ((instr[index] == cr_access_byte) && 
346           (instr[index + 1] == smsw_byte) && 
347           (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
348
349         // SMSW (store machine status word)
350
351         addr_t first_operand;
352         addr_t second_operand;
353         struct cr0_real *cr0;
354         operand_type_t addr_type;
355         char cr0_val = 0;
356
357         index += 2;
358       
359         cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
360       
361       
362         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
363       
364         if (addr_type == MEM_OPERAND) {
365           addr_t host_addr;
366         
367           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
368             // gpf the guest
369             PrintDebug("Could not convert guest physical address to host virtual address\n");
370             return -1;
371           }
372         
373           first_operand = host_addr;
374         } else {
375           // Register operand
376           // Should be ok??
377         }
378
379         cr0_val = *(char*)cr0 & 0x0f;
380
381         *(char *)first_operand &= 0xf0;
382         *(char *)first_operand |= cr0_val;
383
384         PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
385         info->rip += index;
386         PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
387         // success
388
389       } else if ((instr[index] == cr_access_byte) &&
390                  (instr[index+1] == mov_from_cr_byte)) {
391         /* Mov from CR0
392          * This can only take a 32 bit register argument in anything less than 64 bit mode.
393          */
394         addr_t first_operand;
395         addr_t second_operand;
396         operand_type_t addr_type;
397
398         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
399
400         index += 2;
401
402         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
403      
404         struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
405   
406         if (addr_type != REG_OPERAND) {
407           // invalid opcode to guest
408           PrintDebug("Invalid operand type in mov from CR0\n");
409           return -1;
410         }
411
412         if (info->shdw_pg_mode == SHADOW_PAGING) {
413           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
414         } else {
415           *virt_cr0 = *real_cr0;
416         }
417
418         info->rip += index;
419
420       } else {
421         PrintDebug("Unknown read instr from CR0\n");
422         return -1;
423       }
424
425     } 
426
427     break;
428
429   case PROTECTED:
430     {
431     
432       int index = 0;
433       int ret;
434
435       PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n", 
436                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
437                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
438                  get_addr_linear(info, info->rip, &(info->segments.cs)));
439
440       // We need to read the instruction, which is at CS:IP, but that 
441       // linear address is guest physical without PG and guest virtual with PG
442       if (info->cpu_mode == PHYSICAL_MEM) { 
443         // The real rip address is actually a combination of the rip + CS base 
444         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
445       } else { 
446         // The real rip address is actually a combination of the rip + CS base 
447         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
448       }
449
450       if (ret != 15) {
451         // I think we should inject a GPF into the guest
452         PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", 
453                    info->cpu_mode == VIRTUAL_MEM ? "Paged" : "", ret);
454         return -1;
455       }
456
457       while (is_prefix_byte(instr[index])) {
458         index++; 
459       }
460
461
462       if ((instr[index] == cr_access_byte) &&
463           (instr[index+1] == mov_from_cr_byte)) {
464         
465         // MOV from CR0 to register
466
467         addr_t first_operand;
468         addr_t second_operand;
469         operand_type_t addr_type;
470         struct cr0_32 * virt_cr0;
471         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
472
473         index += 2;
474
475         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
476
477         if (addr_type != REG_OPERAND) {
478           PrintDebug("Invalid operand type in mov from CR0\n");
479           return -1;
480         }
481       
482         virt_cr0 = (struct cr0_32 *)first_operand;
483
484         if (info->shdw_pg_mode == SHADOW_PAGING) {
485           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
486         } else {
487           *virt_cr0 = *real_cr0;
488         }
489       
490         info->rip += index;
491
492       } else { 
493         PrintDebug("Unknown read instruction from CR0\n");
494         return -1;
495       }
496     }
497     break;
498
499   case PROTECTED_PAE:
500     PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
501     return -1;
502
503   case LONG:
504     PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
505     return -1;
506
507
508   default:
509     {
510       PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
511       return -1;
512     }
513     break;
514   }
515
516
517   return 0;
518 }
519
520
521
522
523 int handle_cr3_write(struct guest_info * info) {
524   if (info->cpu_mode == PROTECTED) {
525     int index = 0;
526     int ret;
527     char instr[15];
528
529
530     // We need to read the instruction, which is at CS:IP, but that 
531     // linear address is guest physical without PG and guest virtual with PG
532     if (info->cpu_mode == PHYSICAL_MEM) { 
533       // The real rip address is actually a combination of the rip + CS base 
534       PrintDebug("Writing Guest CR3 Write (Physical Address)\n");
535       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
536     } else { 
537       PrintDebug("Writing Guest CR3 Write (Virtual Address)\n");
538       // The real rip address is actually a combination of the rip + CS base 
539       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
540     }
541
542
543     if (ret != 15) {
544       PrintDebug("Could not read instruction (ret=%d)\n", ret);
545       return -1;
546     }
547     
548     while (is_prefix_byte(instr[index])) {
549       index++;
550     }
551
552     if ((instr[index] == cr_access_byte) && 
553         (instr[index + 1] == mov_to_cr_byte)) {
554
555       addr_t first_operand;
556       addr_t second_operand;
557       struct cr3_32 * new_cr3;
558       //      struct cr3_32 * real_cr3;
559       operand_type_t addr_type;
560
561       index += 2;
562
563       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
564
565       if (addr_type != REG_OPERAND) {
566         /* Mov to CR3 can only be a 32 bit register */
567         return -1;
568       }
569
570       new_cr3 = (struct cr3_32 *)first_operand;
571
572       if (info->shdw_pg_mode == SHADOW_PAGING) {
573         addr_t shadow_pt;
574         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
575         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
576
577
578         /* Delete the current Page Tables */
579         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
580
581         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
582                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
583
584
585         *guest_cr3 = *new_cr3;
586
587
588
589         // Something like this
590         shadow_pt =  create_new_shadow_pt32(info);
591         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
592
593         /* Copy Various flags */
594         *shadow_cr3 = *new_cr3;
595
596
597         
598         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
599
600         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
601                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
602
603
604
605         if (info->mem_mode == VIRTUAL_MEM) {
606           // If we aren't in paged mode then we have to preserve the identity mapped CR3
607           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
608         }
609       }
610
611       info->rip += index;
612
613     } else {
614       PrintDebug("Unknown Instruction\n");
615       return -1;
616     }
617   } else {
618     PrintDebug("Invalid operating Mode\n");
619     return -1;
620   }
621
622   return 0;
623 }
624
625
626
627
628 int handle_cr3_read(struct guest_info * info) {
629   if (info->cpu_mode == PROTECTED) {
630     int index = 0;
631     int ret;
632     char instr[15];
633
634    
635     // We need to read the instruction, which is at CS:IP, but that 
636     // linear address is guest physical without PG and guest virtual with PG
637     if (info->cpu_mode == PHYSICAL_MEM) { 
638       // The real rip address is actually a combination of the rip + CS base 
639       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
640     } else { 
641       // The real rip address is actually a combination of the rip + CS base 
642       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
643     }
644
645     if (ret != 15) {
646       PrintDebug("Could not read instruction (ret=%d)\n", ret);
647       return -1;
648     }
649     
650     while (is_prefix_byte(instr[index])) {
651       index++;
652     }
653
654     if ((instr[index] == cr_access_byte) && 
655         (instr[index + 1] == mov_from_cr_byte)) {
656       addr_t first_operand;
657       addr_t second_operand;
658       struct cr3_32 * virt_cr3;
659       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
660       operand_type_t addr_type;
661
662       index += 2;
663
664       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
665
666       if (addr_type != REG_OPERAND) {
667         /* Mov to CR3 can only be a 32 bit register */
668         return -1;
669       }
670
671       virt_cr3 = (struct cr3_32 *)first_operand;
672
673       if (info->shdw_pg_mode == SHADOW_PAGING) {
674         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
675       } else {
676         *virt_cr3 = *real_cr3;
677       }
678       
679       info->rip += index;
680     } else {
681       PrintDebug("Unknown Instruction\n");
682       return -1;
683     }
684   } else {
685     PrintDebug("Invalid operating Mode\n");
686     return -1;
687   }
688
689   return 0;
690 }