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.


Updated to include improved 8254
[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->pe == 0) { 
150           PrintDebug("Entering Real Mode\n");
151           info->cpu_mode = REAL;
152         }
153           
154
155         if (new_cr0->pg == 1) {
156           PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n");
157
158           // GPF the guest??
159           return -1;
160         }
161
162         if (info->shdw_pg_mode == SHADOW_PAGING) {
163           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
164         
165           PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
166           *real_cr0 = *new_cr0;
167           real_cr0->pg = 1;
168
169           *shadow_cr0 = *new_cr0;
170
171           PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);        
172         } else {
173           PrintDebug("Old CR0=%x\n", *real_cr0);        
174           *real_cr0 = *new_cr0;
175           PrintDebug("New CR0=%x\n", *real_cr0);        
176         }
177
178         info->rip += index;
179
180       } else {
181         PrintDebug("Unsupported Instruction\n");
182         // unsupported instruction, UD the guest
183         return -1;
184       }
185
186     } 
187     break;
188  
189   case PROTECTED: 
190     {
191
192       int index = 0;
193       int ret;
194
195       PrintDebug("Protected %s Mode write to CR0 at guest %s linear rip 0x%x\n", 
196                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
197                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
198                  get_addr_linear(info, info->rip, &(info->segments.cs)));
199
200       // OK, now we will read the instruction
201       // The only difference between PROTECTED and PROTECTED_PG is whether we read
202       // from guest_pa or guest_va
203       if (info->mem_mode == PHYSICAL_MEM) { 
204         // The real rip address is actually a combination of the rip + CS base 
205         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
206       } else { 
207         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
208       }
209         
210       if (ret != 15) {
211         // I think we should inject a GPF into the guest
212         PrintDebug("Could not read instruction (ret=%d)\n", ret);
213         return -1;
214       }
215
216       while (is_prefix_byte(instr[index])) {
217         index++; 
218       }
219
220       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
221
222       struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
223
224       if ((instr[index] == cr_access_byte) && 
225           (instr[index + 1] == mov_to_cr_byte)) {
226
227         // MOV to CR0
228     
229         addr_t first_operand;
230         addr_t second_operand;
231         struct cr0_32 *new_cr0;
232         operand_type_t addr_type;
233
234         index += 2;
235  
236
237         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
238
239         if (addr_type != REG_OPERAND) {
240           PrintDebug("Non-register operand in write to CR0\n");
241           return -1;
242         }
243
244         new_cr0 = (struct cr0_32 *)first_operand;
245
246
247
248         if (info->shdw_pg_mode == SHADOW_PAGING) {
249           struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
250
251           if (new_cr0->pg == 1){
252             // This should be new_cr0->pg && !(old_cr->pg), right?
253             // and then a case for turning paging off?
254
255             struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
256
257             info->mem_mode = VIRTUAL_MEM;
258           
259             *shadow_cr0 = *new_cr0;
260             *real_cr0 = *new_cr0;
261
262             //
263             // Activate Shadow Paging
264             //
265             PrintDebug("Turning on paging in the guest\n");
266
267             info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
268           
269
270           } else if (new_cr0->pe == 0) {
271             info->cpu_mode = REAL;
272
273             *shadow_cr0 = *new_cr0;
274             *real_cr0 = *new_cr0;
275             real_cr0->pg = 1;
276           }
277
278
279         } else {
280           *real_cr0 = *new_cr0;
281         }
282
283         info->rip += index;
284
285       } else if ((instr[index] == 0x0f) &&
286                  (instr[index + 1] == 0x06)) { 
287         // CLTS instruction
288         PrintDebug("CLTS instruction - clearing TS flag of real and shadow CR0\n");
289         shadow_cr0->ts=0;
290         real_cr0->ts=0;
291         
292         index+=2;
293         
294         info->rip+=index;
295
296       } else {
297         PrintDebug("Unkown instruction: \n");
298         SerialMemDump(instr,15);
299         return -1;
300       }
301     }
302     break;
303     
304   case PROTECTED_PAE:
305     PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n");
306     return -1;
307
308   case LONG:
309     PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n");
310     return -1;
311
312   default: 
313     {
314       PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode);
315       return -1;
316     }
317     break;
318
319   }
320
321   return 0;
322 }
323
324
325 int handle_cr0_read(struct guest_info * info) {
326   char instr[15];
327
328   switch (info->cpu_mode) { 
329
330   case REAL: 
331     {
332
333       int index = 0;
334       int ret;
335
336       PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
337
338       // The real rip address is actually a combination of the rip + CS base 
339       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
340       if (ret != 15) {
341         // I think we should inject a GPF into the guest
342         PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
343         return -1;
344       }
345
346
347       while (is_prefix_byte(instr[index])) {
348         index++; 
349       }
350
351       if ((instr[index] == cr_access_byte) && 
352           (instr[index + 1] == smsw_byte) && 
353           (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
354
355         // SMSW (store machine status word)
356
357         addr_t first_operand;
358         addr_t second_operand;
359         struct cr0_real *cr0;
360         operand_type_t addr_type;
361         char cr0_val = 0;
362
363         index += 2;
364       
365         cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
366       
367       
368         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
369       
370         if (addr_type == MEM_OPERAND) {
371           addr_t host_addr;
372         
373           if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
374             // gpf the guest
375             PrintDebug("Could not convert guest physical address to host virtual address\n");
376             return -1;
377           }
378         
379           first_operand = host_addr;
380         } else {
381           // Register operand
382           // Should be ok??
383         }
384
385         cr0_val = *(char*)cr0 & 0x0f;
386
387         *(char *)first_operand &= 0xf0;
388         *(char *)first_operand |= cr0_val;
389
390         PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
391         info->rip += index;
392         PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
393         // success
394
395       } else if ((instr[index] == cr_access_byte) &&
396                  (instr[index+1] == mov_from_cr_byte)) {
397         /* Mov from CR0
398          * This can only take a 32 bit register argument in anything less than 64 bit mode.
399          */
400         addr_t first_operand;
401         addr_t second_operand;
402         operand_type_t addr_type;
403
404         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
405
406         index += 2;
407
408         addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
409      
410         struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
411   
412         if (addr_type != REG_OPERAND) {
413           // invalid opcode to guest
414           PrintDebug("Invalid operand type in mov from CR0\n");
415           return -1;
416         }
417
418         if (info->shdw_pg_mode == SHADOW_PAGING) {
419           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
420         } else {
421           *virt_cr0 = *real_cr0;
422         }
423
424         info->rip += index;
425
426       } else {
427         PrintDebug("Unknown read instr from CR0\n");
428         return -1;
429       }
430
431     } 
432
433     break;
434
435   case PROTECTED:
436     {
437     
438       int index = 0;
439       int ret;
440
441       PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n", 
442                  info->mem_mode == VIRTUAL_MEM ? "Paged" : "",
443                  info->mem_mode == VIRTUAL_MEM ? "virtual" : "",
444                  get_addr_linear(info, info->rip, &(info->segments.cs)));
445
446       // We need to read the instruction, which is at CS:IP, but that 
447       // linear address is guest physical without PG and guest virtual with PG
448       if (info->cpu_mode == PHYSICAL_MEM) { 
449         // The real rip address is actually a combination of the rip + CS base 
450         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
451       } else { 
452         // The real rip address is actually a combination of the rip + CS base 
453         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
454       }
455
456       if (ret != 15) {
457         // I think we should inject a GPF into the guest
458         PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", 
459                    info->cpu_mode == VIRTUAL_MEM ? "Paged" : "", ret);
460         return -1;
461       }
462
463       while (is_prefix_byte(instr[index])) {
464         index++; 
465       }
466
467
468       if ((instr[index] == cr_access_byte) &&
469           (instr[index+1] == mov_from_cr_byte)) {
470         
471         // MOV from CR0 to register
472
473         addr_t first_operand;
474         addr_t second_operand;
475         operand_type_t addr_type;
476         struct cr0_32 * virt_cr0;
477         struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
478
479         index += 2;
480
481         addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
482
483         if (addr_type != REG_OPERAND) {
484           PrintDebug("Invalid operand type in mov from CR0\n");
485           return -1;
486         }
487       
488         virt_cr0 = (struct cr0_32 *)first_operand;
489
490         if (info->shdw_pg_mode == SHADOW_PAGING) {
491           *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
492           if (info->cpu_mode==PROTECTED) {
493             virt_cr0->pg=0; // clear the pg bit because guest doesn't think it's on
494           }
495         } else {
496           *virt_cr0 = *real_cr0;
497         }
498       
499         info->rip += index;
500
501       } else { 
502         PrintDebug("Unknown read instruction from CR0\n");
503         return -1;
504       }
505     }
506     break;
507
508   case PROTECTED_PAE:
509     PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
510     return -1;
511
512   case LONG:
513     PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
514     return -1;
515
516
517   default:
518     {
519       PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
520       return -1;
521     }
522     break;
523   }
524
525
526   return 0;
527 }
528
529
530
531
532 int handle_cr3_write(struct guest_info * info) {
533   if (info->cpu_mode == PROTECTED) {
534     int index = 0;
535     int ret;
536     char instr[15];
537
538     PrintDebug("Protected %s mode write to CR3 at %s 0x%x\n",
539                info->cpu_mode==PROTECTED ? "" : "Paged", 
540                info->cpu_mode==PROTECTED ? "guest physical" : "guest virtual",
541                get_addr_linear(info,info->rip,&(info->segments.cs)));
542
543     // We need to read the instruction, which is at CS:IP, but that 
544     // linear address is guest physical without PG and guest virtual with PG
545     if (info->mem_mode == PHYSICAL_MEM) { 
546       // The real rip address is actually a combination of the rip + CS base 
547       PrintDebug("Writing Guest CR3 Write (Physical Address)\n");
548       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
549     } else { 
550       PrintDebug("Writing Guest CR3 Write (Virtual Address)\n");
551       // The real rip address is actually a combination of the rip + CS base 
552       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
553     }
554
555     if (ret != 15) {
556       PrintDebug("Could not read instruction (ret=%d)\n", ret);
557       return -1;
558     }
559     
560     while (is_prefix_byte(instr[index])) {
561       index++;
562     }
563
564     if ((instr[index] == cr_access_byte) && 
565         (instr[index + 1] == mov_to_cr_byte)) {
566
567       addr_t first_operand;
568       addr_t second_operand;
569       struct cr3_32 * new_cr3;
570       //      struct cr3_32 * real_cr3;
571       operand_type_t addr_type;
572
573       index += 2;
574
575       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
576
577       if (addr_type != REG_OPERAND) {
578         /* Mov to CR3 can only be a 32 bit register */
579         return -1;
580       }
581
582       new_cr3 = (struct cr3_32 *)first_operand;
583
584       if (info->shdw_pg_mode == SHADOW_PAGING) {
585         addr_t shadow_pt;
586         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
587         struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
588
589
590         /* Delete the current Page Tables */
591         delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
592
593         PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", 
594                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
595
596
597         *guest_cr3 = *new_cr3;
598
599
600
601         // Something like this
602         shadow_pt =  create_new_shadow_pt32(info);
603         //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
604
605         /* Copy Various flags */
606         *shadow_cr3 = *new_cr3;
607
608
609         
610         shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
611
612         PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", 
613                    *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
614
615
616
617         if (info->mem_mode == VIRTUAL_MEM) {
618           // If we aren't in paged mode then we have to preserve the identity mapped CR3
619           info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
620         }
621       }
622
623       info->rip += index;
624
625     } else {
626       PrintDebug("Unknown Instruction\n");
627       SerialMemDump(instr,15);
628       return -1;
629     }
630   } else {
631     PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);
632     return -1;
633   }
634
635   return 0;
636 }
637
638
639
640
641 int handle_cr3_read(struct guest_info * info) {
642   if (info->cpu_mode == PROTECTED) {
643     int index = 0;
644     int ret;
645     char instr[15];
646
647    
648     // We need to read the instruction, which is at CS:IP, but that 
649     // linear address is guest physical without PG and guest virtual with PG
650     if (info->cpu_mode == PHYSICAL_MEM) { 
651       // The real rip address is actually a combination of the rip + CS base 
652       ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
653     } else { 
654       // The real rip address is actually a combination of the rip + CS base 
655       ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
656     }
657
658     if (ret != 15) {
659       PrintDebug("Could not read instruction (ret=%d)\n", ret);
660       return -1;
661     }
662     
663     while (is_prefix_byte(instr[index])) {
664       index++;
665     }
666
667     if ((instr[index] == cr_access_byte) && 
668         (instr[index + 1] == mov_from_cr_byte)) {
669       addr_t first_operand;
670       addr_t second_operand;
671       struct cr3_32 * virt_cr3;
672       struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
673       operand_type_t addr_type;
674
675       index += 2;
676
677       addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
678
679       if (addr_type != REG_OPERAND) {
680         /* Mov to CR3 can only be a 32 bit register */
681         return -1;
682       }
683
684       virt_cr3 = (struct cr3_32 *)first_operand;
685
686       if (info->shdw_pg_mode == SHADOW_PAGING) {
687         *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
688       } else {
689         *virt_cr3 = *real_cr3;
690       }
691       
692       info->rip += index;
693     } else {
694       PrintDebug("Unknown Instruction\n");
695       SerialMemDump(instr,15);
696       return -1;
697     }
698   } else {
699     PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);
700     return -1;
701   }
702
703   return 0;
704 }