1 #include <palacios/vmm_mem.h>
2 #include <palacios/vmm.h>
3 #include <palacios/vmcb.h>
4 #include <palacios/vmm_emulate.h>
5 #include <palacios/vm_guest_mem.h>
6 #include <palacios/vmm_ctrl_regs.h>
9 /* Segmentation is a problem here...
11 * When we get a memory operand, presumably we use the default segment (which is?)
12 * unless an alternate segment was specfied in the prefix...
16 int handle_cr0_write(struct guest_info * info) {
20 if (info->cpu_mode == REAL) {
24 // The real rip address is actually a combination of the rip + CS base
25 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
27 // I think we should inject a GPF into the guest
28 PrintDebug("Could not read instruction (ret=%d)\n", ret);
32 while (is_prefix_byte(instr[index])) {
36 if ((instr[index] == cr_access_byte) &&
37 (instr[index + 1] == lmsw_byte) &&
38 (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
41 addr_t second_operand;
42 struct cr0_real *real_cr0;
43 struct cr0_real *new_cr0;
44 operand_type_t addr_type;
50 real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
52 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
55 if (addr_type == REG_OPERAND) {
56 new_cr0 = (struct cr0_real *)first_operand;
57 } else if (addr_type == MEM_OPERAND) {
60 if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
65 new_cr0 = (struct cr0_real *)host_addr;
67 // error... don't know what to do
71 if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
72 info->cpu_mode = PROTECTED;
73 } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
74 info->cpu_mode = REAL;
77 new_cr0_val = *(char*)(new_cr0) & 0x0f;
80 if (info->page_mode == SHADOW_PAGING) {
81 struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
83 PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
84 /* struct cr0_real is only 4 bits wide,
85 * so we can overwrite the real_cr0 without worrying about the shadow fields
87 *(char*)real_cr0 &= 0xf0;
88 *(char*)real_cr0 |= new_cr0_val;
90 *(char*)shadow_cr0 &= 0xf0;
91 *(char*)shadow_cr0 |= new_cr0_val;
93 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
95 PrintDebug("Old CR0=%x\n", *real_cr0);
96 // for now we just pass through....
97 *(char*)real_cr0 &= 0xf0;
98 *(char*)real_cr0 |= new_cr0_val;
100 PrintDebug("New CR0=%x\n", *real_cr0);
106 } else if ((instr[index] == cr_access_byte) &&
107 (instr[index + 1] == clts_byte)) {
111 } else if ((instr[index] == cr_access_byte) &&
112 (instr[index + 1] = mov_to_cr_byte)) {
113 addr_t first_operand;
114 addr_t second_operand;
115 struct cr0_32 *real_cr0;
116 struct cr0_32 *new_cr0;
117 operand_type_t addr_type;
122 real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
124 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
126 if (addr_type != REG_OPERAND) {
127 /* Mov to CR0 Can only be a 32 bit register */
132 new_cr0 = (struct cr0_32 *)first_operand;
134 if (new_cr0->pe == 1) {
135 PrintDebug("Entering Protected Mode\n");
136 info->cpu_mode = PROTECTED;
139 if (new_cr0->pg == 1) {
144 if (info->page_mode == SHADOW_PAGING) {
145 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
147 PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
148 *real_cr0 = *new_cr0;
151 *shadow_cr0 = *new_cr0;
153 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
155 PrintDebug("Old CR0=%x\n", *real_cr0);
156 *real_cr0 = *new_cr0;
157 PrintDebug("New CR0=%x\n", *real_cr0);
163 PrintDebug("Unsupported Instruction\n");
164 // unsupported instruction, UD the guest
169 } else if (info->cpu_mode == PROTECTED) {
173 PrintDebug("Protected Mode write to CR0\n");
175 // The real rip address is actually a combination of the rip + CS base
176 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
178 // I think we should inject a GPF into the guest
179 PrintDebug("Could not read instruction (ret=%d)\n", ret);
183 while (is_prefix_byte(instr[index])) {
187 if ((instr[index] == cr_access_byte) &&
188 (instr[index + 1] == mov_to_cr_byte)) {
190 addr_t first_operand;
191 addr_t second_operand;
192 struct cr0_32 *real_cr0;
193 struct cr0_32 *new_cr0;
194 operand_type_t addr_type;
198 real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
200 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
202 if (addr_type != REG_OPERAND) {
206 new_cr0 = (struct cr0_32 *)first_operand;
209 if (info->page_mode == SHADOW_PAGING) {
210 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
212 if (new_cr0->pg == 1){
213 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
215 info->cpu_mode = PROTECTED_PG;
217 *shadow_cr0 = *new_cr0;
218 *real_cr0 = *new_cr0;
221 // Activate Shadow Paging
223 PrintDebug("Turning on paging in the guest\n");
225 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
228 } else if (new_cr0->pe == 0) {
229 info->cpu_mode = REAL;
231 *shadow_cr0 = *new_cr0;
232 *real_cr0 = *new_cr0;
238 *real_cr0 = *new_cr0;
245 PrintDebug("Unknown Mode write to CR0\n");
252 int handle_cr0_read(struct guest_info * info) {
255 if (info->cpu_mode == REAL) {
259 // The real rip address is actually a combination of the rip + CS base
260 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
262 // I think we should inject a GPF into the guest
263 PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
268 while (is_prefix_byte(instr[index])) {
272 if ((instr[index] == cr_access_byte) &&
273 (instr[index + 1] == smsw_byte) &&
274 (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
276 addr_t first_operand;
277 addr_t second_operand;
278 struct cr0_real *cr0;
279 operand_type_t addr_type;
284 cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
287 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
289 if (addr_type == MEM_OPERAND) {
292 if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
294 PrintDebug("Could not convert guest physical address to host virtual address\n");
298 first_operand = host_addr;
304 cr0_val = *(char*)cr0 & 0x0f;
306 *(char *)first_operand &= 0xf0;
307 *(char *)first_operand |= cr0_val;
309 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
311 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
312 } else if ((instr[index] == cr_access_byte) &&
313 (instr[index+1] == mov_from_cr_byte)) {
315 * This can only take a 32 bit register argument in anything less than 64 bit mode.
317 addr_t first_operand;
318 addr_t second_operand;
319 operand_type_t addr_type;
321 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
325 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
327 struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
329 if (addr_type != REG_OPERAND) {
330 // invalid opcode to guest
331 PrintDebug("Invalid operand type in mov from CR0\n");
335 if (info->page_mode == SHADOW_PAGING) {
336 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
338 *virt_cr0 = *real_cr0;
344 PrintDebug("Unknown read instr from CR0\n");
348 } else if (info->cpu_mode == PROTECTED) {
352 // The real rip address is actually a combination of the rip + CS base
353 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
355 // I think we should inject a GPF into the guest
356 PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
360 while (is_prefix_byte(instr[index])) {
365 if ((instr[index] == cr_access_byte) &&
366 (instr[index+1] == mov_from_cr_byte)) {
367 addr_t first_operand;
368 addr_t second_operand;
369 operand_type_t addr_type;
370 struct cr0_32 * virt_cr0;
371 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
375 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
377 if (addr_type != REG_OPERAND) {
378 PrintDebug("Invalid operand type in mov from CR0\n");
382 virt_cr0 = (struct cr0_32 *)first_operand;
384 if (info->page_mode == SHADOW_PAGING) {
385 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
387 *virt_cr0 = *real_cr0;
393 PrintDebug("Unknown read instruction from CR0\n");
398 PrintDebug("Unknown mode read from CR0\n");
409 int handle_cr3_write(struct guest_info * info) {
410 if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
416 /* Isn't the RIP a Guest Virtual Address???????? */
417 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
419 PrintDebug("Could not read instruction (ret=%d)\n", ret);
423 while (is_prefix_byte(instr[index])) {
427 if ((instr[index] == cr_access_byte) &&
428 (instr[index + 1] == mov_to_cr_byte)) {
430 addr_t first_operand;
431 addr_t second_operand;
432 struct cr3_32 * new_cr3;
433 // struct cr3_32 * real_cr3;
434 operand_type_t addr_type;
438 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
440 if (addr_type != REG_OPERAND) {
441 /* Mov to CR3 can only be a 32 bit register */
445 new_cr3 = (struct cr3_32 *)first_operand;
447 if (info->page_mode == SHADOW_PAGING) {
449 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
450 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
453 *guest_cr3 = *new_cr3;
455 // Something like this
456 shadow_pt = create_new_shadow_pt32(info);
457 //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
459 /* Copy Various flags */
460 *shadow_cr3 = *new_cr3;
462 shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
464 if (info->cpu_mode == PROTECTED_PG) {
465 // If we aren't in paged mode then we have to preserve the identity mapped CR3
466 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
473 PrintDebug("Unknown Instruction\n");
477 PrintDebug("Invalid operating Mode\n");
487 int handle_cr3_read(struct guest_info * info) {
488 if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
493 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
495 PrintDebug("Could not read instruction (ret=%d)\n", ret);
499 while (is_prefix_byte(instr[index])) {
503 if ((instr[index] == cr_access_byte) &&
504 (instr[index + 1] == mov_from_cr_byte)) {
505 addr_t first_operand;
506 addr_t second_operand;
507 struct cr3_32 * virt_cr3;
508 struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
509 operand_type_t addr_type;
513 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
515 if (addr_type != REG_OPERAND) {
516 /* Mov to CR3 can only be a 32 bit register */
520 virt_cr3 = (struct cr3_32 *)first_operand;
522 if (info->page_mode == SHADOW_PAGING) {
523 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
525 *virt_cr3 = *real_cr3;
530 PrintDebug("Unknown Instruction\n");
534 PrintDebug("Invalid operating Mode\n");