1 #include <palacios/svm_ctrl_regs.h>
2 #include <palacios/vmm_mem.h>
3 #include <palacios/vmm.h>
4 #include <palacios/vmcb.h>
5 #include <palacios/vmm_emulate.h>
6 #include <palacios/vm_guest_mem.h>
7 #include <palacios/vmm_ctrl_regs.h>
10 /* Segmentation is a problem here...
12 * When we get a memory operand, presumably we use the default segment (which is?)
13 * unless an alternate segment was specfied in the prefix...
17 int handle_cr0_write(struct guest_info * info) {
18 //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
19 vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
23 if (info->cpu_mode == REAL) {
27 // The real rip address is actually a combination of the rip + CS base
28 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.selector), 15, instr);
30 // I think we should inject a GPF into the guest
31 PrintDebug("Could not read instruction (ret=%d)\n", ret);
35 while (is_prefix_byte(instr[index])) {
39 if ((instr[index] == cr_access_byte) &&
40 (instr[index + 1] == lmsw_byte) &&
41 (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
44 addr_t second_operand;
45 struct cr0_real *old_cr0;
46 struct cr0_real *new_cr0;
47 operand_type_t addr_type;
53 old_cr0 = (struct cr0_real*)&(guest_state->cr0);
56 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
59 if (addr_type == REG_OPERAND) {
60 new_cr0 = (struct cr0_real *)first_operand;
61 } else if (addr_type == MEM_OPERAND) {
64 if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) {
69 new_cr0 = (struct cr0_real *)host_addr;
71 // error... don't know what to do
75 if ((new_cr0->pe == 1) && (old_cr0->pe == 0)) {
76 info->cpu_mode = PROTECTED;
77 } else if ((new_cr0->pe == 0) && (old_cr0->pe == 1)) {
78 info->cpu_mode = REAL;
81 new_cr0_val = *(char*)(new_cr0) & 0x0f;
84 if (info->page_mode == SHADOW_PAGING) {
85 struct cr0_real * virt_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
87 /* struct cr0_real is only 4 bits wide,
88 * so we can overwrite the old_cr0 without worrying about the shadow fields
90 *(char*)old_cr0 &= 0xf0;
91 *(char*)old_cr0 |= new_cr0_val;
93 *(char*)virt_cr0 &= 0xf0;
94 *(char*)virt_cr0 |= new_cr0_val;
96 // for now we just pass through....
97 *(char*)old_cr0 &= 0xf0;
98 *(char*)old_cr0 |= new_cr0_val;
101 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
103 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
104 } else if ((instr[index] == cr_access_byte) &&
105 (instr[index + 1] == clts_byte)) {
108 // unsupported instruction, UD the guest
113 } else if (info->cpu_mode == PROTECTED) {
117 PrintDebug("Protected Mode write to CR0\n");
119 // The real rip address is actually a combination of the rip + CS base
120 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr);
122 // I think we should inject a GPF into the guest
123 PrintDebug("Could not read instruction (ret=%d)\n", ret);
127 while (is_prefix_byte(instr[index])) {
132 /* CHECK IF MOV_TO_CR CAN TAKE MEMORY OPERANDS... */
133 if ((instr[index] == cr_access_byte) &&
134 (instr[index + 1] == mov_to_cr_byte)) {
136 addr_t first_operand;
137 addr_t second_operand;
138 struct cr0_32 *old_cr0;
139 struct cr0_32 *new_cr0;
140 operand_type_t addr_type;
144 old_cr0 = (struct cr0_32*)&(guest_state->cr0);
146 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
149 if (addr_type == REG_OPERAND) {
150 new_cr0 = (struct cr0_32 *)first_operand;
151 } else if (addr_type == MEM_OPERAND) {
154 if (guest_pa_to_host_va(info, first_operand + guest_state->ds.base, &host_addr) == -1) {
159 new_cr0 = (struct cr0_32 *)host_addr;
161 // error... don't know what to do
166 if (info->page_mode == SHADOW_PAGING) {
167 struct cr0_32 * virt_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
169 if ((new_cr0->pg == 1) && (virt_cr0->pg == 0)){
170 info->cpu_mode = PROTECTED_PG;
172 // Activate Shadow Paging
175 *virt_cr0 = *new_cr0;
185 PrintDebug("Unknown Mode write to CR0\n");
192 int handle_cr0_read(struct guest_info * info) {
193 //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
194 vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
197 if (info->cpu_mode == REAL) {
201 // The real rip address is actually a combination of the rip + CS base
202 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.selector), 15, instr);
204 // I think we should inject a GPF into the guest
205 PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
210 while (is_prefix_byte(instr[index])) {
214 if ((instr[index] == cr_access_byte) &&
215 (instr[index + 1] == smsw_byte) &&
216 (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
218 addr_t first_operand;
219 addr_t second_operand;
220 struct cr0_real *cr0;
221 operand_type_t addr_type;
226 cr0 = (struct cr0_real*)&(guest_state->cr0);
229 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
231 if (addr_type == MEM_OPERAND) {
234 if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) {
239 first_operand = host_addr;
241 // error... don't know what to do
245 cr0_val = *(char*)cr0 & 0x0f;
247 *(char *)first_operand &= 0xf0;
248 *(char *)first_operand |= cr0_val;
250 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
252 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
256 PrintDebug("Unknown read instr to CR0\n");
257 guest_pa_to_host_pa(info, get_addr_linear(info, guest_state->rip, guest_state->cs.selector), &host_addr);
259 PrintDebug("Instr (15 bytes) at %x:\n", host_addr);
260 PrintTraceMemDump((char*)host_addr, 15);
265 } else if (info->cpu_mode == PROTECTED) {
269 // The real rip address is actually a combination of the rip + CS base
270 ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr);
272 // I think we should inject a GPF into the guest
273 PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
277 while (is_prefix_byte(instr[index])) {