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>
10 extern void SerialMemDump(unsigned char *start, int n);
12 /* Segmentation is a problem here...
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...
19 int handle_cr0_write(struct guest_info * info) {
23 switch (info->cpu_mode) {
29 PrintDebug("Real Mode write to CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
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);
34 // I think we should inject a GPF into the guest
35 PrintDebug("Could not read instruction (ret=%d)\n", ret);
39 while (is_prefix_byte(instr[index])) {
43 if ((instr[index] == cr_access_byte) &&
44 (instr[index + 1] == lmsw_byte) &&
45 (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
48 addr_t second_operand;
49 struct cr0_real *real_cr0;
50 struct cr0_real *new_cr0;
51 operand_type_t addr_type;
57 real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
59 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
62 if (addr_type == REG_OPERAND) {
63 new_cr0 = (struct cr0_real *)first_operand;
64 } else if (addr_type == MEM_OPERAND) {
67 if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
72 new_cr0 = (struct cr0_real *)host_addr;
74 PrintDebug("Memory operand in real mode write to CR0 is UNIMPLEMENTED\n");
75 // error... don't know what to do
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;
85 new_cr0_val = *(char*)(new_cr0) & 0x0f;
88 if (info->shdw_pg_mode == SHADOW_PAGING) {
89 struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
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
95 *(char*)real_cr0 &= 0xf0;
96 *(char*)real_cr0 |= new_cr0_val;
98 *(char*)shadow_cr0 &= 0xf0;
99 *(char*)shadow_cr0 |= new_cr0_val;
101 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
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;
108 PrintDebug("New CR0=%x\n", *real_cr0);
114 } else if ((instr[index] == cr_access_byte) &&
115 (instr[index + 1] == clts_byte)) {
117 PrintDebug("CLTS unhandled in CR0 write\n");
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;
131 real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
133 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
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 */
142 new_cr0 = (struct cr0_32 *)first_operand;
144 if (new_cr0->pe == 1) {
145 PrintDebug("Entering Protected Mode\n");
146 info->cpu_mode = PROTECTED;
149 if (new_cr0->pe == 0) {
150 PrintDebug("Entering Real Mode\n");
151 info->cpu_mode = REAL;
155 if (new_cr0->pg == 1) {
156 PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n");
162 if (info->shdw_pg_mode == SHADOW_PAGING) {
163 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
165 PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
166 *real_cr0 = *new_cr0;
169 *shadow_cr0 = *new_cr0;
171 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
173 PrintDebug("Old CR0=%x\n", *real_cr0);
174 *real_cr0 = *new_cr0;
175 PrintDebug("New CR0=%x\n", *real_cr0);
181 PrintDebug("Unsupported Instruction\n");
182 // unsupported instruction, UD the guest
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)));
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);
207 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
212 // I think we should inject a GPF into the guest
213 PrintDebug("Could not read instruction (ret=%d)\n", ret);
217 while (is_prefix_byte(instr[index])) {
221 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
223 struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
225 if ((instr[index] == cr_access_byte) &&
226 (instr[index + 1] == mov_to_cr_byte)) {
230 addr_t first_operand;
231 addr_t second_operand;
232 struct cr0_32 *new_cr0;
233 operand_type_t addr_type;
238 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
240 if (addr_type != REG_OPERAND) {
241 PrintDebug("Non-register operand in write to CR0\n");
245 new_cr0 = (struct cr0_32 *)first_operand;
249 if (info->shdw_pg_mode == SHADOW_PAGING) {
250 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
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?
256 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
258 info->mem_mode = VIRTUAL_MEM;
260 *shadow_cr0 = *new_cr0;
261 *real_cr0 = *new_cr0;
264 // Activate Shadow Paging
266 PrintDebug("Turning on paging in the guest\n");
268 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
271 } else if (new_cr0->pe == 0) {
272 info->cpu_mode = REAL;
274 *shadow_cr0 = *new_cr0;
275 *real_cr0 = *new_cr0;
281 *real_cr0 = *new_cr0;
286 } else if ((instr[index] == 0x0f) &&
287 (instr[index + 1] == 0x06)) {
289 PrintDebug("CLTS instruction - clearing TS flag of real and shadow CR0\n");
298 PrintDebug("Unkown instruction: \n");
299 SerialMemDump(instr,15);
306 PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n");
310 PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n");
315 PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode);
326 int handle_cr0_read(struct guest_info * info) {
329 switch (info->cpu_mode) {
337 PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
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);
342 // I think we should inject a GPF into the guest
343 PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
348 while (is_prefix_byte(instr[index])) {
352 if ((instr[index] == cr_access_byte) &&
353 (instr[index + 1] == smsw_byte) &&
354 (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
356 // SMSW (store machine status word)
358 addr_t first_operand;
359 addr_t second_operand;
360 struct cr0_real *cr0;
361 operand_type_t addr_type;
366 cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
369 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
371 if (addr_type == MEM_OPERAND) {
374 if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
376 PrintDebug("Could not convert guest physical address to host virtual address\n");
380 first_operand = host_addr;
386 cr0_val = *(char*)cr0 & 0x0f;
388 *(char *)first_operand &= 0xf0;
389 *(char *)first_operand |= cr0_val;
391 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
393 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
396 } else if ((instr[index] == cr_access_byte) &&
397 (instr[index+1] == mov_from_cr_byte)) {
399 * This can only take a 32 bit register argument in anything less than 64 bit mode.
401 addr_t first_operand;
402 addr_t second_operand;
403 operand_type_t addr_type;
405 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
409 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
411 struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
413 if (addr_type != REG_OPERAND) {
414 // invalid opcode to guest
415 PrintDebug("Invalid operand type in mov from CR0\n");
419 if (info->shdw_pg_mode == SHADOW_PAGING) {
420 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
422 *virt_cr0 = *real_cr0;
428 PrintDebug("Unknown read instr from CR0\n");
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)));
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);
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);
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);
464 while (is_prefix_byte(instr[index])) {
469 if ((instr[index] == cr_access_byte) &&
470 (instr[index+1] == mov_from_cr_byte)) {
472 // MOV from CR0 to register
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);
482 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
484 if (addr_type != REG_OPERAND) {
485 PrintDebug("Invalid operand type in mov from CR0\n");
489 virt_cr0 = (struct cr0_32 *)first_operand;
491 if (info->shdw_pg_mode == SHADOW_PAGING) {
492 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
494 if (info->mem_mode == PHYSICAL_MEM) {
495 virt_cr0->pg = 0; // clear the pg bit because guest doesn't think it's on
499 *virt_cr0 = *real_cr0;
505 PrintDebug("Unknown read instruction from CR0\n");
512 PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
516 PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
522 PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
535 int handle_cr3_write(struct guest_info * info) {
536 if (info->cpu_mode == PROTECTED) {
541 PrintDebug("Protected %s mode write to CR3 at %s 0x%x\n",
542 info->cpu_mode==PROTECTED ? "" : "Paged",
543 info->cpu_mode==PROTECTED ? "guest physical" : "guest virtual",
544 get_addr_linear(info,info->rip,&(info->segments.cs)));
546 // We need to read the instruction, which is at CS:IP, but that
547 // linear address is guest physical without PG and guest virtual with PG
548 if (info->mem_mode == PHYSICAL_MEM) {
549 // The real rip address is actually a combination of the rip + CS base
550 PrintDebug("Writing Guest CR3 Write (Physical Address)\n");
551 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
553 PrintDebug("Writing Guest CR3 Write (Virtual Address)\n");
554 // The real rip address is actually a combination of the rip + CS base
555 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
559 PrintDebug("Could not read instruction (ret=%d)\n", ret);
563 while (is_prefix_byte(instr[index])) {
567 if ((instr[index] == cr_access_byte) &&
568 (instr[index + 1] == mov_to_cr_byte)) {
570 addr_t first_operand;
571 addr_t second_operand;
572 struct cr3_32 * new_cr3;
573 // struct cr3_32 * real_cr3;
574 operand_type_t addr_type;
578 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
580 if (addr_type != REG_OPERAND) {
581 /* Mov to CR3 can only be a 32 bit register */
585 new_cr3 = (struct cr3_32 *)first_operand;
587 if (info->shdw_pg_mode == SHADOW_PAGING) {
589 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
590 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
593 if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) {
594 PrintDebug("Shadow Page Table\n");
595 PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
598 /* Delete the current Page Tables */
599 delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
601 PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n",
602 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
605 *guest_cr3 = *new_cr3;
609 // Something like this
610 shadow_pt = create_new_shadow_pt32(info);
611 //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
613 /* Copy Various flags */
614 *shadow_cr3 = *new_cr3;
618 guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr);
619 PrintDebug("Guest PD\n");
620 PrintPD32((pde32_t *)tmp_addr);
626 shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
628 PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n",
629 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
633 if (info->mem_mode == VIRTUAL_MEM) {
634 // If we aren't in paged mode then we have to preserve the identity mapped CR3
635 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
642 PrintDebug("Unknown Instruction\n");
643 SerialMemDump(instr,15);
647 PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);
657 int handle_cr3_read(struct guest_info * info) {
658 if (info->cpu_mode == PROTECTED) {
664 // We need to read the instruction, which is at CS:IP, but that
665 // linear address is guest physical without PG and guest virtual with PG
666 if (info->cpu_mode == PHYSICAL_MEM) {
667 // The real rip address is actually a combination of the rip + CS base
668 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
670 // The real rip address is actually a combination of the rip + CS base
671 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
675 PrintDebug("Could not read instruction (ret=%d)\n", ret);
679 while (is_prefix_byte(instr[index])) {
683 if ((instr[index] == cr_access_byte) &&
684 (instr[index + 1] == mov_from_cr_byte)) {
685 addr_t first_operand;
686 addr_t second_operand;
687 struct cr3_32 * virt_cr3;
688 struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
689 operand_type_t addr_type;
693 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
695 if (addr_type != REG_OPERAND) {
696 /* Mov to CR3 can only be a 32 bit register */
700 virt_cr3 = (struct cr3_32 *)first_operand;
702 if (info->shdw_pg_mode == SHADOW_PAGING) {
703 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
705 *virt_cr3 = *real_cr3;
710 PrintDebug("Unknown Instruction\n");
711 SerialMemDump(instr,15);
715 PrintDebug("Invalid operating Mode (0x%x)\n", info->cpu_mode);