#include <palacios/vmm_ctrl_regs.h>
+
+extern void SerialMemDump(unsigned char *start, int n);
+
/* Segmentation is a problem here...
*
* When we get a memory operand, presumably we use the default segment (which is?)
char instr[15];
- if (info->cpu_mode == REAL) {
- int index = 0;
- int ret;
+ switch (info->cpu_mode) {
+ case REAL:
+ {
+ int index = 0;
+ int ret;
+
+ PrintDebug("Real Mode write to CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
- // The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- if (ret != 15) {
- // I think we should inject a GPF into the guest
- PrintDebug("Could not read instruction (ret=%d)\n", ret);
- return -1;
- }
+ // The real rip address is actually a combination of the rip + CS base
+ ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ if (ret != 15) {
+ // I think we should inject a GPF into the guest
+ PrintDebug("Could not read instruction (ret=%d)\n", ret);
+ return -1;
+ }
- while (is_prefix_byte(instr[index])) {
- index++;
- }
+ while (is_prefix_byte(instr[index])) {
+ index++;
+ }
- if ((instr[index] == cr_access_byte) &&
- (instr[index + 1] == lmsw_byte) &&
- (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
+ if ((instr[index] == cr_access_byte) &&
+ (instr[index + 1] == lmsw_byte) &&
+ (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
- addr_t first_operand;
- addr_t second_operand;
- struct cr0_real *real_cr0;
- struct cr0_real *new_cr0;
- operand_type_t addr_type;
- char new_cr0_val = 0;
- // LMSW
- // decode mod/RM
- index += 2;
+ addr_t first_operand;
+ addr_t second_operand;
+ struct cr0_real *real_cr0;
+ struct cr0_real *new_cr0;
+ operand_type_t addr_type;
+ char new_cr0_val = 0;
+ // LMSW
+ // decode mod/RM
+ index += 2;
- real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
+ real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
+
+ addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
- addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
+ if (addr_type == REG_OPERAND) {
+ new_cr0 = (struct cr0_real *)first_operand;
+ } else if (addr_type == MEM_OPERAND) {
+ addr_t host_addr;
- if (addr_type == REG_OPERAND) {
- new_cr0 = (struct cr0_real *)first_operand;
- } else if (addr_type == MEM_OPERAND) {
- addr_t host_addr;
+ if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
+ // gpf the guest
+ return -1;
+ }
- if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
- // gpf the guest
+ new_cr0 = (struct cr0_real *)host_addr;
+ } else {
+ PrintDebug("Memory operand in real mode write to CR0 is UNIMPLEMENTED\n");
+ // error... don't know what to do
return -1;
}
-
- new_cr0 = (struct cr0_real *)host_addr;
- } else {
- // error... don't know what to do
- return -1;
- }
- if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
- info->cpu_mode = PROTECTED;
- } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
- info->cpu_mode = REAL;
- }
+ if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
+ info->cpu_mode = PROTECTED;
+ } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
+ info->cpu_mode = REAL;
+ }
- new_cr0_val = *(char*)(new_cr0) & 0x0f;
+ new_cr0_val = *(char*)(new_cr0) & 0x0f;
- if (info->page_mode == SHADOW_PAGING) {
- struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
+ if (info->page_mode == SHADOW_PAGING) {
+ struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
- PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
- /* struct cr0_real is only 4 bits wide,
- * so we can overwrite the real_cr0 without worrying about the shadow fields
- */
- *(char*)real_cr0 &= 0xf0;
- *(char*)real_cr0 |= new_cr0_val;
+ PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
+ /* struct cr0_real is only 4 bits wide,
+ * so we can overwrite the real_cr0 without worrying about the shadow fields
+ */
+ *(char*)real_cr0 &= 0xf0;
+ *(char*)real_cr0 |= new_cr0_val;
- *(char*)shadow_cr0 &= 0xf0;
- *(char*)shadow_cr0 |= new_cr0_val;
+ *(char*)shadow_cr0 &= 0xf0;
+ *(char*)shadow_cr0 |= new_cr0_val;
- PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
- } else {
- PrintDebug("Old CR0=%x\n", *real_cr0);
- // for now we just pass through....
- *(char*)real_cr0 &= 0xf0;
- *(char*)real_cr0 |= new_cr0_val;
+ PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
+ } else {
+ PrintDebug("Old CR0=%x\n", *real_cr0);
+ // for now we just pass through....
+ *(char*)real_cr0 &= 0xf0;
+ *(char*)real_cr0 |= new_cr0_val;
- PrintDebug("New CR0=%x\n", *real_cr0);
- }
+ PrintDebug("New CR0=%x\n", *real_cr0);
+ }
- info->rip += index;
+ info->rip += index;
- } else if ((instr[index] == cr_access_byte) &&
- (instr[index + 1] == clts_byte)) {
- // CLTS
- PrintDebug("CLTS unhandled\n");
- return -1;
+ } else if ((instr[index] == cr_access_byte) &&
+ (instr[index + 1] == clts_byte)) {
+ // CLTS
+ PrintDebug("CLTS unhandled in CR0 write\n");
+ return -1;
- } else if ((instr[index] == cr_access_byte) &&
- (instr[index + 1] = mov_to_cr_byte)) {
- addr_t first_operand;
- addr_t second_operand;
- struct cr0_32 *real_cr0;
- struct cr0_32 *new_cr0;
- operand_type_t addr_type;
+ } else if ((instr[index] == cr_access_byte) &&
+ (instr[index + 1] = mov_to_cr_byte)) {
+ addr_t first_operand;
+ addr_t second_operand;
+ struct cr0_32 *real_cr0;
+ struct cr0_32 *new_cr0;
+ operand_type_t addr_type;
- index += 2;
+ index += 2;
- real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
+ real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
- addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+ addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
- if (addr_type != REG_OPERAND) {
- /* Mov to CR0 Can only be a 32 bit register */
- // FIX ME
- return -1;
- }
+ if (addr_type != REG_OPERAND) {
+ PrintDebug("Moving to CR0 from non-register operand in CR0 write\n");
+ /* Mov to CR0 Can only be a 32 bit register */
+ // FIX ME
+ return -1;
+ }
- new_cr0 = (struct cr0_32 *)first_operand;
+ new_cr0 = (struct cr0_32 *)first_operand;
- if (new_cr0->pe == 1) {
- PrintDebug("Entering Protected Mode\n");
- info->cpu_mode = PROTECTED;
- }
+ if (new_cr0->pe == 1) {
+ PrintDebug("Entering Protected Mode\n");
+ info->cpu_mode = PROTECTED;
+ }
- if (new_cr0->pg == 1) {
- // GPF the guest??
- return -1;
- }
+ if (new_cr0->pg == 1) {
+ PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n");
- if (info->page_mode == SHADOW_PAGING) {
- struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+ // GPF the guest??
+ return -1;
+ }
+
+ if (info->page_mode == SHADOW_PAGING) {
+ struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
- PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
- *real_cr0 = *new_cr0;
- real_cr0->pg = 1;
+ PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
+ *real_cr0 = *new_cr0;
+ real_cr0->pg = 1;
- *shadow_cr0 = *new_cr0;
+ *shadow_cr0 = *new_cr0;
- PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
- } else {
- PrintDebug("Old CR0=%x\n", *real_cr0);
- *real_cr0 = *new_cr0;
- PrintDebug("New CR0=%x\n", *real_cr0);
- }
+ PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
+ } else {
+ PrintDebug("Old CR0=%x\n", *real_cr0);
+ *real_cr0 = *new_cr0;
+ PrintDebug("New CR0=%x\n", *real_cr0);
+ }
- info->rip += index;
+ info->rip += index;
- } else {
- PrintDebug("Unsupported Instruction\n");
- // unsupported instruction, UD the guest
- return -1;
- }
+ } else {
+ PrintDebug("Unsupported Instruction\n");
+ // unsupported instruction, UD the guest
+ return -1;
+ }
+ }
+ break;
+
+ case PROTECTED:
+ case PROTECTED_PG:
+ {
+
+ int index = 0;
+ int ret;
+
+ PrintDebug("Protected %s Mode write to CR0 at guest %s linear rip 0x%x\n",
+ info->cpu_mode==PROTECTED_PG ? "Paged" : "",
+ info->cpu_mode==PROTECTED_PG ? "virtual" : "",
+ get_addr_linear(info,info->rip,&(info->segments.cs)));
+
+ // OK, now we will read the instruction
+ // The only difference between PROTECTED and PROTECTED_PG is whether we read
+ // from guest_pa or guest_va
+ if (info->cpu_mode==PROTECTED) {
+ // The real rip address is actually a combination of the rip + CS base
+ ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ } else { //PROTECTED_PG
+ ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ }
+
+ if (ret != 15) {
+ // I think we should inject a GPF into the guest
+ PrintDebug("Could not read instruction (ret=%d)\n", ret);
+ return -1;
+ }
- } else if (info->cpu_mode == PROTECTED) {
- int index = 0;
- int ret;
+ while (is_prefix_byte(instr[index])) {
+ index++;
+ }
- PrintDebug("Protected Mode write to CR0\n");
+ struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
- // The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- if (ret != 15) {
- // I think we should inject a GPF into the guest
- PrintDebug("Could not read instruction (ret=%d)\n", ret);
- return -1;
- }
+ struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
- while (is_prefix_byte(instr[index])) {
- index++;
- }
+ if ((instr[index] == cr_access_byte) &&
+ (instr[index + 1] == mov_to_cr_byte)) {
- if ((instr[index] == cr_access_byte) &&
- (instr[index + 1] == mov_to_cr_byte)) {
+ // MOV to CR0
- addr_t first_operand;
- addr_t second_operand;
- struct cr0_32 *real_cr0;
- struct cr0_32 *new_cr0;
- operand_type_t addr_type;
+ addr_t first_operand;
+ addr_t second_operand;
+ struct cr0_32 *new_cr0;
+ operand_type_t addr_type;
- index += 2;
+ index += 2;
- real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
- addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+ addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
- if (addr_type != REG_OPERAND) {
- return -1;
- }
+ if (addr_type != REG_OPERAND) {
+ PrintDebug("Non-register operand in write to CR0\n");
+ return -1;
+ }
- new_cr0 = (struct cr0_32 *)first_operand;
+ new_cr0 = (struct cr0_32 *)first_operand;
- if (info->page_mode == SHADOW_PAGING) {
- struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
- if (new_cr0->pg == 1){
- struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
+ if (info->page_mode == SHADOW_PAGING) {
+ struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+
+ if (new_cr0->pg == 1){
+ // This should be new_cr0->pg && !(old_cr->pg), right?
+ // and then a case for turning paging off?
- info->cpu_mode = PROTECTED_PG;
+ struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
+
+ info->cpu_mode = PROTECTED_PG;
- *shadow_cr0 = *new_cr0;
- *real_cr0 = *new_cr0;
+ *shadow_cr0 = *new_cr0;
+ *real_cr0 = *new_cr0;
- //
- // Activate Shadow Paging
- //
- PrintDebug("Turning on paging in the guest\n");
+ //
+ // Activate Shadow Paging
+ //
+ PrintDebug("Turning on paging in the guest\n");
- info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
+ info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
- } else if (new_cr0->pe == 0) {
- info->cpu_mode = REAL;
+ } else if (new_cr0->pe == 0) {
+ info->cpu_mode = REAL;
- *shadow_cr0 = *new_cr0;
+ *shadow_cr0 = *new_cr0;
+ *real_cr0 = *new_cr0;
+ real_cr0->pg = 1;
+ }
+
+
+ } else {
*real_cr0 = *new_cr0;
- real_cr0->pg = 1;
}
+ info->rip += index;
+
+ } else if ((instr[index] == 0x0f) &&
+ (instr[index + 1] == 0x06)) {
+ // CLTS instruction
+ PrintDebug("CLTS instruction - clearing TS flag of real and shadow CR0\n");
+ shadow_cr0->ts=0;
+ real_cr0->ts=0;
+
+ index+=2;
+
+ info->rip+=index;
} else {
- *real_cr0 = *new_cr0;
+ PrintDebug("Unkown instruction: \n");
+ SerialMemDump(instr,15);
+ return -1;
}
-
- info->rip += index;
}
+ break;
- } else {
- PrintDebug("Unknown Mode write to CR0\n");
+ case PROTECTED_PAE:
+ PrintDebug("Protected PAE Mode write to CR0 is UNIMPLEMENTED\n");
+ return -1;
+
+ case PROTECTED_PAE_PG:
+ PrintDebug("Protected PAE Paged Mode write to CR0 is UNIMPLEMENTED\n");
+ return -1;
+
+ case LONG:
+ PrintDebug("Protected Long Mode write to CR0 is UNIMPLEMENTED\n");
return -1;
+
+ case LONG_PG:
+ PrintDebug("Protected Long Paged Mode write to CR0 is UNIMPLEMENTED\n");
+ return -1;
+
+ default:
+ {
+ PrintDebug("Unknown Mode write to CR0 (info->cpu_mode=0x%x\n)",info->cpu_mode);
+ return -1;
+ }
+ break;
+
}
+
return 0;
}
int handle_cr0_read(struct guest_info * info) {
char instr[15];
- if (info->cpu_mode == REAL) {
- int index = 0;
- int ret;
+ switch (info->cpu_mode) {
- // The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- if (ret != 15) {
- // I think we should inject a GPF into the guest
- PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
- return -1;
- }
+ case REAL:
+ {
+ int index = 0;
+ int ret;
- while (is_prefix_byte(instr[index])) {
- index++;
- }
+ PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs)));
- if ((instr[index] == cr_access_byte) &&
- (instr[index + 1] == smsw_byte) &&
- (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
+ // The real rip address is actually a combination of the rip + CS base
+ ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ if (ret != 15) {
+ // I think we should inject a GPF into the guest
+ PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
+ return -1;
+ }
- addr_t first_operand;
- addr_t second_operand;
- struct cr0_real *cr0;
- operand_type_t addr_type;
- char cr0_val = 0;
- index += 2;
+ while (is_prefix_byte(instr[index])) {
+ index++;
+ }
+
+ if ((instr[index] == cr_access_byte) &&
+ (instr[index + 1] == smsw_byte) &&
+ (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
+
+ // SMSW (store machine status word)
+
+ addr_t first_operand;
+ addr_t second_operand;
+ struct cr0_real *cr0;
+ operand_type_t addr_type;
+ char cr0_val = 0;
+
+ index += 2;
- cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
+ cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
- addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
+ addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
- if (addr_type == MEM_OPERAND) {
- addr_t host_addr;
+ if (addr_type == MEM_OPERAND) {
+ addr_t host_addr;
- if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
- // gpf the guest
- PrintDebug("Could not convert guest physical address to host virtual address\n");
- return -1;
- }
+ if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
+ // gpf the guest
+ PrintDebug("Could not convert guest physical address to host virtual address\n");
+ return -1;
+ }
- first_operand = host_addr;
- } else {
- // Register operand
- // Should be ok??
- }
+ first_operand = host_addr;
+ } else {
+ // Register operand
+ // Should be ok??
+ }
- cr0_val = *(char*)cr0 & 0x0f;
+ cr0_val = *(char*)cr0 & 0x0f;
- *(char *)first_operand &= 0xf0;
- *(char *)first_operand |= cr0_val;
+ *(char *)first_operand &= 0xf0;
+ *(char *)first_operand |= cr0_val;
- PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
- info->rip += index;
- PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
- } else if ((instr[index] == cr_access_byte) &&
- (instr[index+1] == mov_from_cr_byte)) {
- /* Mov from CR0
- * This can only take a 32 bit register argument in anything less than 64 bit mode.
- */
- addr_t first_operand;
- addr_t second_operand;
- operand_type_t addr_type;
+ PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
+ info->rip += index;
+ PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
+ // success
- struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
+ } else if ((instr[index] == cr_access_byte) &&
+ (instr[index+1] == mov_from_cr_byte)) {
+ /* Mov from CR0
+ * This can only take a 32 bit register argument in anything less than 64 bit mode.
+ */
+ addr_t first_operand;
+ addr_t second_operand;
+ operand_type_t addr_type;
- index += 2;
+ struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
+
+ index += 2;
- addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+ addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
- struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
+ struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
- if (addr_type != REG_OPERAND) {
- // invalid opcode to guest
- PrintDebug("Invalid operand type in mov from CR0\n");
- return -1;
- }
+ if (addr_type != REG_OPERAND) {
+ // invalid opcode to guest
+ PrintDebug("Invalid operand type in mov from CR0\n");
+ return -1;
+ }
+
+ if (info->page_mode == SHADOW_PAGING) {
+ *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+ } else {
+ *virt_cr0 = *real_cr0;
+ }
+
+ info->rip += index;
- if (info->page_mode == SHADOW_PAGING) {
- *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
} else {
- *virt_cr0 = *real_cr0;
+ PrintDebug("Unknown read instr from CR0\n");
+ return -1;
}
- info->rip += index;
+ }
- } else {
- PrintDebug("Unknown read instr from CR0\n");
- return -1;
- }
+ break;
- } else if (info->cpu_mode == PROTECTED) {
- int index = 0;
- int ret;
+ case PROTECTED:
+ case PROTECTED_PG:
+ {
+
+ int index = 0;
+ int ret;
+
+ PrintDebug("Protected %s Mode read from CR0 at guest %s linear rip 0x%x\n",
+ info->cpu_mode==PROTECTED_PG ? "Paged" : "",
+ info->cpu_mode==PROTECTED_PG ? "virtual" : "",
+ get_addr_linear(info,info->rip,&(info->segments.cs)));
+
+ // We need to read the instruction, which is at CS:IP, but that
+ // linear address is guest physical without PG and guest virtual with PG
+ if (info->cpu_mode==PROTECTED) {
+ // The real rip address is actually a combination of the rip + CS base
+ ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ } else { // PROTECTED_PG
+ // The real rip address is actually a combination of the rip + CS base
+ ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+ }
- // The real rip address is actually a combination of the rip + CS base
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- if (ret != 15) {
- // I think we should inject a GPF into the guest
- PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
- return -1;
- }
+ if (ret != 15) {
+ // I think we should inject a GPF into the guest
+ PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n",
+ info->cpu_mode==PROTECTED_PG ? "Paged" : "", ret);
+ return -1;
+ }
- while (is_prefix_byte(instr[index])) {
- index++;
- }
+ while (is_prefix_byte(instr[index])) {
+ index++;
+ }
- if ((instr[index] == cr_access_byte) &&
- (instr[index+1] == mov_from_cr_byte)) {
- addr_t first_operand;
- addr_t second_operand;
- operand_type_t addr_type;
- struct cr0_32 * virt_cr0;
- struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
+ if ((instr[index] == cr_access_byte) &&
+ (instr[index+1] == mov_from_cr_byte)) {
+
+ // MOV from CR0 to register
- index += 2;
+ addr_t first_operand;
+ addr_t second_operand;
+ operand_type_t addr_type;
+ struct cr0_32 * virt_cr0;
+ struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
- addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+ index += 2;
- if (addr_type != REG_OPERAND) {
- PrintDebug("Invalid operand type in mov from CR0\n");
- return -1;
- }
+ addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+ if (addr_type != REG_OPERAND) {
+ PrintDebug("Invalid operand type in mov from CR0\n");
+ return -1;
+ }
- virt_cr0 = (struct cr0_32 *)first_operand;
+ virt_cr0 = (struct cr0_32 *)first_operand;
- if (info->page_mode == SHADOW_PAGING) {
- *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
- } else {
- *virt_cr0 = *real_cr0;
- }
+ if (info->page_mode == SHADOW_PAGING) {
+ *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+ } else {
+ *virt_cr0 = *real_cr0;
+ }
- info->rip += index;
+ info->rip += index;
- } else {
- PrintDebug("Unknown read instruction from CR0\n");
- return -1;
+ } else {
+ PrintDebug("Unknown read instruction from CR0\n");
+ return -1;
+ }
}
+ break;
- } else {
- PrintDebug("Unknown mode read from CR0\n");
+ case PROTECTED_PAE:
+ PrintDebug("Protected PAE Mode read to CR0 is UNIMPLEMENTED\n");
+ return -1;
+
+ case PROTECTED_PAE_PG:
+ PrintDebug("Protected PAE Paged Mode read to CR0 is UNIMPLEMENTED\n");
return -1;
+
+ case LONG:
+ PrintDebug("Protected Long Mode read to CR0 is UNIMPLEMENTED\n");
+ return -1;
+
+ case LONG_PG:
+ PrintDebug("Protected Long Paged Mode read to CR0 is UNIMPLEMENTED\n");
+ return -1;
+ default:
+ {
+ PrintDebug("Unknown Mode read from CR0 (info->cpu_mode=0x%x)\n",info->cpu_mode);
+ return -1;
+ }
+ break;
}