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)) {
109 PrintDebug("CLTS unhandled\n");
112 } else if ((instr[index] == cr_access_byte) &&
113 (instr[index + 1] = mov_to_cr_byte)) {
114 addr_t first_operand;
115 addr_t second_operand;
116 struct cr0_32 *real_cr0;
117 struct cr0_32 *new_cr0;
118 operand_type_t addr_type;
123 real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
125 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
127 if (addr_type != REG_OPERAND) {
128 /* Mov to CR0 Can only be a 32 bit register */
133 new_cr0 = (struct cr0_32 *)first_operand;
135 if (new_cr0->pe == 1) {
136 PrintDebug("Entering Protected Mode\n");
137 info->cpu_mode = PROTECTED;
140 if (new_cr0->pg == 1) {
145 if (info->page_mode == SHADOW_PAGING) {
146 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
148 PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
149 *real_cr0 = *new_cr0;
152 *shadow_cr0 = *new_cr0;
154 PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);
156 PrintDebug("Old CR0=%x\n", *real_cr0);
157 *real_cr0 = *new_cr0;
158 PrintDebug("New CR0=%x\n", *real_cr0);
164 PrintDebug("Unsupported Instruction\n");
165 // unsupported instruction, UD the guest
170 } else if (info->cpu_mode == PROTECTED) {
174 PrintDebug("Protected Mode write to CR0\n");
176 // The real rip address is actually a combination of the rip + CS base
177 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
179 // I think we should inject a GPF into the guest
180 PrintDebug("Could not read instruction (ret=%d)\n", ret);
184 while (is_prefix_byte(instr[index])) {
188 if ((instr[index] == cr_access_byte) &&
189 (instr[index + 1] == mov_to_cr_byte)) {
191 addr_t first_operand;
192 addr_t second_operand;
193 struct cr0_32 *real_cr0;
194 struct cr0_32 *new_cr0;
195 operand_type_t addr_type;
199 real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
201 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
203 if (addr_type != REG_OPERAND) {
207 new_cr0 = (struct cr0_32 *)first_operand;
210 if (info->page_mode == SHADOW_PAGING) {
211 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
213 if (new_cr0->pg == 1){
214 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
216 info->cpu_mode = PROTECTED_PG;
218 *shadow_cr0 = *new_cr0;
219 *real_cr0 = *new_cr0;
222 // Activate Shadow Paging
224 PrintDebug("Turning on paging in the guest\n");
226 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
229 } else if (new_cr0->pe == 0) {
230 info->cpu_mode = REAL;
232 *shadow_cr0 = *new_cr0;
233 *real_cr0 = *new_cr0;
239 *real_cr0 = *new_cr0;
246 PrintDebug("Unknown Mode write to CR0\n");
253 int handle_cr0_read(struct guest_info * info) {
256 if (info->cpu_mode == REAL) {
260 // The real rip address is actually a combination of the rip + CS base
261 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
263 // I think we should inject a GPF into the guest
264 PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
269 while (is_prefix_byte(instr[index])) {
273 if ((instr[index] == cr_access_byte) &&
274 (instr[index + 1] == smsw_byte) &&
275 (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
277 addr_t first_operand;
278 addr_t second_operand;
279 struct cr0_real *cr0;
280 operand_type_t addr_type;
285 cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
288 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
290 if (addr_type == MEM_OPERAND) {
293 if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
295 PrintDebug("Could not convert guest physical address to host virtual address\n");
299 first_operand = host_addr;
305 cr0_val = *(char*)cr0 & 0x0f;
307 *(char *)first_operand &= 0xf0;
308 *(char *)first_operand |= cr0_val;
310 PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
312 PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
313 } else if ((instr[index] == cr_access_byte) &&
314 (instr[index+1] == mov_from_cr_byte)) {
316 * This can only take a 32 bit register argument in anything less than 64 bit mode.
318 addr_t first_operand;
319 addr_t second_operand;
320 operand_type_t addr_type;
322 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
326 addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
328 struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
330 if (addr_type != REG_OPERAND) {
331 // invalid opcode to guest
332 PrintDebug("Invalid operand type in mov from CR0\n");
336 if (info->page_mode == SHADOW_PAGING) {
337 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
339 *virt_cr0 = *real_cr0;
345 PrintDebug("Unknown read instr from CR0\n");
349 } else if (info->cpu_mode == PROTECTED) {
353 // The real rip address is actually a combination of the rip + CS base
354 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
356 // I think we should inject a GPF into the guest
357 PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
361 while (is_prefix_byte(instr[index])) {
366 if ((instr[index] == cr_access_byte) &&
367 (instr[index+1] == mov_from_cr_byte)) {
368 addr_t first_operand;
369 addr_t second_operand;
370 operand_type_t addr_type;
371 struct cr0_32 * virt_cr0;
372 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
376 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
378 if (addr_type != REG_OPERAND) {
379 PrintDebug("Invalid operand type in mov from CR0\n");
383 virt_cr0 = (struct cr0_32 *)first_operand;
385 if (info->page_mode == SHADOW_PAGING) {
386 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
388 *virt_cr0 = *real_cr0;
394 PrintDebug("Unknown read instruction from CR0\n");
399 PrintDebug("Unknown mode read from CR0\n");
410 int handle_cr3_write(struct guest_info * info) {
411 if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
417 /* Isn't the RIP a Guest Virtual Address???????? */
418 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
420 PrintDebug("Could not read instruction (ret=%d)\n", ret);
424 while (is_prefix_byte(instr[index])) {
428 if ((instr[index] == cr_access_byte) &&
429 (instr[index + 1] == mov_to_cr_byte)) {
431 addr_t first_operand;
432 addr_t second_operand;
433 struct cr3_32 * new_cr3;
434 // struct cr3_32 * real_cr3;
435 operand_type_t addr_type;
439 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
441 if (addr_type != REG_OPERAND) {
442 /* Mov to CR3 can only be a 32 bit register */
446 new_cr3 = (struct cr3_32 *)first_operand;
448 if (info->page_mode == SHADOW_PAGING) {
450 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
451 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
453 /* Delete the current Page Tables */
454 delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(shadow_cr3));
456 *guest_cr3 = *new_cr3;
458 // Something like this
459 shadow_pt = create_new_shadow_pt32(info);
460 //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
463 /* Copy Various flags */
464 *shadow_cr3 = *new_cr3;
466 shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
468 if (info->cpu_mode == PROTECTED_PG) {
469 // If we aren't in paged mode then we have to preserve the identity mapped CR3
470 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
477 PrintDebug("Unknown Instruction\n");
481 PrintDebug("Invalid operating Mode\n");
491 int handle_cr3_read(struct guest_info * info) {
492 if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
497 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
499 PrintDebug("Could not read instruction (ret=%d)\n", ret);
503 while (is_prefix_byte(instr[index])) {
507 if ((instr[index] == cr_access_byte) &&
508 (instr[index + 1] == mov_from_cr_byte)) {
509 addr_t first_operand;
510 addr_t second_operand;
511 struct cr3_32 * virt_cr3;
512 struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
513 operand_type_t addr_type;
517 addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
519 if (addr_type != REG_OPERAND) {
520 /* Mov to CR3 can only be a 32 bit register */
524 virt_cr3 = (struct cr3_32 *)first_operand;
526 if (info->page_mode == SHADOW_PAGING) {
527 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
529 *virt_cr3 = *real_cr3;
534 PrintDebug("Unknown Instruction\n");
538 PrintDebug("Invalid operating Mode\n");