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.


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