2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_mem.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmcb.h>
23 #include <palacios/vmm_decoder.h>
24 #include <palacios/vm_guest_mem.h>
25 #include <palacios/vmm_ctrl_regs.h>
29 /* Segmentation is a problem here...
31 * When we get a memory operand, presumably we use the default segment (which is?)
32 * unless an alternate segment was specfied in the prefix...
36 #ifndef DEBUG_CTRL_REGS
38 #define PrintDebug(fmt, args...)
42 // First Attempt = 494 lines
43 // current = 106 lines
44 int v3_handle_cr0_write(struct guest_info * info) {
47 struct x86_instr dec_instr;
49 if (info->mem_mode == PHYSICAL_MEM) {
50 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
52 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
55 /* The IFetch will already have faulted in the necessary bytes for the full instruction
57 // I think we should inject a GPF into the guest
58 PrintError("Could not read instruction (ret=%d)\n", ret);
63 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
64 PrintError("Could not decode instruction\n");
69 if (v3_opcode_cmp(V3_OPCODE_LMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
70 struct cr0_real *real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
71 struct cr0_real *new_cr0 = (struct cr0_real *)(dec_instr.src_operand.operand);
76 new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
78 PrintDebug("OperandVal = %x\n", new_cr0_val);
80 PrintDebug("Old CR0=%x\n", *(uint_t *)real_cr0);
81 *(uchar_t*)real_cr0 &= 0xf0;
82 *(uchar_t*)real_cr0 |= new_cr0_val;
83 PrintDebug("New CR0=%x\n", *(uint_t *)real_cr0);
86 if (info->shdw_pg_mode == SHADOW_PAGING) {
87 struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
89 PrintDebug(" Old Shadow CR0=%x\n", *(uint_t *)shadow_cr0);
90 *(uchar_t*)shadow_cr0 &= 0xf0;
91 *(uchar_t*)shadow_cr0 |= new_cr0_val;
92 PrintDebug("New Shadow CR0=%x\n", *(uint_t *)shadow_cr0);
94 } else if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
95 PrintDebug("MOV2CR0\n");
97 if (info->cpu_mode == LONG) {
99 PrintError("Long mode currently not handled\n");
103 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
104 struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
106 PrintDebug("OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr.src_operand.size);
109 PrintDebug("Old CR0=%x\n", *(uint_t *)real_cr0);
110 *real_cr0 = *new_cr0;
113 if (info->shdw_pg_mode == SHADOW_PAGING) {
114 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
116 PrintDebug("Old Shadow CR0=%x\n", *(uint_t *)shadow_cr0);
120 *shadow_cr0 = *new_cr0;
123 if (v3_get_mem_mode(info) == VIRTUAL_MEM) {
124 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
125 PrintDebug("Setting up Shadow Page Table\n");
126 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
128 info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
132 PrintDebug("New Shadow CR0=%x\n",*(uint_t *)shadow_cr0);
134 PrintDebug("New CR0=%x\n", *(uint_t *)real_cr0);
137 } else if (v3_opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
139 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
143 if (info->shdw_pg_mode == SHADOW_PAGING) {
144 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
148 PrintError("Unhandled opcode in handle_cr0_write\n");
152 info->rip += dec_instr.instr_length;
158 // First attempt = 253 lines
159 // current = 51 lines
160 int v3_handle_cr0_read(struct guest_info * info) {
163 struct x86_instr dec_instr;
165 if (info->mem_mode == PHYSICAL_MEM) {
166 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
168 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
171 /* The IFetch will already have faulted in the necessary bytes for the full instruction
173 // I think we should inject a GPF into the guest
174 PrintError("Could not read instruction (ret=%d)\n", ret);
179 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
180 PrintError("Could not decode instruction\n");
184 if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
185 struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
186 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
188 PrintDebug("MOVCR2\n");
189 PrintDebug("CR0 at 0x%p\n", (void *)real_cr0);
191 if (info->shdw_pg_mode == SHADOW_PAGING) {
192 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
194 *virt_cr0 = *real_cr0;
197 PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
198 PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
199 } else if (v3_opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
200 struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
201 struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
202 char cr0_val = *(char*)real_cr0 & 0x0f;
204 PrintDebug("SMSW\n");
206 PrintDebug("CR0 at 0x%p\n", real_cr0);
208 *(char *)virt_cr0 &= 0xf0;
209 *(char *)virt_cr0 |= cr0_val;
212 PrintError("Unhandled opcode in handle_cr0_read\n");
216 info->rip += dec_instr.instr_length;
223 // First Attempt = 256 lines
224 // current = 65 lines
225 int v3_handle_cr3_write(struct guest_info * info) {
228 struct x86_instr dec_instr;
230 if (info->mem_mode == PHYSICAL_MEM) {
231 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
233 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
236 /* The IFetch will already have faulted in the necessary bytes for the full instruction
238 // I think we should inject a GPF into the guest
239 PrintError("Could not read instruction (ret=%d)\n", ret);
244 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
245 PrintError("Could not decode instruction\n");
249 if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
251 PrintDebug("MOV2CR3\n");
253 PrintDebug("CR3 at 0x%p\n", &(info->ctrl_regs.cr3));
255 if (info->shdw_pg_mode == SHADOW_PAGING) {
256 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
257 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
258 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
262 PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n",
263 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
267 cached = v3_cache_page_tables32(info, (addr_t)V3_PAddr((void *)(addr_t)CR3_TO_PDE32((void *)*(addr_t *)new_cr3)));
270 PrintError("CR3 Cache failed\n");
272 } else if (cached == 0) {
275 if(info->mem_mode == VIRTUAL_MEM) {
276 PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
277 delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
280 shadow_pt = v3_create_new_shadow_pt32();
282 shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PD32_BASE_ADDR(shadow_pt));
283 PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr );
284 //PrintDebugPageTables( (pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3) );
288 PrintDebug("Reusing cached shadow Page table\n");
292 shadow_cr3->pwt = new_cr3->pwt;
293 shadow_cr3->pcd = new_cr3->pcd;
296 *guest_cr3 = *new_cr3;
298 PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n",
299 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
301 if (info->mem_mode == VIRTUAL_MEM) {
302 // If we aren't in paged mode then we have to preserve the identity mapped CR3
303 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
307 PrintError("Unhandled opcode in handle_cr3_write\n");
311 info->rip += dec_instr.instr_length;
318 // first attempt = 156 lines
319 // current = 36 lines
320 int v3_handle_cr3_read(struct guest_info * info) {
323 struct x86_instr dec_instr;
325 if (info->mem_mode == PHYSICAL_MEM) {
326 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
328 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
331 /* The IFetch will already have faulted in the necessary bytes for the full instruction
333 // I think we should inject a GPF into the guest
334 PrintError("Could not read instruction (ret=%d)\n", ret);
339 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
340 PrintError("Could not decode instruction\n");
344 if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
345 PrintDebug("MOVCR32\n");
346 struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
348 PrintDebug("CR3 at 0x%p\n", &(info->ctrl_regs.cr3));
350 if (info->shdw_pg_mode == SHADOW_PAGING) {
351 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
353 *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
356 PrintError("Unhandled opcode in handle_cr3_read\n");
360 info->rip += dec_instr.instr_length;
365 int v3_handle_cr4_read(struct guest_info * info) {
366 PrintError("CR4 Read not handled\n");
370 int v3_handle_cr4_write(struct guest_info * info) {
373 struct x86_instr dec_instr;
375 if (info->mem_mode == PHYSICAL_MEM) {
376 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
378 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
381 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
382 PrintError("Could not decode instruction\n");
386 if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
387 PrintError("Invalid opcode in write to CR4\n");
391 if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PAE)) {
392 struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
393 struct cr4_32 * old_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
395 PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
396 PrintDebug("Old CR4=%x\n", *(uint_t *)old_cr4);
401 if ((info->shdw_pg_mode == SHADOW_PAGING) &&
402 (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
404 if ((old_cr4->pae == 0) && (new_cr4->pae == 1)) {
405 // Create Passthrough PAE pagetables
406 PrintDebug("Creating PAE passthrough tables\n");
407 info->ctrl_regs.cr3 = (addr_t)V3_PAddr(create_passthrough_pts_PAE32(info));
408 } else if ((old_cr4->pae == 1) && (new_cr4->pae == 0)) {
409 // Create passthrough standard 32bit pagetables
415 PrintDebug("New CR4=%x\n", *(uint_t *)old_cr4);
421 info->rip += dec_instr.instr_length;
426 int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
427 PrintError("EFER Read not handled\n");
432 int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
433 // struct guest_info * info = (struct guest_info *)(priv_data);
434 PrintError("EFER Write not handled (rax=%p, rdx=%p)\n",
435 (void *)(addr_t)(src.lo),
436 (void *)(addr_t)(src.hi));